# schemas/options ## Purpose Zod schema validating the input options to `createVaultPlugin`. Every field has a Zod-derived default (or `optional()`) so callers can pass just the required `storage` adapter and get sensible behaviour; operators tightening security policy override defaults at the call site. The schema runs at the factory boundary and `safeParse` failures raise `VaultPluginError(VAULT_PLUGIN_INVALID_INPUT)` with the underlying `ZodError` attached as `cause` for diagnostic surfaces (logs, span events). ## Features - Structural `z.custom` check for the `storage` adapter — Zod cannot introspect the `DriveLike` interface, but a four-method duck-type check covers every `DriveLike` implementation shipping today. - Tight `routePrefix` regex matching the shared prefix-validation rule used by `@suaveplan/api-plugin-auth`. - `maxItemSizeBytes` capped at 256 MiB — bodies larger than that route through the attachments surface (not in v1). - `serverPepper` is a free-form opaque string; the default value is a package-level constant, but production deployments SHOULD supply a per-deployment secret loaded from `@suaveplan/env`. ## Usage: Basic ```ts import { VaultPluginOptionsSchema } from "@suaveplan/api-plugin-vault"; const parsed = VaultPluginOptionsSchema.parse({ storage: myDriveAdapter, }); console.log(parsed.routePrefix); // "/vault" console.log(parsed.maxItemSizeBytes); // 10485760 ``` ## Usage: Advanced ```ts import { type VaultPluginOptionsInput, VaultPluginOptionsSchema, } from "@suaveplan/api-plugin-vault"; const input: VaultPluginOptionsInput = { storage: myDriveAdapter, routePrefix: "/v1/vault", maxItemSizeBytes: 1024 * 1024, serverPepper: process.env["VAULT_SERVER_PEPPER"] ?? "", unlockExtractor: (c) => c.req.header("Authorization")?.slice(7) ?? null, }; const resolved = VaultPluginOptionsSchema.safeParse(input); if (!resolved.success) { throw new Error("Invalid vault options: " + resolved.error.message); } ``` ## API Reference ### `VaultPluginOptionsSchema` Top-level Zod `object`. Fields: - `storage` (required, `z.custom`). - `routePrefix` (default `"/vault"`, regex-validated). - `maxItemSizeBytes` (default `10 * 1024 * 1024`, range `[1, 256 MiB]`). - `applySchemaOnInit` (default `true`). - `unlockExtractor` (optional, function). - `serverPepper` (default `"suaveplan-vault-plugin-pepper-v1"`, non-empty). - `logger` (optional, structural `LoggerLike` check). ### `VaultPluginOptionsInput` `z.input` of the schema — what callers MAY pass. ### `VaultPluginOptionsResolved` `z.output` of the schema — every default applied. ## Implementation Notes - The schema does not enforce mutual exclusion between `routePrefix` ending in `/` and routes carrying leading `/` paths — the route builder normalises this at registration time. - `serverPepper` is not constrained beyond non-empty; if operators re-deploy with a different pepper, existing vaults become unreadable by design. Document this in the deployment runbook. - `storage` is intentionally checked structurally rather than via `instanceof` so any package implementing `DriveLike` (`@suaveplan/drive`, bespoke S3 adapters, in-memory test doubles) passes.