# `testing/run-permissions-conformance` — shared conformance harness _(no submodules)_ ## Purpose This module exports the `runPermissionsConformance(label, factory)` harness that every sandbox host (`api-sandbox-vm`, `api-sandbox-wasm`, and any future host) MUST pass before claiming permission-model conformance. The harness encodes the observable contract from the spec delta — every documented allow / deny / budget scenario — so adapters that diverge from the contract are caught at test time. The harness ships on the package's `./testing` subpath so test files import it as `@suaveplan/api-sandbox-permissions/testing`. The in- package self-test (`run-permissions-conformance.test.ts`) exercises the harness against the built-in fixture so a regression in the harness itself is also caught. ## Features - `runPermissionsConformance(label, factory)` — Vitest-/Bun-test- agnostic harness using `@suaveplan/testing/runner`. - `makeFixtureChecker(overrides?)` — the in-package factory exercising the same production code paths the host would wire. - Asserts deny telemetry as a `Record` snapshot from the factory — no real OTel exporter required. - Verifies `SandboxPermissionError` envelope is redaction-safe: the thrown error's `message` does NOT contain the denied path / host. ## Usage: Basic ```ts import { runPermissionsConformance, makeFixtureChecker } from "@suaveplan/api-sandbox-permissions/testing"; runPermissionsConformance("self", makeFixtureChecker()); ``` ## Usage: Advanced ```ts import { runPermissionsConformance, type PermissionsConformanceFactory, } from "@suaveplan/api-sandbox-permissions/testing"; import { PermissionChecker } from "@suaveplan/api-sandbox-permissions/checker"; import { BudgetTracker } from "@suaveplan/api-sandbox-permissions/budget"; import { PermissionPolicy } from "@suaveplan/api-sandbox-permissions/policy"; // Adapter (api-sandbox-vm / api-sandbox-wasm) supplies its own factory // pointing at its composition root. const adapterFactory: PermissionsConformanceFactory = { make() { const policy = new PermissionPolicy({ permissions: { fs: ["./uploads/*"] }, }); // …adapter-specific instruments + clock wiring… return { plugin: "adapter-under-test", checker: new PermissionChecker({ policy, instruments: /* … */ } as never), budget: new BudgetTracker({ policy, instruments: /* … */, clock: /* … */ } as never), snapshot: () => ({}), }; }, }; runPermissionsConformance("api-sandbox-vm", adapterFactory); ``` ## API Reference - `interface PermissionsConformanceFixture { plugin; checker; budget; snapshot(); }` - `interface PermissionsConformanceFactory { make(): PermissionsConformanceFixture; }` - `makeFixtureChecker(overrides?): PermissionsConformanceFactory` - `runPermissionsConformance(label: string, factory: PermissionsConformanceFactory): void` ## Implementation Notes The harness uses `@suaveplan/testing/runner` so it works under both Vitest (default) and `bun:test` (under the `bun` condition); §11 forbids direct imports of either runner in non-exempt packages, and the package's CI gate enforces that. The snapshot is intentionally a flat `Record` keyed by `${counter}|${capability|budget}|${reason|budget}`. Adapter factories that emit denials through a real `MeterProvider` need only ensure their `snapshot()` returns the same key shape; the harness compares string equality, not OTel attribute objects.