# crypto-vault — OpenTelemetry instruments _(no submodules)_ ## Purpose `instruments.ts` holds the full OTel instrument set emitted by `@suaveplan/crypto-vault` production paths. The module exposes a lazy singleton that defers `metrics.getMeter(...)` until first use, so loading the package does nothing observable when no exporter is wired up. Every instrument is safe-by-construction — no key bytes, salts, plaintext, or user-identifiable data appears in attributes. ## Features - Lazy `getCryptoVaultInstruments()` accessor — first call materialises the instrument set against the global meter; subsequent calls hit the cached set. - `setCryptoVaultMeterProvider(provider)` lets tests register a deterministic in-memory `MeterProvider` and then assert against captured observations. - `resetCryptoVaultInstruments()` clears the cache so tests can re-run with a fresh provider without leaking state. - Counters and histograms covering Argon2id derivations, HKDF derivations, zeroization, SecureBuffer allocations / zeroizations, and the SRP-6a handshake. ## Usage: Basic Example ```ts import { getCryptoVaultInstruments } from "@suaveplan/crypto-vault/otel"; const i = getCryptoVaultInstruments(); i.argon2idDurationMs.record(143.2); i.secureBufferAllocateTotal.add(1, { length: "32" }); ``` ## Usage: Advanced Example ```ts import { getCryptoVaultInstruments, resetCryptoVaultInstruments, setCryptoVaultMeterProvider, } from "@suaveplan/crypto-vault/otel"; class CountingMeter { public readonly events: Array<[string, number]> = []; public createHistogram = (name: string) => ({ record: (v: number) => this.events.push([`hist:${name}`, v]), }); public createCounter = (name: string) => ({ add: (v: number) => this.events.push([`ctr:${name}`, v]), }); } const meter = new CountingMeter(); setCryptoVaultMeterProvider({ getMeter: () => meter as unknown as never }); getCryptoVaultInstruments().secureBufferZeroizeTotal.add(1); console.log(meter.events); // [["ctr:crypto_vault.secure_buffer.zeroize.total", 1]] setCryptoVaultMeterProvider(undefined); resetCryptoVaultInstruments(); ``` ## API Reference ### `getCryptoVaultInstruments(): CryptoVaultInstruments` Returns the cached instrument set, building it on first call against the global OTel meter. ### `setCryptoVaultMeterProvider(provider?)` Replace the meter provider used by subsequent `getCryptoVaultInstruments()` calls. Pass `undefined` to revert to the global default. ### `resetCryptoVaultInstruments(): void` Clear the cache so the next `getCryptoVaultInstruments()` re-acquires the meter. Tests use this to defeat singleton leakage between suites. ### `CryptoVaultInstruments` Bag of `Counter` and `Histogram` instances. Field names map to the metric names listed under "Features". ## Implementation Notes - The cache is intentionally module-level — production code should not need per-instance instrument sets. Tests that want isolation register a provider, run their assertions, then reset. - Metric names follow the OTel semantic-conventions style: `.._`. - The package never adds key material, vault IDs, item IDs, salts, or email addresses to instrument attributes. The only attributes used are fixed-cardinality status / outcome strings.