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,118 @@
# `checker/checker` — `PermissionChecker`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
This module is the composite entry point that the two sandbox hosts
(`api-sandbox-vm`, `api-sandbox-wasm`) wire into their worker capability
proxy. It binds a `PermissionPolicy` to a `PermissionInstruments` handle
and exposes the three production check methods plus three `assert*`
helpers that throw `SandboxPermissionError` in the default `"enforce"`
deny mode.
Construction is per plugin-worker pair — never global — because the
policy and instruments both pin the `plugin` label and the worker
boundary is the natural granularity for the check + telemetry pair.
## Features
- `PermissionChecker.checkFs / checkFetch / checkCapability` — invoke
the underlying pure function AND record the deny counter on a deny
outcome.
- `PermissionChecker.assertFs / assertFetch / assertCapability` — same
as above, but in `"enforce"` mode raise `SandboxPermissionError`
on deny; in `"warn"` mode return the deny result silently after
recording the counter.
- `DenyMode` — `"enforce"` (default) or `"warn"`.
- Deny telemetry — every deny path records exactly one
`plugin.permission_denied_total` increment with the documented
`{ plugin, capability, reason }` label set.
## Usage: Basic
```ts
import { PermissionChecker } from "@suaveplan/api-sandbox-permissions/checker";
import { createPermissionInstruments } from "@suaveplan/api-sandbox-permissions/instruments";
import { PermissionPolicy } from "@suaveplan/api-sandbox-permissions/policy";
const checker = new PermissionChecker({
policy: new PermissionPolicy({
permissions: { fs: ["./uploads/*"], fetch: ["api.stripe.com"] },
}),
instruments: createPermissionInstruments({ plugin: "billing" }),
});
const fs = checker.checkFs("./uploads/avatar.png", "read");
console.assert(fs.outcome === "allow");
```
## Usage: Advanced
```ts
import { PermissionChecker } from "@suaveplan/api-sandbox-permissions/checker";
import { createPermissionInstruments } from "@suaveplan/api-sandbox-permissions/instruments";
import { PermissionPolicy } from "@suaveplan/api-sandbox-permissions/policy";
import { SAND_PERM_CODES, SandboxPermissionError } from "@suaveplan/api-sandbox-permissions/error-codes";
// Canary mode — record denies on metrics, do not block the call.
const canary = new PermissionChecker({
policy: new PermissionPolicy({
permissions: { fs: ["./uploads/*"] },
}),
instruments: createPermissionInstruments({ plugin: "billing" }),
mode: "warn",
});
const warnResult = canary.assertFs("./etc/passwd", "read");
console.assert(warnResult.outcome === "deny");
// `plugin.permission_denied_total{plugin: "billing", capability: "fs",
// reason: "path-not-in-allowlist"}` incremented; no throw.
// Enforcing mode — throws on deny.
const strict = new PermissionChecker({
policy: canary.policy,
instruments: canary.instruments,
// mode: "enforce" — default
});
try {
strict.assertFs("./etc/passwd", "read");
} catch (err) {
if (err instanceof SandboxPermissionError) {
console.assert(err.code === SAND_PERM_CODES.DENIED);
}
}
```
## API Reference
- `class PermissionChecker`
- `constructor({ policy, instruments, mode? })`
- `readonly policy: PermissionPolicy`
- `readonly instruments: PermissionInstruments`
- `readonly mode: DenyMode`
- `checkFs(path, mode): CheckResult`
- `checkFetch(url): CheckResult`
- `checkCapability(payload): CheckResult`
- `assertFs(path, mode): CheckResult` (throws in enforce mode)
- `assertFetch(url): CheckResult`
- `assertCapability(payload): CheckResult`
- `type DenyMode = "enforce" | "warn"`
- `type CheckerCapabilitySource = "fs" | "fetch" | "db" | "secrets" | "events"`
## Implementation Notes
The class is deliberately stateless apart from its three readonly fields —
deny telemetry is delegated to the `PermissionInstruments` handle, which
is itself stateless behind the OTel counters. This means the checker is
safe to instantiate once per plugin-worker pair and share across every
in-flight capability call.
The `assert*` helpers wrap `check*` rather than the pure functions so
the counter increments exactly once per deny: the underlying pure
functions do not call `recordDenial`, only the checker methods do.
A deny-mode-`warn` call therefore records the same counter the
`enforce` mode would, which is what dashboards rely on to detect
canary-phase regressions.