import type { SuaveplanErrorOptions } from "@suaveplan/error"; import { defineCodes, SuaveplanError } from "@suaveplan/error"; /** * Stable error-code registry for `@suaveplan/api-plugin-vault`. * * Every failure path in the vault plugin raises a {@link VaultPluginError} * carrying one of these 9 `VAULT_PLUGIN.*` codes. Consumers branch on the * string value (e.g. `error.code === VAULT_PLUGIN_CODES.ITEM_NOT_FOUND`). * * - `INVALID_INPUT` — `createVaultPlugin(options)` received options that * failed `VaultPluginOptionsSchema` validation. `cause` holds the * `ZodError`. * - `ITEM_NOT_FOUND` — the requested item id does not exist OR is owned * by a different principal. (We DO NOT distinguish; surfacing * ownership as 403 would let an attacker enumerate ids that exist for * other users.) * - `FORBIDDEN` — reserved for explicit ownership-policy failures the * plugin's middleware chain may raise in the future (e.g. shared-link * ACL rejection). Currently raised by the `vaultService` when a caller * attempts to mutate via the service layer outside an open vault. * - `UNLOCK_FAILED` — the principal's password failed to unlock the * underlying `@suaveplan/vault` instance (wrong password, corrupted * container). * - `ITEM_TOO_LARGE` — the encoded body of an item write exceeded * `options.maxItemSizeBytes`. * - `SERVICE_NOT_AVAILABLE` — a required `ServiceRegistry` slot was * absent at `onInit`. `context.missing` lists the missing slot names. * - `SCHEMA_APPLY_FAILED` — the bundled SurrealQL schema apply step * threw (`migrationRunner.run` or the fallback `db.execute` rejected). * - `ROUTE_PREFIX_COLLISION` — the configured `routePrefix` collides * with routes already registered by another plugin in the host's * `OpenAPIRegistry`. * - `UNLOCK_HEADER_MISSING` — the `unlockExtractor` returned `null` for * a route that requires the unlock secret. The default extractor reads * `X-Vault-Unlock`. */ export const VAULT_PLUGIN_CODES = defineCodes("VAULT_PLUGIN", [ "INVALID_INPUT", "ITEM_NOT_FOUND", "FORBIDDEN", "UNLOCK_FAILED", "ITEM_TOO_LARGE", "SERVICE_NOT_AVAILABLE", "SCHEMA_APPLY_FAILED", "ROUTE_PREFIX_COLLISION", "UNLOCK_HEADER_MISSING", ] as const); export type VaultPluginErrorCode = (typeof VAULT_PLUGIN_CODES)[keyof typeof VAULT_PLUGIN_CODES]; /** * Concrete error class for the api-plugin-vault package. Extends * {@link SuaveplanError} so `instanceof VaultPluginError` narrows * `code` to {@link VaultPluginErrorCode}. Constructor is `public` so * callers may construct errors directly. */ export class VaultPluginError extends SuaveplanError { public readonly vaultPluginCode: VaultPluginErrorCode; public constructor( code: VaultPluginErrorCode, message: string, options?: SuaveplanErrorOptions ) { super(code, message, options); this.vaultPluginCode = code; } }