@absolutejs/secrets 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -71,6 +71,7 @@ export type AuditEvent = {
71
71
  at: number;
72
72
  };
73
73
  export type AuditHook = (event: AuditEvent) => void | Promise<void>;
74
+ export type RedactionEncoding = 'plain' | 'base64';
74
75
  export type SecretBrokerOptions = {
75
76
  /** The adapter the broker delegates fetch / rotate / put to. */
76
77
  adapter: SecretAdapter;
@@ -82,6 +83,13 @@ export type SecretBrokerOptions = {
82
83
  * `Infinity` to disable TTL — only `rotate` / `invalidate` evict.
83
84
  */
84
85
  cacheTtlMs?: number;
86
+ /**
87
+ * Per-name TTL overrides. The override wins over `cacheTtlMs`. Use
88
+ * a short TTL for high-blast-radius secrets (admin tokens, signing
89
+ * keys) so a compromised value's lifetime is bounded by the override,
90
+ * not the global default.
91
+ */
92
+ cacheTtlOverrides?: Record<string, number>;
85
93
  /**
86
94
  * Minimum length a cached value must have before `redact` will rewrite
87
95
  * occurrences of it in arbitrary text. Default 8 — short values risk
@@ -89,9 +97,23 @@ export type SecretBrokerOptions = {
89
97
  * appearing as a substring of unrelated text).
90
98
  */
91
99
  redactionMinLength?: number;
100
+ /**
101
+ * Encodings to redact alongside the plaintext value. Default `['plain']`.
102
+ * Add `'base64'` to also catch base64-encoded forms — useful when
103
+ * secrets end up inside JWTs, cookies, or any payload that base64-wraps
104
+ * a credential.
105
+ */
106
+ redactionEncodings?: RedactionEncoding[];
92
107
  /** Override `Date.now` for tests. */
93
108
  clock?: () => number;
94
109
  };
110
+ /** Listener registered via {@link SecretBroker.onRotate}. */
111
+ export type RotationListener = (event: {
112
+ name: string;
113
+ value: string;
114
+ fingerprint: string;
115
+ at: number;
116
+ }) => void | Promise<void>;
95
117
  export type SecretBroker = {
96
118
  /**
97
119
  * Resolve a secret by name. Returns `null` if the adapter reports
@@ -110,19 +132,94 @@ export type SecretBroker = {
110
132
  * `redactionMinLength` are skipped.
111
133
  */
112
134
  redact: (text: string) => string;
135
+ /**
136
+ * Streaming variant of {@link redact}. Returns a `TransformStream`
137
+ * that catches secrets even when they're split across chunks (a chunk
138
+ * boundary in the middle of `sk_live_abc...` would otherwise miss). The
139
+ * stream keeps a lookback buffer the size of the longest cached secret;
140
+ * once the buffer outgrows that, the safe-region prefix is emitted.
141
+ *
142
+ * Use this on `process.stdout` / `process.stderr` / a tenant log forwarder
143
+ * so plaintext secrets never reach the sink.
144
+ */
145
+ redactStream: () => TransformStream<string, string>;
113
146
  /**
114
147
  * Rotate a secret. Calls `adapter.rotate(name)`, invalidates the cache,
115
148
  * returns the new `{ value, fingerprint }`. Throws if the adapter does
116
- * not support rotation.
149
+ * not support rotation. Fires every `onRotate` listener registered for
150
+ * this name.
117
151
  */
118
152
  rotate: (name: string) => Promise<SecretValue>;
153
+ /**
154
+ * Subscribe to rotation events for a specific name. Listener fires
155
+ * AFTER the new value is in the cache. Returns an unsubscribe handle.
156
+ * Use this for long-lived connections (DB clients, AI provider SDKs)
157
+ * that need to swap credentials in-place when rotation lands.
158
+ */
159
+ onRotate: (name: string, listener: RotationListener) => () => void;
119
160
  /**
120
161
  * Invalidate one cache entry, or the whole cache when `name` is omitted.
121
162
  */
122
163
  invalidate: (name?: string) => void;
123
164
  /** Tear down the broker — clears the cache; further resolves still hit the adapter. */
124
165
  dispose: () => void;
166
+ /**
167
+ * Operator-shaped cumulative counters since `createSecretBroker()`.
168
+ * Scrape on a 30s interval for tier monitoring + rotation cadence.
169
+ * Added in 0.2.0.
170
+ */
171
+ metrics: () => SecretBrokerMetrics;
172
+ /**
173
+ * Refuse new `resolve()` / `rotate()` calls (they reject with
174
+ * `BrokerDrainedError`); in-flight adapter calls keep running. Use
175
+ * during graceful shutdown so a tenant whose process is about to
176
+ * stop doesn't issue a fresh fetch against the secret store mid-
177
+ * teardown. Symmetric with `runtime.drain()` / `queue.drain()`.
178
+ * Added in 0.2.0.
179
+ */
180
+ drain: () => void;
125
181
  };
182
+ /**
183
+ * Returned by {@link SecretBroker.metrics}. All counters cumulative
184
+ * since `createSecretBroker()`; cleared by neither `dispose()` nor
185
+ * `drain()` (so the operator can see what happened pre-shutdown).
186
+ * Added in 0.2.0.
187
+ */
188
+ export type SecretBrokerMetrics = {
189
+ /** `resolve()` calls — including cached hits, misses, and errors. */
190
+ resolves: number;
191
+ /** `resolve()` calls served from cache (no adapter hit). */
192
+ resolveHits: number;
193
+ /** `resolve()` calls that hit the adapter (cache miss OR expired). */
194
+ resolveMisses: number;
195
+ /** `resolve()` calls where the adapter threw. */
196
+ resolveErrors: number;
197
+ /** Successful `rotate()` calls. */
198
+ rotates: number;
199
+ /** `rotate()` calls where the adapter threw. */
200
+ rotateErrors: number;
201
+ /** `invalidate()` calls (per call, regardless of cache size). */
202
+ invalidations: number;
203
+ /** `redact()` calls (whether anything was rewritten or not). */
204
+ redactCalls: number;
205
+ /**
206
+ * Distinct (secret, encoding) pairs that triggered a replacement —
207
+ * NOT total occurrences. A `redact()` call that rewrites the same
208
+ * key three times in one string bumps this by 1. Useful for
209
+ * "is anything ever actually getting redacted, or are we configured
210
+ * for nothing."
211
+ */
212
+ redactionsApplied: number;
213
+ /** Subset of `redactionsApplied` for base64 encoding. */
214
+ redactionsBase64: number;
215
+ };
216
+ /**
217
+ * Thrown by `resolve()` / `rotate()` after `drain()` has been called.
218
+ * Added in 0.2.0.
219
+ */
220
+ export declare class BrokerDrainedError extends Error {
221
+ constructor();
222
+ }
126
223
  export type InMemoryAdapterOptions = {
127
224
  initial?: Record<string, string>;
128
225
  /** Override the rotation strategy. Default = random 32-char base36 string. */
package/dist/index.js CHANGED
@@ -1,5 +1,11 @@
1
1
  // @bun
2
2
  // src/index.ts
3
+ class BrokerDrainedError extends Error {
4
+ constructor() {
5
+ super("[secrets] Broker is draining \u2014 resolve/rotate refused. " + "Use the broker before the shutdown handler fires.");
6
+ this.name = "BrokerDrainedError";
7
+ }
8
+ }
3
9
  var HEX = "0123456789abcdef";
4
10
  var sha256Hex = (input) => {
5
11
  return sha256(input);
@@ -222,11 +228,45 @@ var compositeAdapter = (adapters) => {
222
228
  };
223
229
  var createSecretBroker = (options) => {
224
230
  const clock = options.clock ?? Date.now;
225
- const ttl = options.cacheTtlMs ?? 60000;
231
+ const defaultTtl = options.cacheTtlMs ?? 60000;
232
+ const ttlOverrides = options.cacheTtlOverrides ?? {};
226
233
  const minLen = options.redactionMinLength ?? 8;
234
+ const encodings = options.redactionEncodings ?? ["plain"];
227
235
  const audit = options.audit;
228
236
  const cache = new Map;
237
+ const rotationListeners = new Map;
229
238
  let disposed = false;
239
+ let draining = false;
240
+ const counters = {
241
+ invalidations: 0,
242
+ redactCalls: 0,
243
+ redactionsApplied: 0,
244
+ redactionsBase64: 0,
245
+ resolveErrors: 0,
246
+ resolveHits: 0,
247
+ resolveMisses: 0,
248
+ resolves: 0,
249
+ rotateErrors: 0,
250
+ rotates: 0
251
+ };
252
+ const ttlFor = (name) => ttlOverrides[name] ?? defaultTtl;
253
+ const fireRotation = (name, value, fingerprint, at) => {
254
+ const set = rotationListeners.get(name);
255
+ if (!set || set.size === 0)
256
+ return;
257
+ for (const listener of set) {
258
+ try {
259
+ const ret = listener({ at, fingerprint, name, value });
260
+ if (ret && typeof ret.then === "function") {
261
+ ret.catch((error) => {
262
+ console.error("[secrets] rotation listener rejected:", error);
263
+ });
264
+ }
265
+ } catch (error) {
266
+ console.error("[secrets] rotation listener threw:", error);
267
+ }
268
+ }
269
+ };
230
270
  const fireAudit = (event) => {
231
271
  if (!audit)
232
272
  return;
@@ -253,12 +293,17 @@ var createSecretBroker = (options) => {
253
293
  const resolve = async (name) => {
254
294
  if (disposed)
255
295
  return null;
296
+ if (draining)
297
+ throw new BrokerDrainedError;
298
+ counters.resolves += 1;
256
299
  const now = clock();
257
300
  const cached = cache.get(name);
258
- if (cached && now - cached.storedAt < ttl) {
301
+ if (cached && now - cached.storedAt < ttlFor(name)) {
302
+ counters.resolveHits += 1;
259
303
  fireAudit({ at: now, event: "resolve.hit", fingerprint: cached.fingerprint, name });
260
304
  return { fingerprint: cached.fingerprint, value: cached.value };
261
305
  }
306
+ counters.resolveMisses += 1;
262
307
  try {
263
308
  const value = await options.adapter.fetch(name);
264
309
  if (value === null) {
@@ -270,6 +315,7 @@ var createSecretBroker = (options) => {
270
315
  fireAudit({ at: now, event: "resolve.miss", fingerprint: entry.fingerprint, name });
271
316
  return { fingerprint: entry.fingerprint, value: entry.value };
272
317
  } catch (error) {
318
+ counters.resolveErrors += 1;
273
319
  fireAudit({
274
320
  at: now,
275
321
  error: error instanceof Error ? error.message : String(error),
@@ -282,14 +328,23 @@ var createSecretBroker = (options) => {
282
328
  const rotate = async (name) => {
283
329
  if (disposed)
284
330
  throw new Error("Broker is disposed");
331
+ if (draining)
332
+ throw new BrokerDrainedError;
285
333
  if (!options.adapter.rotate) {
286
334
  throw new Error("Adapter does not support rotate()");
287
335
  }
288
- const next = await options.adapter.rotate(name);
289
- const now = clock();
290
- const entry = cacheEntry(name, next, now);
291
- fireAudit({ at: now, event: "rotate", fingerprint: entry.fingerprint, name });
292
- return { fingerprint: entry.fingerprint, value: entry.value };
336
+ try {
337
+ const next = await options.adapter.rotate(name);
338
+ const now = clock();
339
+ const entry = cacheEntry(name, next, now);
340
+ counters.rotates += 1;
341
+ fireAudit({ at: now, event: "rotate", fingerprint: entry.fingerprint, name });
342
+ fireRotation(name, entry.value, entry.fingerprint, now);
343
+ return { fingerprint: entry.fingerprint, value: entry.value };
344
+ } catch (error) {
345
+ counters.rotateErrors += 1;
346
+ throw error;
347
+ }
293
348
  };
294
349
  const invalidate = (name) => {
295
350
  if (name === undefined) {
@@ -297,28 +352,101 @@ var createSecretBroker = (options) => {
297
352
  } else {
298
353
  cache.delete(name);
299
354
  }
355
+ counters.invalidations += 1;
300
356
  fireAudit({ at: clock(), event: "invalidate", name: name ?? null });
301
357
  };
358
+ const redactionPairs = () => {
359
+ const pairs = [];
360
+ for (const [name, entry] of cache) {
361
+ if (entry.value.length < minLen)
362
+ continue;
363
+ for (const enc of encodings) {
364
+ if (enc === "plain") {
365
+ pairs.push([entry.value, `[REDACTED:${name}]`]);
366
+ } else if (enc === "base64") {
367
+ try {
368
+ const encoded = btoa(entry.value);
369
+ if (encoded.length >= minLen) {
370
+ pairs.push([encoded, `[REDACTED:${name}:b64]`]);
371
+ }
372
+ } catch {}
373
+ }
374
+ }
375
+ }
376
+ pairs.sort((a, b) => b[0].length - a[0].length);
377
+ return pairs;
378
+ };
302
379
  const redact = (text) => {
380
+ counters.redactCalls += 1;
303
381
  if (text.length === 0 || cache.size === 0)
304
382
  return text;
305
- const ordered = Array.from(cache.entries()).filter(([, entry]) => entry.value.length >= minLen).sort(([, a], [, b]) => b.value.length - a.value.length);
306
383
  let out = text;
307
- for (const [name, entry] of ordered) {
308
- if (!out.includes(entry.value))
384
+ for (const [needle, replacement] of redactionPairs()) {
385
+ if (!out.includes(needle))
309
386
  continue;
310
- out = out.split(entry.value).join(`[REDACTED:${name}]`);
387
+ out = out.split(needle).join(replacement);
388
+ counters.redactionsApplied += 1;
389
+ if (replacement.endsWith(":b64]"))
390
+ counters.redactionsBase64 += 1;
311
391
  }
312
392
  return out;
313
393
  };
394
+ const redactStream = () => {
395
+ let buffer = "";
396
+ const maxLen = () => redactionPairs().reduce((max, [needle]) => Math.max(max, needle.length), 0);
397
+ return new TransformStream({
398
+ transform: (chunk, controller) => {
399
+ buffer += chunk;
400
+ const lookback = maxLen();
401
+ const reduced = redact(buffer);
402
+ if (reduced.length <= lookback) {
403
+ buffer = reduced;
404
+ return;
405
+ }
406
+ const safe = reduced.slice(0, reduced.length - lookback);
407
+ buffer = reduced.slice(reduced.length - lookback);
408
+ if (safe.length > 0)
409
+ controller.enqueue(safe);
410
+ },
411
+ flush: (controller) => {
412
+ if (buffer.length === 0)
413
+ return;
414
+ controller.enqueue(redact(buffer));
415
+ buffer = "";
416
+ }
417
+ });
418
+ };
419
+ const onRotate = (name, listener) => {
420
+ let set = rotationListeners.get(name);
421
+ if (!set) {
422
+ set = new Set;
423
+ rotationListeners.set(name, set);
424
+ }
425
+ set.add(listener);
426
+ return () => {
427
+ const current = rotationListeners.get(name);
428
+ if (!current)
429
+ return;
430
+ current.delete(listener);
431
+ if (current.size === 0)
432
+ rotationListeners.delete(name);
433
+ };
434
+ };
314
435
  return {
315
436
  dispose: () => {
316
437
  disposed = true;
317
438
  cache.clear();
439
+ rotationListeners.clear();
440
+ },
441
+ drain: () => {
442
+ draining = true;
318
443
  },
319
444
  fingerprint: fingerprintOf,
320
445
  invalidate,
446
+ metrics: () => ({ ...counters }),
447
+ onRotate,
321
448
  redact,
449
+ redactStream,
322
450
  resolve,
323
451
  rotate
324
452
  };
@@ -327,8 +455,9 @@ export {
327
455
  inMemoryAdapter,
328
456
  envAdapter,
329
457
  createSecretBroker,
330
- compositeAdapter
458
+ compositeAdapter,
459
+ BrokerDrainedError
331
460
  };
332
461
 
333
- //# debugId=EE866E47E57910C764756E2164756E21
462
+ //# debugId=68E7DA7EF9820B8264756E2164756E21
334
463
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * @absolutejs/secrets — host-side secret broker for multi-tenant Bun\n * runtimes.\n *\n * Three responsibilities, kept narrow on purpose:\n *\n * 1. **Resolve.** A pluggable adapter fetches a secret by name. The broker\n * caches the answer, hands the caller back a `{ value, fingerprint }`\n * pair (fingerprint is a sha256 prefix safe to put in logs), and fires\n * an audit event for every lookup.\n * 2. **Redact.** Walks every known cached secret out of an arbitrary string\n * before it leaves the host (e.g. an error message that contains the\n * leaked API key the host call just made). The replacement is\n * `[REDACTED:name]`; matches shorter than `redactionMinLength` are\n * skipped to avoid blanking coincidental short tokens.\n * 3. **Rotate.** Delegates to `adapter.rotate?(name)` if the adapter\n * supports it, invalidates the cache entry. Caller is expected to\n * re-distribute to dependent surfaces.\n *\n * v0.0.1 ships three adapters: `inMemoryAdapter`, `envAdapter`,\n * `compositeAdapter`. AWS Secrets Manager / Vault / Doppler / Infisical\n * adapters ship later as siblings.\n *\n * The broker is bun/elysia-agnostic — same posture as router + meter.\n */\n\nexport type SecretValue = {\n\t/** The plaintext secret. Treat as poison: never log, never serialize. */\n\tvalue: string;\n\t/**\n\t * Short sha256-derived id (first 8 hex chars). Stable across calls for\n\t * the same value; safe to print in logs and traces. Useful for \"which\n\t * version of the key did this request use?\" diagnostics without leaking.\n\t */\n\tfingerprint: string;\n};\n\nexport type SecretAdapter = {\n\t/** Return the plaintext value for a name, or `null` if not stored here. */\n\tfetch: (name: string) => Promise<string | null>;\n\t/** Write a value. Optional — adapters may be read-only. */\n\tput?: (name: string, value: string) => Promise<void>;\n\t/** Delete a value. Optional. */\n\tremove?: (name: string) => Promise<void>;\n\t/** Rotate a value; return the NEW plaintext. Optional. */\n\trotate?: (name: string) => Promise<string>;\n\t/** Enumerate names. Optional; default omitted to avoid leaking the index. */\n\tlist?: () => Promise<string[]>;\n};\n\nexport type AuditEvent =\n\t| { event: 'resolve.hit'; name: string; fingerprint: string; at: number }\n\t| { event: 'resolve.miss'; name: string; fingerprint?: string; at: number }\n\t| { event: 'resolve.error'; name: string; error: string; at: number }\n\t| { event: 'rotate'; name: string; fingerprint: string; at: number }\n\t| { event: 'invalidate'; name: string | null; at: number };\n\nexport type AuditHook = (event: AuditEvent) => void | Promise<void>;\n\nexport type SecretBrokerOptions = {\n\t/** The adapter the broker delegates fetch / rotate / put to. */\n\tadapter: SecretAdapter;\n\t/** Audit hook fired on every resolve / rotate / invalidate. */\n\taudit?: AuditHook;\n\t/**\n\t * How long a cached secret stays fresh, in ms. After this, the next\n\t * resolve re-hits the adapter. Default 60_000 (1 minute). Set to\n\t * `Infinity` to disable TTL — only `rotate` / `invalidate` evict.\n\t */\n\tcacheTtlMs?: number;\n\t/**\n\t * Minimum length a cached value must have before `redact` will rewrite\n\t * occurrences of it in arbitrary text. Default 8 — short values risk\n\t * blanking out coincidental matches (e.g. a short password \"abc1\"\n\t * appearing as a substring of unrelated text).\n\t */\n\tredactionMinLength?: number;\n\t/** Override `Date.now` for tests. */\n\tclock?: () => number;\n};\n\nexport type SecretBroker = {\n\t/**\n\t * Resolve a secret by name. Returns `null` if the adapter reports\n\t * no value. Caches the answer for `cacheTtlMs`.\n\t */\n\tresolve: (name: string) => Promise<SecretValue | null>;\n\t/**\n\t * Returns the fingerprint of a value WITHOUT touching the adapter.\n\t * Useful for hashing a value the caller already has — e.g. a webhook\n\t * payload — to compare against an audit log.\n\t */\n\tfingerprint: (value: string) => string;\n\t/**\n\t * Replace every cached secret value found in `text` with\n\t * `[REDACTED:name]`. Returns the rewritten text. Subjects shorter than\n\t * `redactionMinLength` are skipped.\n\t */\n\tredact: (text: string) => string;\n\t/**\n\t * Rotate a secret. Calls `adapter.rotate(name)`, invalidates the cache,\n\t * returns the new `{ value, fingerprint }`. Throws if the adapter does\n\t * not support rotation.\n\t */\n\trotate: (name: string) => Promise<SecretValue>;\n\t/**\n\t * Invalidate one cache entry, or the whole cache when `name` is omitted.\n\t */\n\tinvalidate: (name?: string) => void;\n\t/** Tear down the broker — clears the cache; further resolves still hit the adapter. */\n\tdispose: () => void;\n};\n\n// -----------------------------------------------------------------------------\n// Fingerprint\n// -----------------------------------------------------------------------------\n\nconst HEX = '0123456789abcdef';\n\nconst sha256Hex = (input: string): string => {\n\t// 2026-era Bun: `crypto.subtle.digest` is the portable path. Synchronous\n\t// path via `Bun.CryptoHasher` is faster but requires Bun globals; we use\n\t// subtle to keep the broker runtime-agnostic at the cost of being async.\n\t// For the `fingerprint(value)` *public* method we want a synchronous\n\t// answer — so we use a tiny in-house sha256. It's slower than the native\n\t// digest but only runs on the secret value (small, ~ < 1KB), once per\n\t// distinct value over the broker's lifetime (memoized in the cache entry).\n\treturn sha256(input);\n};\n\n// Pure JS sha256, NIST FIPS 180-4. Small + dependency-free. Returns lowercase hex.\nconst ROUND_CONSTANTS = new Uint32Array([\n\t0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,\n\t0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\n\t0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,\n\t0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n\t0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,\n\t0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\n\t0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,\n\t0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n\t0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,\n\t0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\n\t0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n]);\n\nconst sha256 = (input: string): string => {\n\tconst bytes = new TextEncoder().encode(input);\n\tconst bitLength = bytes.length * 8;\n\tconst padLength = ((bytes.length + 9 + 63) & ~63) - bytes.length;\n\tconst padded = new Uint8Array(bytes.length + padLength);\n\tpadded.set(bytes);\n\tpadded[bytes.length] = 0x80;\n\tconst view = new DataView(padded.buffer);\n\tview.setUint32(padded.length - 4, bitLength >>> 0);\n\tview.setUint32(padded.length - 8, Math.floor(bitLength / 0x1_0000_0000));\n\n\tlet h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, h3 = 0xa54ff53a;\n\tlet h4 = 0x510e527f, h5 = 0x9b05688c, h6 = 0x1f83d9ab, h7 = 0x5be0cd19;\n\tconst w = new Uint32Array(64);\n\tfor (let i = 0; i < padded.length; i += 64) {\n\t\tfor (let t = 0; t < 16; t++) {\n\t\t\tw[t] = view.getUint32(i + t * 4);\n\t\t}\n\t\tfor (let t = 16; t < 64; t++) {\n\t\t\tconst w15 = w[t - 15]!;\n\t\t\tconst w2 = w[t - 2]!;\n\t\t\tconst s0 = ((w15 >>> 7) | (w15 << 25)) ^ ((w15 >>> 18) | (w15 << 14)) ^ (w15 >>> 3);\n\t\t\tconst s1 = ((w2 >>> 17) | (w2 << 15)) ^ ((w2 >>> 19) | (w2 << 13)) ^ (w2 >>> 10);\n\t\t\tw[t] = (w[t - 16]! + s0 + w[t - 7]! + s1) >>> 0;\n\t\t}\n\t\tlet a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7;\n\t\tfor (let t = 0; t < 64; t++) {\n\t\t\tconst S1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));\n\t\t\tconst ch = (e & f) ^ (~e & g);\n\t\t\tconst T1 = (h + S1 + ch + ROUND_CONSTANTS[t]! + w[t]!) >>> 0;\n\t\t\tconst S0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));\n\t\t\tconst maj = (a & b) ^ (a & c) ^ (b & c);\n\t\t\tconst T2 = (S0 + maj) >>> 0;\n\t\t\th = g;\n\t\t\tg = f;\n\t\t\tf = e;\n\t\t\te = (d + T1) >>> 0;\n\t\t\td = c;\n\t\t\tc = b;\n\t\t\tb = a;\n\t\t\ta = (T1 + T2) >>> 0;\n\t\t}\n\t\th0 = (h0 + a) >>> 0;\n\t\th1 = (h1 + b) >>> 0;\n\t\th2 = (h2 + c) >>> 0;\n\t\th3 = (h3 + d) >>> 0;\n\t\th4 = (h4 + e) >>> 0;\n\t\th5 = (h5 + f) >>> 0;\n\t\th6 = (h6 + g) >>> 0;\n\t\th7 = (h7 + h) >>> 0;\n\t}\n\tconst toHex = (n: number): string => {\n\t\tlet result = '';\n\t\tfor (let i = 7; i >= 0; i--) {\n\t\t\tresult += HEX[(n >>> (i * 4)) & 0xf];\n\t\t}\n\t\treturn result;\n\t};\n\treturn toHex(h0) + toHex(h1) + toHex(h2) + toHex(h3) + toHex(h4) + toHex(h5) + toHex(h6) + toHex(h7);\n};\n\nconst fingerprintOf = (value: string): string => sha256Hex(value).slice(0, 8);\n\n// -----------------------------------------------------------------------------\n// Bundled adapters\n// -----------------------------------------------------------------------------\n\nexport type InMemoryAdapterOptions = {\n\tinitial?: Record<string, string>;\n\t/** Override the rotation strategy. Default = random 32-char base36 string. */\n\trotate?: (name: string, previous: string | null) => string;\n};\n\nconst randomBase36 = (length: number): string => {\n\tlet out = '';\n\twhile (out.length < length) {\n\t\tout += Math.random().toString(36).slice(2);\n\t}\n\treturn out.slice(0, length);\n};\n\nexport const inMemoryAdapter = (\n\toptions: InMemoryAdapterOptions = {},\n): SecretAdapter => {\n\tconst store = new Map<string, string>();\n\tfor (const [k, v] of Object.entries(options.initial ?? {})) store.set(k, v);\n\tconst rotate = options.rotate ?? (() => randomBase36(32));\n\treturn {\n\t\tfetch: async (name) => store.get(name) ?? null,\n\t\tlist: async () => Array.from(store.keys()),\n\t\tput: async (name, value) => { store.set(name, value); },\n\t\tremove: async (name) => { store.delete(name); },\n\t\trotate: async (name) => {\n\t\t\tconst next = rotate(name, store.get(name) ?? null);\n\t\t\tstore.set(name, next);\n\t\t\treturn next;\n\t\t},\n\t};\n};\n\nexport type EnvAdapterOptions = {\n\t/**\n\t * If set, lookups are prefixed before reading from env. e.g.\n\t * `prefix: 'ABS_SECRET_'` and `resolve('STRIPE_KEY')` reads `ABS_SECRET_STRIPE_KEY`.\n\t * Default `''` (no prefix).\n\t */\n\tprefix?: string;\n\t/** The env object to read from. Default `process.env`. */\n\tenv?: Record<string, string | undefined>;\n};\n\nexport const envAdapter = (options: EnvAdapterOptions = {}): SecretAdapter => {\n\tconst prefix = options.prefix ?? '';\n\tconst env = options.env ?? (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env ?? {};\n\treturn {\n\t\tfetch: async (name) => {\n\t\t\tconst key = `${prefix}${name}`;\n\t\t\tconst value = env[key];\n\t\t\treturn value === undefined ? null : value;\n\t\t},\n\t\tlist: async () => {\n\t\t\tif (!prefix) return Object.keys(env);\n\t\t\tconst matches: string[] = [];\n\t\t\tfor (const key of Object.keys(env)) {\n\t\t\t\tif (key.startsWith(prefix)) matches.push(key.slice(prefix.length));\n\t\t\t}\n\t\t\treturn matches;\n\t\t},\n\t};\n};\n\n/**\n * Compose adapters: `fetch` falls through to the first non-null result;\n * `put` / `rotate` / `remove` go to the first adapter that implements them.\n */\nexport const compositeAdapter = (adapters: SecretAdapter[]): SecretAdapter => {\n\tconst firstWith = <K extends keyof SecretAdapter>(method: K) =>\n\t\tadapters.find((adapter) => adapter[method] !== undefined);\n\treturn {\n\t\tfetch: async (name) => {\n\t\t\tfor (const adapter of adapters) {\n\t\t\t\tconst value = await adapter.fetch(name);\n\t\t\t\tif (value !== null) return value;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tlist: async () => {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const adapter of adapters) {\n\t\t\t\tif (!adapter.list) continue;\n\t\t\t\tfor (const name of await adapter.list()) seen.add(name);\n\t\t\t}\n\t\t\treturn Array.from(seen);\n\t\t},\n\t\tput: async (name, value) => {\n\t\t\tconst target = firstWith('put');\n\t\t\tif (!target?.put) throw new Error('No adapter in the composite supports put()');\n\t\t\tawait target.put(name, value);\n\t\t},\n\t\tremove: async (name) => {\n\t\t\tconst target = firstWith('remove');\n\t\t\tif (!target?.remove) throw new Error('No adapter in the composite supports remove()');\n\t\t\tawait target.remove(name);\n\t\t},\n\t\trotate: async (name) => {\n\t\t\tconst target = firstWith('rotate');\n\t\t\tif (!target?.rotate) throw new Error('No adapter in the composite supports rotate()');\n\t\t\treturn target.rotate(name);\n\t\t},\n\t};\n};\n\n// -----------------------------------------------------------------------------\n// Broker\n// -----------------------------------------------------------------------------\n\ntype CacheEntry = {\n\tvalue: string;\n\tfingerprint: string;\n\tstoredAt: number;\n};\n\nexport const createSecretBroker = (options: SecretBrokerOptions): SecretBroker => {\n\tconst clock = options.clock ?? Date.now;\n\tconst ttl = options.cacheTtlMs ?? 60_000;\n\tconst minLen = options.redactionMinLength ?? 8;\n\tconst audit = options.audit;\n\tconst cache = new Map<string, CacheEntry>();\n\tlet disposed = false;\n\n\tconst fireAudit = (event: AuditEvent) => {\n\t\tif (!audit) return;\n\t\ttry {\n\t\t\tconst result = audit(event);\n\t\t\tif (result && typeof (result as Promise<void>).then === 'function') {\n\t\t\t\t(result as Promise<void>).catch((error) => {\n\t\t\t\t\tconsole.error('[secrets] audit hook rejected:', error);\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[secrets] audit hook threw:', error);\n\t\t}\n\t};\n\n\tconst cacheEntry = (name: string, value: string, now: number): CacheEntry => {\n\t\tconst entry: CacheEntry = {\n\t\t\tfingerprint: fingerprintOf(value),\n\t\t\tstoredAt: now,\n\t\t\tvalue,\n\t\t};\n\t\tcache.set(name, entry);\n\t\treturn entry;\n\t};\n\n\tconst resolve: SecretBroker['resolve'] = async (name) => {\n\t\tif (disposed) return null;\n\t\tconst now = clock();\n\t\tconst cached = cache.get(name);\n\t\tif (cached && now - cached.storedAt < ttl) {\n\t\t\tfireAudit({ at: now, event: 'resolve.hit', fingerprint: cached.fingerprint, name });\n\t\t\treturn { fingerprint: cached.fingerprint, value: cached.value };\n\t\t}\n\t\ttry {\n\t\t\tconst value = await options.adapter.fetch(name);\n\t\t\tif (value === null) {\n\t\t\t\tfireAudit({ at: now, event: 'resolve.miss', name });\n\t\t\t\tcache.delete(name);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst entry = cacheEntry(name, value, now);\n\t\t\tfireAudit({ at: now, event: 'resolve.miss', fingerprint: entry.fingerprint, name });\n\t\t\treturn { fingerprint: entry.fingerprint, value: entry.value };\n\t\t} catch (error) {\n\t\t\tfireAudit({\n\t\t\t\tat: now,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\tevent: 'resolve.error',\n\t\t\t\tname,\n\t\t\t});\n\t\t\tthrow error;\n\t\t}\n\t};\n\n\tconst rotate: SecretBroker['rotate'] = async (name) => {\n\t\tif (disposed) throw new Error('Broker is disposed');\n\t\tif (!options.adapter.rotate) {\n\t\t\tthrow new Error('Adapter does not support rotate()');\n\t\t}\n\t\tconst next = await options.adapter.rotate(name);\n\t\tconst now = clock();\n\t\tconst entry = cacheEntry(name, next, now);\n\t\tfireAudit({ at: now, event: 'rotate', fingerprint: entry.fingerprint, name });\n\t\treturn { fingerprint: entry.fingerprint, value: entry.value };\n\t};\n\n\tconst invalidate: SecretBroker['invalidate'] = (name) => {\n\t\tif (name === undefined) {\n\t\t\tcache.clear();\n\t\t} else {\n\t\t\tcache.delete(name);\n\t\t}\n\t\tfireAudit({ at: clock(), event: 'invalidate', name: name ?? null });\n\t};\n\n\tconst redact: SecretBroker['redact'] = (text) => {\n\t\tif (text.length === 0 || cache.size === 0) return text;\n\t\t// Replace longest values first so a substring of a longer secret\n\t\t// isn't blanked before its full match is found.\n\t\tconst ordered = Array.from(cache.entries())\n\t\t\t.filter(([, entry]) => entry.value.length >= minLen)\n\t\t\t.sort(([, a], [, b]) => b.value.length - a.value.length);\n\t\tlet out = text;\n\t\tfor (const [name, entry] of ordered) {\n\t\t\tif (!out.includes(entry.value)) continue;\n\t\t\tout = out.split(entry.value).join(`[REDACTED:${name}]`);\n\t\t}\n\t\treturn out;\n\t};\n\n\treturn {\n\t\tdispose: () => {\n\t\t\tdisposed = true;\n\t\t\tcache.clear();\n\t\t},\n\t\tfingerprint: fingerprintOf,\n\t\tinvalidate,\n\t\tredact,\n\t\tresolve,\n\t\trotate,\n\t};\n};\n"
5
+ "/**\n * @absolutejs/secrets — host-side secret broker for multi-tenant Bun\n * runtimes.\n *\n * Three responsibilities, kept narrow on purpose:\n *\n * 1. **Resolve.** A pluggable adapter fetches a secret by name. The broker\n * caches the answer, hands the caller back a `{ value, fingerprint }`\n * pair (fingerprint is a sha256 prefix safe to put in logs), and fires\n * an audit event for every lookup.\n * 2. **Redact.** Walks every known cached secret out of an arbitrary string\n * before it leaves the host (e.g. an error message that contains the\n * leaked API key the host call just made). The replacement is\n * `[REDACTED:name]`; matches shorter than `redactionMinLength` are\n * skipped to avoid blanking coincidental short tokens.\n * 3. **Rotate.** Delegates to `adapter.rotate?(name)` if the adapter\n * supports it, invalidates the cache entry. Caller is expected to\n * re-distribute to dependent surfaces.\n *\n * v0.0.1 ships three adapters: `inMemoryAdapter`, `envAdapter`,\n * `compositeAdapter`. AWS Secrets Manager / Vault / Doppler / Infisical\n * adapters ship later as siblings.\n *\n * The broker is bun/elysia-agnostic — same posture as router + meter.\n */\n\nexport type SecretValue = {\n\t/** The plaintext secret. Treat as poison: never log, never serialize. */\n\tvalue: string;\n\t/**\n\t * Short sha256-derived id (first 8 hex chars). Stable across calls for\n\t * the same value; safe to print in logs and traces. Useful for \"which\n\t * version of the key did this request use?\" diagnostics without leaking.\n\t */\n\tfingerprint: string;\n};\n\nexport type SecretAdapter = {\n\t/** Return the plaintext value for a name, or `null` if not stored here. */\n\tfetch: (name: string) => Promise<string | null>;\n\t/** Write a value. Optional — adapters may be read-only. */\n\tput?: (name: string, value: string) => Promise<void>;\n\t/** Delete a value. Optional. */\n\tremove?: (name: string) => Promise<void>;\n\t/** Rotate a value; return the NEW plaintext. Optional. */\n\trotate?: (name: string) => Promise<string>;\n\t/** Enumerate names. Optional; default omitted to avoid leaking the index. */\n\tlist?: () => Promise<string[]>;\n};\n\nexport type AuditEvent =\n\t| { event: 'resolve.hit'; name: string; fingerprint: string; at: number }\n\t| { event: 'resolve.miss'; name: string; fingerprint?: string; at: number }\n\t| { event: 'resolve.error'; name: string; error: string; at: number }\n\t| { event: 'rotate'; name: string; fingerprint: string; at: number }\n\t| { event: 'invalidate'; name: string | null; at: number };\n\nexport type AuditHook = (event: AuditEvent) => void | Promise<void>;\n\nexport type RedactionEncoding = 'plain' | 'base64';\n\nexport type SecretBrokerOptions = {\n\t/** The adapter the broker delegates fetch / rotate / put to. */\n\tadapter: SecretAdapter;\n\t/** Audit hook fired on every resolve / rotate / invalidate. */\n\taudit?: AuditHook;\n\t/**\n\t * How long a cached secret stays fresh, in ms. After this, the next\n\t * resolve re-hits the adapter. Default 60_000 (1 minute). Set to\n\t * `Infinity` to disable TTL — only `rotate` / `invalidate` evict.\n\t */\n\tcacheTtlMs?: number;\n\t/**\n\t * Per-name TTL overrides. The override wins over `cacheTtlMs`. Use\n\t * a short TTL for high-blast-radius secrets (admin tokens, signing\n\t * keys) so a compromised value's lifetime is bounded by the override,\n\t * not the global default.\n\t */\n\tcacheTtlOverrides?: Record<string, number>;\n\t/**\n\t * Minimum length a cached value must have before `redact` will rewrite\n\t * occurrences of it in arbitrary text. Default 8 — short values risk\n\t * blanking out coincidental matches (e.g. a short password \"abc1\"\n\t * appearing as a substring of unrelated text).\n\t */\n\tredactionMinLength?: number;\n\t/**\n\t * Encodings to redact alongside the plaintext value. Default `['plain']`.\n\t * Add `'base64'` to also catch base64-encoded forms — useful when\n\t * secrets end up inside JWTs, cookies, or any payload that base64-wraps\n\t * a credential.\n\t */\n\tredactionEncodings?: RedactionEncoding[];\n\t/** Override `Date.now` for tests. */\n\tclock?: () => number;\n};\n\n/** Listener registered via {@link SecretBroker.onRotate}. */\nexport type RotationListener = (event: {\n\tname: string;\n\tvalue: string;\n\tfingerprint: string;\n\tat: number;\n}) => void | Promise<void>;\n\nexport type SecretBroker = {\n\t/**\n\t * Resolve a secret by name. Returns `null` if the adapter reports\n\t * no value. Caches the answer for `cacheTtlMs`.\n\t */\n\tresolve: (name: string) => Promise<SecretValue | null>;\n\t/**\n\t * Returns the fingerprint of a value WITHOUT touching the adapter.\n\t * Useful for hashing a value the caller already has — e.g. a webhook\n\t * payload — to compare against an audit log.\n\t */\n\tfingerprint: (value: string) => string;\n\t/**\n\t * Replace every cached secret value found in `text` with\n\t * `[REDACTED:name]`. Returns the rewritten text. Subjects shorter than\n\t * `redactionMinLength` are skipped.\n\t */\n\tredact: (text: string) => string;\n\t/**\n\t * Streaming variant of {@link redact}. Returns a `TransformStream`\n\t * that catches secrets even when they're split across chunks (a chunk\n\t * boundary in the middle of `sk_live_abc...` would otherwise miss). The\n\t * stream keeps a lookback buffer the size of the longest cached secret;\n\t * once the buffer outgrows that, the safe-region prefix is emitted.\n\t *\n\t * Use this on `process.stdout` / `process.stderr` / a tenant log forwarder\n\t * so plaintext secrets never reach the sink.\n\t */\n\tredactStream: () => TransformStream<string, string>;\n\t/**\n\t * Rotate a secret. Calls `adapter.rotate(name)`, invalidates the cache,\n\t * returns the new `{ value, fingerprint }`. Throws if the adapter does\n\t * not support rotation. Fires every `onRotate` listener registered for\n\t * this name.\n\t */\n\trotate: (name: string) => Promise<SecretValue>;\n\t/**\n\t * Subscribe to rotation events for a specific name. Listener fires\n\t * AFTER the new value is in the cache. Returns an unsubscribe handle.\n\t * Use this for long-lived connections (DB clients, AI provider SDKs)\n\t * that need to swap credentials in-place when rotation lands.\n\t */\n\tonRotate: (name: string, listener: RotationListener) => () => void;\n\t/**\n\t * Invalidate one cache entry, or the whole cache when `name` is omitted.\n\t */\n\tinvalidate: (name?: string) => void;\n\t/** Tear down the broker — clears the cache; further resolves still hit the adapter. */\n\tdispose: () => void;\n\t/**\n\t * Operator-shaped cumulative counters since `createSecretBroker()`.\n\t * Scrape on a 30s interval for tier monitoring + rotation cadence.\n\t * Added in 0.2.0.\n\t */\n\tmetrics: () => SecretBrokerMetrics;\n\t/**\n\t * Refuse new `resolve()` / `rotate()` calls (they reject with\n\t * `BrokerDrainedError`); in-flight adapter calls keep running. Use\n\t * during graceful shutdown so a tenant whose process is about to\n\t * stop doesn't issue a fresh fetch against the secret store mid-\n\t * teardown. Symmetric with `runtime.drain()` / `queue.drain()`.\n\t * Added in 0.2.0.\n\t */\n\tdrain: () => void;\n};\n\n/**\n * Returned by {@link SecretBroker.metrics}. All counters cumulative\n * since `createSecretBroker()`; cleared by neither `dispose()` nor\n * `drain()` (so the operator can see what happened pre-shutdown).\n * Added in 0.2.0.\n */\nexport type SecretBrokerMetrics = {\n\t/** `resolve()` calls — including cached hits, misses, and errors. */\n\tresolves: number;\n\t/** `resolve()` calls served from cache (no adapter hit). */\n\tresolveHits: number;\n\t/** `resolve()` calls that hit the adapter (cache miss OR expired). */\n\tresolveMisses: number;\n\t/** `resolve()` calls where the adapter threw. */\n\tresolveErrors: number;\n\t/** Successful `rotate()` calls. */\n\trotates: number;\n\t/** `rotate()` calls where the adapter threw. */\n\trotateErrors: number;\n\t/** `invalidate()` calls (per call, regardless of cache size). */\n\tinvalidations: number;\n\t/** `redact()` calls (whether anything was rewritten or not). */\n\tredactCalls: number;\n\t/**\n\t * Distinct (secret, encoding) pairs that triggered a replacement —\n\t * NOT total occurrences. A `redact()` call that rewrites the same\n\t * key three times in one string bumps this by 1. Useful for\n\t * \"is anything ever actually getting redacted, or are we configured\n\t * for nothing.\"\n\t */\n\tredactionsApplied: number;\n\t/** Subset of `redactionsApplied` for base64 encoding. */\n\tredactionsBase64: number;\n};\n\n/**\n * Thrown by `resolve()` / `rotate()` after `drain()` has been called.\n * Added in 0.2.0.\n */\nexport class BrokerDrainedError extends Error {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'[secrets] Broker is draining — resolve/rotate refused. ' +\n\t\t\t\t'Use the broker before the shutdown handler fires.'\n\t\t);\n\t\tthis.name = 'BrokerDrainedError';\n\t}\n}\n\n// -----------------------------------------------------------------------------\n// Fingerprint\n// -----------------------------------------------------------------------------\n\nconst HEX = '0123456789abcdef';\n\nconst sha256Hex = (input: string): string => {\n\t// 2026-era Bun: `crypto.subtle.digest` is the portable path. Synchronous\n\t// path via `Bun.CryptoHasher` is faster but requires Bun globals; we use\n\t// subtle to keep the broker runtime-agnostic at the cost of being async.\n\t// For the `fingerprint(value)` *public* method we want a synchronous\n\t// answer — so we use a tiny in-house sha256. It's slower than the native\n\t// digest but only runs on the secret value (small, ~ < 1KB), once per\n\t// distinct value over the broker's lifetime (memoized in the cache entry).\n\treturn sha256(input);\n};\n\n// Pure JS sha256, NIST FIPS 180-4. Small + dependency-free. Returns lowercase hex.\nconst ROUND_CONSTANTS = new Uint32Array([\n\t0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,\n\t0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\n\t0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,\n\t0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n\t0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,\n\t0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\n\t0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,\n\t0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n\t0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,\n\t0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\n\t0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n]);\n\nconst sha256 = (input: string): string => {\n\tconst bytes = new TextEncoder().encode(input);\n\tconst bitLength = bytes.length * 8;\n\tconst padLength = ((bytes.length + 9 + 63) & ~63) - bytes.length;\n\tconst padded = new Uint8Array(bytes.length + padLength);\n\tpadded.set(bytes);\n\tpadded[bytes.length] = 0x80;\n\tconst view = new DataView(padded.buffer);\n\tview.setUint32(padded.length - 4, bitLength >>> 0);\n\tview.setUint32(padded.length - 8, Math.floor(bitLength / 0x1_0000_0000));\n\n\tlet h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, h3 = 0xa54ff53a;\n\tlet h4 = 0x510e527f, h5 = 0x9b05688c, h6 = 0x1f83d9ab, h7 = 0x5be0cd19;\n\tconst w = new Uint32Array(64);\n\tfor (let i = 0; i < padded.length; i += 64) {\n\t\tfor (let t = 0; t < 16; t++) {\n\t\t\tw[t] = view.getUint32(i + t * 4);\n\t\t}\n\t\tfor (let t = 16; t < 64; t++) {\n\t\t\tconst w15 = w[t - 15]!;\n\t\t\tconst w2 = w[t - 2]!;\n\t\t\tconst s0 = ((w15 >>> 7) | (w15 << 25)) ^ ((w15 >>> 18) | (w15 << 14)) ^ (w15 >>> 3);\n\t\t\tconst s1 = ((w2 >>> 17) | (w2 << 15)) ^ ((w2 >>> 19) | (w2 << 13)) ^ (w2 >>> 10);\n\t\t\tw[t] = (w[t - 16]! + s0 + w[t - 7]! + s1) >>> 0;\n\t\t}\n\t\tlet a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7;\n\t\tfor (let t = 0; t < 64; t++) {\n\t\t\tconst S1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));\n\t\t\tconst ch = (e & f) ^ (~e & g);\n\t\t\tconst T1 = (h + S1 + ch + ROUND_CONSTANTS[t]! + w[t]!) >>> 0;\n\t\t\tconst S0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));\n\t\t\tconst maj = (a & b) ^ (a & c) ^ (b & c);\n\t\t\tconst T2 = (S0 + maj) >>> 0;\n\t\t\th = g;\n\t\t\tg = f;\n\t\t\tf = e;\n\t\t\te = (d + T1) >>> 0;\n\t\t\td = c;\n\t\t\tc = b;\n\t\t\tb = a;\n\t\t\ta = (T1 + T2) >>> 0;\n\t\t}\n\t\th0 = (h0 + a) >>> 0;\n\t\th1 = (h1 + b) >>> 0;\n\t\th2 = (h2 + c) >>> 0;\n\t\th3 = (h3 + d) >>> 0;\n\t\th4 = (h4 + e) >>> 0;\n\t\th5 = (h5 + f) >>> 0;\n\t\th6 = (h6 + g) >>> 0;\n\t\th7 = (h7 + h) >>> 0;\n\t}\n\tconst toHex = (n: number): string => {\n\t\tlet result = '';\n\t\tfor (let i = 7; i >= 0; i--) {\n\t\t\tresult += HEX[(n >>> (i * 4)) & 0xf];\n\t\t}\n\t\treturn result;\n\t};\n\treturn toHex(h0) + toHex(h1) + toHex(h2) + toHex(h3) + toHex(h4) + toHex(h5) + toHex(h6) + toHex(h7);\n};\n\nconst fingerprintOf = (value: string): string => sha256Hex(value).slice(0, 8);\n\n// -----------------------------------------------------------------------------\n// Bundled adapters\n// -----------------------------------------------------------------------------\n\nexport type InMemoryAdapterOptions = {\n\tinitial?: Record<string, string>;\n\t/** Override the rotation strategy. Default = random 32-char base36 string. */\n\trotate?: (name: string, previous: string | null) => string;\n};\n\nconst randomBase36 = (length: number): string => {\n\tlet out = '';\n\twhile (out.length < length) {\n\t\tout += Math.random().toString(36).slice(2);\n\t}\n\treturn out.slice(0, length);\n};\n\nexport const inMemoryAdapter = (\n\toptions: InMemoryAdapterOptions = {},\n): SecretAdapter => {\n\tconst store = new Map<string, string>();\n\tfor (const [k, v] of Object.entries(options.initial ?? {})) store.set(k, v);\n\tconst rotate = options.rotate ?? (() => randomBase36(32));\n\treturn {\n\t\tfetch: async (name) => store.get(name) ?? null,\n\t\tlist: async () => Array.from(store.keys()),\n\t\tput: async (name, value) => { store.set(name, value); },\n\t\tremove: async (name) => { store.delete(name); },\n\t\trotate: async (name) => {\n\t\t\tconst next = rotate(name, store.get(name) ?? null);\n\t\t\tstore.set(name, next);\n\t\t\treturn next;\n\t\t},\n\t};\n};\n\nexport type EnvAdapterOptions = {\n\t/**\n\t * If set, lookups are prefixed before reading from env. e.g.\n\t * `prefix: 'ABS_SECRET_'` and `resolve('STRIPE_KEY')` reads `ABS_SECRET_STRIPE_KEY`.\n\t * Default `''` (no prefix).\n\t */\n\tprefix?: string;\n\t/** The env object to read from. Default `process.env`. */\n\tenv?: Record<string, string | undefined>;\n};\n\nexport const envAdapter = (options: EnvAdapterOptions = {}): SecretAdapter => {\n\tconst prefix = options.prefix ?? '';\n\tconst env = options.env ?? (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env ?? {};\n\treturn {\n\t\tfetch: async (name) => {\n\t\t\tconst key = `${prefix}${name}`;\n\t\t\tconst value = env[key];\n\t\t\treturn value === undefined ? null : value;\n\t\t},\n\t\tlist: async () => {\n\t\t\tif (!prefix) return Object.keys(env);\n\t\t\tconst matches: string[] = [];\n\t\t\tfor (const key of Object.keys(env)) {\n\t\t\t\tif (key.startsWith(prefix)) matches.push(key.slice(prefix.length));\n\t\t\t}\n\t\t\treturn matches;\n\t\t},\n\t};\n};\n\n/**\n * Compose adapters: `fetch` falls through to the first non-null result;\n * `put` / `rotate` / `remove` go to the first adapter that implements them.\n */\nexport const compositeAdapter = (adapters: SecretAdapter[]): SecretAdapter => {\n\tconst firstWith = <K extends keyof SecretAdapter>(method: K) =>\n\t\tadapters.find((adapter) => adapter[method] !== undefined);\n\treturn {\n\t\tfetch: async (name) => {\n\t\t\tfor (const adapter of adapters) {\n\t\t\t\tconst value = await adapter.fetch(name);\n\t\t\t\tif (value !== null) return value;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tlist: async () => {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const adapter of adapters) {\n\t\t\t\tif (!adapter.list) continue;\n\t\t\t\tfor (const name of await adapter.list()) seen.add(name);\n\t\t\t}\n\t\t\treturn Array.from(seen);\n\t\t},\n\t\tput: async (name, value) => {\n\t\t\tconst target = firstWith('put');\n\t\t\tif (!target?.put) throw new Error('No adapter in the composite supports put()');\n\t\t\tawait target.put(name, value);\n\t\t},\n\t\tremove: async (name) => {\n\t\t\tconst target = firstWith('remove');\n\t\t\tif (!target?.remove) throw new Error('No adapter in the composite supports remove()');\n\t\t\tawait target.remove(name);\n\t\t},\n\t\trotate: async (name) => {\n\t\t\tconst target = firstWith('rotate');\n\t\t\tif (!target?.rotate) throw new Error('No adapter in the composite supports rotate()');\n\t\t\treturn target.rotate(name);\n\t\t},\n\t};\n};\n\n// -----------------------------------------------------------------------------\n// Broker\n// -----------------------------------------------------------------------------\n\ntype CacheEntry = {\n\tvalue: string;\n\tfingerprint: string;\n\tstoredAt: number;\n};\n\nexport const createSecretBroker = (options: SecretBrokerOptions): SecretBroker => {\n\tconst clock = options.clock ?? Date.now;\n\tconst defaultTtl = options.cacheTtlMs ?? 60_000;\n\tconst ttlOverrides = options.cacheTtlOverrides ?? {};\n\tconst minLen = options.redactionMinLength ?? 8;\n\tconst encodings = options.redactionEncodings ?? ['plain'];\n\tconst audit = options.audit;\n\tconst cache = new Map<string, CacheEntry>();\n\tconst rotationListeners = new Map<string, Set<RotationListener>>();\n\tlet disposed = false;\n\tlet draining = false;\n\t// 0.2.0: cumulative operator counters. Survive `drain()` and\n\t// `dispose()` so the operator can read final state post-shutdown.\n\tconst counters: SecretBrokerMetrics = {\n\t\tinvalidations: 0,\n\t\tredactCalls: 0,\n\t\tredactionsApplied: 0,\n\t\tredactionsBase64: 0,\n\t\tresolveErrors: 0,\n\t\tresolveHits: 0,\n\t\tresolveMisses: 0,\n\t\tresolves: 0,\n\t\trotateErrors: 0,\n\t\trotates: 0\n\t};\n\n\tconst ttlFor = (name: string): number => ttlOverrides[name] ?? defaultTtl;\n\n\tconst fireRotation = (name: string, value: string, fingerprint: string, at: number) => {\n\t\tconst set = rotationListeners.get(name);\n\t\tif (!set || set.size === 0) return;\n\t\tfor (const listener of set) {\n\t\t\ttry {\n\t\t\t\tconst ret = listener({ at, fingerprint, name, value });\n\t\t\t\tif (ret && typeof (ret as Promise<void>).then === 'function') {\n\t\t\t\t\t(ret as Promise<void>).catch((error) => {\n\t\t\t\t\t\tconsole.error('[secrets] rotation listener rejected:', error);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[secrets] rotation listener threw:', error);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst fireAudit = (event: AuditEvent) => {\n\t\tif (!audit) return;\n\t\ttry {\n\t\t\tconst result = audit(event);\n\t\t\tif (result && typeof (result as Promise<void>).then === 'function') {\n\t\t\t\t(result as Promise<void>).catch((error) => {\n\t\t\t\t\tconsole.error('[secrets] audit hook rejected:', error);\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[secrets] audit hook threw:', error);\n\t\t}\n\t};\n\n\tconst cacheEntry = (name: string, value: string, now: number): CacheEntry => {\n\t\tconst entry: CacheEntry = {\n\t\t\tfingerprint: fingerprintOf(value),\n\t\t\tstoredAt: now,\n\t\t\tvalue,\n\t\t};\n\t\tcache.set(name, entry);\n\t\treturn entry;\n\t};\n\n\tconst resolve: SecretBroker['resolve'] = async (name) => {\n\t\tif (disposed) return null;\n\t\tif (draining) throw new BrokerDrainedError();\n\t\tcounters.resolves += 1;\n\t\tconst now = clock();\n\t\tconst cached = cache.get(name);\n\t\tif (cached && now - cached.storedAt < ttlFor(name)) {\n\t\t\tcounters.resolveHits += 1;\n\t\t\tfireAudit({ at: now, event: 'resolve.hit', fingerprint: cached.fingerprint, name });\n\t\t\treturn { fingerprint: cached.fingerprint, value: cached.value };\n\t\t}\n\t\tcounters.resolveMisses += 1;\n\t\ttry {\n\t\t\tconst value = await options.adapter.fetch(name);\n\t\t\tif (value === null) {\n\t\t\t\tfireAudit({ at: now, event: 'resolve.miss', name });\n\t\t\t\tcache.delete(name);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst entry = cacheEntry(name, value, now);\n\t\t\tfireAudit({ at: now, event: 'resolve.miss', fingerprint: entry.fingerprint, name });\n\t\t\treturn { fingerprint: entry.fingerprint, value: entry.value };\n\t\t} catch (error) {\n\t\t\tcounters.resolveErrors += 1;\n\t\t\tfireAudit({\n\t\t\t\tat: now,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\tevent: 'resolve.error',\n\t\t\t\tname,\n\t\t\t});\n\t\t\tthrow error;\n\t\t}\n\t};\n\n\tconst rotate: SecretBroker['rotate'] = async (name) => {\n\t\tif (disposed) throw new Error('Broker is disposed');\n\t\tif (draining) throw new BrokerDrainedError();\n\t\tif (!options.adapter.rotate) {\n\t\t\tthrow new Error('Adapter does not support rotate()');\n\t\t}\n\t\ttry {\n\t\t\tconst next = await options.adapter.rotate(name);\n\t\t\tconst now = clock();\n\t\t\tconst entry = cacheEntry(name, next, now);\n\t\t\tcounters.rotates += 1;\n\t\t\tfireAudit({ at: now, event: 'rotate', fingerprint: entry.fingerprint, name });\n\t\t\tfireRotation(name, entry.value, entry.fingerprint, now);\n\t\t\treturn { fingerprint: entry.fingerprint, value: entry.value };\n\t\t} catch (error) {\n\t\t\tcounters.rotateErrors += 1;\n\t\t\tthrow error;\n\t\t}\n\t};\n\n\tconst invalidate: SecretBroker['invalidate'] = (name) => {\n\t\tif (name === undefined) {\n\t\t\tcache.clear();\n\t\t} else {\n\t\t\tcache.delete(name);\n\t\t}\n\t\tcounters.invalidations += 1;\n\t\tfireAudit({ at: clock(), event: 'invalidate', name: name ?? null });\n\t};\n\n\t// Returns every (representation, replacementLabel) pair currently in\n\t// the cache that's worth searching for. Longest-first so a longer\n\t// secret blanks BEFORE one of its substrings would.\n\tconst redactionPairs = (): Array<[string, string]> => {\n\t\tconst pairs: Array<[string, string]> = [];\n\t\tfor (const [name, entry] of cache) {\n\t\t\tif (entry.value.length < minLen) continue;\n\t\t\tfor (const enc of encodings) {\n\t\t\t\tif (enc === 'plain') {\n\t\t\t\t\tpairs.push([entry.value, `[REDACTED:${name}]`]);\n\t\t\t\t} else if (enc === 'base64') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst encoded = btoa(entry.value);\n\t\t\t\t\t\t// Skip if encoding produces a too-short token to be safe.\n\t\t\t\t\t\tif (encoded.length >= minLen) {\n\t\t\t\t\t\t\tpairs.push([encoded, `[REDACTED:${name}:b64]`]);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// btoa rejects non-Latin-1; skip silently.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tpairs.sort((a, b) => b[0].length - a[0].length);\n\t\treturn pairs;\n\t};\n\n\tconst redact: SecretBroker['redact'] = (text) => {\n\t\tcounters.redactCalls += 1;\n\t\tif (text.length === 0 || cache.size === 0) return text;\n\t\tlet out = text;\n\t\tfor (const [needle, replacement] of redactionPairs()) {\n\t\t\tif (!out.includes(needle)) continue;\n\t\t\tout = out.split(needle).join(replacement);\n\t\t\tcounters.redactionsApplied += 1;\n\t\t\tif (replacement.endsWith(':b64]')) counters.redactionsBase64 += 1;\n\t\t}\n\t\treturn out;\n\t};\n\n\tconst redactStream: SecretBroker['redactStream'] = () => {\n\t\t// Per-chunk algorithm:\n\t\t// 1. Append chunk to buffer.\n\t\t// 2. Redact the WHOLE buffer (complete secrets → labels).\n\t\t// 3. Hold back the last `lookback` chars — they might contain a\n\t\t// partial secret that completes on the next chunk. The next\n\t\t// chunk's redact() will catch it once the full secret arrives.\n\t\t// 4. Emit the safe prefix.\n\t\t// Without step 2 happening BEFORE the split, a secret straddling the\n\t\t// boundary would have its prefix emitted un-redacted before the suffix\n\t\t// even shows up.\n\t\tlet buffer = '';\n\t\tconst maxLen = () =>\n\t\t\tredactionPairs().reduce((max, [needle]) => Math.max(max, needle.length), 0);\n\t\treturn new TransformStream<string, string>({\n\t\t\ttransform: (chunk, controller) => {\n\t\t\t\tbuffer += chunk;\n\t\t\t\tconst lookback = maxLen();\n\t\t\t\tconst reduced = redact(buffer);\n\t\t\t\tif (reduced.length <= lookback) {\n\t\t\t\t\tbuffer = reduced;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst safe = reduced.slice(0, reduced.length - lookback);\n\t\t\t\tbuffer = reduced.slice(reduced.length - lookback);\n\t\t\t\tif (safe.length > 0) controller.enqueue(safe);\n\t\t\t},\n\t\t\tflush: (controller) => {\n\t\t\t\tif (buffer.length === 0) return;\n\t\t\t\tcontroller.enqueue(redact(buffer));\n\t\t\t\tbuffer = '';\n\t\t\t},\n\t\t});\n\t};\n\n\tconst onRotate: SecretBroker['onRotate'] = (name, listener) => {\n\t\tlet set = rotationListeners.get(name);\n\t\tif (!set) {\n\t\t\tset = new Set();\n\t\t\trotationListeners.set(name, set);\n\t\t}\n\t\tset.add(listener);\n\t\treturn () => {\n\t\t\tconst current = rotationListeners.get(name);\n\t\t\tif (!current) return;\n\t\t\tcurrent.delete(listener);\n\t\t\tif (current.size === 0) rotationListeners.delete(name);\n\t\t};\n\t};\n\n\treturn {\n\t\tdispose: () => {\n\t\t\tdisposed = true;\n\t\t\tcache.clear();\n\t\t\trotationListeners.clear();\n\t\t},\n\t\tdrain: () => {\n\t\t\tdraining = true;\n\t\t},\n\t\tfingerprint: fingerprintOf,\n\t\tinvalidate,\n\t\tmetrics: () => ({ ...counters }),\n\t\tonRotate,\n\t\tredact,\n\t\tredactStream,\n\t\tresolve,\n\t\trotate,\n\t};\n};\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "EE866E47E57910C764756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "68E7DA7EF9820B8264756E2164756E21",
9
9
  "names": []
10
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/secrets",
3
- "version": "0.0.1",
3
+ "version": "0.2.0",
4
4
  "description": "Host-side secret broker for multi-tenant Bun runtimes. Pluggable adapters (env-var, in-memory, composite); audit hook per resolve; safe fingerprints for logs; redact() walks known secrets out of arbitrary text before it lands in a log sink.",
5
5
  "repository": {
6
6
  "type": "git",