first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
# vault OTel instruments
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`instruments.ts` is the single source of truth for OpenTelemetry instruments emitted by `@suaveplan/vault`. It exports a frozen `VaultInstruments` interface plus lazy-singleton accessors (`getVaultInstruments`, `getVaultTracer`) and test-only overrides (`setVaultMeterProvider`, `setVaultTracerProvider`, `resetVaultInstruments`, `resetVaultTracer`).
Every histogram, counter, and span is **safe-by-construction**: no password, no secret key, no AUK, no item content, no vault identifier, no item id, and no key material is permitted in any attribute. Only operation labels, status enums (`status` ∈ documented allowlist), durations in ms, and counts cross the OTel boundary. This guarantees that enabling vault telemetry can never leak vault contents into a tracing backend, even when the backend is misconfigured or compromised.
## Features
- `unlockDurationMs` / `lockDurationMs` / `flushDurationMs` — lifecycle latency histograms with no per-vault attributes.
- `itemOpDurationMs` / `attachmentOpDurationMs` / `shareOpDurationMs` / `syncOpDurationMs` — operation latency histograms keyed by operation kind.
- `lifecycleOutcomeTotal` / `itemOutcomeTotal` / `attachmentOutcomeTotal` / `shareOutcomeTotal` / `syncOutcomeTotal` — outcome counters with `status` allowlist enforced at the call site.
- Lazy-singleton accessors so no OTel cost is paid until the first use.
- `set*Provider` overrides for deterministic in-memory test providers; `reset*` to clear cached state between tests.
## Usage: Basic Example
```ts
import { getVaultInstruments } from "@suaveplan/vault/otel/instruments";
const instruments = getVaultInstruments();
const start = Date.now();
await vault.unlock(password, secretKey);
instruments.unlockDurationMs.record(Date.now() - start);
instruments.lifecycleOutcomeTotal.add(1, { status: "unlocked" });
```
## Usage: Advanced Example
```ts
import { metrics, type MeterProvider } from "@opentelemetry/api";
import {
getVaultInstruments,
resetVaultInstruments,
setVaultMeterProvider,
} from "@suaveplan/vault/otel/instruments";
// Inject an in-memory test provider for assertion-driven tests.
const testProvider: MeterProvider = createInMemoryMeterProvider();
setVaultMeterProvider(testProvider);
try {
const instruments = getVaultInstruments();
instruments.itemOpDurationMs.record(12, { op: "create" });
instruments.itemOutcomeTotal.add(1, { op: "create", status: "success" });
// ... assert against testProvider's recorded data points ...
} finally {
resetVaultInstruments();
setVaultMeterProvider(undefined);
}
```
## API Reference
- `interface VaultInstruments` — frozen shape of the instrument set.
- `getVaultInstruments(): VaultInstruments` — lazy accessor for the cached instrument set.
- `setVaultMeterProvider(provider: MeterProvider | undefined): void` — override the meter provider for tests.
- `resetVaultInstruments(): void` — drop the cached instrument set.
- `getVaultTracer(): Tracer` — lazy accessor for the cached tracer.
- `setVaultTracerProvider(provider: TracerProvider | undefined): void` — override the tracer provider for tests.
- `resetVaultTracer(): void` — drop the cached tracer.
## Implementation Notes
- Histograms are recorded in milliseconds against the OTel `unit: "ms"` convention; consumers can configure histogram buckets globally via the SDK without per-instrument code.
- Counters expose a documented `status` allowlist for each surface (lifecycle: `opened | unlocked | locked | denied`; items: `success | not_found | conflict | rejected`; attachments: `success | not_found | rejected`; shares: `success | not_found | revoked | rejected`; sync: `success | failed | rejected`). Call sites pass a string from this list — adding a new value requires an OpenSpec change.
- Resetting a provider mid-process drops the cached singleton so subsequent `getVaultInstruments()` calls re-acquire from the new provider — used in test isolation only.
- The global OTel API returns no-op instruments when no provider is registered; production code can call `getVaultInstruments()` unconditionally without performance impact when telemetry is disabled.