@blamejs/core 0.15.12 → 0.15.14

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 (365) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/index.js +2 -0
  3. package/lib/a2a-tasks.js +45 -29
  4. package/lib/acme.js +6 -5
  5. package/lib/agent-event-bus.js +18 -4
  6. package/lib/agent-idempotency.js +7 -6
  7. package/lib/agent-orchestrator.js +2 -5
  8. package/lib/agent-saga.js +3 -5
  9. package/lib/agent-snapshot.js +32 -2
  10. package/lib/agent-tenant.js +2 -5
  11. package/lib/ai-adverse-decision.js +2 -15
  12. package/lib/ai-aedt-bias-audit.js +2 -1
  13. package/lib/ai-capability.js +1 -6
  14. package/lib/ai-content-detect.js +1 -3
  15. package/lib/ai-dp.js +1 -5
  16. package/lib/ai-frontier-protocol.js +1 -1
  17. package/lib/ai-input.js +2 -2
  18. package/lib/ai-model-manifest.js +1 -1
  19. package/lib/ai-output.js +16 -7
  20. package/lib/ai-pref.js +3 -8
  21. package/lib/ai-quota.js +3 -14
  22. package/lib/api-key.js +37 -28
  23. package/lib/api-snapshot.js +4 -1
  24. package/lib/app-shutdown.js +7 -1
  25. package/lib/archive-adapters.js +2 -4
  26. package/lib/archive-entry-policy.js +32 -0
  27. package/lib/archive-gz.js +9 -0
  28. package/lib/archive-read.js +14 -24
  29. package/lib/archive-tar-read.js +56 -24
  30. package/lib/archive.js +6 -12
  31. package/lib/arg-parser.js +7 -6
  32. package/lib/asn1-der.js +70 -22
  33. package/lib/asyncapi-traits.js +2 -6
  34. package/lib/atomic-file.js +312 -33
  35. package/lib/audit-chain.js +183 -54
  36. package/lib/audit-daily-review.js +36 -16
  37. package/lib/audit-emit.js +82 -0
  38. package/lib/audit-sign.js +258 -0
  39. package/lib/audit-tools.js +108 -23
  40. package/lib/audit.js +91 -2
  41. package/lib/auth/access-lock.js +7 -29
  42. package/lib/auth/bot-challenge.js +1 -1
  43. package/lib/auth/ciba.js +43 -4
  44. package/lib/auth/dpop.js +29 -36
  45. package/lib/auth/fido-mds3.js +14 -16
  46. package/lib/auth/jwt-external.js +26 -8
  47. package/lib/auth/jwt.js +15 -17
  48. package/lib/auth/lockout.js +24 -27
  49. package/lib/auth/oauth.js +67 -45
  50. package/lib/auth/oid4vci.js +55 -32
  51. package/lib/auth/oid4vp.js +3 -2
  52. package/lib/auth/openid-federation.js +6 -6
  53. package/lib/auth/passkey.js +4 -4
  54. package/lib/auth/password.js +8 -2
  55. package/lib/auth/saml.js +70 -40
  56. package/lib/auth/sd-jwt-vc-holder.js +2 -14
  57. package/lib/auth/sd-jwt-vc-issuer.js +2 -14
  58. package/lib/auth/sd-jwt-vc.js +25 -5
  59. package/lib/auth/status-list.js +21 -9
  60. package/lib/auth/step-up.js +15 -13
  61. package/lib/auth-bot-challenge.js +27 -39
  62. package/lib/backup/bundle.js +18 -20
  63. package/lib/backup/crypto.js +23 -8
  64. package/lib/backup/index.js +55 -67
  65. package/lib/backup/manifest.js +7 -1
  66. package/lib/bounded-map.js +112 -1
  67. package/lib/breach-deadline.js +1 -11
  68. package/lib/break-glass.js +41 -22
  69. package/lib/cache.js +7 -18
  70. package/lib/cbor.js +36 -12
  71. package/lib/cdn-cache-control.js +15 -12
  72. package/lib/cert.js +8 -13
  73. package/lib/chain-writer.js +162 -47
  74. package/lib/cli.js +10 -2
  75. package/lib/client-hints.js +7 -9
  76. package/lib/cloud-events.js +43 -33
  77. package/lib/cluster-storage.js +9 -41
  78. package/lib/cms-codec.js +2 -1
  79. package/lib/codepoint-class.js +84 -1
  80. package/lib/compliance-ai-act-logging.js +1 -6
  81. package/lib/compliance-ai-act-transparency.js +2 -4
  82. package/lib/compliance-eaa.js +2 -12
  83. package/lib/compliance-sanctions-fetcher.js +21 -28
  84. package/lib/compliance-sanctions.js +11 -21
  85. package/lib/compliance.js +3 -10
  86. package/lib/config-drift.js +24 -20
  87. package/lib/content-credentials.js +11 -8
  88. package/lib/content-digest.js +21 -12
  89. package/lib/cookies.js +15 -13
  90. package/lib/cose.js +39 -11
  91. package/lib/cra-report.js +1 -11
  92. package/lib/crdt.js +2 -1
  93. package/lib/crypto-field.js +34 -33
  94. package/lib/crypto.js +138 -7
  95. package/lib/csp.js +239 -3
  96. package/lib/daemon.js +46 -42
  97. package/lib/data-act.js +46 -13
  98. package/lib/db-file-lifecycle.js +14 -6
  99. package/lib/db-query.js +75 -49
  100. package/lib/db.js +66 -27
  101. package/lib/dbsc.js +5 -6
  102. package/lib/ddl-change-control.js +18 -14
  103. package/lib/deprecate.js +4 -5
  104. package/lib/did.js +6 -2
  105. package/lib/dora.js +43 -13
  106. package/lib/dr-runbook.js +1 -1
  107. package/lib/dsa.js +2 -1
  108. package/lib/dsr.js +30 -20
  109. package/lib/early-hints.js +19 -0
  110. package/lib/eat.js +5 -1
  111. package/lib/external-db-migrate.js +21 -22
  112. package/lib/external-db.js +74 -30
  113. package/lib/fda-21cfr11.js +42 -13
  114. package/lib/fdx.js +22 -18
  115. package/lib/file-upload.js +80 -66
  116. package/lib/flag-evaluation-context.js +5 -8
  117. package/lib/flag-providers.js +6 -2
  118. package/lib/forms.js +1 -1
  119. package/lib/framework-error.js +12 -0
  120. package/lib/framework-schema.js +19 -0
  121. package/lib/fsm.js +7 -12
  122. package/lib/gate-contract.js +911 -39
  123. package/lib/gdpr-ropa.js +22 -22
  124. package/lib/graphql-federation.js +18 -5
  125. package/lib/guard-agent-registry.js +2 -1
  126. package/lib/guard-all.js +3 -2
  127. package/lib/guard-archive.js +9 -30
  128. package/lib/guard-auth.js +23 -80
  129. package/lib/guard-cidr.js +20 -96
  130. package/lib/guard-csv.js +135 -196
  131. package/lib/guard-domain.js +23 -106
  132. package/lib/guard-dsn.js +17 -14
  133. package/lib/guard-email.js +46 -53
  134. package/lib/guard-envelope.js +2 -2
  135. package/lib/guard-event-bus-topic.js +2 -1
  136. package/lib/guard-filename.js +12 -60
  137. package/lib/guard-graphql.js +28 -75
  138. package/lib/guard-html-wcag.js +15 -2
  139. package/lib/guard-html.js +74 -128
  140. package/lib/guard-idempotency-key.js +2 -1
  141. package/lib/guard-image.js +280 -77
  142. package/lib/guard-imap-command.js +9 -10
  143. package/lib/guard-jmap.js +1 -1
  144. package/lib/guard-json.js +101 -109
  145. package/lib/guard-jsonpath.js +20 -88
  146. package/lib/guard-jwt.js +32 -114
  147. package/lib/guard-list-id.js +2 -7
  148. package/lib/guard-list-unsubscribe.js +2 -7
  149. package/lib/guard-mail-compose.js +5 -6
  150. package/lib/guard-mail-move.js +3 -2
  151. package/lib/guard-mail-query.js +5 -3
  152. package/lib/guard-mail-sieve.js +6 -7
  153. package/lib/guard-managesieve-command.js +6 -5
  154. package/lib/guard-markdown.js +76 -110
  155. package/lib/guard-message-id.js +5 -6
  156. package/lib/guard-mime.js +20 -99
  157. package/lib/guard-oauth.js +19 -73
  158. package/lib/guard-pdf.js +65 -72
  159. package/lib/guard-pop3-command.js +13 -14
  160. package/lib/guard-posture-chain.js +2 -1
  161. package/lib/guard-regex.js +24 -99
  162. package/lib/guard-saga-config.js +2 -1
  163. package/lib/guard-shell.js +22 -87
  164. package/lib/guard-smtp-command.js +9 -12
  165. package/lib/guard-sql.js +15 -13
  166. package/lib/guard-stream-args.js +2 -1
  167. package/lib/guard-svg.js +103 -149
  168. package/lib/guard-template.js +23 -80
  169. package/lib/guard-tenant-id.js +2 -1
  170. package/lib/guard-text.js +592 -0
  171. package/lib/guard-time.js +27 -95
  172. package/lib/guard-uuid.js +21 -93
  173. package/lib/guard-xml.js +76 -106
  174. package/lib/guard-yaml.js +24 -60
  175. package/lib/html-balance.js +7 -3
  176. package/lib/http-client-cache.js +5 -12
  177. package/lib/http-client-cookie-jar.js +35 -16
  178. package/lib/http-client.js +233 -74
  179. package/lib/http-message-signature.js +3 -2
  180. package/lib/i18n-messageformat.js +5 -7
  181. package/lib/i18n.js +83 -26
  182. package/lib/iab-tcf.js +3 -2
  183. package/lib/importmap-integrity.js +41 -1
  184. package/lib/inbox.js +8 -8
  185. package/lib/incident-report.js +12 -27
  186. package/lib/ip-utils.js +49 -6
  187. package/lib/jobs.js +3 -2
  188. package/lib/json-patch.js +1 -1
  189. package/lib/json-path.js +24 -3
  190. package/lib/jtd.js +2 -2
  191. package/lib/keychain.js +6 -18
  192. package/lib/legal-hold.js +30 -23
  193. package/lib/log-stream-cloudwatch.js +44 -112
  194. package/lib/log-stream-otlp-grpc.js +17 -14
  195. package/lib/log-stream-otlp.js +16 -80
  196. package/lib/log-stream-webhook.js +20 -92
  197. package/lib/log.js +2 -2
  198. package/lib/mail-agent.js +2 -2
  199. package/lib/mail-arc-sign.js +8 -3
  200. package/lib/mail-arf.js +4 -3
  201. package/lib/mail-auth.js +43 -69
  202. package/lib/mail-bimi.js +35 -55
  203. package/lib/mail-bounce.js +3 -3
  204. package/lib/mail-crypto-pgp.js +3 -2
  205. package/lib/mail-crypto-smime.js +71 -6
  206. package/lib/mail-dav.js +8 -35
  207. package/lib/mail-deploy.js +15 -14
  208. package/lib/mail-dkim.js +19 -38
  209. package/lib/mail-greylist.js +17 -30
  210. package/lib/mail-helo.js +4 -7
  211. package/lib/mail-journal.js +13 -9
  212. package/lib/mail-mdn.js +12 -7
  213. package/lib/mail-rbl.js +7 -12
  214. package/lib/mail-scan.js +5 -7
  215. package/lib/mail-send-deliver.js +33 -20
  216. package/lib/mail-server-imap.js +32 -87
  217. package/lib/mail-server-jmap.js +39 -52
  218. package/lib/mail-server-managesieve.js +29 -83
  219. package/lib/mail-server-mx.js +33 -74
  220. package/lib/mail-server-net.js +177 -0
  221. package/lib/mail-server-pop3.js +30 -83
  222. package/lib/mail-server-rate-limit.js +30 -6
  223. package/lib/mail-server-registry.js +1 -1
  224. package/lib/mail-server-submission.js +34 -73
  225. package/lib/mail-server-tls.js +98 -2
  226. package/lib/mail-spam-score.js +9 -12
  227. package/lib/mail-store-fts.js +1 -1
  228. package/lib/mail-store.js +3 -2
  229. package/lib/mail.js +28 -13
  230. package/lib/markup-escape.js +31 -0
  231. package/lib/markup-tokenizer.js +78 -0
  232. package/lib/mcp-tool-registry.js +26 -23
  233. package/lib/mcp.js +7 -5
  234. package/lib/mdoc.js +36 -14
  235. package/lib/metrics.js +46 -33
  236. package/lib/middleware/age-gate.js +3 -23
  237. package/lib/middleware/api-encrypt.js +13 -24
  238. package/lib/middleware/assetlinks.js +2 -7
  239. package/lib/middleware/bearer-auth.js +2 -1
  240. package/lib/middleware/body-parser.js +41 -52
  241. package/lib/middleware/bot-disclose.js +7 -10
  242. package/lib/middleware/bot-guard.js +28 -28
  243. package/lib/middleware/clear-site-data.js +5 -1
  244. package/lib/middleware/compression.js +9 -0
  245. package/lib/middleware/cors.js +32 -23
  246. package/lib/middleware/csrf-protect.js +73 -23
  247. package/lib/middleware/daily-byte-quota.js +12 -30
  248. package/lib/middleware/deny-response.js +19 -1
  249. package/lib/middleware/fetch-metadata.js +35 -4
  250. package/lib/middleware/idempotency-key.js +4 -20
  251. package/lib/middleware/network-allowlist.js +61 -30
  252. package/lib/middleware/rate-limit.js +45 -44
  253. package/lib/middleware/scim-server.js +5 -3
  254. package/lib/middleware/security-headers.js +33 -7
  255. package/lib/middleware/security-txt.js +2 -6
  256. package/lib/middleware/speculation-rules.js +6 -3
  257. package/lib/middleware/tus-upload.js +14 -29
  258. package/lib/middleware/web-app-manifest.js +2 -7
  259. package/lib/migrations.js +4 -13
  260. package/lib/mime-parse.js +34 -17
  261. package/lib/module-loader.js +44 -0
  262. package/lib/money.js +105 -0
  263. package/lib/mtls-ca.js +125 -41
  264. package/lib/network-byte-quota.js +4 -18
  265. package/lib/network-dane.js +8 -6
  266. package/lib/network-dns-resolver.js +98 -7
  267. package/lib/network-dns.js +9 -2
  268. package/lib/network-dnssec.js +18 -17
  269. package/lib/network-heartbeat.js +3 -2
  270. package/lib/network-smtp-policy.js +52 -46
  271. package/lib/network-tls.js +67 -47
  272. package/lib/network-tsig.js +2 -2
  273. package/lib/nis2-report.js +2 -12
  274. package/lib/nist-crosswalk.js +1 -1
  275. package/lib/nonce-store.js +81 -3
  276. package/lib/ntp-check.js +28 -0
  277. package/lib/numeric-bounds.js +31 -8
  278. package/lib/object-store/azure-blob-bucket-ops.js +2 -6
  279. package/lib/object-store/azure-blob.js +6 -47
  280. package/lib/object-store/gcs-bucket-ops.js +4 -2
  281. package/lib/object-store/gcs.js +14 -75
  282. package/lib/object-store/http-put.js +2 -7
  283. package/lib/object-store/http-request.js +157 -0
  284. package/lib/object-store/local.js +37 -17
  285. package/lib/object-store/sigv4-bucket-ops.js +2 -1
  286. package/lib/object-store/sigv4.js +10 -79
  287. package/lib/observability-otlp-exporter.js +29 -29
  288. package/lib/observability.js +95 -0
  289. package/lib/openapi-paths-builder.js +7 -3
  290. package/lib/otel-export.js +7 -10
  291. package/lib/outbox.js +54 -41
  292. package/lib/pagination.js +11 -15
  293. package/lib/parsers/safe-env.js +5 -4
  294. package/lib/parsers/safe-ini.js +10 -4
  295. package/lib/parsers/safe-toml.js +11 -9
  296. package/lib/parsers/safe-xml.js +3 -3
  297. package/lib/parsers/safe-yaml.js +28 -9
  298. package/lib/pick.js +63 -5
  299. package/lib/pipl-cn.js +69 -59
  300. package/lib/privacy-pass.js +8 -6
  301. package/lib/problem-details.js +2 -5
  302. package/lib/pubsub.js +4 -8
  303. package/lib/queue-local.js +10 -3
  304. package/lib/redact.js +9 -4
  305. package/lib/render.js +4 -2
  306. package/lib/request-helpers.js +334 -29
  307. package/lib/resource-access-lock.js +3 -3
  308. package/lib/restore-bundle.js +46 -18
  309. package/lib/restore-rollback.js +10 -4
  310. package/lib/restore.js +24 -22
  311. package/lib/retention.js +23 -9
  312. package/lib/router.js +17 -4
  313. package/lib/safe-async.js +457 -0
  314. package/lib/safe-buffer.js +137 -6
  315. package/lib/safe-decompress.js +2 -1
  316. package/lib/safe-dns.js +2 -1
  317. package/lib/safe-ical.js +14 -28
  318. package/lib/safe-icap.js +1 -1
  319. package/lib/safe-json.js +51 -8
  320. package/lib/safe-jsonpath.js +6 -5
  321. package/lib/safe-mime.js +25 -29
  322. package/lib/safe-redirect.js +2 -5
  323. package/lib/safe-schema.js +7 -6
  324. package/lib/safe-sieve.js +1 -1
  325. package/lib/safe-sql.js +126 -0
  326. package/lib/safe-vcard.js +13 -27
  327. package/lib/sandbox-worker.js +15 -2
  328. package/lib/sandbox.js +4 -3
  329. package/lib/scheduler.js +22 -13
  330. package/lib/sec-cyber.js +82 -37
  331. package/lib/seeders.js +4 -11
  332. package/lib/self-update-standalone-verifier.js +16 -0
  333. package/lib/self-update.js +92 -69
  334. package/lib/session-device-binding.js +112 -66
  335. package/lib/session.js +219 -7
  336. package/lib/sql.js +228 -81
  337. package/lib/sse.js +6 -10
  338. package/lib/static.js +201 -111
  339. package/lib/storage.js +4 -2
  340. package/lib/structured-fields.js +275 -16
  341. package/lib/template.js +7 -5
  342. package/lib/tenant-quota.js +53 -38
  343. package/lib/tsa.js +16 -17
  344. package/lib/validate-opts.js +154 -8
  345. package/lib/vault/index.js +5 -0
  346. package/lib/vault/passphrase-ops.js +22 -26
  347. package/lib/vault/passphrase-source.js +8 -3
  348. package/lib/vault/rotate.js +13 -18
  349. package/lib/vault/seal-pem-file.js +34 -49
  350. package/lib/vault-aad.js +3 -2
  351. package/lib/vc.js +3 -8
  352. package/lib/vendor/MANIFEST.json +10 -10
  353. package/lib/vendor/public-suffix-list.dat +23 -10
  354. package/lib/vendor/public-suffix-list.data.js +5498 -5494
  355. package/lib/vex.js +35 -13
  356. package/lib/web-push-vapid.js +23 -20
  357. package/lib/webhook-dispatcher.js +706 -0
  358. package/lib/webhook.js +59 -19
  359. package/lib/websocket-channels.js +9 -7
  360. package/lib/websocket.js +8 -4
  361. package/lib/worm.js +3 -4
  362. package/lib/ws-client.js +65 -56
  363. package/lib/x509-chain.js +44 -0
  364. package/package.json +1 -1
  365. package/sbom.cdx.json +6 -6
@@ -259,73 +259,87 @@ function _validateUploadId(id) {
259
259
  }
260
260
 
261
261
  function _validateCreateOpts(opts) {
262
- validateOpts.requireObject(opts, "fileUpload.create", FileUploadError);
263
- validateOpts.requireNonEmptyString(opts.stagingDir, "fileUpload.create: stagingDir", FileUploadError);
264
- if (!nodePath.isAbsolute(opts.stagingDir)) {
265
- throw _err("BAD_OPT", "fileUpload.create: stagingDir must be an absolute path, got " +
266
- JSON.stringify(opts.stagingDir));
267
- }
268
- validateOpts.optionalFunction(opts.onFinalize, "fileUpload.create: onFinalize", FileUploadError);
269
- validateOpts.optionalFunction(opts.onChunk, "fileUpload.create: onChunk", FileUploadError);
270
- numericBounds.requireAllPositiveFiniteIntIfPresent(opts,
271
- ["maxFileBytes", "maxChunkBytes", "maxStreamReassemblyBytes",
272
- "maxStagingBytes", "maxActiveUploadsPerActor"],
273
- "fileUpload.create", FileUploadError, "BAD_OPT");
274
- numericBounds.requireNonNegativeFiniteIntIfPresent(opts.incompleteTtlMs,
275
- "fileUpload.create: incompleteTtlMs", FileUploadError, "BAD_OPT");
276
- numericBounds.requireNonNegativeFiniteIntIfPresent(opts.maxIdleMs,
277
- "fileUpload.create: maxIdleMs", FileUploadError, "BAD_OPT");
278
- numericBounds.requirePositiveFiniteIntIfPresent(opts.maxChunks,
279
- "fileUpload.create: maxChunks", FileUploadError, "BAD_OPT");
280
- validateOpts.auditShape(opts.audit, "fileUpload.create", FileUploadError);
281
- validateOpts.observabilityShape(opts.observability, "fileUpload.create", FileUploadError);
282
- validateOpts.optionalFunction(opts.clock, "fileUpload.create: clock", FileUploadError);
283
- // allowedFileTypes — operator's MIME allowlist. Empty / undefined
284
- // disables the gate. Setting it without wiring a fileType primitive
285
- // is a misconfig — the gate would have nothing to enforce against.
286
- validateOpts.optionalNonEmptyStringArray(opts.allowedFileTypes,
287
- "fileUpload.create: allowedFileTypes", FileUploadError, "BAD_OPT");
288
- if (Array.isArray(opts.allowedFileTypes) && opts.allowedFileTypes.length > 0 &&
289
- (!opts.fileType || typeof opts.fileType.detect !== "function")) {
290
- throw _err("BAD_OPT",
291
- "fileUpload.create: allowedFileTypes is set but fileType primitive is not wired " +
292
- "(pass fileType: b.fileType so the framework can sniff magic bytes at finalize)");
293
- }
294
- // permissions — when set, must expose check(actor, scope) → boolean.
295
- validateOpts.optionalObjectWithMethod(opts.permissions, "check",
296
- "fileUpload.create: permissions", FileUploadError, "BAD_OPT",
297
- "must be a b.permissions instance (check fn)");
298
- // contentSafety — extension-keyed gate map for per-extension content
299
- // validation. Default behaviour: when undefined, the framework wires
300
- // b.guardAll.byExtension({ profile: "strict" }) automatically so every
301
- // shipped guard is ON by default. Explicit opt-out: contentSafety:
302
- // null (audited at create() time so a security review can reconstruct
303
- // which deploys disabled the default-on protection).
304
- // Example: contentSafety: { ".csv": b.guardCsv.gate({ profile: "strict" }) }
305
- if (opts.contentSafety !== undefined && opts.contentSafety !== null) {
306
- validateOpts.optionalPlainObject(opts.contentSafety,
307
- "fileUpload.create: contentSafety", FileUploadError, "BAD_OPT",
308
- "must be a plain { ext: gate } object, null to opt out, or " +
309
- "undefined for the default-on b.guardAll wiring");
310
- var safetyKeys = Object.keys(opts.contentSafety);
311
- for (var sk = 0; sk < safetyKeys.length; sk++) {
312
- var ext = safetyKeys[sk];
313
- var g = opts.contentSafety[ext];
314
- if (!g || typeof g.check !== "function") {
262
+ validateOpts.shape(opts, {
263
+ stagingDir: function (v, label) {
264
+ validateOpts.requireNonEmptyString(v, label, FileUploadError);
265
+ if (!nodePath.isAbsolute(v)) {
266
+ throw _err("BAD_OPT", "fileUpload.create: stagingDir must be an absolute path, got " +
267
+ JSON.stringify(v));
268
+ }
269
+ },
270
+ onFinalize: "optional-function",
271
+ onChunk: "optional-function",
272
+ // Byte / count caps — finite positive ints; TTL/idle windows allow 0.
273
+ maxFileBytes: "optional-positive-finite-int",
274
+ maxChunkBytes: "optional-positive-finite-int",
275
+ maxStreamReassemblyBytes: "optional-positive-finite-int",
276
+ maxStagingBytes: "optional-positive-finite-int",
277
+ maxActiveUploadsPerActor: "optional-positive-finite-int",
278
+ maxChunks: "optional-positive-finite-int",
279
+ incompleteTtlMs: "optional-non-negative-finite-int",
280
+ maxIdleMs: "optional-non-negative-finite-int",
281
+ audit: function (v) { validateOpts.auditShape(v, "fileUpload.create", FileUploadError); },
282
+ observability: function (v) { validateOpts.observabilityShape(v, "fileUpload.create", FileUploadError); },
283
+ clock: "optional-function",
284
+ // allowedFileTypes operator's MIME allowlist. Empty / undefined
285
+ // disables the gate. Setting it without wiring a fileType primitive
286
+ // is a misconfig — the gate would have nothing to enforce against.
287
+ allowedFileTypes: function (v, label) {
288
+ validateOpts.optionalNonEmptyStringArray(v, label, FileUploadError, "BAD_OPT");
289
+ if (Array.isArray(v) && v.length > 0 &&
290
+ (!opts.fileType || typeof opts.fileType.detect !== "function")) {
315
291
  throw _err("BAD_OPT",
316
- "fileUpload.create: contentSafety[" + JSON.stringify(ext) +
317
- "] must be a gate (b.guardCsv.gate / b.guardHtml.gate / etc.)");
292
+ "fileUpload.create: allowedFileTypes is set but fileType primitive is not wired " +
293
+ "(pass fileType: b.fileType so the framework can sniff magic bytes at finalize)");
318
294
  }
319
- }
320
- }
321
- // filenameSafety single gate for filename validation. Default: on.
322
- // Operator opts out with filenameSafety: null (audited).
323
- if (opts.filenameSafety !== undefined && opts.filenameSafety !== null) {
324
- validateOpts.optionalObjectWithMethod(opts.filenameSafety, "check",
325
- "fileUpload.create: filenameSafety", FileUploadError, "BAD_OPT",
326
- "must be a gate (b.guardFilename.gate(...)), null to opt out, or " +
327
- "undefined for the default-on wiring");
328
- }
295
+ },
296
+ // permissions — when set, must expose check(actor, scope) → boolean.
297
+ permissions: function (v, label) {
298
+ validateOpts.optionalObjectWithMethod(v, "check", label, FileUploadError, "BAD_OPT",
299
+ "must be a b.permissions instance (check fn)");
300
+ },
301
+ // contentSafety extension-keyed gate map for per-extension content
302
+ // validation. Default behaviour: when undefined, the framework wires
303
+ // b.guardAll.byExtension({ profile: "strict" }) automatically so every
304
+ // shipped guard is ON by default. Explicit opt-out: contentSafety:
305
+ // null (audited at create() time so a security review can reconstruct
306
+ // which deploys disabled the default-on protection).
307
+ // Example: contentSafety: { ".csv": b.guardCsv.gate({ profile: "strict" }) }
308
+ contentSafety: function (v, label) {
309
+ if (v === undefined || v === null) return;
310
+ validateOpts.optionalPlainObject(v, label, FileUploadError, "BAD_OPT",
311
+ "must be a plain { ext: gate } object, null to opt out, or " +
312
+ "undefined for the default-on b.guardAll wiring");
313
+ var safetyKeys = Object.keys(v);
314
+ for (var sk = 0; sk < safetyKeys.length; sk++) {
315
+ var ext = safetyKeys[sk];
316
+ var g = v[ext];
317
+ if (!g || typeof g.check !== "function") {
318
+ throw _err("BAD_OPT",
319
+ "fileUpload.create: contentSafety[" + JSON.stringify(ext) +
320
+ "] must be a gate (b.guardCsv.gate / b.guardHtml.gate / etc.)");
321
+ }
322
+ }
323
+ },
324
+ // filenameSafety — single gate for filename validation. Default: on.
325
+ // Operator opts out with filenameSafety: null (audited).
326
+ filenameSafety: function (v, label) {
327
+ if (v === undefined || v === null) return;
328
+ validateOpts.optionalObjectWithMethod(v, "check", label, FileUploadError, "BAD_OPT",
329
+ "must be a gate (b.guardFilename.gate(...)), null to opt out, or " +
330
+ "undefined for the default-on wiring");
331
+ },
332
+ // fileType — magic-byte sniffer (b.fileType) consumed at finalize when
333
+ // allowedFileTypes is set; validated here so it can't be passed un-typed.
334
+ fileType: function (v, label) {
335
+ if (v === undefined || v === null) return;
336
+ validateOpts.optionalObjectWithMethod(v, "detect", label, FileUploadError, "BAD_OPT",
337
+ "must be a b.fileType instance (detect fn)");
338
+ },
339
+ // Reason strings recorded when a default-on safety is explicitly disabled.
340
+ contentSafetyDisabledReason: "optional-string",
341
+ filenameSafetyDisabledReason: "optional-string",
342
+ }, "fileUpload.create", FileUploadError, "BAD_OPT", { exhaustive: true });
329
343
  }
330
344
 
331
345
  /**
@@ -698,7 +712,7 @@ function create(opts) {
698
712
  throw _err("EMPTY_CHUNK",
699
713
  "fileUpload.acceptChunk: body is empty (0 bytes)");
700
714
  }
701
- if (body.length > maxChunkBytes) {
715
+ if (safeBuffer.byteLengthOf(body) > maxChunkBytes) {
702
716
  _emitObs("fileUpload.chunk_too_large", 1);
703
717
  throw _err("CHUNK_TOO_LARGE",
704
718
  "fileUpload.acceptChunk: chunk body is " + body.length +
@@ -17,6 +17,7 @@
17
17
  */
18
18
 
19
19
  var nodeCrypto = require("node:crypto");
20
+ var pick = require("./pick");
20
21
  var validateOpts = require("./validate-opts");
21
22
  var lazyRequire = require("./lazy-require");
22
23
  var { defineClass } = require("./framework-error");
@@ -33,7 +34,7 @@ function _normalize(input, label) {
33
34
  var out = {};
34
35
  for (var key in input) {
35
36
  if (!Object.prototype.hasOwnProperty.call(input, key)) continue;
36
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
37
+ if (pick.isPoisonedKey(key)) {
37
38
  continue; // poisoned-keys defense
38
39
  }
39
40
  out[key] = input[key];
@@ -55,12 +56,8 @@ function merge(base, overlay) {
55
56
  var b = _normalize(base, "merge.base");
56
57
  var o = _normalize(overlay, "merge.overlay");
57
58
  var out = {};
58
- for (var k1 in b) {
59
- if (Object.prototype.hasOwnProperty.call(b, k1)) out[k1] = b[k1];
60
- }
61
- for (var k2 in o) {
62
- if (Object.prototype.hasOwnProperty.call(o, k2)) out[k2] = o[k2];
63
- }
59
+ validateOpts.assignOwnEnumerable(out, b);
60
+ validateOpts.assignOwnEnumerable(out, o);
64
61
  return Object.freeze(out);
65
62
  }
66
63
 
@@ -110,7 +107,7 @@ function fromRequest(req, opts) {
110
107
  if (opts.extra && typeof opts.extra === "object") {
111
108
  for (var k in opts.extra) {
112
109
  if (Object.prototype.hasOwnProperty.call(opts.extra, k)) {
113
- if (k === "__proto__" || k === "constructor" || k === "prototype") continue;
110
+ if (pick.isPoisonedKey(k)) continue;
114
111
  ctx[k] = opts.extra[k];
115
112
  }
116
113
  }
@@ -41,6 +41,7 @@ var validateOpts = require("./validate-opts");
41
41
  var lazyRequire = require("./lazy-require");
42
42
  var safeJson = require("./safe-json");
43
43
  var C = require("./constants");
44
+ var atomicFile = require("./atomic-file");
44
45
  var { defineClass } = require("./framework-error");
45
46
  var FlagError = defineClass("FlagError", { alwaysPermanent: true });
46
47
 
@@ -128,7 +129,10 @@ function localFile(opts) {
128
129
  validateOpts.requireNonEmptyString(opts.path,
129
130
  "providers.localFile: path", FlagError, "flag/bad-provider");
130
131
  var raw;
131
- try { raw = nodeFs.readFileSync(opts.path, "utf8"); }
132
+ // Capped fd-bound read; the cap precedes the alloc so an oversized flag file
133
+ // can't OOM boot. refuseSymlink stays OFF: a flag file is commonly a k8s
134
+ // ConfigMap mount, which is a symlink chain — refusing it would break that.
135
+ try { raw = atomicFile.fdSafeReadSync(opts.path, { maxBytes: C.BYTES.mib(1), encoding: "utf8" }); }
132
136
  catch (e) {
133
137
  throw new FlagError("flag/bad-provider",
134
138
  "providers.localFile: cannot read file " + JSON.stringify(opts.path) +
@@ -154,7 +158,7 @@ function localFile(opts) {
154
158
  try {
155
159
  nodeFs.watch(opts.path, { persistent: false }, function () {
156
160
  try {
157
- var nextRaw = nodeFs.readFileSync(opts.path, "utf8");
161
+ var nextRaw = atomicFile.fdSafeReadSync(opts.path, { maxBytes: C.BYTES.mib(1), encoding: "utf8" });
158
162
  var nextParsed = safeJson.parse(nextRaw, { maxBytes: C.BYTES.mib(1) });
159
163
  if (nextParsed && nextParsed.flags) {
160
164
  for (var k in nextParsed.flags) {
package/lib/forms.js CHANGED
@@ -252,7 +252,7 @@ function _renderField(field) {
252
252
  var control;
253
253
  if (type === "textarea") control = _renderTextarea(field);
254
254
  else if (type === "select") control = _renderSelect(field);
255
- else if (INPUT_TYPES[type]) control = _renderInput(field);
255
+ else if (Object.prototype.hasOwnProperty.call(INPUT_TYPES, type)) control = _renderInput(field);
256
256
  else throw new Error("forms.render: unsupported field type: " + type);
257
257
 
258
258
  // Hidden + submit fields don't need a label wrapper
@@ -144,6 +144,11 @@ var SchedulerError = defineClass("SchedulerError");
144
144
  var SessionError = defineClass("SessionError");
145
145
  var SlugError = defineClass("SlugError", { alwaysPermanent: true });
146
146
  var WebhookError = defineClass("WebhookError", { alwaysPermanent: true });
147
+ // WebhookDispatcherError covers the durable signed-webhook delivery store
148
+ // (b.webhook.dispatcher): endpoint registration, fan-out, retry/backoff, and
149
+ // dead-letter operations. Distinct from WebhookError (the stateless
150
+ // sign/verify surface) so the persistence-layer error codes stay separable.
151
+ var WebhookDispatcherError = defineClass("WebhookDispatcherError", { alwaysPermanent: true });
147
152
  var ApiKeyError = defineClass("ApiKeyError", { alwaysPermanent: true });
148
153
  var PermissionsError = defineClass("PermissionsError", { alwaysPermanent: true });
149
154
  // CacheError is alwaysPermanent: bad opts / missing key / closed-state
@@ -196,6 +201,11 @@ var GateContractError = defineClass("GateContractError", { alwaysPermane
196
201
  // validate paths. alwaysPermanent — chunk-shape errors / formula-injection
197
202
  // attempts / schema drift are all caller-shape errors.
198
203
  var GuardCsvError = defineClass("GuardCsvError", { alwaysPermanent: true });
204
+ // GuardTextError covers free-text codepoint-threat violations on the validate /
205
+ // sanitize / gate paths (bidi-override / control / null / zero-width /
206
+ // Unicode-Tags / mixed-script-confusable). alwaysPermanent — every case is a
207
+ // hostile-codepoint detection or a caller-shape opt error.
208
+ var GuardTextError = defineClass("GuardTextError", { alwaysPermanent: true });
199
209
  // GuardAllError covers parity-check failures, exceptFor opt validation, and
200
210
  // override opt validation in the b.guardAll registry. alwaysPermanent — every
201
211
  // case is a config-time programming bug, not a transient runtime condition.
@@ -693,6 +703,7 @@ module.exports = {
693
703
  SessionError: SessionError,
694
704
  SlugError: SlugError,
695
705
  WebhookError: WebhookError,
706
+ WebhookDispatcherError: WebhookDispatcherError,
696
707
  ApiKeyError: ApiKeyError,
697
708
  PermissionsError: PermissionsError,
698
709
  CacheError: CacheError,
@@ -705,6 +716,7 @@ module.exports = {
705
716
  StaticServeError: StaticServeError,
706
717
  GateContractError: GateContractError,
707
718
  GuardCsvError: GuardCsvError,
719
+ GuardTextError: GuardTextError,
708
720
  GuardAllError: GuardAllError,
709
721
  GuardHtmlError: GuardHtmlError,
710
722
  GuardSvgError: GuardSvgError,
@@ -116,6 +116,10 @@ var LOCAL_TO_EXTERNAL = Object.freeze({
116
116
  // places — cluster-storage.execute routes the SQL to the right DB
117
117
  // based on cluster.isClusterMode().
118
118
  _blamejs_sessions: "_blamejs_sessions",
119
+ // _blamejs_session_valid_from — per-subject valid-from boundary for
120
+ // stateless-token revocation (b.session.bump / check / validFrom). Same
121
+ // dual-storage shape as _blamejs_sessions; identity-mapped.
122
+ _blamejs_session_valid_from: "_blamejs_session_valid_from",
119
123
  // _blamejs_jobs — same dual-storage pattern as sessions. The local-
120
124
  // protocol queue (lib/queue-local.js) routes through cluster-storage
121
125
  // so writes/reads land in the leader's external-db when cluster
@@ -649,6 +653,20 @@ function _sessionsDDL(dialect) {
649
653
  ]);
650
654
  }
651
655
 
656
+ // _blamejs_session_valid_from — monotonic per-subject valid-from boundary for
657
+ // stateless-token revocation. Mirrors the local-SQLite schema in db.js's
658
+ // FRAMEWORK_SCHEMA so single-node and cluster behavior are identical.
659
+ // subjectHash is the PRIMARY KEY (the plaintext subject id never lands here);
660
+ // validFromEpoch is the monotonic boundary (ms); updatedAt records the bump.
661
+ function _sessionValidFromDDL(dialect) {
662
+ var t = _types(dialect);
663
+ return _table(tableName("_blamejs_session_valid_from"), dialect, [
664
+ { col: "subjectHash", def: t.KT + " PRIMARY KEY" },
665
+ { col: "validFromEpoch", def: t.INT + " NOT NULL" },
666
+ { col: "updatedAt", def: t.INT + " NOT NULL" },
667
+ ], []);
668
+ }
669
+
652
670
  // _blamejs_jobs — local-protocol queue jobs. Mirrors db.js's
653
671
  // FRAMEWORK_SCHEMA for the same table; sealed columns (payload,
654
672
  // lastError) are stored vault-sealed. Indexes target the lease
@@ -824,6 +842,7 @@ function _allDDLs(dialect) {
824
842
  _apiEncryptNoncesDDL(dialect),
825
843
  _apiKeysDDL(dialect),
826
844
  _sessionsDDL(dialect),
845
+ _sessionValidFromDDL(dialect),
827
846
  _jobsDDL(dialect),
828
847
  _cacheDDL(dialect),
829
848
  _cacheTagsDDL(dialect),
package/lib/fsm.js CHANGED
@@ -439,18 +439,13 @@ async function _runTransition(instance, name, opts) {
439
439
  // drop-silent; the additional try/catch protects against the
440
440
  // lazy-loaded audit module throwing at first-access time.
441
441
  try {
442
- audit().safeEmit({
443
- action: "fsm." + instance._def.name + ".transition",
444
- actor: opts.actor ? { id: opts.actor } : { id: "<system>" },
445
- outcome: "success",
446
- metadata: {
447
- from: fromState,
448
- to: toState,
449
- transition: name,
450
- machine: instance._def.name,
451
- callerMeta: opts.metadata || null,
452
- },
453
- });
442
+ audit().namespaced("fsm")(instance._def.name + ".transition", "success", {
443
+ from: fromState,
444
+ to: toState,
445
+ transition: name,
446
+ machine: instance._def.name,
447
+ callerMeta: opts.metadata || null,
448
+ }, { actor: opts.actor ? { id: opts.actor } : { id: "<system>" } });
454
449
  } catch (_e) { /* drop-silent — audit best-effort */ }
455
450
  return { from: fromState, to: toState, on: name };
456
451
  }