Initial Commit
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# 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<DriveLike>`).
|
||||
- `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.
|
||||
Reference in New Issue
Block a user