@blamejs/core 0.8.43 → 0.8.49

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 (222) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/README.md +10 -10
  3. package/index.js +52 -0
  4. package/lib/a2a.js +159 -34
  5. package/lib/acme.js +762 -0
  6. package/lib/ai-pref.js +166 -43
  7. package/lib/api-key.js +108 -47
  8. package/lib/api-snapshot.js +157 -40
  9. package/lib/app-shutdown.js +113 -77
  10. package/lib/archive.js +337 -40
  11. package/lib/arg-parser.js +697 -0
  12. package/lib/asyncapi.js +99 -55
  13. package/lib/atomic-file.js +465 -104
  14. package/lib/audit-chain.js +123 -34
  15. package/lib/audit-daily-review.js +389 -0
  16. package/lib/audit-sign.js +302 -56
  17. package/lib/audit-tools.js +412 -63
  18. package/lib/audit.js +656 -35
  19. package/lib/auth/jwt-external.js +17 -0
  20. package/lib/auth/oauth.js +7 -0
  21. package/lib/auth-bot-challenge.js +505 -0
  22. package/lib/auth-header.js +92 -25
  23. package/lib/backup/bundle.js +26 -0
  24. package/lib/backup/index.js +512 -89
  25. package/lib/backup/manifest.js +168 -7
  26. package/lib/break-glass.js +415 -39
  27. package/lib/budr.js +103 -30
  28. package/lib/bundler.js +86 -66
  29. package/lib/cache.js +192 -72
  30. package/lib/chain-writer.js +65 -40
  31. package/lib/circuit-breaker.js +56 -33
  32. package/lib/cli-helpers.js +106 -75
  33. package/lib/cli.js +6 -30
  34. package/lib/cloud-events.js +99 -32
  35. package/lib/cluster-storage.js +162 -37
  36. package/lib/cluster.js +340 -49
  37. package/lib/codepoint-class.js +66 -0
  38. package/lib/compliance.js +424 -24
  39. package/lib/config-drift.js +111 -46
  40. package/lib/config.js +94 -40
  41. package/lib/consent.js +165 -18
  42. package/lib/constants.js +1 -0
  43. package/lib/content-credentials.js +153 -48
  44. package/lib/cookies.js +154 -62
  45. package/lib/credential-hash.js +133 -61
  46. package/lib/crypto-field.js +702 -18
  47. package/lib/crypto-hpke.js +256 -0
  48. package/lib/crypto.js +744 -22
  49. package/lib/csv.js +178 -35
  50. package/lib/daemon.js +456 -0
  51. package/lib/dark-patterns.js +186 -55
  52. package/lib/db-query.js +79 -2
  53. package/lib/db.js +1431 -60
  54. package/lib/ddl-change-control.js +523 -0
  55. package/lib/deprecate.js +195 -40
  56. package/lib/dev.js +82 -39
  57. package/lib/dora.js +67 -48
  58. package/lib/dr-runbook.js +368 -0
  59. package/lib/dsr.js +142 -11
  60. package/lib/dual-control.js +91 -56
  61. package/lib/events.js +120 -41
  62. package/lib/external-db-migrate.js +192 -2
  63. package/lib/external-db.js +795 -50
  64. package/lib/fapi2.js +122 -1
  65. package/lib/fda-21cfr11.js +395 -0
  66. package/lib/fdx.js +132 -2
  67. package/lib/file-type.js +87 -0
  68. package/lib/file-upload.js +93 -0
  69. package/lib/flag.js +82 -20
  70. package/lib/forms.js +132 -29
  71. package/lib/framework-error.js +169 -0
  72. package/lib/framework-schema.js +163 -35
  73. package/lib/gate-contract.js +849 -175
  74. package/lib/graphql-federation.js +68 -7
  75. package/lib/guard-all.js +172 -55
  76. package/lib/guard-archive.js +286 -124
  77. package/lib/guard-auth.js +194 -21
  78. package/lib/guard-cidr.js +190 -28
  79. package/lib/guard-csv.js +397 -51
  80. package/lib/guard-domain.js +213 -91
  81. package/lib/guard-email.js +236 -29
  82. package/lib/guard-filename.js +307 -75
  83. package/lib/guard-graphql.js +263 -30
  84. package/lib/guard-html.js +310 -116
  85. package/lib/guard-image.js +243 -30
  86. package/lib/guard-json.js +260 -54
  87. package/lib/guard-jsonpath.js +235 -23
  88. package/lib/guard-jwt.js +284 -30
  89. package/lib/guard-markdown.js +204 -22
  90. package/lib/guard-mime.js +190 -26
  91. package/lib/guard-oauth.js +277 -28
  92. package/lib/guard-pdf.js +251 -27
  93. package/lib/guard-regex.js +226 -18
  94. package/lib/guard-shell.js +229 -26
  95. package/lib/guard-svg.js +177 -10
  96. package/lib/guard-template.js +232 -21
  97. package/lib/guard-time.js +195 -29
  98. package/lib/guard-uuid.js +189 -30
  99. package/lib/guard-xml.js +259 -36
  100. package/lib/guard-yaml.js +241 -44
  101. package/lib/honeytoken.js +63 -27
  102. package/lib/html-balance.js +83 -0
  103. package/lib/http-client.js +486 -59
  104. package/lib/http-message-signature.js +582 -0
  105. package/lib/i18n.js +102 -49
  106. package/lib/iab-mspa.js +112 -32
  107. package/lib/iab-tcf.js +107 -2
  108. package/lib/inbox.js +90 -52
  109. package/lib/keychain.js +865 -0
  110. package/lib/legal-hold.js +374 -0
  111. package/lib/local-db-thin.js +320 -0
  112. package/lib/log-stream.js +281 -51
  113. package/lib/log.js +184 -86
  114. package/lib/mail-bounce.js +107 -62
  115. package/lib/mail.js +295 -58
  116. package/lib/mcp.js +108 -27
  117. package/lib/metrics.js +98 -89
  118. package/lib/middleware/age-gate.js +36 -0
  119. package/lib/middleware/ai-act-disclosure.js +37 -0
  120. package/lib/middleware/api-encrypt.js +45 -0
  121. package/lib/middleware/assetlinks.js +40 -0
  122. package/lib/middleware/asyncapi-serve.js +35 -0
  123. package/lib/middleware/attach-user.js +40 -0
  124. package/lib/middleware/bearer-auth.js +40 -0
  125. package/lib/middleware/body-parser.js +230 -0
  126. package/lib/middleware/bot-disclose.js +34 -0
  127. package/lib/middleware/bot-guard.js +39 -0
  128. package/lib/middleware/compression.js +37 -0
  129. package/lib/middleware/cookies.js +32 -0
  130. package/lib/middleware/cors.js +40 -0
  131. package/lib/middleware/csp-nonce.js +40 -0
  132. package/lib/middleware/csp-report.js +34 -0
  133. package/lib/middleware/csrf-protect.js +43 -0
  134. package/lib/middleware/daily-byte-quota.js +53 -85
  135. package/lib/middleware/db-role-for.js +40 -0
  136. package/lib/middleware/dpop.js +40 -0
  137. package/lib/middleware/error-handler.js +37 -14
  138. package/lib/middleware/fetch-metadata.js +39 -0
  139. package/lib/middleware/flag-context.js +34 -0
  140. package/lib/middleware/gpc.js +33 -0
  141. package/lib/middleware/headers.js +35 -0
  142. package/lib/middleware/health.js +46 -0
  143. package/lib/middleware/host-allowlist.js +30 -0
  144. package/lib/middleware/network-allowlist.js +38 -0
  145. package/lib/middleware/openapi-serve.js +34 -0
  146. package/lib/middleware/rate-limit.js +160 -18
  147. package/lib/middleware/request-id.js +36 -18
  148. package/lib/middleware/request-log.js +37 -0
  149. package/lib/middleware/require-aal.js +29 -0
  150. package/lib/middleware/require-auth.js +32 -0
  151. package/lib/middleware/require-bound-key.js +41 -0
  152. package/lib/middleware/require-content-type.js +32 -0
  153. package/lib/middleware/require-methods.js +27 -0
  154. package/lib/middleware/require-mtls.js +33 -0
  155. package/lib/middleware/require-step-up.js +37 -0
  156. package/lib/middleware/security-headers.js +44 -0
  157. package/lib/middleware/security-txt.js +38 -0
  158. package/lib/middleware/span-http-server.js +37 -0
  159. package/lib/middleware/sse.js +36 -0
  160. package/lib/middleware/trace-log-correlation.js +33 -0
  161. package/lib/middleware/trace-propagate.js +32 -0
  162. package/lib/middleware/tus-upload.js +90 -0
  163. package/lib/middleware/web-app-manifest.js +53 -0
  164. package/lib/mtls-ca.js +100 -70
  165. package/lib/network-byte-quota.js +308 -0
  166. package/lib/network-heartbeat.js +135 -0
  167. package/lib/network-tls.js +534 -4
  168. package/lib/network.js +103 -0
  169. package/lib/notify.js +114 -43
  170. package/lib/ntp-check.js +192 -51
  171. package/lib/observability.js +145 -47
  172. package/lib/openapi.js +90 -44
  173. package/lib/outbox.js +99 -1
  174. package/lib/pagination.js +168 -86
  175. package/lib/parsers/index.js +16 -5
  176. package/lib/permissions.js +93 -40
  177. package/lib/pqc-agent.js +84 -8
  178. package/lib/pqc-software.js +94 -60
  179. package/lib/process-spawn.js +95 -21
  180. package/lib/pubsub.js +96 -66
  181. package/lib/queue.js +375 -54
  182. package/lib/redact.js +793 -21
  183. package/lib/render.js +139 -47
  184. package/lib/request-helpers.js +485 -121
  185. package/lib/restore-bundle.js +142 -39
  186. package/lib/restore-rollback.js +136 -45
  187. package/lib/retention.js +178 -50
  188. package/lib/retry.js +116 -33
  189. package/lib/router.js +475 -23
  190. package/lib/safe-async.js +543 -94
  191. package/lib/safe-buffer.js +337 -41
  192. package/lib/safe-json.js +467 -62
  193. package/lib/safe-jsonpath.js +285 -0
  194. package/lib/safe-schema.js +631 -87
  195. package/lib/safe-sql.js +221 -59
  196. package/lib/safe-url.js +278 -46
  197. package/lib/sandbox-worker.js +135 -0
  198. package/lib/sandbox.js +358 -0
  199. package/lib/scheduler.js +135 -70
  200. package/lib/self-update.js +647 -0
  201. package/lib/session-device-binding.js +431 -0
  202. package/lib/session.js +259 -49
  203. package/lib/slug.js +138 -26
  204. package/lib/ssrf-guard.js +316 -56
  205. package/lib/storage.js +433 -70
  206. package/lib/subject.js +405 -23
  207. package/lib/template.js +148 -8
  208. package/lib/tenant-quota.js +545 -0
  209. package/lib/testing.js +440 -53
  210. package/lib/time.js +291 -23
  211. package/lib/tls-exporter.js +239 -0
  212. package/lib/tracing.js +90 -74
  213. package/lib/uuid.js +97 -22
  214. package/lib/vault/index.js +284 -22
  215. package/lib/vault/seal-pem-file.js +66 -0
  216. package/lib/watcher.js +368 -0
  217. package/lib/webhook.js +196 -63
  218. package/lib/websocket.js +393 -68
  219. package/lib/wiki-concepts.js +338 -0
  220. package/lib/worker-pool.js +464 -0
  221. package/package.json +3 -3
  222. package/sbom.cyclonedx.json +7 -7
@@ -69,10 +69,16 @@
69
69
  */
70
70
 
71
71
  var C = require("../constants");
72
+ var lazyRequire = require("../lazy-require");
72
73
  var safeBuffer = require("../safe-buffer");
73
74
  var safeJson = require("../safe-json");
74
75
  var { FrameworkError } = require("../framework-error");
75
76
 
77
+ // audit-sign is loaded lazily — manifest.js is consumed by both the
78
+ // backup writer (which has audit-sign initialized) and read-only
79
+ // inspectors (CLI / verifier) where audit-sign may not be wired.
80
+ var auditSign = lazyRequire(function () { return require("../audit-sign"); });
81
+
76
82
  class BackupManifestError extends FrameworkError {
77
83
  constructor(code, message) {
78
84
  super(message, code);
@@ -189,6 +195,31 @@ function validate(manifest) {
189
195
  (manifest.metadata === null || typeof manifest.metadata !== "object" || Array.isArray(manifest.metadata))) {
190
196
  errors.push("metadata: must be a plain object when present");
191
197
  }
198
+ // Optional signature block. When present, every sub-field is
199
+ // required — partial signatures are a smell (operators saw an
200
+ // unsigned bundle and tried to hand-edit a signature in).
201
+ if (manifest.signature !== undefined) {
202
+ if (manifest.signature === null || typeof manifest.signature !== "object" ||
203
+ Array.isArray(manifest.signature)) {
204
+ errors.push("signature: must be a plain object when present");
205
+ } else {
206
+ if (typeof manifest.signature.algorithm !== "string" || manifest.signature.algorithm.length === 0) {
207
+ errors.push("signature.algorithm: required non-empty string");
208
+ }
209
+ if (typeof manifest.signature.publicKey !== "string" || manifest.signature.publicKey.length === 0) {
210
+ errors.push("signature.publicKey: required non-empty string");
211
+ }
212
+ if (typeof manifest.signature.fingerprint !== "string" || manifest.signature.fingerprint.length === 0) {
213
+ errors.push("signature.fingerprint: required non-empty string");
214
+ }
215
+ if (!_isBase64(manifest.signature.value)) {
216
+ errors.push("signature.value: required base64 string");
217
+ }
218
+ if (!_isIso8601(manifest.signature.signedAt)) {
219
+ errors.push("signature.signedAt: required ISO-8601 timestamp string");
220
+ }
221
+ }
222
+ }
192
223
  return { ok: errors.length === 0, errors: errors };
193
224
  }
194
225
 
@@ -216,12 +247,7 @@ function create(opts) {
216
247
  return manifest;
217
248
  }
218
249
 
219
- function serialize(manifest) {
220
- var v = validate(manifest);
221
- if (!v.ok) {
222
- throw new BackupManifestError("backup-manifest/invalid",
223
- "serialize: " + v.errors.join("; "));
224
- }
250
+ function _canonical(manifest, includeSignature) {
225
251
  // Stable key ordering so the same manifest object always serializes
226
252
  // to the same bytes (operators can hash the manifest as part of
227
253
  // bundle-integrity logging without surprises across runs).
@@ -245,7 +271,139 @@ function serialize(manifest) {
245
271
  }),
246
272
  };
247
273
  if (manifest.metadata) canonical.metadata = manifest.metadata;
248
- return JSON.stringify(canonical, null, 2) + "\n";
274
+ // Signature block lives alongside the rest of the manifest fields
275
+ // and is itself stable-ordered. Sign-time canonicalization (the
276
+ // bytes the audit-sign keypair signs) excludes the signature field
277
+ // so the signature can be appended without altering the signed
278
+ // payload.
279
+ if (includeSignature && manifest.signature) {
280
+ canonical.signature = {
281
+ algorithm: manifest.signature.algorithm,
282
+ publicKey: manifest.signature.publicKey,
283
+ fingerprint: manifest.signature.fingerprint,
284
+ value: manifest.signature.value,
285
+ signedAt: manifest.signature.signedAt,
286
+ };
287
+ }
288
+ return canonical;
289
+ }
290
+
291
+ // The canonical payload the audit-sign keypair signs over — the
292
+ // manifest serialized without its `signature` field. Exposed so
293
+ // verifiers can recompute the exact bytes that produced the signature.
294
+ function signingPayload(manifest) {
295
+ return JSON.stringify(_canonical(manifest, false), null, 2) + "\n";
296
+ }
297
+
298
+ function serialize(manifest) {
299
+ var v = validate(manifest);
300
+ if (!v.ok) {
301
+ throw new BackupManifestError("backup-manifest/invalid",
302
+ "serialize: " + v.errors.join("; "));
303
+ }
304
+ return JSON.stringify(_canonical(manifest, true), null, 2) + "\n";
305
+ }
306
+
307
+ // Sign the manifest in-place via the audit-sign keypair (ML-DSA-87
308
+ // or SLH-DSA-SHAKE-256f — whichever audit-sign was initialized with).
309
+ // The signature covers the manifest's canonical bytes WITHOUT the
310
+ // signature field; appending it does not change the signed payload.
311
+ function sign(manifest) {
312
+ var v = validate(manifest);
313
+ if (!v.ok) {
314
+ throw new BackupManifestError("backup-manifest/invalid",
315
+ "sign: " + v.errors.join("; "));
316
+ }
317
+ var signer = auditSign();
318
+ if (!signer || typeof signer.sign !== "function") {
319
+ throw new BackupManifestError("backup-manifest/no-signer",
320
+ "sign: audit-sign module is not available; call b.auditSign.init() first");
321
+ }
322
+ var payload = signingPayload(manifest);
323
+ var signatureBytes;
324
+ try { signatureBytes = signer.sign(payload); }
325
+ catch (e) {
326
+ throw new BackupManifestError("backup-manifest/sign-failed",
327
+ "sign: audit-sign.sign threw: " + ((e && e.message) || String(e)));
328
+ }
329
+ manifest.signature = {
330
+ algorithm: signer.getAlgorithm(),
331
+ publicKey: signer.getPublicKey(),
332
+ fingerprint: signer.getPublicKeyFingerprint(),
333
+ value: signatureBytes.toString("base64"),
334
+ signedAt: new Date().toISOString(),
335
+ };
336
+ return manifest;
337
+ }
338
+
339
+ // Verify a previously-signed manifest. Returns { ok, reason?,
340
+ // fingerprint? }. Caller policy decides whether a missing or
341
+ // fingerprint-mismatched signature is fatal — verifyManifestSignature
342
+ // in lib/backup/index.js wraps this with operator-facing semantics.
343
+ function verifySignature(manifest, opts) {
344
+ opts = opts || {};
345
+ if (!manifest || typeof manifest !== "object") {
346
+ return { ok: false, reason: "manifest must be an object" };
347
+ }
348
+ if (!manifest.signature || typeof manifest.signature !== "object") {
349
+ return { ok: false, reason: "manifest has no signature block" };
350
+ }
351
+ var sig = manifest.signature;
352
+ if (typeof sig.algorithm !== "string" || sig.algorithm.length === 0) {
353
+ return { ok: false, reason: "signature.algorithm is required" };
354
+ }
355
+ if (typeof sig.publicKey !== "string" || sig.publicKey.length === 0) {
356
+ return { ok: false, reason: "signature.publicKey is required" };
357
+ }
358
+ if (typeof sig.value !== "string" || sig.value.length === 0) {
359
+ return { ok: false, reason: "signature.value is required" };
360
+ }
361
+ // Caller may pin the expected fingerprint — operators tracking key
362
+ // rotation pass the active audit-sign fingerprint and refuse any
363
+ // bundle signed under a different historical key.
364
+ if (typeof opts.expectedFingerprint === "string" &&
365
+ opts.expectedFingerprint.length > 0 &&
366
+ sig.fingerprint !== opts.expectedFingerprint) {
367
+ return {
368
+ ok: false,
369
+ reason: "signature.fingerprint=" + sig.fingerprint +
370
+ " does not match expectedFingerprint=" + opts.expectedFingerprint,
371
+ fingerprint: sig.fingerprint,
372
+ };
373
+ }
374
+ var payload = signingPayload(manifest);
375
+ var sigBuf;
376
+ try { sigBuf = Buffer.from(sig.value, "base64"); }
377
+ catch (_e) {
378
+ return { ok: false, reason: "signature.value is not valid base64" };
379
+ }
380
+ // Use audit-sign.verify when available (handles algorithm dispatch
381
+ // identically to the signer); fall back to nodeCrypto.verify for
382
+ // verifier processes that don't init audit-sign.
383
+ var ok;
384
+ try {
385
+ var signer = auditSign();
386
+ if (signer && typeof signer.verify === "function") {
387
+ ok = signer.verify(payload, sigBuf, sig.publicKey);
388
+ } else {
389
+ ok = require("node:crypto").verify(null,
390
+ Buffer.from(payload, "utf8"), sig.publicKey, sigBuf);
391
+ }
392
+ } catch (e) {
393
+ return {
394
+ ok: false,
395
+ reason: "verify threw: " + ((e && e.message) || String(e)),
396
+ fingerprint: sig.fingerprint,
397
+ };
398
+ }
399
+ if (!ok) {
400
+ return {
401
+ ok: false,
402
+ reason: "signature did not verify under provided publicKey",
403
+ fingerprint: sig.fingerprint,
404
+ };
405
+ }
406
+ return { ok: true, fingerprint: sig.fingerprint };
249
407
  }
250
408
 
251
409
  function parse(jsonStr) {
@@ -275,6 +433,9 @@ module.exports = {
275
433
  validate: validate,
276
434
  serialize: serialize,
277
435
  parse: parse,
436
+ sign: sign,
437
+ signingPayload: signingPayload,
438
+ verifySignature: verifySignature,
278
439
  FORMAT_VERSION: FORMAT_VERSION,
279
440
  FRAMEWORK_NAME: FRAMEWORK_NAME,
280
441
  VALID_KINDS: VALID_KINDS,