Move docs/ package mirror into document-navigator plugin

Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 01:10:00 +01:00
parent fe3fedf42e
commit 9bf56a806b
6022 changed files with 12437 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
# `instruments` — OTel counter descriptors
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
This module owns the OTel counter pair that every sandboxed-tier host
emits on a deny / budget-breach path. Centralising them here ensures
both `api-sandbox-vm` and `api-sandbox-wasm` (and any future host) emit
the SAME metric name with the SAME label set, so dashboards built
against one host work identically against the other.
The descriptors are also enumerated by the conformance harness, so any
host that omits a counter or emits a different label set is caught at
test time rather than in production.
## Features
- `PERMISSION_COUNTER_NAMES` — frozen tuple naming every counter in the
registry: `plugin.permission_denied_total`,
`plugin.budget_exceeded_total`.
- `createPermissionInstruments({ plugin, meterProvider?, meterName? })`
— bundles every counter pre-bound to the supplied (or global) meter
provider.
- `PermissionInstruments` — runtime handle whose `recordDenial` /
`recordBudgetBreach` methods auto-attach the stable `plugin` label.
- `PermissionDenyAttributes` / `BudgetBreachAttributes` — label-set
contracts consumed by both production code and the conformance test.
## Usage: Basic
```ts
import { createPermissionInstruments } from "@suaveplan/api-sandbox-permissions/instruments";
const inst = createPermissionInstruments({ plugin: "billing" });
inst.recordDenial({ capability: "fs", reason: "path-not-in-allowlist" });
```
## Usage: Advanced
```ts
import { metrics } from "@opentelemetry/api";
import { createPermissionInstruments } from "@suaveplan/api-sandbox-permissions/instruments";
// Wire to a custom provider for in-process unit tests so denials can be
// asserted against the captured `add()` calls.
const provider = metrics.getMeterProvider();
const inst = createPermissionInstruments({
plugin: "billing",
meterProvider: provider,
meterName: "@billing/sandbox",
});
inst.recordBudgetBreach({ budget: "wallClockMs" });
```
The label-set contract is intentionally narrow — `plugin`, `capability`,
`reason` for denials and `plugin`, `budget` for budget breaches. New
labels MUST be added through the spec because OTel exporter
cardinality is bounded by the union of every label observed.
## API Reference
- `PERMISSION_COUNTER_NAMES: readonly ["plugin.permission_denied_total", "plugin.budget_exceeded_total"]`
- `type PermissionCounterName = (typeof PERMISSION_COUNTER_NAMES)[number]`
- `interface PermissionDenyAttributes { plugin; capability; reason; }`
- `interface BudgetBreachAttributes { plugin; budget: "cpuPercent"|"memoryMb"|"wallClockMs"; }`
- `interface PermissionInstrumentsConfig { plugin; meterProvider?; meterName?; }`
- `interface PermissionInstruments { plugin; recordDenial; recordBudgetBreach; }`
- `createPermissionInstruments(config): PermissionInstruments`
## Implementation Notes
The module never installs a `MeterProvider` — operator config owns SDK
installation. When the global provider is the no-op default,
`recordDenial` and `recordBudgetBreach` succeed silently, which is the
documented production behaviour when telemetry is disabled.
The handle pre-binds the `plugin` label so call sites cannot forget
it. The `recordDenial` / `recordBudgetBreach` signatures take the
remaining labels — `Omit<…, "plugin">` — so the type system enforces
the partition.