first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
# schemas
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`schemas.ts` provides Zod runtime validators for every public boundary type
declared in `types.ts`. The validators are the contract enforced at API
entry and exit: a `VaultItem` reaching `mergeVaultItems`, a `SyncOperation`
queued by `SyncQueue.enqueue`, an `EncryptedSyncPayload` decoded by
`decryptSyncPayload` — all are first parsed by the appropriate schema so a
malformed input fails fast with a structured error rather than producing a
hard-to-debug shape mismatch later in the pipeline.
## Features
- `VectorClockSchema` — `Record<string, non-negative-int>`
- `VaultHistoryEntrySchema` — `{ historyId; timestamp; note }`, strict
- `VaultItemSchema` — full canonical vault-item shape, strict
- `MergeStrategySchema` — `"lww" | "append" | "atomic"`
- `SyncOperationKindSchema` — `"create" | "update" | "delete"`
- `SyncOperationSchema` — durable-queue entry shape with partial `fields`
- `VaultSnapshotSchema` — `{ items; clock; snapshotAt }`, strict
- `EncryptedSyncPayloadSchema` — version + 24-byte nonce + ciphertext
- All schemas are `.strict()` — extra keys raise an error
## Usage: Basic Example
```ts
import { VaultItemSchema } from "@suaveplan/vault-sync/schemas/schemas";
const parsed = VaultItemSchema.safeParse({
id: "i1",
title: "Email",
password: "hunter2",
folderId: null,
history: [],
nodeId: "n1",
updatedAt: 0,
clock: { n1: 1 },
});
if (!parsed.success) throw new Error("invalid item");
```
## Usage: Advanced Example
```ts
import {
EncryptedSyncPayloadSchema,
SyncOperationSchema,
VaultSnapshotSchema,
} from "@suaveplan/vault-sync/schemas/schemas";
import { VaultSyncError } from "@suaveplan/vault-sync";
import { VAULT_SYNC_CODES } from "@suaveplan/vault-sync/errors";
function asPayload(input: unknown): import("@suaveplan/vault-sync/types").EncryptedSyncPayload {
const parsed = EncryptedSyncPayloadSchema.safeParse(input);
if (!parsed.success) {
throw new VaultSyncError(
VAULT_SYNC_CODES["SYNC.PAYLOAD_INVALID_VERSION"],
"error.vault-sync.sync.payload-invalid-version",
{ context: { issues: parsed.error.issues.length } }
);
}
return parsed.data;
}
declare const wireSnapshot: unknown;
declare const wireOperation: unknown;
const snapshot = VaultSnapshotSchema.parse(wireSnapshot);
const operation = SyncOperationSchema.parse(wireOperation);
```
## API Reference
- `VectorClockSchema: ZodSchema<Record<string, number>>` — keys must be
non-empty strings; values must be non-negative integers.
- `VaultHistoryEntrySchema: ZodSchema<VaultHistoryEntry>` — strict.
- `VaultItemSchema: ZodSchema<VaultItem>` — strict; `folderId` is `string |
null`; `history` is an array; `clock` validated by `VectorClockSchema`.
- `MergeStrategySchema: ZodUnion<[lww, append, atomic]>`.
- `SyncOperationKindSchema: ZodUnion<[create, update, delete]>`.
- `SyncOperationSchema: ZodSchema<SyncOperation>` — strict; `fields` validated
with `VaultItemSchema.partial()` so any subset of vault fields is acceptable.
- `VaultSnapshotSchema: ZodSchema<VaultSnapshot>` — strict.
- `EncryptedSyncPayloadSchema: ZodSchema<EncryptedSyncPayload>` — `version`
must equal `"v1"`; `nonce` must be exactly 24 bytes (XChaCha20).
## Implementation Notes
Strict mode (`.strict()`) is intentional — `vault-sync` is a wire
boundary, and silently accepting unknown fields opens a downgrade attack
where a malicious peer adds a future-version field that gets ignored. The
`nonce` byte-length check is duplicated (also enforced by
`crypto-cipher`'s XChaCha primitive) so callers parsing a payload without
attempting to decrypt still see a clear schema-level failure. All schemas
are pure values — they take no constructor arguments, they have no shared
state, and they are safe to use in any execution context.