# `errors/error-codes` — `TPM_STRUCT` error registry _(no submodules)_ ## Purpose The `errors` module ships the canonical `defineCodes("TPM_STRUCT", [...])` registry (10 codes) and the `TpmStructError extends SuaveplanError` base class every other module throws from. Stable codes are non-negotiable: consumers (WebAuthn verifiers, attestation gateways, log scrapers) branch on `err.code` to distinguish "buffer was short" from "magic prefix wrong" from "the registered code I care about for my dashboard." A registry with a fixed alphabet is also what makes the `tpm_struct.parse_errors_total{code}` OTel counter bounded. ## Features - Ten registered codes covering every failure class from §8.3 (object attributes), §10.x (attest), §11.x (algorithm and curve), §12.x (public area), and §16 (name). - `TpmStructError` extends `SuaveplanError` so `instanceof` narrows the `.code` union. - `tpmStructError(code, message, detail?)` helper attaches a structured `detail` payload (cursor, requested length, Zod issues) to the cause chain so log adapters can format failures without downcasting. ## Usage: Basic Example ```ts import { TPM_STRUCT_CODES, TpmStructError, tpmStructError, } from "@suaveplan/tpm-struct/errors"; try { // ... parser code } catch (e) { if (e instanceof TpmStructError) { console.error(`tpm-struct failure: ${e.code}`); if (e.code === TPM_STRUCT_CODES.TRUNCATED) { // recoverable: ask the upstream for a longer buffer } } } void tpmStructError; ``` ## Usage: Advanced Example ```ts import { TPM_STRUCT_CODES, TpmStructError, } from "@suaveplan/tpm-struct/errors"; type ParseFailureMetric = "magic" | "truncated" | "alg" | "curve" | "other"; function classify(err: TpmStructError): ParseFailureMetric { switch (err.code) { case TPM_STRUCT_CODES.MAGIC_INVALID: return "magic"; case TPM_STRUCT_CODES.TRUNCATED: return "truncated"; case TPM_STRUCT_CODES.ALG_UNSUPPORTED: return "alg"; case TPM_STRUCT_CODES.CURVE_UNSUPPORTED: return "curve"; default: return "other"; } } // `cause.detail` carries the structured failure context. function reportTruncated(err: TpmStructError) { const detail = ((err as unknown as { cause?: { detail?: Record } }) .cause?.detail) ?? {}; return { cursor: detail.cursor, requested: detail.requested }; } ``` ## API Reference - **`TPM_STRUCT_CODES`** — frozen registry: `MAGIC_INVALID`, `TRUNCATED`, `ALG_UNSUPPORTED`, `CURVE_UNSUPPORTED`, `TYPE_MISMATCH`, `MALFORMED`, `NAME_ALG_NULL`, `ATTEST_TYPE_UNSUPPORTED`, `PARAMETERS_INVALID`, `OBJECT_ATTRIBUTES_RESERVED_NONZERO`. Each value is the literal `TPM_STRUCT.`. - **`TpmStructError`** — base class, message is always prefixed with the code literal. - **`TpmStructErrorCode`** — literal union of the ten code strings. - **`tpmStructError(code, message, detail?)`** — convenience constructor; `detail` (when provided) is wrapped in an Error so it survives through the `cause` chain. ## Implementation Notes The error message is always prefixed with the code literal so log scrapers find a stable substring without inspecting `.code`. Non-Error detail payloads are wrapped in a synthetic `Error` carrying a `detail` slot — this preserves the standard ECMAScript Error.cause shape while still surfacing structured fields downstream code can read.