mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-05 22:21:42 +00:00
* fix(doctor): isolate host service management * fix(doctor): clarify service isolation recovery * test(doctor): isolate service identity fixtures * test(daemon): keep lifecycle fixtures lint-clean * test(daemon): isolate install identity fixtures
149 lines
4.7 KiB
TypeScript
149 lines
4.7 KiB
TypeScript
/** Typed errors for SecretRef provider and ref-level resolution failures. */
|
|
import type { SecretRef, SecretRefSource } from "../config/types.secrets.js";
|
|
|
|
type SecretRefResolutionCode =
|
|
| "SECRET_REF_NOT_FOUND"
|
|
| "SECRET_REF_POLICY_DENIED"
|
|
| "SECRET_REF_INVALID"
|
|
| "SECRET_REF_PROVIDER_ERROR"
|
|
| "SECRET_REF_PROVIDER_CONTRACT";
|
|
|
|
type SecretProviderResolutionCode =
|
|
| "SECRET_PROVIDER_INVALID"
|
|
| "SECRET_PROVIDER_NOT_CONFIGURED"
|
|
| "SECRET_PROVIDER_UNAVAILABLE";
|
|
|
|
export type SecretResolutionFailureReason =
|
|
| "secret provider failed"
|
|
| "secret provider policy denied resolution"
|
|
| "secret provider response violated its contract"
|
|
| "secret reference was not found";
|
|
|
|
/** Error for failures that affect an entire configured secret provider. */
|
|
class SecretProviderResolutionError extends Error {
|
|
readonly scope = "provider" as const;
|
|
readonly code: SecretProviderResolutionCode;
|
|
readonly source: SecretRefSource;
|
|
readonly provider: string;
|
|
|
|
constructor(params: {
|
|
code: SecretProviderResolutionCode;
|
|
source: SecretRefSource;
|
|
provider: string;
|
|
message: string;
|
|
cause?: unknown;
|
|
}) {
|
|
super(params.message, params.cause !== undefined ? { cause: params.cause } : undefined);
|
|
this.name = "SecretProviderResolutionError";
|
|
this.code = params.code;
|
|
this.source = params.source;
|
|
this.provider = params.provider;
|
|
}
|
|
}
|
|
|
|
/** Error for failures limited to one SecretRef id under a provider. */
|
|
class SecretRefResolutionError extends Error {
|
|
readonly scope = "ref" as const;
|
|
readonly code: SecretRefResolutionCode;
|
|
readonly source: SecretRefSource;
|
|
readonly provider: string;
|
|
readonly refId: string;
|
|
|
|
constructor(params: {
|
|
code: SecretRefResolutionCode;
|
|
source: SecretRefSource;
|
|
provider: string;
|
|
refId: string;
|
|
message: string;
|
|
cause?: unknown;
|
|
}) {
|
|
super(params.message, params.cause !== undefined ? { cause: params.cause } : undefined);
|
|
this.name = "SecretRefResolutionError";
|
|
this.code = params.code;
|
|
this.source = params.source;
|
|
this.provider = params.provider;
|
|
this.refId = params.refId;
|
|
}
|
|
}
|
|
|
|
/** Type guard for provider-scoped secret resolution failures. */
|
|
export function isProviderScopedSecretResolutionError(
|
|
value: unknown,
|
|
): value is SecretProviderResolutionError {
|
|
return value instanceof SecretProviderResolutionError;
|
|
}
|
|
|
|
export function isSecretResolutionError(
|
|
value: unknown,
|
|
): value is SecretProviderResolutionError | SecretRefResolutionError {
|
|
return (
|
|
value instanceof SecretProviderResolutionError || value instanceof SecretRefResolutionError
|
|
);
|
|
}
|
|
|
|
/** Redacted reason suitable for warnings and status output. */
|
|
export function describeSecretResolutionError(
|
|
value: unknown,
|
|
): SecretResolutionFailureReason | undefined {
|
|
if (value instanceof SecretProviderResolutionError) {
|
|
return value.code === "SECRET_PROVIDER_UNAVAILABLE" ? "secret provider failed" : undefined;
|
|
}
|
|
if (!(value instanceof SecretRefResolutionError)) {
|
|
return undefined;
|
|
}
|
|
switch (value.code) {
|
|
case "SECRET_REF_NOT_FOUND":
|
|
return "secret reference was not found";
|
|
case "SECRET_REF_POLICY_DENIED":
|
|
return "secret provider policy denied resolution";
|
|
case "SECRET_REF_PROVIDER_ERROR":
|
|
return "secret provider failed";
|
|
case "SECRET_REF_PROVIDER_CONTRACT":
|
|
return "secret provider response violated its contract";
|
|
case "SECRET_REF_INVALID":
|
|
return undefined;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
export function providerResolutionError(params: {
|
|
code?: SecretProviderResolutionCode;
|
|
source: SecretRefSource;
|
|
provider: string;
|
|
message: string;
|
|
cause?: unknown;
|
|
}): SecretProviderResolutionError {
|
|
return new SecretProviderResolutionError({
|
|
...params,
|
|
code: params.code ?? "SECRET_PROVIDER_UNAVAILABLE",
|
|
});
|
|
}
|
|
|
|
export function refResolutionError(params: {
|
|
code: SecretRefResolutionCode;
|
|
source: SecretRefSource;
|
|
provider: string;
|
|
refId: string;
|
|
message: string;
|
|
cause?: unknown;
|
|
}): SecretRefResolutionError {
|
|
return new SecretRefResolutionError(params);
|
|
}
|
|
|
|
/** Returns whether one SecretRef failed because its configured value is absent. */
|
|
export function isMissingSecretRefResolutionError(params: {
|
|
ref: SecretRef;
|
|
error: unknown;
|
|
}): boolean {
|
|
const refId = params.ref.id.trim();
|
|
// Canonical refs already own their provider identity. Config defaults only fill an omitted
|
|
// provider during coercion; resolution never rewrites an explicit provider such as "default".
|
|
return (
|
|
params.error instanceof SecretRefResolutionError &&
|
|
params.error.code === "SECRET_REF_NOT_FOUND" &&
|
|
params.error.source === params.ref.source &&
|
|
params.error.provider === params.ref.provider &&
|
|
params.error.refId === refId
|
|
);
|
|
}
|