2.0 KiB
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.
countertyped asbigintnon-negative.passwordHashandsessionInfotyped asUint8Array.timestampMstyped as non-negative integer.
Usage: Basic Example
import { OcraParamsSchema } from "@suaveplan/otp/ocra";
OcraParamsSchema.parse({ challenge: "12345678", counter: 1n });
Usage: Advanced Example
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 fiveOcraParamsfields.
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.