@blamejs/core 0.14.6 → 0.14.8

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.
Files changed (110) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +3 -2
  3. package/lib/a2a-tasks.js +6 -6
  4. package/lib/agent-event-bus.js +4 -4
  5. package/lib/agent-idempotency.js +6 -6
  6. package/lib/agent-orchestrator.js +9 -9
  7. package/lib/agent-posture-chain.js +10 -10
  8. package/lib/agent-saga.js +6 -7
  9. package/lib/agent-snapshot.js +8 -8
  10. package/lib/agent-stream.js +3 -3
  11. package/lib/agent-tenant.js +4 -4
  12. package/lib/agent-trace.js +5 -5
  13. package/lib/ai-disclosure.js +3 -3
  14. package/lib/ai-input.js +1 -1
  15. package/lib/app.js +2 -2
  16. package/lib/archive-read.js +1 -1
  17. package/lib/archive-tar-read.js +1 -1
  18. package/lib/archive-wrap.js +5 -5
  19. package/lib/audit-tools.js +65 -5
  20. package/lib/audit.js +2 -2
  21. package/lib/auth/acr-vocabulary.js +1 -1
  22. package/lib/auth/ciba.js +4 -4
  23. package/lib/auth/dpop.js +1 -1
  24. package/lib/auth/fal.js +1 -1
  25. package/lib/auth/fido-mds3.js +2 -3
  26. package/lib/auth/jwt-external.js +2 -2
  27. package/lib/auth/oauth.js +10 -10
  28. package/lib/auth/oid4vci.js +8 -8
  29. package/lib/auth/oid4vp.js +1 -1
  30. package/lib/auth/openid-federation.js +6 -6
  31. package/lib/auth/passkey.js +6 -6
  32. package/lib/auth/saml.js +1 -1
  33. package/lib/auth/sd-jwt-vc.js +3 -6
  34. package/lib/backup/index.js +18 -18
  35. package/lib/breach-deadline.js +3 -3
  36. package/lib/cache.js +4 -4
  37. package/lib/calendar.js +7 -7
  38. package/lib/circuit-breaker.js +1 -1
  39. package/lib/cms-codec.js +2 -2
  40. package/lib/compliance.js +14 -14
  41. package/lib/content-credentials.js +3 -3
  42. package/lib/crypto-field.js +58 -21
  43. package/lib/crypto.js +5 -6
  44. package/lib/db-query.js +131 -9
  45. package/lib/db.js +106 -22
  46. package/lib/ddl-change-control.js +2 -2
  47. package/lib/did.js +2 -2
  48. package/lib/dsr.js +4 -4
  49. package/lib/external-db.js +65 -17
  50. package/lib/framework-schema.js +4 -4
  51. package/lib/guard-cidr.js +1 -1
  52. package/lib/guard-image.js +1 -1
  53. package/lib/guard-list-id.js +2 -2
  54. package/lib/guard-list-unsubscribe.js +2 -3
  55. package/lib/guard-time.js +1 -1
  56. package/lib/guard-xml.js +1 -1
  57. package/lib/http-client-cache.js +1 -1
  58. package/lib/iab-tcf.js +4 -4
  59. package/lib/incident-report.js +150 -0
  60. package/lib/json-schema.js +1 -1
  61. package/lib/jtd.js +1 -1
  62. package/lib/mail-auth.js +1 -1
  63. package/lib/mail-bimi.js +1 -1
  64. package/lib/mail-crypto-smime.js +2 -2
  65. package/lib/mail-deploy.js +3 -3
  66. package/lib/mail-server-managesieve.js +2 -2
  67. package/lib/mail-server-mx.js +1 -1
  68. package/lib/mail-server-pop3.js +2 -2
  69. package/lib/mail-server-rate-limit.js +1 -1
  70. package/lib/mail-server-submission.js +1 -1
  71. package/lib/mail-store.js +1 -1
  72. package/lib/mcp.js +7 -7
  73. package/lib/mdoc.js +1 -1
  74. package/lib/metrics.js +10 -10
  75. package/lib/middleware/compose-pipeline.js +1 -1
  76. package/lib/middleware/csrf-protect.js +1 -1
  77. package/lib/middleware/dpop.js +5 -5
  78. package/lib/middleware/idempotency-key.js +21 -22
  79. package/lib/middleware/protected-resource-metadata.js +2 -2
  80. package/lib/network-dns-resolver.js +2 -2
  81. package/lib/network-dns.js +1 -2
  82. package/lib/network-dnssec.js +2 -2
  83. package/lib/network-smtp-policy.js +1 -1
  84. package/lib/network-tls.js +1 -2
  85. package/lib/network-tsig.js +3 -3
  86. package/lib/outbox.js +1 -1
  87. package/lib/pqc-agent.js +1 -1
  88. package/lib/retention.js +1 -1
  89. package/lib/retry.js +1 -1
  90. package/lib/rfc3339.js +2 -2
  91. package/lib/safe-archive.js +2 -2
  92. package/lib/safe-decompress.js +1 -1
  93. package/lib/safe-ical.js +2 -2
  94. package/lib/safe-mime.js +1 -1
  95. package/lib/self-update-standalone-verifier.js +1 -1
  96. package/lib/self-update.js +2 -2
  97. package/lib/standard-webhooks.js +3 -3
  98. package/lib/static.js +1 -1
  99. package/lib/stream-throttle.js +2 -2
  100. package/lib/structured-fields.js +1 -1
  101. package/lib/subject.js +2 -2
  102. package/lib/vault/index.js +64 -1
  103. package/lib/vault/rotate.js +19 -0
  104. package/lib/vault/seal-pem-file.js +1 -1
  105. package/lib/vendor-data.js +1 -1
  106. package/lib/web-push-vapid.js +1 -1
  107. package/lib/webhook.js +1 -1
  108. package/lib/websocket.js +1 -1
  109. package/package.json +1 -1
  110. package/sbom.cdx.json +6 -6
package/lib/mcp.js CHANGED
@@ -45,12 +45,12 @@ var METHOD_NAME_MAX = 256;
45
45
  // JSON-RPC 2.0 error codes (https://www.jsonrpc.org/specification#error_object).
46
46
  // Negative numerics by spec; mapped to HTTP status for the framework's
47
47
  // HTTP-shaped reply envelope.
48
- var JSONRPC_PARSE_ERROR = -32700; // allow:raw-time-literal — not seconds
49
- var JSONRPC_INVALID_REQUEST = -32600; // allow:raw-time-literal — not seconds
50
- var JSONRPC_METHOD_NOT_FOUND= -32601; // allow:raw-time-literal — not seconds
51
- var JSONRPC_INVALID_PARAMS = -32602; // allow:raw-time-literal — not seconds
52
- var JSONRPC_INTERNAL_ERROR = -32603; // allow:raw-time-literal — not seconds
53
- var JSONRPC_AUTH_REQUIRED = -32001; // allow:raw-time-literal — not seconds
48
+ var JSONRPC_PARSE_ERROR = -32700; // allow:raw-time-literal — JSON-RPC error code -32700; coincidental multiple-of-60, not a time value, C.TIME N/A
49
+ var JSONRPC_INVALID_REQUEST = -32600;
50
+ var JSONRPC_METHOD_NOT_FOUND= -32601;
51
+ var JSONRPC_INVALID_PARAMS = -32602;
52
+ var JSONRPC_INTERNAL_ERROR = -32603;
53
+ var JSONRPC_AUTH_REQUIRED = -32001;
54
54
  var TOOL_NAME_RE = /^[a-zA-Z][a-zA-Z0-9._-]{0,63}$/;
55
55
  var RESOURCE_NAME_RE = /^[a-zA-Z][a-zA-Z0-9._/-]{0,255}$/;
56
56
 
@@ -424,7 +424,7 @@ function serverGuard(opts) {
424
424
  * var safe = b.mcp.toolResult.sanitize(toolResp, { posture: "sanitize" });
425
425
  * // → { content: [{ type: "text", text: "<cleaned>" }] }
426
426
  */
427
- var DEFAULT_TOOL_OUTPUT_MAX_BYTES = 64 * 1024; // allow:raw-byte-literal — 64 KiB per content block
427
+ var DEFAULT_TOOL_OUTPUT_MAX_BYTES = 64 * 1024;
428
428
  var PROMPT_INJECTION_MARKERS = [
429
429
  "ignore (previous|prior|all) instructions",
430
430
  "system:\\s*you are",
package/lib/mdoc.js CHANGED
@@ -58,7 +58,7 @@ var { defineClass } = require("./framework-error");
58
58
 
59
59
  var MdocError = defineClass("MdocError", { alwaysPermanent: true });
60
60
 
61
- var HDR_X5CHAIN = 33; // allow:raw-time-literal — x5chain COSE header label (RFC 9360 is a spec number, not a size/duration)
61
+ var HDR_X5CHAIN = 33;
62
62
  var TAG_ENCODED_CBOR = 24; // RFC 8949 §3.4.5.1 embedded-CBOR tag
63
63
  // Tags ISO 18013-5 uses in issuer data: tdate(0), epoch(1), embedded
64
64
  // CBOR(24), full-date(1004, RFC 8943). Bounded — others are refused.
package/lib/metrics.js CHANGED
@@ -143,7 +143,7 @@ function _normalizeLabelArg(callLabels, value, defaultValue) {
143
143
  };
144
144
  }
145
145
 
146
- // CRYPTO-18 — credential-shape detector. Operators routinely tap their
146
+ // Credential-shape detector. Operators routinely tap their
147
147
  // own observability with `{ token: req.headers.authorization }` or
148
148
  // `{ apiKey: req.headers["x-api-key"] }`, which then leak through the
149
149
  // /metrics scrape surface to any reader of the metrics endpoint. The
@@ -199,7 +199,7 @@ function _validateLabelValue(value) {
199
199
  // counters indexed by various input types still work.
200
200
  if (value === null || value === undefined) return "";
201
201
  var coerced = String(value);
202
- // CRYPTO-18 — credential-shape detector. Operators who tap their
202
+ // Credential-shape detector. Operators who tap their
203
203
  // observability with raw header values leak bearer tokens / API
204
204
  // keys through /metrics to every scrape reader. Refuse the value
205
205
  // and surface a redaction marker so the metric still labels (so
@@ -642,8 +642,8 @@ function create(opts) {
642
642
  // `Accept: application/openmetrics-text; version=1.0.0`. The
643
643
  // handler returns the OpenMetrics-1.0 wire format when that
644
644
  // media type has the highest q-value among supported types;
645
- // defaults to Prometheus 0.0.4 otherwise. Codex P1 v0.12.5 —
646
- // honor RFC 9110 §12.5.1 weighted negotiation: a client that
645
+ // defaults to Prometheus 0.0.4 otherwise.
646
+ // Honor RFC 9110 §12.5.1 weighted negotiation: a client that
647
647
  // sends `Accept: text/plain;q=1.0, application/openmetrics-
648
648
  // text;q=0.5` (or `;q=0`) gets text/plain back, even though
649
649
  // both media types are supported.
@@ -719,7 +719,7 @@ function create(opts) {
719
719
  // (Prometheus 2.x, Grafana exemplar-renderer) can pivot
720
720
  // from a slow-request bucket to the trace that produced it.
721
721
  //
722
- // Codex P2 v0.12.5 — the span_id MUST be the server-handling
722
+ // The span_id MUST be the server-handling
723
723
  // span (created by b.middleware.spanHttpServer + stamped on
724
724
  // req.span), not the upstream `traceparent`'s parent-id.
725
725
  // The parent-id points at the CALLER's span (or nothing for
@@ -729,7 +729,7 @@ function create(opts) {
729
729
  exemplar = {
730
730
  labels: { trace_id: req.span.traceId, span_id: req.span.spanId },
731
731
  value: elapsedSec,
732
- timestamp: Date.now() / 1000, // allow:raw-time-literal — OpenMetrics §6.2 unix epoch seconds with subsecond fraction
732
+ timestamp: Date.now() / 1000,
733
733
  };
734
734
  } else if (req.trace && req.trace.sampled && req.trace.traceId && req.trace.spanId) {
735
735
  // Operators wiring traceparent directly without
@@ -740,7 +740,7 @@ function create(opts) {
740
740
  exemplar = {
741
741
  labels: { trace_id: req.trace.traceId, span_id: req.trace.spanId },
742
742
  value: elapsedSec,
743
- timestamp: Date.now() / 1000, // allow:raw-time-literal — OpenMetrics §6.2 unix epoch seconds with subsecond fraction
743
+ timestamp: Date.now() / 1000,
744
744
  };
745
745
  }
746
746
  try { requestDuration.observe(durLabels, elapsedSec, exemplar); }
@@ -986,7 +986,7 @@ function snapshotStartWriter(opts) {
986
986
  var fieldsFn = opts.fields;
987
987
  var registry = opts.registry || null;
988
988
  var intervalMs = opts.intervalMs;
989
- // CRYPTO-6 — file mode for the atomic write. Default 0o640
989
+ // File mode for the atomic write. Default 0o640
990
990
  // (owner rw, group r, world none). Operators with a sidecar
991
991
  // reader in a different group override to 0o644; multi-tenant
992
992
  // hosts may even tighten to 0o600.
@@ -1019,7 +1019,7 @@ function snapshotStartWriter(opts) {
1019
1019
  catch (e2) { log("snapshot.metrics serialize failed: " + ((e2 && e2.message) || String(e2))); }
1020
1020
  }
1021
1021
  try {
1022
- // CRYPTO-6 — default 0o640 (owner rw, group r, world none) so
1022
+ // Default 0o640 (owner rw, group r, world none) so
1023
1023
  // operator-supplied snapshot fields aren't world-readable on a
1024
1024
  // multi-tenant host. Operators with a sidecar reader running as
1025
1025
  // a different group override via opts.fileMode at startWriter
@@ -1078,7 +1078,7 @@ function snapshotRead(p) {
1078
1078
  // is well above the framework's expected snapshot size (~5-50 KiB)
1079
1079
  // and the safeJson absolute cap stays within reach.
1080
1080
  try {
1081
- // CRYPTO-21 — route through C.BYTES.mib(4); the raw byte literal
1081
+ // Route through C.BYTES.mib(4); the raw byte literal
1082
1082
  // was a drift smell flagged by codebase-patterns.
1083
1083
  parsed = safeJson.parse(raw, { maxBytes: C.BYTES.mib(4) });
1084
1084
  } catch (e) {
@@ -97,7 +97,7 @@ var CANONICAL_POSITIONS = Object.freeze({
97
97
  botGuard: 42, // canonical position bucket
98
98
  requireAuth: 50, // canonical position bucket
99
99
  attachUser: 52, // canonical position bucket
100
- handler: 60, // allow:raw-time-literal — pipeline position int, not seconds
100
+ handler: 60, // allow:raw-time-literal — pipeline position bucket; coincidental multiple-of-60, C.TIME N/A
101
101
  errorHandler: 90, // canonical position bucket
102
102
  });
103
103
 
@@ -316,7 +316,7 @@ function create(opts) {
316
316
  // refuse before the token check.
317
317
  //
318
318
  // Default: enabled (defense-in-depth — same shape as bot-guard /
319
- // rate-limit / CSP nonce — every default ON per Core Rule §3).
319
+ // rate-limit / CSP nonce — every default ON).
320
320
  // Operator opt-out: opts.checkOrigin = false.
321
321
  // Operator allowlist: opts.allowedOrigins = ["https://app.example.com"].
322
322
  var checkOrigin = opts.checkOrigin !== false;
@@ -119,7 +119,7 @@ function _nonceManager(rotateSec) {
119
119
  if (previous && bCrypto.timingSafeEqual(n, previous.nonce)) return true;
120
120
  return false;
121
121
  },
122
- // AUTH-36 — hot-reload coexistence. Operators redeploying without
122
+ // Hot-reload coexistence. Operators redeploying without
123
123
  // a clean process restart need a way to drain in-flight clients
124
124
  // before swapping the middleware instance. shutdown() returns no
125
125
  // fresh nonces and refuses every presented nonce, so the
@@ -156,7 +156,7 @@ function _reconstructHtu(req, mopts) {
156
156
  //
157
157
  // Default: ignore X-Forwarded-* and derive proto/host from the
158
158
  // socket. Operators with a confirmed-trusted front proxy opt in
159
- // via opts.trustForwardedHeaders: true. (Audit 2026-05-11.)
159
+ // via opts.trustForwardedHeaders: true.
160
160
  mopts = mopts || {};
161
161
  var trustForwarded = mopts.trustForwardedHeaders === true;
162
162
  var proto;
@@ -229,7 +229,7 @@ function create(opts) {
229
229
  "getAccessToken", "getNonce", "getHtu", "audit",
230
230
  "nonceStore", "nonceWindowSec", "nonceRotateSec", "requireNonce",
231
231
  // v0.9.4 — opt-in trust gate for X-Forwarded-Proto/Host when
232
- // reconstructing htu. Default off (audit 2026-05-11); operators
232
+ // reconstructing htu. Default off; operators
233
233
  // with a confirmed-trusted front proxy set this to `true`.
234
234
  "trustForwardedHeaders", "onDeny", "problemDetails",
235
235
  ], "middleware.dpop");
@@ -287,7 +287,7 @@ function create(opts) {
287
287
  return _writeUnauthorized(req, res, "invalid_dpop_proof",
288
288
  "multiple DPoP headers are not allowed", null, onDeny, problemMode);
289
289
  }
290
- // AUTH-15 — RFC 9449 §4.1 single-value invariant. node:http
290
+ // RFC 9449 §4.1 single-value invariant. node:http
291
291
  // collapses repeated headers into a comma-joined string when the
292
292
  // client ships `DPoP: proof1, DPoP: proof2`; the Array.isArray
293
293
  // check above catches the multi-value array shape but a
@@ -399,7 +399,7 @@ function create(opts) {
399
399
  return next();
400
400
  };
401
401
 
402
- // AUTH-36 — surface the nonce manager's lifecycle hooks on the
402
+ // Surface the nonce manager's lifecycle hooks on the
403
403
  // returned middleware so hot-reload deploys can drain in-flight
404
404
  // clients before swapping instances. shutdown() refuses every
405
405
  // subsequent proof + issues no fresh nonces; revoke() rotates the
@@ -175,7 +175,7 @@ function memoryStore(opts) {
175
175
  * headers. Requires `b.vault.init(...)` to have run; falls back to
176
176
  * plain-text with a one-shot audit warning when vault isn't ready,
177
177
  * so test-fixture / boot-script callers still work.
178
- * - `aad: true` (since 0.9.58 — CRYPTO-1) — sealed columns are bound
178
+ * - `aad: true` (since 0.9.58) — sealed columns are bound
179
179
  * via Additional Authenticated Data to (table, k, column,
180
180
  * schemaVersion) so a DB-write attacker can't copy a sealed
181
181
  * header/body cell from one row to another (which previously
@@ -184,12 +184,12 @@ function memoryStore(opts) {
184
184
  * detects the envelope shape; lazy re-seal on next `set()` upgrades
185
185
  * each row to AAD form. Operators wanting a one-shot migration
186
186
  * call `b.middleware.idempotencyKey.resealMigrate(store)`.
187
- * - `fingerprintSeal: true` (since 0.9.58 — CRYPTO-4) — the request
187
+ * - `fingerprintSeal: true` (since 0.9.58) — the request
188
188
  * `fingerprint` column carries an HMAC under a vault-derived
189
189
  * secret instead of a bare SHA3-256 of method+path+body. The
190
190
  * compare path is constant-time so the column doubles as a
191
191
  * mismatch oracle without offline-brute-force exposure.
192
- * - `bodyFingerprintFallback: "deny"` (since 0.9.58 — SUBSTRATE-13) —
192
+ * - `bodyFingerprintFallback: "deny"` (since 0.9.58) —
193
193
  * when neither `bodyFingerprint` nor `req._rawBody`/`req.body` is
194
194
  * populated for a body-bearing method, the middleware previously
195
195
  * silently degraded the fingerprint to method+path. Set to
@@ -228,8 +228,8 @@ function memoryStore(opts) {
228
228
  * init?: boolean, // default true — run CREATE TABLE IF NOT EXISTS at construction
229
229
  * hashKeys?: boolean, // default true — store sha3-512 namespace-hash of the key, not the raw key
230
230
  * seal?: boolean, // default true — seal headers + body via b.cryptoField when vault is ready
231
- * aad?: boolean, // default true — AAD-bind seal to (table,k,column) so a DB-write attacker can't cross-row swap (CRYPTO-1)
232
- * fingerprintSeal?: boolean, // default true — HMAC fingerprint under a vault-derived secret instead of bare sha3-256 (CRYPTO-4)
231
+ * aad?: boolean, // default true — AAD-bind seal to (table,k,column) so a DB-write attacker can't cross-row swap
232
+ * fingerprintSeal?: boolean, // default true — HMAC fingerprint under a vault-derived secret instead of bare sha3-256
233
233
  *
234
234
  * @example
235
235
  * // single-process daemon, framework's internal sqlite, both defaults on:
@@ -264,11 +264,11 @@ function dbStore(opts) {
264
264
  var doInit = opts.init !== false;
265
265
  var hashKeys = opts.hashKeys !== false;
266
266
  var sealReq = opts.seal !== false;
267
- // CRYPTO-1 — AAD-bind sealing to (table, k, column) by default.
267
+ // AAD-bind sealing to (table, k, column) by default.
268
268
  // Forms a defense-in-depth pair with seal: cross-row swap fails
269
269
  // Poly1305 even when the attacker controls the DB layer.
270
270
  var aadOn = opts.aad !== false;
271
- // CRYPTO-4 — HMAC the fingerprint under a vault-derived secret by
271
+ // HMAC the fingerprint under a vault-derived secret by
272
272
  // default. Bare SHA3-256 of method+path+body is offline-brute-
273
273
  // forceable for any DB-dump attacker; HMAC under a vault secret
274
274
  // forces them to break the vault first.
@@ -297,7 +297,7 @@ function dbStore(opts) {
297
297
 
298
298
  // Register the table with cryptoField. registerTable is idempotent
299
299
  // — subsequent dbStore() calls with the same tableName re-declare
300
- // the same sealedFields and no-op. CRYPTO-1: when aad is on,
300
+ // the same sealedFields and no-op. When aad is on,
301
301
  // (table, k, column) is threaded into the AEAD AAD so a DB-write
302
302
  // attacker can't copy a sealed value between rows.
303
303
  if (sealEnabled) {
@@ -309,7 +309,7 @@ function dbStore(opts) {
309
309
  });
310
310
  }
311
311
 
312
- // CRYPTO-4 — derive a per-vault HMAC secret for fingerprint sealing.
312
+ // Derive a per-vault HMAC secret for fingerprint sealing.
313
313
  // The vault root key is the trust root; without it the secret is
314
314
  // unrecoverable. Lazy: only derived when fpSealOn is enabled AND the
315
315
  // vault is ready, so test fixtures that haven't initialized the
@@ -349,7 +349,7 @@ function dbStore(opts) {
349
349
  // so audit/forensic SELECTs don't have to unseal-everything. The
350
350
  // `k` column is selected even when not strictly needed for read
351
351
  // because cryptoField.unsealRow uses it as the rowId in AAD when
352
- // the table is AAD-bound (CRYPTO-1).
352
+ // the table is AAD-bound.
353
353
  var stmtGet = db.prepare(
354
354
  "SELECT k, fingerprint, status_code, headers, body, expires_at FROM " +
355
355
  qTable + " WHERE k = ?");
@@ -372,7 +372,7 @@ function dbStore(opts) {
372
372
  return bCrypto.namespaceHash("idempotency-key", rawKey);
373
373
  }
374
374
 
375
- // CRYPTO-4 — emit / compare HMAC-shape fingerprints. The store
375
+ // Emit / compare HMAC-shape fingerprints. The store
376
376
  // round-trips the column as plain text (no transformation per-get);
377
377
  // sealing happens at MINT time (when the middleware builds the
378
378
  // fingerprint and hands it to set()). The store's responsibility is
@@ -391,7 +391,7 @@ function dbStore(opts) {
391
391
  if (sealEnabled) {
392
392
  try { liveRow = cryptoField.unsealRow(tableNameRaw, row); }
393
393
  catch (_unsealErr) {
394
- // CRYPTO-13 — decryption failure used to delete the row,
394
+ // Decryption failure used to delete the row,
395
395
  // which let an attacker probe key presence via a "tamper +
396
396
  // observe subsequent SELECT" oracle. The fix: emit audit,
397
397
  // return null, do NOT delete. TTL sweeps stale rows out
@@ -407,7 +407,7 @@ function dbStore(opts) {
407
407
  }
408
408
  var headersObj;
409
409
  try {
410
- // CRYPTO-22 — route through C.BYTES.mib(4); raw `4 * 1024 * 1024`
410
+ // Route through C.BYTES.mib(4); raw `4 * 1024 * 1024`
411
411
  // was a drift smell flagged by codebase-patterns. 4 MiB ceiling
412
412
  // unchanged.
413
413
  headersObj = safeJson.parse(liveRow.headers, { maxBytes: C.BYTES.mib(4) });
@@ -421,7 +421,6 @@ function dbStore(opts) {
421
421
  // DELETING it would clobber another process's cache and
422
422
  // turn a hit into a miss with potential side-effect re-
423
423
  // execution. Treat as miss + LEAVE the row in place.
424
- // Per Codex P1 on PR #45.
425
424
  var lookedSealed = typeof liveRow.headers === "string" &&
426
425
  (liveRow.headers.indexOf("vault:") === 0 ||
427
426
  liveRow.headers.indexOf("vault.aad:") === 0);
@@ -456,7 +455,7 @@ function dbStore(opts) {
456
455
  delete: function (rawKey) {
457
456
  stmtDelete.run(_k(rawKey));
458
457
  },
459
- // CRYPTO-4 — the middleware consults this hook to HMAC the
458
+ // The middleware consults this hook to HMAC the
460
459
  // method+path+body digest under a vault-derived secret before
461
460
  // insert + compare. Returns null when fpSeal is disabled OR the
462
461
  // vault wasn't ready at construction; the middleware then falls
@@ -466,7 +465,7 @@ function dbStore(opts) {
466
465
  return nodeCrypto.createHmac("sha3-256", fpHmacSecret)
467
466
  .update(preimageBytes).digest("hex");
468
467
  },
469
- // CRYPTO-1 — operator helper: walk the table and reseal every row
468
+ // Operator helper: walk the table and reseal every row
470
469
  // under the AAD form. Existing v0.9.15-v0.9.57 rows continue to
471
470
  // read on a per-row basis (unsealRow auto-detects shape), but
472
471
  // operators wanting an explicit migration step call this once.
@@ -526,7 +525,7 @@ function _fingerprintRequest(req, bodyBytes, store) {
526
525
  // Fingerprint preimage = method + path + body. Per the draft §4.3,
527
526
  // a key+body mismatch is a client-side mistake; our preimage covers
528
527
  // method + path so a client reusing a key across different
529
- // endpoints is also caught. CRYPTO-4: when the store exposes a
528
+ // endpoints is also caught. When the store exposes a
530
529
  // `fingerprintHmac` hook (dbStore with fingerprintSeal:true + vault
531
530
  // ready), the preimage is HMAC'd under a vault-derived secret so a
532
531
  // DB dump leaks neither the preimage nor a brute-forceable digest.
@@ -602,7 +601,7 @@ function _emitAudit(action, metadata, outcome) {
602
601
  * requireIdempotencyKey: boolean, // default: false — refuse missing-key
603
602
  * bodyFingerprint: function, // (req) => Buffer|string|object|null — operator-supplied body extractor
604
603
  * maxBodyBytes: number, // default: 1 MiB — replay-cache body cap
605
- * bodyFingerprintFallback: string, // default "deny" (SUBSTRATE-13) — when neither
604
+ * bodyFingerprintFallback: string, // default "deny" — when neither
606
605
  * // bodyFingerprint nor req._rawBody / req.body is
607
606
  * // available for POST/PUT/PATCH, refuse with HTTP 400
608
607
  * // idempotency/missing-body-fingerprint instead of
@@ -669,7 +668,7 @@ function create(opts) {
669
668
  opts.bodyFingerprint, "idempotencyKey.bodyFingerprint",
670
669
  IdempotencyError, "idempotency/bad-body-fingerprint"
671
670
  ) || null;
672
- // SUBSTRATE-13 — default "deny" refuses body-bearing requests that
671
+ // Default "deny" refuses body-bearing requests that
673
672
  // arrive with neither req._rawBody / req.body NOR an operator-
674
673
  // supplied bodyFingerprint hook. The silent-degrade-to-method+path
675
674
  // path was a §4.3 violation (same key + different body returned
@@ -762,7 +761,7 @@ function create(opts) {
762
761
  // Misordered-mount detector — body-bearing method reached us
763
762
  // with neither a parsed body nor a raw-body buffer. Most likely
764
763
  // body-parser hasn't run yet, which used to silently degrade the
765
- // fingerprint to method+path; SUBSTRATE-13 (v0.9.58) makes that
764
+ // fingerprint to method+path; v0.9.58 makes that
766
765
  // case refuse with HTTP 400 by default. The audit emit fires in
767
766
  // both fallback modes so operator review surfaces the
768
767
  // misconfiguration regardless of the chosen fallback.
@@ -929,8 +928,8 @@ function _redactKey(key) {
929
928
  * @related b.middleware.idempotencyKey.dbStore
930
929
  *
931
930
  * One-shot operator helper that walks a dbStore's table and reseals
932
- * every row under the AAD-bound envelope shape introduced in v0.9.58
933
- * (CRYPTO-1). Existing v0.9.15-v0.9.57 rows continue to read on a
931
+ * every row under the AAD-bound envelope shape introduced in v0.9.58.
932
+ * Existing v0.9.15-v0.9.57 rows continue to read on a
934
933
  * per-row basis (unsealRow auto-detects shape) so a deploy without
935
934
  * this call is correct, but operators who want to upgrade in bulk
936
935
  * call this once after upgrading.
@@ -94,7 +94,7 @@ function create(opts) {
94
94
  "middleware/protected-resource-metadata/no-as",
95
95
  "authorizationServers must be a non-empty array of issuer URLs");
96
96
  }
97
- // AUTH-17 — RFC 9728 §3 + RFC 8414 §3.1: authorizationServers entries
97
+ // RFC 9728 §3 + RFC 8414 §3.1: authorizationServers entries
98
98
  // are issuer URLs and MUST be https://. Pre-v0.9.x only required
99
99
  // non-empty string, so an operator typo could ship `http://idp.test`
100
100
  // (or, worse, `javascript:` / `data:`) to clients via the well-known
@@ -156,7 +156,7 @@ function create(opts) {
156
156
  if (opts.dpopBoundAccessTokensRequired === true) doc.dpop_bound_access_tokens_required = true;
157
157
  if (opts.mtlsBoundAccessTokensRequired === true) doc.tls_client_certificate_bound_access_tokens = true;
158
158
 
159
- // AUTH-18 — RFC 9728 §3.2 signed_metadata. Operators with an
159
+ // RFC 9728 §3.2 signed_metadata. Operators with an
160
160
  // anti-tamper requirement pass `signMetadata: { key, alg, kid }`;
161
161
  // the middleware emits `application/jwt` carrying the JWS-signed
162
162
  // metadata. Default output remains cleartext `application/json`.
@@ -126,7 +126,7 @@ var DEFAULT_MAX_TTL_MS = C.TIME.hours(24);
126
126
  var DEFAULT_MIN_TTL_MS = C.TIME.seconds(60);
127
127
  var DEFAULT_STALE_WINDOW = C.TIME.hours(6);
128
128
  var DEFAULT_PROFILE = "strict";
129
- // BUG-1 / MAIL-26 — CWE-400/770. Bound the cache so a hostile peer
129
+ // CWE-400/770. Bound the cache so a hostile peer
130
130
  // that can drive query-name selection (e.g. inbound SMTP forwarding
131
131
  // DKIM `s=` / `d=` tag-controlled lookups) cannot inflate the Map to
132
132
  // OOM. Default 5000 entries: a parsed-response object ~100 bytes ×
@@ -216,7 +216,7 @@ function create(opts) {
216
216
 
217
217
  var cache = new Map(); // key → { response, parsed, ttl, expiresAt, staleUntil }
218
218
 
219
- // CWE-400/770 / BUG-1 — LRU eviction on insert when the cache is at
219
+ // CWE-400/770. LRU eviction on insert when the cache is at
220
220
  // capacity. v8 Map preserves insertion order; oldest key is the
221
221
  // first entry returned by Map.keys().next().
222
222
  function _evictIfFull() {
@@ -39,8 +39,7 @@ var STATE = {
39
39
  // Default-on secure DNS (DoH via Cloudflare) when neither doh nor dot
40
40
  // is operator-configured AND no opt-out env var is set. Operators
41
41
  // who explicitly want the system resolver call useSystemResolver()
42
- // or set BLAMEJS_DNS_TRANSPORT=system. Default-on per Core Rule §3
43
- // ("security defaults are not opt-in").
42
+ // or set BLAMEJS_DNS_TRANSPORT=system. Default-on (security defaults are not opt-in).
44
43
  systemResolver: false,
45
44
  };
46
45
 
@@ -293,7 +293,7 @@ function verifyRrset(opts) {
293
293
  } else {
294
294
  atMs = Date.now();
295
295
  }
296
- var nowSec = Math.floor(atMs / 1000); // allow:raw-time-literal — ms→NumericDate seconds (RRSIG inception/expiration are seconds since epoch, RFC 4034 §3.1.5)
296
+ var nowSec = Math.floor(atMs / 1000);
297
297
  if (nowSec < (rrsig.inception >>> 0)) throw new DnssecError("dnssec/not-yet-valid", "dnssec.verifyRrset: RRSIG inception is in the future");
298
298
  if (nowSec > (rrsig.expiration >>> 0)) throw new DnssecError("dnssec/expired", "dnssec.verifyRrset: RRSIG has expired");
299
299
 
@@ -349,7 +349,7 @@ var BASE32HEX = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; // RFC 4648 §7 ext
349
349
  var TYPE_DS = 43; // IANA RR type DS
350
350
  var TYPE_CNAME = 5;
351
351
  var NSEC3_HASH_SHA1 = 1; // RFC 5155 §5 — the only registered NSEC3 hash
352
- var DEFAULT_MAX_NSEC3_ITERATIONS = 150; // allow:raw-time-literal — DoS ceiling on iterated SHA-1; matches BIND 9.16.33+/Unbound 1.17.1 post-CVE-2023-50868 (RFC 9276 wants 0; deployed zones still use >0)
352
+ var DEFAULT_MAX_NSEC3_ITERATIONS = 150;
353
353
 
354
354
  // KeyTrap (CVE-2023-50387) amplification caps. A hostile zone can publish
355
355
  // many DNSKEYs sharing one 16-bit key tag and many RRSIGs, forcing a
@@ -716,7 +716,7 @@ async function tlsRptSubmit(report, opts) {
716
716
  // tlsRpt.recordShape / tlsRpt.submit on the send side.
717
717
 
718
718
  var TLS_RPT_MAX_REPORT_BYTES = C.BYTES.mib(8);
719
- var TLS_RPT_MAX_POLICIES_PER_REPORT = 1024; // allow:raw-time-literal — count cap, not seconds
719
+ var TLS_RPT_MAX_POLICIES_PER_REPORT = 1024;
720
720
 
721
721
  function tlsRptParseReport(body, opts) {
722
722
  opts = opts || {};
@@ -837,7 +837,7 @@ function _parseTime(node) {
837
837
  if (s.length === 13 && s.charAt(12) === "Z") { // UTCTime length per X.690
838
838
  // UTCTime YYMMDDhhmmssZ — 50+ → 19xx, else 20xx (RFC 5280 §4.1.2.5).
839
839
  year = parseInt(s.slice(0, 2), 10);
840
- year += year >= 50 ? 1900 : 2000; // allow:raw-time-literal — RFC 5280 century pivot, calendar years
840
+ year += year >= 50 ? 1900 : 2000;
841
841
  month = parseInt(s.slice(2, 4), 10);
842
842
  day = parseInt(s.slice(4, 6), 10);
843
843
  hour = parseInt(s.slice(6, 8), 10); // UTCTime hour-byte offsets
@@ -1136,7 +1136,6 @@ function evaluateOcspResponse(ocspDer, opts) {
1136
1136
  // length inputs but fast-paths on length mismatch; not security-
1137
1137
  // critical here (the OCSP response is CA-signed and signature
1138
1138
  // already verified) but matches the project discipline.
1139
- // (Audit 2026-05-11.)
1140
1139
  if (!bCrypto.timingSafeEqual(parsed.basic.nonce, opts.expectedNonce)) {
1141
1140
  return { ok: false, status: parsed.status, signatureValid: true,
1142
1141
  errors: ["OCSP nonce mismatch — possible replay or wrong responder"] };
@@ -41,7 +41,7 @@ var TsigError = defineClass("TsigError", { alwaysPermanent: true });
41
41
 
42
42
  var TYPE_TSIG = 250; // IANA RR type TSIG
43
43
  var CLASS_ANY = 255; // TSIG RRs use CLASS ANY
44
- var DEFAULT_FUDGE = 300; // allow:raw-time-literal — RFC 8945 recommended fudge window (seconds)
44
+ var DEFAULT_FUDGE = 300;
45
45
 
46
46
  // Algorithm name → Node hash. The strong HMAC-SHA-2 family is the safe set;
47
47
  // HMAC-MD5 and HMAC-SHA-1 are refused unless allowLegacy (kept only for
@@ -225,7 +225,7 @@ function sign(message, opts) {
225
225
  var secret = _secretBuf(opts.secret);
226
226
  var fudge = opts.fudge == null ? DEFAULT_FUDGE : opts.fudge;
227
227
  if (typeof fudge !== "number" || !isFinite(fudge) || fudge < 0 || fudge > 0xffff) throw new TsigError("tsig/bad-opt", "tsig.sign: fudge must be 0..65535 seconds"); // 16-bit fudge field
228
- var time = opts.time == null ? Math.floor(Date.now() / 1000) : opts.time; // allow:raw-time-literal — ms→s
228
+ var time = opts.time == null ? Math.floor(Date.now() / 1000) : opts.time;
229
229
  if (typeof time !== "number" || !isFinite(time) || time < 0) throw new TsigError("tsig/bad-opt", "tsig.sign: time must be a non-negative Unix-seconds number");
230
230
  var error = opts.error == null ? 0 : opts.error;
231
231
  var otherData = Buffer.isBuffer(opts.otherData) ? opts.otherData : Buffer.alloc(0);
@@ -379,7 +379,7 @@ function verify(message, opts) {
379
379
  macValid = timingSafeEqual(rr.mac, expected.slice(0, rr.mac.length));
380
380
  }
381
381
 
382
- var now = opts.now == null ? Math.floor(Date.now() / 1000) : opts.now; // allow:raw-time-literal — ms→s
382
+ var now = opts.now == null ? Math.floor(Date.now() / 1000) : opts.now;
383
383
  var timeValid = Math.abs(now - rr.timeSigned) <= rr.fudge;
384
384
 
385
385
  var reason = null;
package/lib/outbox.js CHANGED
@@ -342,7 +342,7 @@ function create(opts) {
342
342
  var stopping = false;
343
343
  var inFlight = null;
344
344
 
345
- // SUBSTRATE-23 — `FOR UPDATE SKIP LOCKED` is Postgres / MySQL 8+ only.
345
+ // `FOR UPDATE SKIP LOCKED` is Postgres / MySQL 8+ only.
346
346
  // SQLite (single-writer at the DB level, but WAL mode lets multiple
347
347
  // processes share the file with concurrent SELECTs) doesn't support
348
348
  // SKIP LOCKED — feeding it Postgres syntax silently double-publishes
package/lib/pqc-agent.js CHANGED
@@ -322,7 +322,7 @@ function _getDefaultAgent() {
322
322
  * logger.info("pqc-agent reloaded", res);
323
323
  */
324
324
  function reload() {
325
- // CRYPTO-9 — null the cached agent BEFORE calling destroy. The
325
+ // Null the cached agent BEFORE calling destroy. The
326
326
  // previous order let a concurrent _getDefaultAgent() see the
327
327
  // destroyed-not-null agent and hand it to a caller; the caller
328
328
  // then tries to issue a request through a torn-down keep-alive
package/lib/retention.js CHANGED
@@ -569,7 +569,7 @@ function complianceFloor(posture, candidateTtlMs) {
569
569
  return candidateTtlMs > floor ? candidateTtlMs : floor;
570
570
  }
571
571
 
572
- // applyPosture — F-POSTURE-1 cascade hook. b.compliance.set(posture)
572
+ // applyPosture — cascade hook. b.compliance.set(posture)
573
573
  // calls this to merge posture defaults into retention's state. The
574
574
  // retention module itself doesn't carry per-instance global defaults;
575
575
  // the cascade's job here is to surface the posture's audit-log
package/lib/retry.js CHANGED
@@ -275,7 +275,7 @@ function backoffDelay(attempt, opts) {
275
275
  opts = opts || DEFAULT_RETRY;
276
276
  var base = opts.baseDelayMs * Math.pow(2, attempt - 1);
277
277
  var capped = Math.min(base, opts.maxDelayMs);
278
- // CRYPTO-12 — jitter exists to spread retry storms across the
278
+ // Jitter exists to spread retry storms across the
279
279
  // millisecond window so N peer clients waking from the same
280
280
  // upstream outage don't all hit the recovering service at the same
281
281
  // tick. The value is observable to every client by construction
package/lib/rfc3339.js CHANGED
@@ -25,11 +25,11 @@ function isValidDateTime(s) {
25
25
  if (!m) return false;
26
26
  var mo = +m[2], d = +m[3], h = +m[4], mi = +m[5], se = +m[6];
27
27
  if (mo < 1 || mo > 12 || d < 1 || d > 31 || h > 23 || mi > 59 || se > 60) return false; // allow:raw-time-literal — RFC 3339 field ranges (60 = leap second)
28
- var days = [31, ((+m[1] % 4 === 0 && +m[1] % 100 !== 0) || +m[1] % 400 === 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // allow:raw-time-literal — days per month (Gregorian)
28
+ var days = [31, ((+m[1] % 4 === 0 && +m[1] % 100 !== 0) || +m[1] % 400 === 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
29
29
  if (d > days[mo - 1]) return false;
30
30
  var tz = m[8];
31
31
  if (tz !== "Z" && tz !== "z") {
32
- if (+tz.slice(1, 3) > 23 || +tz.slice(4, 6) > 59) return false; // allow:raw-time-literal — RFC 3339 offset hour/minute ranges
32
+ if (+tz.slice(1, 3) > 23 || +tz.slice(4, 6) > 59) return false;
33
33
  }
34
34
  return true;
35
35
  }
@@ -225,7 +225,7 @@ async function extract(opts) {
225
225
  }
226
226
  inner = await archiveWrap().unwrapWithPassphrase(sealedBytes, { passphrase: opts.passphrase });
227
227
  }
228
- // Codex P1 on v0.12.15 PR #166 — close the original source
228
+ // Close the original source
229
229
  // adapter BEFORE replacing it. When opts.source was a string
230
230
  // path, the fs adapter opened a file descriptor; overwriting
231
231
  // `source` loses the close reference and the descriptor
@@ -236,7 +236,7 @@ async function extract(opts) {
236
236
  if (typeof source.close === "function" && typeof opts.source === "string") {
237
237
  try { source.close(); } catch (_e) { /* drop-silent */ }
238
238
  }
239
- // Codex P2 on v0.12.15 PR #166 — forward opts.signal to the
239
+ // Forward opts.signal to the
240
240
  // inner buffer adapter so abort propagation stays intact
241
241
  // across the unwrap boundary. Without it, an abort raised
242
242
  // after unwrapping would no longer cancel inner range()
@@ -105,7 +105,7 @@ var _algorithms = {
105
105
  // classic bomb shapes (1000:1) while leaving headroom for legitimate
106
106
  // text / JSON / XML payloads (which compress 20-50:1 commonly). Per
107
107
  // RFC 8460 §5.2 community guidance for TLS-RPT report decompression.
108
- var DEFAULT_MAX_RATIO = 50; // allow:raw-time-literal — RFC number not seconds
108
+ var DEFAULT_MAX_RATIO = 50;
109
109
 
110
110
  // Default input cap when operator omits opts.maxCompressedBytes —
111
111
  // 4 MiB matches the TLS-RPT receive surface and is a reasonable
package/lib/safe-ical.js CHANGED
@@ -251,9 +251,9 @@ function parse(text, opts) {
251
251
  var vcal = consumed.component;
252
252
  // RFC 5545 §3.4 — a stream may carry multiple VCALENDAR objects.
253
253
  // Walk the remainder so trailing objects are validated under the
254
- // same caps + control-char + property allowlist (Codex P2 — without
254
+ // same caps + control-char + property allowlist; without
255
255
  // this, CalDAV ingest can pass validation on the first object while
256
- // trailing malformed objects ride through untouched).
256
+ // trailing malformed objects ride through untouched.
257
257
  var vcalendars = [_shapeVcalendar(vcal)];
258
258
  var cursor = consumed.nextIdx;
259
259
  while (cursor < lines.length) {
package/lib/safe-mime.js CHANGED
@@ -549,7 +549,7 @@ function _splitMultipart(buf, boundary) {
549
549
  // Per RFC 2046 §5.1.1 a boundary delimiter is `--<value>` preceded
550
550
  // by CRLF (or LF) — OR at the very start of the body. A boundary-
551
551
  // shaped sequence elsewhere in a part's body MUST NOT be treated
552
- // as a delimiter. Per Codex P1 on PR #49.
552
+ // as a delimiter.
553
553
  var idx = _findBoundaryAtLineStart(buf, delimiter, pos);
554
554
  if (idx < 0) break;
555
555
  if (buf[idx + delimiter.length] === 0x2D && buf[idx + delimiter.length + 1] === 0x2D) {
@@ -208,7 +208,7 @@ function verify(assetPath, signaturePath, pubkeyPem) {
208
208
  // produces. 64 KiB chunks match the framework's hash-while-streaming
209
209
  // convention elsewhere.
210
210
  //
211
- // CRYPTO-2 hardening (v0.9.58): fstat the asset BEFORE the read loop
211
+ // Hardening (v0.9.58): fstat the asset BEFORE the read loop
212
212
  // for every alg path, clamp every readSync to (assetStat.size -
213
213
  // fullOff), and reject if the final fullOff diverges from
214
214
  // assetStat.size. A grow-during-read race (writer appends as we
@@ -115,7 +115,7 @@ function _normalizeTag(tag) {
115
115
  * Missing numeric components on either side are treated as `"0"` so
116
116
  * `"1.0"` and `"1.0.0"` compare equal.
117
117
  *
118
- * CRYPTO-20 (v0.9.58) — pre-v0.9.58 the pre-release segment fell back
118
+ * Hardening (v0.9.58) — pre-v0.9.58 the pre-release segment fell back
119
119
  * to lexicographic comparison, which silently misordered `"1.0.0-alpha.10"`
120
120
  * (the strict-§11 LARGER pre-release) and `"1.0.0-alpha.9"`: as strings
121
121
  * "10" < "9" so `alpha.10 < alpha.9`, and a downstream consumer polling
@@ -294,7 +294,7 @@ function _matchAsset(name, pattern, fallback) {
294
294
  * timeoutMs: number, // request timeout (default 15s)
295
295
  * headers: object, // additional request headers
296
296
  * etag: string, // last-seen etag for If-None-Match
297
- * // (CRYPTO-16 — etags are RFC 9110 §13.1.1
297
+ * // (etags are RFC 9110 §13.1.1
298
298
  * // per-resource; an etag captured for
299
299
  * // releasesUrl=A is meaningless against
300
300
  * // releasesUrl=B. Operators rotating