Initial Commit
This commit is contained in:
95
packages/networking/drive/drive-template/src/error-codes.md
Normal file
95
packages/networking/drive/drive-template/src/error-codes.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# DTP_CODES + DriveTemplateError
|
||||
|
||||
## Purpose
|
||||
|
||||
Frozen registry of error codes plus the error class for the `@suaveplan/drive-template` package. Eleven codes cover the complete failure surface: the eight-step validation pipeline that `Drive.hydrateFrom(template)` runs (version check, expiry, freshness, replay, issuer trust, signature, recursion depth, file consistency) plus three operational codes for CDN signature failure, inline-file signature failure, and key-grant rejection. Consumers branch on `code` programmatically; messages are for humans only.
|
||||
|
||||
## Features
|
||||
|
||||
- Eleven codes mapping one-to-one to the eight-step pipeline plus three operational paths.
|
||||
- `DTP_CODES` is frozen via `defineCodes` from `@suaveplan/error` — adding a code requires a code change and a spec update.
|
||||
- `DriveTemplateError extends SuaveplanError<DtpErrorCode>` — inherits cause-chain traversal, redaction, and JSON wire format.
|
||||
- Type-level exhaustiveness on switch statements via the literal-string `DtpErrorCode` union.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { DriveTemplateError, DTP_CODES } from "@suaveplan/drive-template/errors";
|
||||
|
||||
throw new DriveTemplateError(
|
||||
DTP_CODES.TEMPLATE_EXPIRED,
|
||||
"template expired at 2026-01-01T00:00:00Z",
|
||||
);
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
DriveTemplateError,
|
||||
DTP_CODES,
|
||||
type DtpErrorCode,
|
||||
} from "@suaveplan/drive-template/errors";
|
||||
|
||||
const remediation: Record<DtpErrorCode, string> = {
|
||||
"DTP.TEMPLATE_VERSION_UNSUPPORTED": "Update the client; this template uses a newer schema.",
|
||||
"DTP.TEMPLATE_EXPIRED": "Request a fresh template from the issuer.",
|
||||
"DTP.TEMPLATE_STALE": "Request a fresh template; this one is more than 24h old.",
|
||||
"DTP.TEMPLATE_REPLAY": "Template nonce already seen; the issuer must mint a new one.",
|
||||
"DTP.TEMPLATE_UNTRUSTED_ISSUER": "Add the issuer to globalPolicy.trustedKeyAuthorities.",
|
||||
"DTP.TEMPLATE_SIG_INVALID": "Template signature does not match the canonical bytes; possible tampering.",
|
||||
"DTP.TEMPLATE_TOO_DEEP": "Folder recursion exceeds the 32-level cap.",
|
||||
"DTP.TEMPLATE_MALFORMED": "Per-file consistency violated; check chunkSize, totalChunks, and manifest fields.",
|
||||
"DTP.CDN_BAD_SIGNATURE": "CDN response failed Ed25519 verification; falling back to mesh.",
|
||||
"DTP.INLINE_SIG_INVALID": "Inline file's stored signature does not match the bytes.",
|
||||
"DTP.KEY_GRANT_REJECTED": "Key grant signature, recipient, or issuer did not match the template.",
|
||||
};
|
||||
|
||||
try {
|
||||
// hydrate code...
|
||||
} catch (err) {
|
||||
if (err instanceof DriveTemplateError) {
|
||||
console.error(`[${err.code}] ${err.message}`);
|
||||
console.error("Remediation:", remediation[err.code]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `const DTP_CODES`
|
||||
|
||||
Frozen object mapping uppercase code names to wire-format strings. Eleven entries:
|
||||
|
||||
**Eight-step validation pipeline** (matches `DTP-05` ordering):
|
||||
|
||||
- `TEMPLATE_VERSION_UNSUPPORTED` — `template.schemaVersion !== 1`. Future schema versions ship as new packages.
|
||||
- `TEMPLATE_EXPIRED` — `Date.now() >= template.expiresAt`.
|
||||
- `TEMPLATE_STALE` — `Date.now() - template.issuedAt > 24h`. Templates issued more than 24h ago are rejected even if not yet expired.
|
||||
- `TEMPLATE_REPLAY` — `(driveId, nonce)` already seen in the local LRU cache (last 1024 entries).
|
||||
- `TEMPLATE_UNTRUSTED_ISSUER` — `template.issuer` is not in `globalPolicy.trustedKeyAuthorities`.
|
||||
- `TEMPLATE_SIG_INVALID` — Ed25519 verification of `serverSignature` over `canonicalSerialize(template - sig)` failed.
|
||||
- `TEMPLATE_TOO_DEEP` — folder recursion exceeds 32 levels.
|
||||
- `TEMPLATE_MALFORMED` — per-file consistency violated: `chunkSize <= 164`, `totalChunks * chunkSize < size`, `manifestKey` empty, etc.
|
||||
|
||||
**Operational**:
|
||||
|
||||
- `CDN_BAD_SIGNATURE` — chunk fetched from CDN failed Ed25519 sig verification. Drive falls back to mesh.
|
||||
- `INLINE_SIG_INVALID` — inline file's stored Ed25519 signature does not match `Ed25519-sign(driveSecretKey, fileId ‖ bytes)`.
|
||||
- `KEY_GRANT_REJECTED` — incoming `KeyGrantEnvelope` failed validation: issuer mismatch, recipient mismatch, sig invalid, or expired.
|
||||
|
||||
### `type DtpErrorCode`
|
||||
|
||||
Union: `(typeof DTP_CODES)[keyof typeof DTP_CODES]`.
|
||||
|
||||
### `class DriveTemplateError extends SuaveplanError<DtpErrorCode>`
|
||||
|
||||
Constructor: `new DriveTemplateError(code, message, options?)`. Inherits all `SuaveplanError` features.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The eight pipeline codes are ordered by check sequence in `DTP-05`. Implementations MUST throw the first applicable code — they are mutually exclusive in a single hydrate call. The three operational codes are independent: a single drive may emit multiple `CDN_BAD_SIGNATURE` and `INLINE_SIG_INVALID` errors during normal operation; both are observable signals, not blockers.
|
||||
|
||||
`KEY_GRANT_REJECTED` is the only error code whose `context` field carries structured detail by convention. Implementations should populate `context` with `{ reason: 'untrusted-issuer' | 'wrong-recipient' | 'bad-signature' | 'expired' }` so callers can branch on the specific failure.
|
||||
|
||||
The `error-codes.spec-conformance.test.ts` enforces (1) the registry is frozen, (2) every code value starts with `DTP.`, (3) the eleven names match what the spec requires.
|
||||
Reference in New Issue
Block a user