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,57 @@
# `ocra/ocra.schema`
## Purpose
Zod boundary schema for `OcraParams` — the runtime parameter bag passed
alongside a suite string and a key. Optional fields (`counter`, `passwordHash`,
`sessionInfo`, `timestampMs`) are validated when present so callers cannot
silently pass through malformed values; the actual presence/absence rule is
enforced by `buildOcraMessage` against the parsed suite directives.
## Features
- Strict-mode object — unknown keys rejected.
- `counter` typed as `bigint` non-negative.
- `passwordHash` and `sessionInfo` typed as `Uint8Array`.
- `timestampMs` typed as non-negative integer.
## Usage: Basic Example
```ts
import { OcraParamsSchema } from "@suaveplan/otp/ocra";
OcraParamsSchema.parse({ challenge: "12345678", counter: 1n });
```
## Usage: Advanced Example
```ts
import { OcraParamsSchema } from "@suaveplan/otp/ocra";
// Validate before passing through to ocra() — useful at API boundaries.
const safe = OcraParamsSchema.safeParse(req.body);
if (!safe.success) return res.status(400).json(safe.error);
```
## API Reference
- `OcraParamsSchema` — strict Zod object covering all five `OcraParams`
fields.
## Implementation Notes
The schema is intentionally permissive about WHICH optional fields are
present — that's the suite parser's responsibility. Validating the shape
of values that ARE present catches cases like `counter: -1n` or
`timestampMs: -5` that would otherwise produce nonsensical OCRA outputs
without raising.
The schema lives in its own module so consumers that only need validation
(e.g. an API gateway that records OCRA-bound transactions) can import it
without pulling in the OCRA codec. The `Uint8Array` instance check uses
Zod's `z.instanceof` so tagged byte arrays round-trip cleanly. Callers
passing `ArrayBuffer` instead must convert at the boundary; the schema
deliberately does not accept arbitrary buffer shapes to avoid silent
slice / endianness surprises. The `counter` and `timestampMs` lower-bounds
are non-negative because OCRA inherits the unsigned counter rules from
RFC 4226 §5.1.