3.2 KiB
3.2 KiB
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.customcheck for thestorageadapter — Zod cannot introspect theDriveLikeinterface, but a four-method duck-type check covers everyDriveLikeimplementation shipping today. - Tight
routePrefixregex matching the shared prefix-validation rule used by@suaveplan/api-plugin-auth. maxItemSizeBytescapped at 256 MiB — bodies larger than that route through the attachments surface (not in v1).serverPepperis 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
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
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<DriveLike>).routePrefix(default"/vault", regex-validated).maxItemSizeBytes(default10 * 1024 * 1024, range[1, 256 MiB]).applySchemaOnInit(defaulttrue).unlockExtractor(optional, function).serverPepper(default"suaveplan-vault-plugin-pepper-v1", non-empty).logger(optional, structuralLoggerLikecheck).
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
routePrefixending in/and routes carrying leading/paths — the route builder normalises this at registration time. serverPepperis 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.storageis intentionally checked structurally rather than viainstanceofso any package implementingDriveLike(@suaveplan/drive, bespoke S3 adapters, in-memory test doubles) passes.