# `claims` ## Purpose Encode and decode RFC 8392 CBOR Web Token claim sets. The seven IANA- registered claims (`iss`, `sub`, `aud`, `exp`, `nbf`, `iat`, `cti`) are typed; private claims keyed by IANA-numeric label survive the round-trip unchanged. ## Features - `encodeCwt(claims)` — deterministic claim-set encoding so token bytes are byte-stable across runs. - `decodeCwt(bytes)` — typed `CwtClaims` output with full validation at the field boundaries. - Time fields (`exp`, `nbf`, `iat`) accept `Date` on the input side; the decoder produces `Date` from raw integers, bigints, or values wrapped in CBOR tag 1 (epoch). - `aud` accepts both `string` and `string[]` per RFC 8392 §3.1. - Private claims threaded through `claims.private` keyed by integer label number — opaque to the typed claims but preserved on round-trip. ## Usage ```ts import { decodeCwt, encodeCwt } from "@suaveplan/cbor/cwt"; const wire = encodeCwt({ iss: "https://issuer.example", exp: new Date("2030-01-01"), cti: new Uint8Array([0x01, 0x02]), private: { 100: "tenant-a" }, }); const claims = decodeCwt(wire); ``` ## API - `encodeCwt(claims: CwtClaims): Uint8Array` - `decodeCwt(bytes: Uint8Array): CwtClaims` Throws `CborError(UNEXPECTED_TYPE)` for malformed claim labels, wrong inner types, non-string `iss`/`sub`, malformed `aud`, etc. ## Notes `exp`/`nbf`/`iat` always serialise as integer epoch seconds rather than `Tagged(1, …)` — both forms are valid on the wire per RFC 8392, but the integer form is shorter and the deterministic profile prefers shortest-form. Private claims must use integer labels per the CWT registry; non-integer keys are silently dropped on encode (the `Object.entries` walk filters them) — the typed `private` shape is keyed by `number`.