Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
# `error-codes` — `SAND_PERM.*` registry
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
This module owns the stable error-code registry for the
`@suaveplan/api-sandbox-permissions` package. Every deny path raised by
`PermissionChecker` or `BudgetTracker` surfaces as a
`SandboxPermissionError` carrying a code from `SAND_PERM_CODES`. The
namespace is pinned at module-import time so consumers can match either
structurally (`instanceof SandboxPermissionError`) or by stable string
constant (`error.code === SAND_PERM_CODES.DENIED`).
Pinning the registry in a leaf module that depends only on
`@suaveplan/error` keeps the deny-code surface tree-shakeable: a host
that only consumes the budget tracker pulls one code, not the whole
package, and avoids the OTel metric package on cold paths.
## Features
- `SAND_PERM_CODES.DENIED` (`"SAND_PERM.DENIED"`) — raised by every
`PermissionChecker.check*` deny return that the caller chooses to
surface as a thrown error.
- `SAND_PERM_CODES.BUDGET_EXCEEDED` (`"SAND_PERM.BUDGET_EXCEEDED"`) —
raised by `BudgetTracker.tick()` when any of `cpuPercent`,
`memoryMb`, or `wallClockMs` is exceeded.
- `SandboxPermissionCode` discriminated string union.
- `SandboxPermissionError` typed subclass of `SuaveplanError` with
pre-set `name = "SandboxPermissionError"` for stack-trace clarity.
## Usage: Basic
```ts
import {
SAND_PERM_CODES,
SandboxPermissionError,
} from "@suaveplan/api-sandbox-permissions/error-codes";
try {
// call into the checker
} catch (err) {
if (err instanceof SandboxPermissionError) {
if (err.code === SAND_PERM_CODES.DENIED) {
// map to PERMISSION_DENIED inside the plugin
}
}
}
```
## Usage: Advanced
```ts
import {
SAND_PERM_CODES,
SandboxPermissionError,
} from "@suaveplan/api-sandbox-permissions/error-codes";
function reraiseDeny(capability: string, reason: string): never {
throw new SandboxPermissionError(
SAND_PERM_CODES.DENIED,
`sandbox permission denied for capability "${capability}"`,
{ context: { capability, reason } }
);
}
```
The constructor signature mirrors `SuaveplanError`, so
`{ cause, traceId, clock, context }` are all supported. The
`context` object is what the wire boundary serialises as
`details` — it MUST stay redaction-safe (no paths, no hosts, no
secret names), exactly the `{ capability, reason }` envelope
documented in the conformance spec.
## API Reference
- `SAND_PERM_CODES: { readonly DENIED: "SAND_PERM.DENIED"; readonly BUDGET_EXCEEDED: "SAND_PERM.BUDGET_EXCEEDED" }`
- `SandboxPermissionCode = "SAND_PERM.DENIED" | "SAND_PERM.BUDGET_EXCEEDED"`
- `class SandboxPermissionError extends SuaveplanError<SandboxPermissionCode>`
- `constructor(code, message, options?)` — accepts `{ context, cause, traceId, clock }`.
## Implementation Notes
The registry uses `defineCodes` rather than a hand-rolled object literal
so the union type is inferred from the `as const` tuple of reasons. This
is the same pattern as `@suaveplan/api-host`'s `HOST_CODES` /
`PLUGIN_CODES` etc. — every host-stack package collapses its codes to a
single `defineCodes` call so adding a reason is one-line and the type
flows through the rest of the package automatically.
No OTel or zod imports here on purpose — the registry must compile
even when the rest of the package is tree-shaken out. The instrument
descriptors and `Zod` ingestion validators live in their own
sub-modules.