Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
# `errors/error-codes` — `TPM_STRUCT` error registry
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The `errors` module ships the canonical `defineCodes("TPM_STRUCT", [...])`
registry (10 codes) and the `TpmStructError extends SuaveplanError<TpmStructErrorCode>`
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<TpmStructErrorCode>` 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<string, unknown> } })
.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.<NAME>`.
- **`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.