# `@suaveplan/license` — codec/payload _(no submodules)_ ## Purpose `packPayload` and `unpackPayload` are the 72-bit payload codec on top of the bitpack primitives. They emit exactly 9 bytes (the binary contract shared with upstream `@suaveplan/license`) and walk the 9 schema fields in the canonical order declared by `FIELD_BITS`. `packPayload` raises `LicenseError(LICENSE.PAYLOAD_OUT_OF_RANGE)` when a field exceeds its declared bit width (via the underlying bitpacker). `unpackPayload` raises `LicenseError(LICENSE.MALFORMED)` for any input length other than `PAYLOAD_BYTES` (9). ## Features - Bit-for-bit wire compatibility with upstream's `packPayload` / `unpackPayload`. - Field-bound validation via `SimpleBitPacker.packUint`, surfaced as typed `LicenseError`s. - Strict 9-byte length invariant on both sides — no implicit truncation or padding. - Returns a fresh `Uint8Array`; safe to mutate the caller's buffer. ## Usage: Basic ```ts import { packPayload, unpackPayload, } from "@suaveplan/license/codec/payload/payload"; import { PackageTier, TimeEncodingType } from "@suaveplan/license/types/license"; const bytes = packPayload({ version: 2, signingKeyId: 0, productId: 1, packageTier: PackageTier.PRO, flags: 0, timeEncodingType: TimeEncodingType.NONE, timeValue: 0, featureMask: 0, nonce: 0x123, }); console.log(bytes.length); // 9 const round = unpackPayload(bytes); ``` ## Usage: Advanced Catching a field-overflow at the generation boundary: ```ts import { LicenseError } from "@suaveplan/license"; import { packPayload } from "@suaveplan/license/codec/payload/payload"; try { packPayload({ /* ...valid */ productId: 64 } as never); // 6 bits, max 63 } catch (err) { if (err instanceof LicenseError && err.code === "LICENSE.PAYLOAD_OUT_OF_RANGE") { // surface to the user as a form-validation failure } } ``` ## API Reference ### `packPayload(payload: LicensePayload): Uint8Array` Pack a payload to its 9-byte representation. Throws `LicenseError(LICENSE.PAYLOAD_OUT_OF_RANGE)` on field overflow. ### `unpackPayload(data: Uint8Array): LicensePayload` Unpack a 9-byte buffer. Throws `LicenseError(LICENSE.MALFORMED)` for any other length. ## Implementation Notes The unpacker casts `timeEncodingType` to the `TimeEncodingType` enum even though the bit width (2) admits any value in `[0, 3]` — all four values map to legitimate enum members, so the cast is safe. The constant `PAYLOAD_BYTES = 9` lives in `constants/constants.ts` so any future schema change (which would require a `LICENSE_VERSION` bump) updates a single source of truth.