import { Buffer } from "node:buffer"; import { NODEJS_INSPECT_CUSTOM, SECRET_VALUE_BRAND, SecretValue, SecretValueOptions } from "@graphorin/core/contracts"; //#region src/secrets/secret-value.d.ts /** * Hook signature subscribed by the audit log. The audit log is wired up * by a sibling sub-package; this module merely calls every registered * listener on `.reveal()` and `.use(...)` so the audit log can attribute * each unwrap event. * * @stable */ type SecretValueAuditEvent = { readonly action: 'reveal' | 'use' | 'use-buffer' | 'dispose' | 'construct'; readonly source?: { readonly resolver?: string; readonly ref?: string; }; /** Best-effort caller scope (set by `withSecret(...)` if active). */ readonly scopeId?: string; /** Best-effort caller name (set by `withSecret(...)` if active). */ readonly caller?: string; /** Length of the underlying buffer in bytes. Safe to log. */ readonly length: number; /** Epoch milliseconds at the moment of the event. */ readonly ts: number; }; /** * Callback shape accepted by {@link onSecretValueAudit}. * * @stable */ type SecretValueAuditListener = (event: SecretValueAuditEvent) => void; /** * Subscribe to `SecretValue` lifecycle events (construct / reveal / use / * dispose). The audit-log sub-package uses this to record every unwrap * with the active actor; tests use it to assert that scoped access * patterns trigger exactly one event per call. * * Returns an unsubscribe function. * * @stable */ declare function onSecretValueAudit(listener: SecretValueAuditListener): () => void; /** * Resets the audit listener set. Tests use this to isolate fixtures; * production code never calls it. * * @experimental */ declare function _resetSecretValueAuditListenersForTesting(): void; /** * Runtime-safe wrapper around an opaque secret string or byte string. * * `SecretValue` is the **single canonical implementation** of the * `SecretValue` contract declared in `@graphorin/core`. Every secret * crossing module boundaries inside the framework is wrapped in a * `SecretValue` so that: * * - `console.log(value)`, `JSON.stringify({ apiKey: value })`, * `` `Bearer ${value}` ``, `String(value)`, `util.inspect(value)`, * and `new Error(String(value)).message` all emit a redacted * placeholder rather than the underlying value. * - The wrapper exposes the raw bytes only through `use(fn)` / * `useBuffer(fn)` (scoped reads) or the audited one-shot `reveal()` * escape hatch. * - `dispose()` makes a best-effort attempt to zero the backing * `Buffer`. (V8 strings derived through `use(fn)` / `reveal()` are * immutable and cannot be zeroed; this is documented honestly.) * * The class fixes the `[SECRET_VALUE_BRAND]` symbol so the cross-realm * type guard `SecretValue.isSecretValue(...)` works for instances * constructed in Worker threads or `vm` contexts. * * @stable */ declare class SecretValue$1 implements SecretValue { #private; /** Free-form provenance string carried for audit telemetry. */ readonly source?: { readonly resolver?: string; readonly ref?: string; }; /** Epoch milliseconds at construction time. Safe to log. */ readonly fetchedAt: number; /** Optional TTL in milliseconds. Carriers for resolver caching. */ readonly ttlMs?: number; readonly [SECRET_VALUE_BRAND]: true; private constructor(); /** * Wrap a UTF-8 string. Use this at the I/O boundary (env reads, * keyring reads, file reads, OAuth callback response) - not from * deep inside business logic where the raw value would already have * leaked to a V8 string. * * @stable */ static fromString(raw: string, opts?: SecretValueOptions & { ttlMs?: number; }): SecretValue$1; /** * Wrap a `Buffer`. The buffer is **defensively copied**; callers may * safely zero or reuse their input. * * @stable */ static fromBuffer(buf: Buffer, opts?: SecretValueOptions & { ttlMs?: number; }): SecretValue$1; /** * Cross-realm safe `instanceof` replacement. Returns `true` for any * object carrying `Symbol.for('graphorin.SecretValue')` set to `true` * - including instances constructed in Worker threads / vm contexts. * * @stable */ static isSecretValue(value: unknown): value is SecretValue$1; /** * Constant-time byte equality. Returns `false` if either input has * been disposed or the lengths differ; otherwise delegates to * `crypto.timingSafeEqual` to avoid leaking length-independent * timing information. * * @stable */ static timingSafeEquals(a: SecretValue$1, b: SecretValue$1): boolean; /** Length of the wrapped value in bytes. Safe to log. */ get length(): number; /** Whether `dispose()` has been called. */ get disposed(): boolean; /** * Run `fn` with the unwrapped string and return its (possibly * `Promise`-wrapped) result. Preferred over `.reveal()` because it * scopes the V8 string literal to a single call. * * @stable */ use(fn: (raw: string) => T | Promise): Promise; /** * Run `fn` with the unwrapped value as a `Buffer`. Use this for * binary secrets (encryption keys, HMAC keys) where round-tripping * through a V8 string would defeat the wrapper's hygiene. * * @stable */ useBuffer(fn: (buf: Buffer) => T | Promise): Promise; /** * One-shot escape hatch - returns the unwrapped string. Audited. * Prefer `.use(fn)` whenever possible. * * @stable */ reveal(): string; /** * @deprecated Use `.reveal()` for the explicit one-shot read or * `.use(fn)` for the preferred scoped read. Retained for the * `0.x` compatibility window only - slated for removal in the * next major release. The companion lint rule * `@graphorin/no-secret-unwrap` flags every use of this method. * * @stable */ unwrap(): string; /** * Best-effort zeroization of the underlying buffer. Idempotent. Does * not affect derived V8 strings already created via `.use(fn)` / * `.reveal()` - that limitation is fundamental and documented. * * @stable */ dispose(): void; /** * `String(value)` / `'' + value` / `Buffer.from(value)` go through * `Symbol.toPrimitive` first per ECMA-262 § 7.1.1 and end up here. * * @stable */ toString(): string; /** * `Symbol.toPrimitive` takes precedence over `toString` / * `valueOf` for both `String` and `Number` hints, so this is the * primary leakage barrier for template literals. * * @stable */ [Symbol.toPrimitive](hint: string): string | number; /** * `JSON.stringify({ apiKey: secret })` invokes `toJSON()` per * ECMA-262 § 25.5.2 - returning the placeholder ensures structured * logging never serializes the raw value. * * @stable */ toJSON(): string; /** * Custom inspector hook used by `console.log`, `util.inspect`, and * `util.format('%O', value)`. Returns a verbose, distinct marker so * a `SecretValue` is recognisable in REPL / structured output. * * @stable */ [NODEJS_INSPECT_CUSTOM](): string; } //#endregion export { SecretValue$1 as SecretValue, SecretValueAuditEvent, SecretValueAuditListener, _resetSecretValueAuditListenersForTesting, onSecretValueAudit }; //# sourceMappingURL=secret-value.d.ts.map