@blamejs/blamejs-shop 0.3.4 → 0.3.6

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 (354) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/lib/admin.js +428 -6
  3. package/lib/asset-manifest.json +1 -1
  4. package/lib/vendor/MANIFEST.json +3 -3
  5. package/lib/vendor/blamejs/CHANGELOG.md +14 -0
  6. package/lib/vendor/blamejs/api-snapshot.json +2 -2
  7. package/lib/vendor/blamejs/lib/_test/crypto-fixtures.js +3 -3
  8. package/lib/vendor/blamejs/lib/a2a-tasks.js +24 -24
  9. package/lib/vendor/blamejs/lib/a2a.js +4 -4
  10. package/lib/vendor/blamejs/lib/acme.js +3 -3
  11. package/lib/vendor/blamejs/lib/agent-idempotency.js +1 -1
  12. package/lib/vendor/blamejs/lib/agent-orchestrator.js +8 -8
  13. package/lib/vendor/blamejs/lib/agent-posture-chain.js +2 -2
  14. package/lib/vendor/blamejs/lib/agent-saga.js +1 -1
  15. package/lib/vendor/blamejs/lib/agent-snapshot.js +1 -1
  16. package/lib/vendor/blamejs/lib/agent-stream.js +1 -1
  17. package/lib/vendor/blamejs/lib/agent-tenant.js +1 -1
  18. package/lib/vendor/blamejs/lib/agent-trace.js +3 -3
  19. package/lib/vendor/blamejs/lib/ai-capability.js +1 -1
  20. package/lib/vendor/blamejs/lib/ai-dp.js +4 -4
  21. package/lib/vendor/blamejs/lib/ai-input.js +4 -4
  22. package/lib/vendor/blamejs/lib/ai-model-manifest.js +7 -7
  23. package/lib/vendor/blamejs/lib/ai-pref.js +3 -3
  24. package/lib/vendor/blamejs/lib/archive-gz.js +2 -2
  25. package/lib/vendor/blamejs/lib/archive-read.js +25 -25
  26. package/lib/vendor/blamejs/lib/archive-tar-read.js +2 -2
  27. package/lib/vendor/blamejs/lib/archive-tar.js +20 -20
  28. package/lib/vendor/blamejs/lib/archive-wrap.js +10 -10
  29. package/lib/vendor/blamejs/lib/argon2-builtin.js +1 -1
  30. package/lib/vendor/blamejs/lib/asn1-der.js +45 -34
  31. package/lib/vendor/blamejs/lib/atomic-file.js +2 -2
  32. package/lib/vendor/blamejs/lib/audit-daily-review.js +3 -3
  33. package/lib/vendor/blamejs/lib/audit-sign.js +5 -5
  34. package/lib/vendor/blamejs/lib/audit-tools.js +1 -1
  35. package/lib/vendor/blamejs/lib/audit.js +2 -2
  36. package/lib/vendor/blamejs/lib/auth/acr-vocabulary.js +2 -2
  37. package/lib/vendor/blamejs/lib/auth/bot-challenge.js +3 -3
  38. package/lib/vendor/blamejs/lib/auth/ciba.js +7 -7
  39. package/lib/vendor/blamejs/lib/auth/dpop.js +3 -3
  40. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +8 -8
  41. package/lib/vendor/blamejs/lib/auth/jar.js +11 -0
  42. package/lib/vendor/blamejs/lib/auth/jwt-external.js +5 -5
  43. package/lib/vendor/blamejs/lib/auth/oauth.js +7 -9
  44. package/lib/vendor/blamejs/lib/auth/oid4vci.js +10 -10
  45. package/lib/vendor/blamejs/lib/auth/oid4vp.js +2 -2
  46. package/lib/vendor/blamejs/lib/auth/openid-federation.js +2 -2
  47. package/lib/vendor/blamejs/lib/auth/passkey.js +3 -3
  48. package/lib/vendor/blamejs/lib/auth/saml.js +31 -43
  49. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-disclosure.js +1 -1
  50. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +5 -5
  51. package/lib/vendor/blamejs/lib/auth/status-list.js +10 -10
  52. package/lib/vendor/blamejs/lib/auth/step-up.js +1 -1
  53. package/lib/vendor/blamejs/lib/auth-bot-challenge.js +1 -1
  54. package/lib/vendor/blamejs/lib/backup/index.js +7 -7
  55. package/lib/vendor/blamejs/lib/base32.js +8 -8
  56. package/lib/vendor/blamejs/lib/budr.js +2 -2
  57. package/lib/vendor/blamejs/lib/cache-status.js +2 -2
  58. package/lib/vendor/blamejs/lib/calendar.js +29 -29
  59. package/lib/vendor/blamejs/lib/cbor.js +12 -12
  60. package/lib/vendor/blamejs/lib/cdn-cache-control.js +1 -1
  61. package/lib/vendor/blamejs/lib/cert.js +5 -5
  62. package/lib/vendor/blamejs/lib/cloud-events.js +5 -5
  63. package/lib/vendor/blamejs/lib/cms-codec.js +21 -21
  64. package/lib/vendor/blamejs/lib/codepoint-class.js +12 -12
  65. package/lib/vendor/blamejs/lib/compliance-sanctions-fuzzy.js +4 -4
  66. package/lib/vendor/blamejs/lib/compliance-sanctions.js +4 -4
  67. package/lib/vendor/blamejs/lib/compliance.js +29 -29
  68. package/lib/vendor/blamejs/lib/content-credentials.js +38 -38
  69. package/lib/vendor/blamejs/lib/cookies.js +1 -1
  70. package/lib/vendor/blamejs/lib/cose.js +13 -13
  71. package/lib/vendor/blamejs/lib/cra-report.js +1 -1
  72. package/lib/vendor/blamejs/lib/crdt.js +1 -1
  73. package/lib/vendor/blamejs/lib/crypto-field.js +2 -2
  74. package/lib/vendor/blamejs/lib/crypto-xwing.js +7 -7
  75. package/lib/vendor/blamejs/lib/crypto.js +6 -6
  76. package/lib/vendor/blamejs/lib/csp.js +2 -2
  77. package/lib/vendor/blamejs/lib/cwt.js +4 -4
  78. package/lib/vendor/blamejs/lib/dark-patterns.js +2 -2
  79. package/lib/vendor/blamejs/lib/data-act.js +2 -2
  80. package/lib/vendor/blamejs/lib/db-file-lifecycle.js +4 -4
  81. package/lib/vendor/blamejs/lib/db-query.js +1 -1
  82. package/lib/vendor/blamejs/lib/db.js +6 -6
  83. package/lib/vendor/blamejs/lib/dbsc.js +13 -13
  84. package/lib/vendor/blamejs/lib/did.js +17 -17
  85. package/lib/vendor/blamejs/lib/dora.js +4 -4
  86. package/lib/vendor/blamejs/lib/dsr.js +1 -1
  87. package/lib/vendor/blamejs/lib/early-hints.js +2 -2
  88. package/lib/vendor/blamejs/lib/eat.js +4 -4
  89. package/lib/vendor/blamejs/lib/external-db-migrate.js +1 -1
  90. package/lib/vendor/blamejs/lib/external-db.js +1 -1
  91. package/lib/vendor/blamejs/lib/flag-cache.js +1 -1
  92. package/lib/vendor/blamejs/lib/flag-evaluation-context.js +2 -2
  93. package/lib/vendor/blamejs/lib/graphql-federation.js +13 -6
  94. package/lib/vendor/blamejs/lib/guard-agent-registry.js +5 -5
  95. package/lib/vendor/blamejs/lib/guard-archive.js +24 -24
  96. package/lib/vendor/blamejs/lib/guard-cidr.js +34 -34
  97. package/lib/vendor/blamejs/lib/guard-csv.js +1 -1
  98. package/lib/vendor/blamejs/lib/guard-domain.js +10 -10
  99. package/lib/vendor/blamejs/lib/guard-dsn.js +4 -4
  100. package/lib/vendor/blamejs/lib/guard-email.js +19 -19
  101. package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +4 -4
  102. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +6 -6
  103. package/lib/vendor/blamejs/lib/guard-filename.js +7 -7
  104. package/lib/vendor/blamejs/lib/guard-graphql.js +9 -9
  105. package/lib/vendor/blamejs/lib/guard-html-wcag-tagwalk.js +1 -1
  106. package/lib/vendor/blamejs/lib/guard-html-wcag.js +4 -4
  107. package/lib/vendor/blamejs/lib/guard-html.js +7 -7
  108. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +6 -6
  109. package/lib/vendor/blamejs/lib/guard-image.js +4 -4
  110. package/lib/vendor/blamejs/lib/guard-imap-command.js +17 -17
  111. package/lib/vendor/blamejs/lib/guard-jmap.js +20 -20
  112. package/lib/vendor/blamejs/lib/guard-json.js +12 -12
  113. package/lib/vendor/blamejs/lib/guard-jsonpath.js +3 -3
  114. package/lib/vendor/blamejs/lib/guard-jwt.js +4 -4
  115. package/lib/vendor/blamejs/lib/guard-list-id.js +7 -7
  116. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +8 -8
  117. package/lib/vendor/blamejs/lib/guard-mail-compose.js +4 -4
  118. package/lib/vendor/blamejs/lib/guard-mail-move.js +5 -5
  119. package/lib/vendor/blamejs/lib/guard-mail-query.js +3 -3
  120. package/lib/vendor/blamejs/lib/guard-mail-reply.js +3 -3
  121. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +6 -6
  122. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +25 -25
  123. package/lib/vendor/blamejs/lib/guard-markdown.js +31 -31
  124. package/lib/vendor/blamejs/lib/guard-message-id.js +5 -5
  125. package/lib/vendor/blamejs/lib/guard-mime.js +1 -1
  126. package/lib/vendor/blamejs/lib/guard-oauth.js +3 -3
  127. package/lib/vendor/blamejs/lib/guard-pdf.js +6 -6
  128. package/lib/vendor/blamejs/lib/guard-pop3-command.js +11 -11
  129. package/lib/vendor/blamejs/lib/guard-posture-chain.js +5 -5
  130. package/lib/vendor/blamejs/lib/guard-regex.js +10 -10
  131. package/lib/vendor/blamejs/lib/guard-saga-config.js +5 -5
  132. package/lib/vendor/blamejs/lib/guard-smtp-command.js +6 -6
  133. package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +3 -3
  134. package/lib/vendor/blamejs/lib/guard-stream-args.js +4 -4
  135. package/lib/vendor/blamejs/lib/guard-svg.js +11 -11
  136. package/lib/vendor/blamejs/lib/guard-tenant-id.js +5 -5
  137. package/lib/vendor/blamejs/lib/guard-time.js +15 -15
  138. package/lib/vendor/blamejs/lib/guard-trace-context.js +4 -4
  139. package/lib/vendor/blamejs/lib/guard-uuid.js +11 -11
  140. package/lib/vendor/blamejs/lib/guard-xml.js +12 -12
  141. package/lib/vendor/blamejs/lib/guard-yaml.js +16 -16
  142. package/lib/vendor/blamejs/lib/honeytoken.js +5 -5
  143. package/lib/vendor/blamejs/lib/http-client-cache.js +18 -1
  144. package/lib/vendor/blamejs/lib/http-client.js +13 -10
  145. package/lib/vendor/blamejs/lib/http-message-signature.js +2 -2
  146. package/lib/vendor/blamejs/lib/iab-mspa.js +3 -3
  147. package/lib/vendor/blamejs/lib/iab-tcf.js +70 -70
  148. package/lib/vendor/blamejs/lib/inbox.js +4 -4
  149. package/lib/vendor/blamejs/lib/ip-utils.js +15 -15
  150. package/lib/vendor/blamejs/lib/jose-jwe-experimental.js +2 -2
  151. package/lib/vendor/blamejs/lib/json-path.js +3 -3
  152. package/lib/vendor/blamejs/lib/json-schema.js +1 -1
  153. package/lib/vendor/blamejs/lib/jsonapi.js +3 -3
  154. package/lib/vendor/blamejs/lib/jtd.js +2 -2
  155. package/lib/vendor/blamejs/lib/link-header.js +1 -1
  156. package/lib/vendor/blamejs/lib/local-db-thin.js +1 -1
  157. package/lib/vendor/blamejs/lib/log.js +8 -3
  158. package/lib/vendor/blamejs/lib/lro.js +4 -4
  159. package/lib/vendor/blamejs/lib/mail-agent.js +1 -1
  160. package/lib/vendor/blamejs/lib/mail-arc-sign.js +6 -6
  161. package/lib/vendor/blamejs/lib/mail-auth.js +44 -44
  162. package/lib/vendor/blamejs/lib/mail-bimi.js +3 -3
  163. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +53 -45
  164. package/lib/vendor/blamejs/lib/mail-crypto-smime.js +6 -6
  165. package/lib/vendor/blamejs/lib/mail-dav.js +1 -1
  166. package/lib/vendor/blamejs/lib/mail-deploy.js +40 -40
  167. package/lib/vendor/blamejs/lib/mail-dkim.js +12 -12
  168. package/lib/vendor/blamejs/lib/mail-greylist.js +12 -12
  169. package/lib/vendor/blamejs/lib/mail-helo.js +1 -1
  170. package/lib/vendor/blamejs/lib/mail-journal.js +8 -8
  171. package/lib/vendor/blamejs/lib/mail-rbl.js +7 -7
  172. package/lib/vendor/blamejs/lib/mail-scan.js +7 -7
  173. package/lib/vendor/blamejs/lib/mail-send-deliver.js +2 -2
  174. package/lib/vendor/blamejs/lib/mail-server-imap.js +12 -12
  175. package/lib/vendor/blamejs/lib/mail-server-jmap.js +18 -20
  176. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +4 -4
  177. package/lib/vendor/blamejs/lib/mail-server-mx.js +17 -17
  178. package/lib/vendor/blamejs/lib/mail-server-pop3.js +4 -4
  179. package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +2 -2
  180. package/lib/vendor/blamejs/lib/mail-server-submission.js +21 -21
  181. package/lib/vendor/blamejs/lib/mail-sieve.js +2 -2
  182. package/lib/vendor/blamejs/lib/mail-spam-score.js +5 -5
  183. package/lib/vendor/blamejs/lib/mail-srs.js +12 -12
  184. package/lib/vendor/blamejs/lib/mail-store-fts.js +2 -2
  185. package/lib/vendor/blamejs/lib/mail-store.js +8 -8
  186. package/lib/vendor/blamejs/lib/mail-unsubscribe.js +4 -4
  187. package/lib/vendor/blamejs/lib/mail.js +4 -4
  188. package/lib/vendor/blamejs/lib/mcp-tool-registry.js +4 -4
  189. package/lib/vendor/blamejs/lib/mcp.js +15 -15
  190. package/lib/vendor/blamejs/lib/mdoc.js +2 -2
  191. package/lib/vendor/blamejs/lib/metrics.js +8 -8
  192. package/lib/vendor/blamejs/lib/middleware/age-gate.js +15 -3
  193. package/lib/vendor/blamejs/lib/middleware/ai-act-disclosure.js +11 -4
  194. package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +7 -7
  195. package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -2
  196. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +2 -2
  197. package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +5 -5
  198. package/lib/vendor/blamejs/lib/middleware/body-parser.js +5 -5
  199. package/lib/vendor/blamejs/lib/middleware/compose-pipeline.js +16 -16
  200. package/lib/vendor/blamejs/lib/middleware/csp-report.js +4 -4
  201. package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +1 -1
  202. package/lib/vendor/blamejs/lib/middleware/dpop.js +1 -1
  203. package/lib/vendor/blamejs/lib/middleware/headers.js +2 -2
  204. package/lib/vendor/blamejs/lib/middleware/host-allowlist.js +1 -1
  205. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +12 -12
  206. package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
  207. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +2 -2
  208. package/lib/vendor/blamejs/lib/middleware/protected-resource-metadata.js +2 -2
  209. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +14 -5
  210. package/lib/vendor/blamejs/lib/middleware/require-aal.js +1 -1
  211. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +2 -2
  212. package/lib/vendor/blamejs/lib/middleware/require-content-type.js +1 -1
  213. package/lib/vendor/blamejs/lib/middleware/require-methods.js +1 -1
  214. package/lib/vendor/blamejs/lib/middleware/require-step-up.js +2 -2
  215. package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
  216. package/lib/vendor/blamejs/lib/middleware/security-txt.js +3 -3
  217. package/lib/vendor/blamejs/lib/middleware/sse.js +14 -8
  218. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +12 -12
  219. package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -2
  220. package/lib/vendor/blamejs/lib/network-byte-quota.js +1 -1
  221. package/lib/vendor/blamejs/lib/network-dns-resolver.js +23 -23
  222. package/lib/vendor/blamejs/lib/network-dns.js +29 -29
  223. package/lib/vendor/blamejs/lib/network-dnssec.js +33 -33
  224. package/lib/vendor/blamejs/lib/network-smtp-policy.js +10 -10
  225. package/lib/vendor/blamejs/lib/network-tls.js +100 -98
  226. package/lib/vendor/blamejs/lib/network-tsig.js +33 -33
  227. package/lib/vendor/blamejs/lib/nis2-report.js +1 -1
  228. package/lib/vendor/blamejs/lib/ntp-check.js +3 -3
  229. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +17 -17
  230. package/lib/vendor/blamejs/lib/observability-tracer.js +6 -6
  231. package/lib/vendor/blamejs/lib/observability.js +8 -8
  232. package/lib/vendor/blamejs/lib/openapi-yaml.js +1 -1
  233. package/lib/vendor/blamejs/lib/openapi.js +1 -1
  234. package/lib/vendor/blamejs/lib/outbox.js +6 -6
  235. package/lib/vendor/blamejs/lib/pqc-agent.js +4 -4
  236. package/lib/vendor/blamejs/lib/pqc-software.js +1 -1
  237. package/lib/vendor/blamejs/lib/privacy-pass.js +5 -5
  238. package/lib/vendor/blamejs/lib/problem-details.js +5 -5
  239. package/lib/vendor/blamejs/lib/promise-pool.js +1 -1
  240. package/lib/vendor/blamejs/lib/protobuf-encoder.js +9 -1
  241. package/lib/vendor/blamejs/lib/queue.js +4 -2
  242. package/lib/vendor/blamejs/lib/redact.js +2 -2
  243. package/lib/vendor/blamejs/lib/request-helpers.js +1 -1
  244. package/lib/vendor/blamejs/lib/router.js +10 -10
  245. package/lib/vendor/blamejs/lib/safe-async.js +2 -2
  246. package/lib/vendor/blamejs/lib/safe-decompress.js +1 -1
  247. package/lib/vendor/blamejs/lib/safe-dns.js +71 -71
  248. package/lib/vendor/blamejs/lib/safe-ical.js +19 -19
  249. package/lib/vendor/blamejs/lib/safe-icap.js +24 -24
  250. package/lib/vendor/blamejs/lib/safe-jsonpath.js +2 -2
  251. package/lib/vendor/blamejs/lib/safe-mime.js +10 -10
  252. package/lib/vendor/blamejs/lib/safe-mount-info.js +3 -3
  253. package/lib/vendor/blamejs/lib/safe-redirect.js +1 -1
  254. package/lib/vendor/blamejs/lib/safe-sieve.js +23 -23
  255. package/lib/vendor/blamejs/lib/safe-smtp.js +1 -1
  256. package/lib/vendor/blamejs/lib/safe-url.js +1 -1
  257. package/lib/vendor/blamejs/lib/safe-vcard.js +14 -14
  258. package/lib/vendor/blamejs/lib/sandbox.js +5 -5
  259. package/lib/vendor/blamejs/lib/sec-cyber.js +1 -1
  260. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +3 -3
  261. package/lib/vendor/blamejs/lib/self-update.js +3 -3
  262. package/lib/vendor/blamejs/lib/server-timing.js +3 -3
  263. package/lib/vendor/blamejs/lib/session-device-binding.js +7 -7
  264. package/lib/vendor/blamejs/lib/session.js +8 -8
  265. package/lib/vendor/blamejs/lib/sse.js +12 -5
  266. package/lib/vendor/blamejs/lib/standard-webhooks.js +4 -4
  267. package/lib/vendor/blamejs/lib/storage.js +2 -2
  268. package/lib/vendor/blamejs/lib/stream-throttle.js +3 -3
  269. package/lib/vendor/blamejs/lib/structured-fields.js +15 -15
  270. package/lib/vendor/blamejs/lib/subject.js +1 -1
  271. package/lib/vendor/blamejs/lib/tcpa-10dlc.js +1 -1
  272. package/lib/vendor/blamejs/lib/tenant-quota.js +3 -3
  273. package/lib/vendor/blamejs/lib/test-harness.js +1 -1
  274. package/lib/vendor/blamejs/lib/tracing.js +1 -1
  275. package/lib/vendor/blamejs/lib/tsa.js +5 -5
  276. package/lib/vendor/blamejs/lib/uri-template.js +5 -5
  277. package/lib/vendor/blamejs/lib/vault/index.js +2 -2
  278. package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +4 -4
  279. package/lib/vendor/blamejs/lib/vc.js +2 -2
  280. package/lib/vendor/blamejs/lib/vendor-data.js +1 -1
  281. package/lib/vendor/blamejs/lib/watcher.js +4 -4
  282. package/lib/vendor/blamejs/lib/web-push-vapid.js +21 -21
  283. package/lib/vendor/blamejs/lib/webhook.js +2 -2
  284. package/lib/vendor/blamejs/lib/websocket.js +5 -5
  285. package/lib/vendor/blamejs/lib/worker-pool.js +3 -3
  286. package/lib/vendor/blamejs/lib/ws-client.js +24 -24
  287. package/lib/vendor/blamejs/lib/xml-c14n.js +2 -2
  288. package/lib/vendor/blamejs/package.json +1 -1
  289. package/lib/vendor/blamejs/release-notes/v0.13.x.json +1248 -0
  290. package/lib/vendor/blamejs/release-notes/v0.14.0.json +43 -0
  291. package/lib/vendor/blamejs/release-notes/v0.14.1.json +60 -0
  292. package/lib/vendor/blamejs/release-notes/v0.14.2.json +18 -0
  293. package/lib/vendor/blamejs/release-notes/v0.14.3.json +18 -0
  294. package/lib/vendor/blamejs/release-notes/v0.14.4.json +18 -0
  295. package/lib/vendor/blamejs/release-notes/v0.14.5.json +18 -0
  296. package/lib/vendor/blamejs/test/00-primitives.js +15 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +22 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jar.test.js +29 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +105 -9
  300. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +15 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/graphql-federation.test.js +10 -0
  302. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +12 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +7 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +11 -5
  305. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-registry.test.js +34 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/sse.test.js +12 -0
  307. package/package.json +1 -1
  308. package/lib/vendor/blamejs/release-notes/v0.13.0.json +0 -22
  309. package/lib/vendor/blamejs/release-notes/v0.13.1.json +0 -18
  310. package/lib/vendor/blamejs/release-notes/v0.13.10.json +0 -44
  311. package/lib/vendor/blamejs/release-notes/v0.13.11.json +0 -27
  312. package/lib/vendor/blamejs/release-notes/v0.13.12.json +0 -36
  313. package/lib/vendor/blamejs/release-notes/v0.13.13.json +0 -18
  314. package/lib/vendor/blamejs/release-notes/v0.13.14.json +0 -22
  315. package/lib/vendor/blamejs/release-notes/v0.13.15.json +0 -27
  316. package/lib/vendor/blamejs/release-notes/v0.13.16.json +0 -27
  317. package/lib/vendor/blamejs/release-notes/v0.13.17.json +0 -27
  318. package/lib/vendor/blamejs/release-notes/v0.13.18.json +0 -18
  319. package/lib/vendor/blamejs/release-notes/v0.13.19.json +0 -27
  320. package/lib/vendor/blamejs/release-notes/v0.13.2.json +0 -27
  321. package/lib/vendor/blamejs/release-notes/v0.13.20.json +0 -22
  322. package/lib/vendor/blamejs/release-notes/v0.13.21.json +0 -18
  323. package/lib/vendor/blamejs/release-notes/v0.13.22.json +0 -18
  324. package/lib/vendor/blamejs/release-notes/v0.13.23.json +0 -42
  325. package/lib/vendor/blamejs/release-notes/v0.13.24.json +0 -26
  326. package/lib/vendor/blamejs/release-notes/v0.13.25.json +0 -39
  327. package/lib/vendor/blamejs/release-notes/v0.13.26.json +0 -31
  328. package/lib/vendor/blamejs/release-notes/v0.13.27.json +0 -34
  329. package/lib/vendor/blamejs/release-notes/v0.13.28.json +0 -30
  330. package/lib/vendor/blamejs/release-notes/v0.13.29.json +0 -30
  331. package/lib/vendor/blamejs/release-notes/v0.13.3.json +0 -18
  332. package/lib/vendor/blamejs/release-notes/v0.13.30.json +0 -30
  333. package/lib/vendor/blamejs/release-notes/v0.13.31.json +0 -26
  334. package/lib/vendor/blamejs/release-notes/v0.13.32.json +0 -34
  335. package/lib/vendor/blamejs/release-notes/v0.13.33.json +0 -26
  336. package/lib/vendor/blamejs/release-notes/v0.13.34.json +0 -48
  337. package/lib/vendor/blamejs/release-notes/v0.13.35.json +0 -35
  338. package/lib/vendor/blamejs/release-notes/v0.13.36.json +0 -27
  339. package/lib/vendor/blamejs/release-notes/v0.13.37.json +0 -18
  340. package/lib/vendor/blamejs/release-notes/v0.13.38.json +0 -27
  341. package/lib/vendor/blamejs/release-notes/v0.13.39.json +0 -27
  342. package/lib/vendor/blamejs/release-notes/v0.13.4.json +0 -23
  343. package/lib/vendor/blamejs/release-notes/v0.13.40.json +0 -22
  344. package/lib/vendor/blamejs/release-notes/v0.13.41.json +0 -27
  345. package/lib/vendor/blamejs/release-notes/v0.13.42.json +0 -18
  346. package/lib/vendor/blamejs/release-notes/v0.13.43.json +0 -39
  347. package/lib/vendor/blamejs/release-notes/v0.13.44.json +0 -31
  348. package/lib/vendor/blamejs/release-notes/v0.13.45.json +0 -31
  349. package/lib/vendor/blamejs/release-notes/v0.13.46.json +0 -35
  350. package/lib/vendor/blamejs/release-notes/v0.13.5.json +0 -18
  351. package/lib/vendor/blamejs/release-notes/v0.13.6.json +0 -18
  352. package/lib/vendor/blamejs/release-notes/v0.13.7.json +0 -27
  353. package/lib/vendor/blamejs/release-notes/v0.13.8.json +0 -27
  354. package/lib/vendor/blamejs/release-notes/v0.13.9.json +0 -27
package/CHANGELOG.md CHANGED
@@ -8,6 +8,10 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.3.x
10
10
 
11
+ - v0.3.6 (2026-05-30) — **Update the vendored blamejs runtime to v0.14.5.** Refreshes the vendored blamejs runtime from v0.13.46 to v0.14.5, a maintenance update. The request-lifecycle security stack the storefront and admin depend on — CSRF, fetch-metadata, body-parser, cookies, and rate limiting — is unchanged across this range. The runtime's breaking changes in this window (stricter OAuth JAR request-object typing and a PGP signature return type) are in surfaces this shop does not use, so there is no behavior change and no operator action is required. **Changed:** *Vendored blamejs runtime updated to v0.14.5* — The pinned blamejs runtime moves from v0.13.46 to v0.14.5, picking up the framework's maintenance and hardening work across that range. The createApp request-lifecycle middleware the shop composes (CSRF, fetch-metadata, body-parser, cookie, and rate-limit layers) is unchanged, so this refresh carries no behavior change for the storefront or admin console.
12
+
13
+ - v0.3.5 (2026-05-30) — **Shipping-label management in the admin console.** The admin console gains shipping-label tools. On an order, void a purchased label — with a reason — when it needs reprinting, alongside the existing mark-as-used action. A new Shipping labels section adds cross-order visibility: a status-filtered list, the mint queue of labels awaiting a broker, and a broker-spend report that totals label costs by carrier and currency over a date range. This is bookkeeping and reporting only — nothing in the storefront, cart, or checkout changes. **Added:** *Void a shipping label from the order* — Each purchased label on an order now offers a Void action with a reason, for when a label is reprinted at a different weight or carrier. Voiding is refused once a label has been used or already voided, or once it is past the carrier's void window. · *Shipping labels admin section* — A new Shipping labels section gives cross-order visibility: a status-filtered label list, the mint queue of labels awaiting a broker, and a broker-spend report totalling label cost grouped by carrier and currency over a date range.
14
+
11
15
  - v0.3.4 (2026-05-30) — **Sales-tax filings and remittance tracking in the admin console.** The admin console gains a Tax filings section for tracking sales-tax remittance across reporting periods. Open a filing period for a jurisdiction, compute the tax collected from completed orders in that window, then record the submission and the payment as you remit. Each filing carries a per-rate breakdown and an audit trail, and the list surfaces what's due soon or already overdue. A per-jurisdiction remittance report totals the tax owed across a date range. Every figure derives from completed orders — nothing in the storefront, cart, or checkout changes. **Added:** *Tax filings admin console* — A new Tax filings section tracks sales-tax remittance: open a filing period for a jurisdiction and reporting kind, compute the tax collected from completed orders in the window with a per-rate breakdown, then record submission and payment through the filing lifecycle. The list surfaces filings due soon or overdue, and a remittance report totals tax owed per jurisdiction across a date range. This is reporting only — it reads completed orders and changes nothing in checkout.
12
16
 
13
17
  - v0.3.3 (2026-05-30) — **Manage quantity-break (volume) pricing from the admin console.** The admin console gains a Quantity breaks section for creating and managing volume-pricing tier sets — buy-more-save-more rules scoped to a SKU, product, collection, vendor, category, or the whole store. Each set defines one or more quantity thresholds (e.g. buy 5, buy 10) with a percentage off, an amount off each unit, an amount off the line, or a fixed per-unit price, and can be marked exclusive or left to stack with others. A sample-price preview shows the discounted unit at each threshold before you commit, and sets archive and restore. The tiers take effect immediately on the product page, in the cart, and at checkout. **Added:** *Quantity Breaks admin console* — A new Quantity breaks section manages volume-pricing tier sets: create a set scoped to a SKU, product, collection, vendor, category, or globally; define one or more quantity thresholds with a percent-off, amount-off-each, amount-off-line, or fixed-per-unit discount; mark a set exclusive or let it stack. A sample-price preview shows the discounted unit at each threshold, and sets archive and restore. The tiers apply automatically on the product page, the cart, and at checkout.
package/lib/admin.js CHANGED
@@ -145,6 +145,11 @@ var _UPLOAD_IMAGE_CT = {
145
145
  // generic 413.
146
146
  var _UPLOAD_MAX_BYTES = b.constants.BYTES.mib(10);
147
147
 
148
+ // Cap on the standalone shipping-labels list / pending-queue reads. Matches
149
+ // the labels primitive's own MAX_PENDING_LIMIT so a console drain can never
150
+ // ask for more than the primitive will return.
151
+ var MAX_LABEL_LIST_LIMIT = 200;
152
+
148
153
  // ---- shared helpers -----------------------------------------------------
149
154
 
150
155
  function _parseEpochMs(str, label) {
@@ -446,7 +451,7 @@ function mount(router, deps) {
446
451
  // `reports` is always present in the nav (read-only sales summary needs no
447
452
  // extra dep); its route mounts unconditionally and renders an unconfigured
448
453
  // notice when the salesReports primitive isn't wired.
449
- var navAvailable = { returns: !!returns, reviews: !!reviews, productQa: !!productQa, subscriptions: !!deps.subscriptions, webhooks: !!deps.webhooks, collections: !!deps.collections, customers: !!deps.customers, giftcards: !!deps.giftcards, announcementBar: !!deps.announcementBar, customerSurveys: !!deps.customerSurveys, businessHours: !!deps.businessHours, taxRates: !!deps.taxRates, shippingZones: !!deps.shippingZones, autoDiscount: !!deps.autoDiscount, quantityDiscounts: !!deps.quantityDiscounts, pickLists: !!pickLists, salesTaxFilings: !!salesTaxFilings };
454
+ var navAvailable = { returns: !!returns, reviews: !!reviews, productQa: !!productQa, subscriptions: !!deps.subscriptions, webhooks: !!deps.webhooks, collections: !!deps.collections, customers: !!deps.customers, giftcards: !!deps.giftcards, announcementBar: !!deps.announcementBar, customerSurveys: !!deps.customerSurveys, businessHours: !!deps.businessHours, taxRates: !!deps.taxRates, shippingZones: !!deps.shippingZones, autoDiscount: !!deps.autoDiscount, quantityDiscounts: !!deps.quantityDiscounts, pickLists: !!pickLists, salesTaxFilings: !!salesTaxFilings, shippingLabels: !!shippingLabels };
450
455
 
451
456
  try { b.audit.registerNamespace(AUDIT_NAMESPACE); } catch (_e) { /* idempotent */ }
452
457
 
@@ -1671,6 +1676,46 @@ function mount(router, deps) {
1671
1676
  _redirect(res, "/admin/orders/" + enc + "?label=1");
1672
1677
  },
1673
1678
  ));
1679
+
1680
+ // Void a recorded label (broker void, within the 30-day window).
1681
+ // purchased → voided. Mirrors the /used route: the primitive enforces
1682
+ // the transition + window, a TypeError (bad id / missing reason) or a
1683
+ // SHIPPING_LABELS_* coded error (wrong status / expired window) surfaces
1684
+ // as a 400 on the JSON path and an `?err` notice on the browser path.
1685
+ router.post("/admin/orders/:id/labels/:labelId/void", _pageOrApi(false,
1686
+ W("order.shipment.label.void", async function (req, res) {
1687
+ var body = req.body || {};
1688
+ var out;
1689
+ try {
1690
+ out = await shippingLabels.voidLabel({ label_id: req.params.labelId, reason: body.reason });
1691
+ } catch (e) {
1692
+ if (e instanceof TypeError) return _problem(res, 400, "bad-request", e.message);
1693
+ if (e && e.code && /SHIPPING_LABELS/.test(e.code)) return _problem(res, 400, "bad-request", e.message);
1694
+ throw e;
1695
+ }
1696
+ _json(res, 200, out);
1697
+ return { id: req.params.id };
1698
+ }),
1699
+ async function (req, res) {
1700
+ var id = req.params.id;
1701
+ var enc = encodeURIComponent(id);
1702
+ var body = req.body || {};
1703
+ try {
1704
+ await shippingLabels.voidLabel({
1705
+ label_id: req.params.labelId,
1706
+ // A blank reason field reaches the primitive as undefined so the
1707
+ // operator-facing "reason required" message surfaces, rather than
1708
+ // the empty string slipping past the non-empty check.
1709
+ reason: (body.reason && body.reason.length) ? body.reason : undefined,
1710
+ });
1711
+ } catch (e) {
1712
+ if (!(e instanceof TypeError) && !(e && e.code && /SHIPPING_LABELS/.test(e.code))) throw e;
1713
+ return _redirect(res, "/admin/orders/" + enc + "?err=1");
1714
+ }
1715
+ b.audit.safeEmit({ action: AUDIT_NAMESPACE + ".order.shipment.label.void", outcome: "success", metadata: { id: id, label_id: req.params.labelId } });
1716
+ _redirect(res, "/admin/orders/" + enc + "?label=1");
1717
+ },
1718
+ ));
1674
1719
  }
1675
1720
 
1676
1721
  // Compose requestLabel + markPurchased into one recorded label. The
@@ -1713,6 +1758,206 @@ function mount(router, deps) {
1713
1758
  });
1714
1759
  }
1715
1760
 
1761
+ // ---- shipping labels (standalone back-office console) ---------------
1762
+ //
1763
+ // A cross-order view of the carrier-label store, separate from the
1764
+ // per-shipment panel on the order detail. Three screens, each composing
1765
+ // a labels-primitive read:
1766
+ // - /admin/shipping-labels — a status-filtered list. The
1767
+ // primitive exposes a list read per backable status: `pending`
1768
+ // (pendingLabels) and `voided` (voidedInWindow over a date range).
1769
+ // There is no cross-order list for purchased/used labels — those
1770
+ // are reached from their order detail — so the filter offers the
1771
+ // two engine-backed views, defaulting to pending.
1772
+ // - /admin/shipping-labels/costs — broker-spend report grouped by
1773
+ // broker + currency over a date range (costsByPeriod).
1774
+ // - /admin/shipping-labels/pending — the mint queue (pendingLabels,
1775
+ // capped at 200) the operator's broker worker drains.
1776
+ // Mounted only when the labels primitive is wired. Every HTML handler
1777
+ // parses its from/to/carrier query params defensively: a malformed value
1778
+ // re-renders the page with a correction notice (never a 500). The bearer
1779
+ // JSON contract returns the same composed payload.
1780
+ if (shippingLabels) {
1781
+ // Resolve a {from, to} epoch-ms window from the query string, accepting
1782
+ // either raw epoch-ms (from/to — machine clients) or calendar dates
1783
+ // (from-date/to-date — the browser date inputs). `to-date` is the
1784
+ // inclusive end day, advanced to the next UTC midnight. Throws TypeError
1785
+ // on a malformed value; defaults to the trailing 30 days. Mirrors the
1786
+ // reports window resolver so both report surfaces parse identically.
1787
+ function _labelWindow(url) {
1788
+ var from = _parseEpochMs(url && url.searchParams.get("from"), "from");
1789
+ var to = _parseEpochMs(url && url.searchParams.get("to"), "to");
1790
+ if (from == null) from = _parseDateParam(url && url.searchParams.get("from-date"), "from");
1791
+ if (to == null) {
1792
+ var toDate = _parseDateParam(url && url.searchParams.get("to-date"), "to");
1793
+ if (toDate != null) to = toDate + b.constants.TIME.days(1);
1794
+ }
1795
+ var now = Date.now();
1796
+ return {
1797
+ to: to == null ? now : to,
1798
+ from: from == null ? (now - b.constants.TIME.days(30)) : from,
1799
+ };
1800
+ }
1801
+
1802
+ // The status filter on the standalone list — only the values the
1803
+ // primitive exposes a cross-order list read for.
1804
+ function _labelStatusParam(url) {
1805
+ var raw = url && url.searchParams.get("status");
1806
+ if (raw == null || raw === "") return "pending";
1807
+ if (raw !== "pending" && raw !== "voided") {
1808
+ throw new TypeError("admin: status must be one of pending, voided");
1809
+ }
1810
+ return raw;
1811
+ }
1812
+
1813
+ // Optional carrier filter for the costs report. Validated against the
1814
+ // primitive's frozen enum so a bad value is a notice, not a 500.
1815
+ function _labelCarrierParam(url) {
1816
+ var raw = url && url.searchParams.get("carrier");
1817
+ if (raw == null || raw === "") return null;
1818
+ if (shippingLabels.CARRIERS.indexOf(raw) === -1) {
1819
+ throw new TypeError("admin: carrier must be one of " + shippingLabels.CARRIERS.join(", "));
1820
+ }
1821
+ return raw;
1822
+ }
1823
+
1824
+ // Compose the list payload for the chosen status. `pending` drains the
1825
+ // queue (limit 200, ignoring the window — a pending label has no
1826
+ // purchased/voided timestamp to range on); `voided` ranges voided_at
1827
+ // over the window.
1828
+ async function _labelListPayload(status, win) {
1829
+ if (status === "voided") {
1830
+ var voided = await shippingLabels.voidedInWindow({ from: win.from, to: win.to });
1831
+ return { status: "voided", from: win.from, to: win.to, labels: voided };
1832
+ }
1833
+ var pending = await shippingLabels.pendingLabels({ limit: MAX_LABEL_LIST_LIMIT });
1834
+ return { status: "pending", from: win.from, to: win.to, labels: pending };
1835
+ }
1836
+
1837
+ router.get("/admin/shipping-labels", _pageOrApi(true,
1838
+ R(async function (req, res) {
1839
+ var url = req.url ? new URL(req.url, "http://localhost") : null;
1840
+ var status, win;
1841
+ try { status = _labelStatusParam(url); win = _labelWindow(url); }
1842
+ catch (e) { if (e instanceof TypeError) return _problem(res, 400, "bad-request", e.message); throw e; }
1843
+ var payload;
1844
+ try { payload = await _labelListPayload(status, win); }
1845
+ catch (e) { if (e instanceof TypeError) return _problem(res, 400, "bad-request", e.message); throw e; }
1846
+ _json(res, 200, payload);
1847
+ }),
1848
+ async function (req, res) {
1849
+ var url = req.url ? new URL(req.url, "http://localhost") : null;
1850
+ var status = "pending", notice = null;
1851
+ var win = { to: Date.now(), from: Date.now() - b.constants.TIME.days(30) };
1852
+ try { status = _labelStatusParam(url); win = _labelWindow(url); }
1853
+ catch (e) {
1854
+ if (!(e instanceof TypeError)) throw e;
1855
+ notice = e.message.replace(/^admin:\s*/, "");
1856
+ }
1857
+ var payload;
1858
+ try { payload = await _labelListPayload(status, win); }
1859
+ catch (e2) {
1860
+ if (!(e2 instanceof TypeError)) throw e2;
1861
+ // A bad range that slipped past the param parse (primitive
1862
+ // re-validates from < to) → fall back to the default window.
1863
+ win = { to: Date.now(), from: Date.now() - b.constants.TIME.days(30) };
1864
+ notice = e2.message.replace(/^shipping-labels:\s*/, "");
1865
+ payload = await _labelListPayload(status, win);
1866
+ }
1867
+ _sendHtml(res, 200, renderAdminShippingLabels({
1868
+ shop_name: deps.shop_name, nav_available: navAvailable,
1869
+ payload: payload, notice: notice,
1870
+ }));
1871
+ },
1872
+ ));
1873
+
1874
+ router.get("/admin/shipping-labels/pending", _pageOrApi(true,
1875
+ R(async function (req, res) {
1876
+ var rows;
1877
+ try { rows = await shippingLabels.pendingLabels({ limit: MAX_LABEL_LIST_LIMIT }); }
1878
+ catch (e) { if (e instanceof TypeError) return _problem(res, 400, "bad-request", e.message); throw e; }
1879
+ _json(res, 200, { limit: MAX_LABEL_LIST_LIMIT, labels: rows });
1880
+ }),
1881
+ async function (req, res) {
1882
+ var rows = [], notice = null;
1883
+ try { rows = await shippingLabels.pendingLabels({ limit: MAX_LABEL_LIST_LIMIT }); }
1884
+ catch (e) {
1885
+ if (!(e instanceof TypeError)) throw e;
1886
+ notice = e.message.replace(/^shipping-labels:\s*/, "");
1887
+ }
1888
+ _sendHtml(res, 200, renderAdminShippingLabelsPending({
1889
+ shop_name: deps.shop_name, nav_available: navAvailable,
1890
+ labels: rows, notice: notice,
1891
+ }));
1892
+ },
1893
+ ));
1894
+
1895
+ router.get("/admin/shipping-labels/costs", _pageOrApi(true,
1896
+ R(async function (req, res) {
1897
+ var url = req.url ? new URL(req.url, "http://localhost") : null;
1898
+ var win, carrier;
1899
+ try { win = _labelWindow(url); carrier = _labelCarrierParam(url); }
1900
+ catch (e) { if (e instanceof TypeError) return _problem(res, 400, "bad-request", e.message); throw e; }
1901
+ var report;
1902
+ try { report = await _labelCostsReport(win, carrier); }
1903
+ catch (e) { if (e instanceof TypeError) return _problem(res, 400, "bad-request", e.message); throw e; }
1904
+ _json(res, 200, report);
1905
+ }),
1906
+ async function (req, res) {
1907
+ var url = req.url ? new URL(req.url, "http://localhost") : null;
1908
+ var notice = null, carrier = null;
1909
+ var win = { to: Date.now(), from: Date.now() - b.constants.TIME.days(30) };
1910
+ try { win = _labelWindow(url); carrier = _labelCarrierParam(url); }
1911
+ catch (e) {
1912
+ if (!(e instanceof TypeError)) throw e;
1913
+ notice = e.message.replace(/^admin:\s*/, "");
1914
+ }
1915
+ var report;
1916
+ try { report = await _labelCostsReport(win, carrier); }
1917
+ catch (e2) {
1918
+ if (!(e2 instanceof TypeError)) throw e2;
1919
+ win = { to: Date.now(), from: Date.now() - b.constants.TIME.days(30) };
1920
+ carrier = null;
1921
+ notice = e2.message.replace(/^shipping-labels:\s*/, "");
1922
+ report = await _labelCostsReport(win, carrier);
1923
+ }
1924
+ _sendHtml(res, 200, renderAdminShippingLabelCosts({
1925
+ shop_name: deps.shop_name, nav_available: navAvailable,
1926
+ report: report, carriers: shippingLabels.CARRIERS, notice: notice,
1927
+ }));
1928
+ },
1929
+ ));
1930
+ }
1931
+
1932
+ // Compose the broker-spend report: the per-(broker, currency) aggregate
1933
+ // from costsByPeriod plus a per-currency rollup of the gross spend +
1934
+ // label count across the window. `_strictMinorInt`-safe — the primitive
1935
+ // already returns integer minor units; the rollup only sums them.
1936
+ async function _labelCostsReport(win, carrier) {
1937
+ var opts2 = { from: win.from, to: win.to };
1938
+ if (carrier) opts2.carrier = carrier;
1939
+ var rows = await shippingLabels.costsByPeriod(opts2);
1940
+ var byCurrency = {};
1941
+ for (var i = 0; i < rows.length; i += 1) {
1942
+ var r = rows[i];
1943
+ var cur = r.currency || "USD";
1944
+ if (!byCurrency[cur]) byCurrency[cur] = { currency: cur, total_minor: 0, label_count: 0 };
1945
+ // costsByPeriod coerces these to plain numbers already; treat them as
1946
+ // integer minor units (admin never renders raw broker prose here).
1947
+ byCurrency[cur].total_minor += _strictMinorInt(r.total_minor, "shippingLabels", "total_minor");
1948
+ byCurrency[cur].label_count += _strictMinorInt(r.label_count, "shippingLabels", "label_count");
1949
+ }
1950
+ var totals = Object.keys(byCurrency).map(function (k) { return byCurrency[k]; });
1951
+ totals.sort(function (a, c) { return a.currency < c.currency ? -1 : a.currency > c.currency ? 1 : 0; });
1952
+ return {
1953
+ from: win.from,
1954
+ to: win.to,
1955
+ carrier: carrier || null,
1956
+ by_broker: rows,
1957
+ totals: totals,
1958
+ };
1959
+ }
1960
+
1716
1961
  // ---- split shipments (order-detail planner) -------------------------
1717
1962
  //
1718
1963
  // Splits one order into N parcels: ship some lines now, the rest later.
@@ -5894,6 +6139,7 @@ var ADMIN_NAV_ITEMS = [
5894
6139
  { key: "tax", href: "/admin/tax-rates", label: "Tax", requires: "taxRates" },
5895
6140
  { key: "tax-filings", href: "/admin/tax-filings", label: "Tax filings", requires: "salesTaxFilings" },
5896
6141
  { key: "shipping", href: "/admin/shipping", label: "Shipping", requires: "shippingZones" },
6142
+ { key: "shipping-labels", href: "/admin/shipping-labels", label: "Shipping labels", requires: "shippingLabels" },
5897
6143
  { key: "pick-lists", href: "/admin/pick-lists", label: "Pick lists", requires: "pickLists" },
5898
6144
  { key: "announcements", href: "/admin/announcements", label: "Announcements", requires: "announcementBar" },
5899
6145
  { key: "surveys", href: "/admin/surveys", label: "Surveys", requires: "customerSurveys" },
@@ -6296,6 +6542,173 @@ function renderAdminReports(opts) {
6296
6542
  return _renderAdminShell(opts.shop_name, "Reports", body, "reports", opts.nav_available);
6297
6543
  }
6298
6544
 
6545
+ // A single shipping-label row for the standalone cross-order tables. Shows
6546
+ // carrier + service, tracking number, cost (via pricing.format from the
6547
+ // label's own minor units + currency), the broker it came from, its status
6548
+ // pill, and a link to the broker's label URL. Read-only — lifecycle actions
6549
+ // (mark used / void) live on the order detail where the shipment context is.
6550
+ function _shippingLabelRow(l) {
6551
+ var costCell = (l.cost_minor != null && l.currency)
6552
+ ? _htmlEscape(pricing.format(l.cost_minor, l.currency))
6553
+ : "<span class=\"meta\">—</span>";
6554
+ var trackCell = l.tracking_number
6555
+ ? "<code class=\"order-id\">" + _htmlEscape(String(l.tracking_number)) + "</code>"
6556
+ : "<span class=\"meta\">—</span>";
6557
+ var urlCell = l.label_url
6558
+ ? "<a class=\"order-id\" href=\"" + _htmlEscape(String(l.label_url)) + "\" rel=\"noopener nofollow\" target=\"_blank\">Open ↗</a>"
6559
+ : "<span class=\"meta\">—</span>";
6560
+ var viaCell = l.purchased_via
6561
+ ? _htmlEscape(String(l.purchased_via))
6562
+ : "<span class=\"meta\">—</span>";
6563
+ return "<tr>" +
6564
+ "<td>" + _htmlEscape(String(l.carrier)) + " <span class=\"meta\">" + _htmlEscape(String(l.service_level || "")) + "</span></td>" +
6565
+ "<td>" + trackCell + "</td>" +
6566
+ "<td class=\"num\">" + costCell + "</td>" +
6567
+ "<td>" + viaCell + "</td>" +
6568
+ "<td><span class=\"status-pill " + _htmlEscape(String(l.status)) + "\">" + _htmlEscape(String(l.status)) + "</span></td>" +
6569
+ "<td>" + urlCell + "</td>" +
6570
+ "<td>" + _htmlEscape(_fmtDate(l.created_at)) + "</td>" +
6571
+ "</tr>";
6572
+ }
6573
+
6574
+ // Sub-nav shared by the three standalone shipping-label screens — the
6575
+ // list, the broker-spend report, and the mint queue.
6576
+ function _shippingLabelSubnav(active) {
6577
+ var tabs = [
6578
+ ["list", "/admin/shipping-labels", "All labels"],
6579
+ ["pending", "/admin/shipping-labels/pending", "Mint queue"],
6580
+ ["costs", "/admin/shipping-labels/costs", "Broker spend"],
6581
+ ];
6582
+ return "<div class=\"order-filters\">" + tabs.map(function (t) {
6583
+ return "<a class=\"chip" + (active === t[0] ? " chip--on" : "") + "\" href=\"" + t[1] + "\">" + _htmlEscape(t[2]) + "</a>";
6584
+ }).join("") + "</div>";
6585
+ }
6586
+
6587
+ // Standalone cross-order label list. The primitive exposes a list read for
6588
+ // two statuses — pending (the mint queue) and voided (over a date range) —
6589
+ // so the status filter offers those two. Purchased + used labels are
6590
+ // reached from their order's detail panel, not browsed cross-order. A date
6591
+ // range narrows the voided view (ignored for pending, which has no
6592
+ // purchased/voided timestamp to range on).
6593
+ function renderAdminShippingLabels(opts) {
6594
+ opts = opts || {};
6595
+ var payload = opts.payload || { status: "pending", labels: [], from: Date.now(), to: Date.now() };
6596
+ var notice = opts.notice ? "<div class=\"banner banner--warn\">" + _htmlEscape(opts.notice) + "</div>" : "";
6597
+ var labels = payload.labels || [];
6598
+ var status = payload.status || "pending";
6599
+
6600
+ var statuses = [["pending", "Pending"], ["voided", "Voided"]];
6601
+ var chips = "<div class=\"order-filters\">" + statuses.map(function (s) {
6602
+ return "<a class=\"chip" + (status === s[0] ? " chip--on" : "") + "\" href=\"/admin/shipping-labels?status=" + encodeURIComponent(s[0]) + "\">" + _htmlEscape(s[1]) + "</a>";
6603
+ }).join("") + "</div>";
6604
+
6605
+ // Date-range form only narrows the voided view (GET so the window lives in
6606
+ // the URL). For pending it's still shown for consistency but the window is
6607
+ // not applied.
6608
+ var fromVal = _dateInputValue(payload.from);
6609
+ var toVal = _dateInputValue((payload.to || Date.now()) - b.constants.TIME.days(1));
6610
+ var rangeForm =
6611
+ "<form method=\"get\" action=\"/admin/shipping-labels\" class=\"order-filters\">" +
6612
+ "<input type=\"hidden\" name=\"status\" value=\"" + _htmlEscape(status) + "\">" +
6613
+ "<label class=\"form-field\"><span>From</span><input type=\"date\" name=\"from-date\" value=\"" + _htmlEscape(fromVal) + "\"></label>" +
6614
+ "<label class=\"form-field\"><span>To</span><input type=\"date\" name=\"to-date\" value=\"" + _htmlEscape(toVal) + "\"></label>" +
6615
+ "<button class=\"btn\" type=\"submit\">Apply</button>" +
6616
+ "</form>";
6617
+
6618
+ var rows = labels.map(_shippingLabelRow).join("");
6619
+ var table = labels.length
6620
+ ? "<div class=\"panel\"><table><thead><tr><th scope=\"col\">Carrier</th><th scope=\"col\">Tracking</th><th scope=\"col\" class=\"num\">Cost</th><th scope=\"col\">Broker</th><th scope=\"col\">Status</th><th scope=\"col\">Label</th><th scope=\"col\">Created</th></tr></thead><tbody>" + rows + "</tbody></table></div>"
6621
+ : "<p class=\"empty\">No " + _htmlEscape(status) + " labels" + (status === "voided" ? " in this window" : "") + ".</p>";
6622
+
6623
+ var body =
6624
+ "<section><h2>Shipping labels</h2>" + notice +
6625
+ _shippingLabelSubnav("list") +
6626
+ chips +
6627
+ (status === "voided" ? rangeForm : "") +
6628
+ table +
6629
+ "</section>";
6630
+ return _renderAdminShell(opts.shop_name, "Shipping labels", body, "shipping-labels", opts.nav_available);
6631
+ }
6632
+
6633
+ // The mint queue: pending labels awaiting a broker mint, oldest first. The
6634
+ // operator's broker worker drains this (requestLabel wrote each row;
6635
+ // markPurchased clears it). Read-only console view of the same queue.
6636
+ function renderAdminShippingLabelsPending(opts) {
6637
+ opts = opts || {};
6638
+ var labels = opts.labels || [];
6639
+ var notice = opts.notice ? "<div class=\"banner banner--warn\">" + _htmlEscape(opts.notice) + "</div>" : "";
6640
+ var rows = labels.map(_shippingLabelRow).join("");
6641
+ var table = labels.length
6642
+ ? "<div class=\"panel\"><table><thead><tr><th scope=\"col\">Carrier</th><th scope=\"col\">Tracking</th><th scope=\"col\" class=\"num\">Cost</th><th scope=\"col\">Broker</th><th scope=\"col\">Status</th><th scope=\"col\">Label</th><th scope=\"col\">Created</th></tr></thead><tbody>" + rows + "</tbody></table></div>"
6643
+ : "<p class=\"empty\">No labels awaiting a broker mint.</p>";
6644
+ var body =
6645
+ "<section><h2>Shipping labels</h2>" + notice +
6646
+ _shippingLabelSubnav("pending") +
6647
+ "<p class=\"meta\">Pending labels awaiting a broker mint, oldest first (up to " + String(MAX_LABEL_LIST_LIMIT) + ").</p>" +
6648
+ table +
6649
+ "</section>";
6650
+ return _renderAdminShell(opts.shop_name, "Shipping labels", body, "shipping-labels", opts.nav_available);
6651
+ }
6652
+
6653
+ // Broker-spend report: gross label spend + label count grouped by broker +
6654
+ // currency over a date range, with an optional carrier filter and a
6655
+ // per-currency headline rollup. Money formats through the same pricing
6656
+ // helper the order + reports pages use.
6657
+ function renderAdminShippingLabelCosts(opts) {
6658
+ opts = opts || {};
6659
+ var report = opts.report || { from: Date.now(), to: Date.now(), by_broker: [], totals: [], carrier: null };
6660
+ var carriers = opts.carriers || [];
6661
+ var notice = opts.notice ? "<div class=\"banner banner--warn\">" + _htmlEscape(opts.notice) + "</div>" : "";
6662
+
6663
+ var fromVal = _dateInputValue(report.from);
6664
+ var toVal = _dateInputValue(report.to - b.constants.TIME.days(1));
6665
+ var carrierOpts = "<option value=\"\">All carriers</option>" + carriers.map(function (c) {
6666
+ return "<option value=\"" + _htmlEscape(c) + "\"" + (report.carrier === c ? " selected" : "") + ">" + _htmlEscape(c) + "</option>";
6667
+ }).join("");
6668
+ var rangeForm =
6669
+ "<form method=\"get\" action=\"/admin/shipping-labels/costs\" class=\"order-filters\">" +
6670
+ "<label class=\"form-field\"><span>From</span><input type=\"date\" name=\"from-date\" value=\"" + _htmlEscape(fromVal) + "\"></label>" +
6671
+ "<label class=\"form-field\"><span>To</span><input type=\"date\" name=\"to-date\" value=\"" + _htmlEscape(toVal) + "\"></label>" +
6672
+ "<label class=\"form-field\"><span>Carrier</span><select name=\"carrier\">" + carrierOpts + "</select></label>" +
6673
+ "<button class=\"btn\" type=\"submit\">Apply</button>" +
6674
+ "</form>";
6675
+
6676
+ // Per-currency headline cards — total gross spend + label count.
6677
+ var totals = report.totals || [];
6678
+ var statsBlock = totals.length
6679
+ ? "<section><h2>Total spend</h2><div class=\"stat-grid\">" + totals.map(function (t) {
6680
+ return _statCard("Spend (" + t.currency + ")", pricing.format(t.total_minor, t.currency)) +
6681
+ _statCard("Labels (" + t.currency + ")", String(t.label_count));
6682
+ }).join("") + "</div></section>"
6683
+ : "<section><h2>Total spend</h2><p class=\"empty\">No labels purchased in this window.</p></section>";
6684
+
6685
+ var byBroker = report.by_broker || [];
6686
+ var brokerRows = byBroker.length
6687
+ ? byBroker.map(function (r) {
6688
+ return "<tr>" +
6689
+ "<td>" + _htmlEscape(String(r.purchased_via)) + "</td>" +
6690
+ "<td>" + _htmlEscape(String(r.currency)) + "</td>" +
6691
+ "<td class=\"num\">" + _htmlEscape(String(r.label_count)) + "</td>" +
6692
+ "<td class=\"num\">" + _htmlEscape(pricing.format(r.total_minor, r.currency)) + "</td>" +
6693
+ "</tr>";
6694
+ }).join("")
6695
+ : "<tr><td colspan=\"4\" class=\"empty\">No labels purchased in this window.</td></tr>";
6696
+ var brokerBlock =
6697
+ "<section><h2>By broker</h2><div class=\"panel\">" +
6698
+ "<table><thead><tr><th scope=\"col\">Broker</th><th scope=\"col\">Currency</th><th scope=\"col\" class=\"num\">Labels</th><th scope=\"col\" class=\"num\">Spend</th></tr></thead><tbody>" + brokerRows + "</tbody></table>" +
6699
+ "</div></section>";
6700
+
6701
+ var body =
6702
+ "<section><h2>Shipping labels</h2>" + notice +
6703
+ _shippingLabelSubnav("costs") +
6704
+ "<p class=\"meta\">Window: " + _htmlEscape(_fmtDate(report.from)) + " → " + _htmlEscape(_fmtDate(report.to)) +
6705
+ (report.carrier ? " · carrier " + _htmlEscape(String(report.carrier)) : "") + "</p>" +
6706
+ rangeForm +
6707
+ "</section>" +
6708
+ statsBlock + brokerBlock;
6709
+ return _renderAdminShell(opts.shop_name, "Shipping labels", body, "shipping-labels", opts.nav_available);
6710
+ }
6711
+
6299
6712
  function renderAdminOrder(opts) {
6300
6713
  opts = opts || {};
6301
6714
  var o = opts.order;
@@ -6506,17 +6919,26 @@ function _orderLabelPanel(orderId, shipment, carriers, packageTypes, purchasedVi
6506
6919
  var urlCell = l.label_url
6507
6920
  ? "<a class=\"order-id\" href=\"" + _htmlEscape(String(l.label_url)) + "\" rel=\"noopener nofollow\" target=\"_blank\">Open ↗</a>"
6508
6921
  : "<span class=\"meta\">—</span>";
6509
- var usedForm = (l.status === "purchased")
6510
- ? "<form method=\"post\" action=\"/admin/orders/" + _htmlEscape(orderId) + "/labels/" + _htmlEscape(l.id) + "/used\" class=\"form-inline\">" +
6511
- "<button class=\"btn btn--ghost\" type=\"submit\">Mark used</button></form>"
6512
- : "<span class=\"meta\">—</span>";
6922
+ // A purchased label can be marked used (handed to the carrier) OR voided
6923
+ // (broker void, within the 30-day window). The void form carries a
6924
+ // required reason input so the operator records WHY before the POST; the
6925
+ // primitive refuses a blank/expired void with a 400 → notice.
6926
+ var actionCell = "<span class=\"meta\">—</span>";
6927
+ if (l.status === "purchased") {
6928
+ actionCell =
6929
+ "<form method=\"post\" action=\"/admin/orders/" + _htmlEscape(orderId) + "/labels/" + _htmlEscape(l.id) + "/used\" class=\"form-inline\">" +
6930
+ "<button class=\"btn btn--ghost\" type=\"submit\">Mark used</button></form> " +
6931
+ "<form method=\"post\" action=\"/admin/orders/" + _htmlEscape(orderId) + "/labels/" + _htmlEscape(l.id) + "/void\" class=\"form-inline\">" +
6932
+ "<input type=\"text\" name=\"reason\" placeholder=\"Void reason\" maxlength=\"512\" aria-label=\"Void reason\" required>" +
6933
+ "<button class=\"btn btn--danger\" type=\"submit\">Void</button></form>";
6934
+ }
6513
6935
  return "<tr>" +
6514
6936
  "<td>" + _htmlEscape(String(l.carrier)) + " <span class=\"meta\">" + _htmlEscape(String(l.service_level || "")) + "</span></td>" +
6515
6937
  "<td>" + trackCell + "</td>" +
6516
6938
  "<td class=\"num\">" + costCell + "</td>" +
6517
6939
  "<td><span class=\"status-pill " + _htmlEscape(l.status) + "\">" + _htmlEscape(l.status) + "</span></td>" +
6518
6940
  "<td>" + urlCell + "</td>" +
6519
- "<td>" + usedForm + "</td>" +
6941
+ "<td>" + actionCell + "</td>" +
6520
6942
  "</tr>";
6521
6943
  }).join("");
6522
6944
  var labelsTable = labels.length
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.3.4",
2
+ "version": "0.3.6",
3
3
  "assets": {
4
4
  "css/admin.css": {
5
5
  "integrity": "sha384-1SIn6oAf1DjECbRfKENZasdKHJiywGdXR58wn0hsFGcdVHzUmvfgMkEz5ANIAZJ3",
@@ -3,8 +3,8 @@
3
3
  "_about": "blamejs.shop vendors a single framework — blamejs — which itself bundles every server-side crypto/identity dependency. The transitive packages blamejs ships are surfaced in its own MANIFEST.json at lib/vendor/blamejs/lib/vendor/MANIFEST.json — Trivy / Grype rely on that nested data for CVE attribution.",
4
4
  "packages": {
5
5
  "blamejs": {
6
- "version": "0.13.46",
7
- "tag": "v0.13.46",
6
+ "version": "0.14.5",
7
+ "tag": "v0.14.5",
8
8
  "license": "Apache-2.0",
9
9
  "author": "blamejs contributors",
10
10
  "source": "https://github.com/blamejs/blamejs",
@@ -13,7 +13,7 @@
13
13
  "server": "lib/vendor/blamejs/"
14
14
  },
15
15
  "bundler": "shallow git clone of release tag from github.com/blamejs/blamejs",
16
- "bundledAt": "2026-05-29"
16
+ "bundledAt": "2026-05-30"
17
17
  }
18
18
  }
19
19
  }
@@ -6,6 +6,20 @@ Pre-1.0 the surface is intentionally evolving — every release may
6
6
  change something operators depend on. Read each entry before
7
7
  upgrading across more than a few patches at a time.
8
8
 
9
+ ## v0.14.x
10
+
11
+ - v0.14.5 (2026-05-30) — **Finished cleaning up the mislabeled byte-literal lint suppressions, with no API or behavior changes.** A follow-up to the byte-literal lint tightening. The remaining suppression comments that named the byte-literal check on values that are not byte sizes — JSON-RPC error codes, HTTP status codes, octet ranges, day-in-milliseconds constants — are removed, keeping their explanatory text and any correctly-named companion suppression. Every byte-literal suppression that remains is now on genuine 1024-scale byte arithmetic. Source-comment hygiene only. **Changed:** *Remaining mislabeled byte-literal suppressions removed* — The byte-literal lint was previously a check on any multiple-of-8 integer, so suppression comments naming it were scattered across non-byte values. The last of those (in a handful of files, in mixed comment formats) are now removed — their explanatory text is retained as plain comments, and any correctly-named companion suppression is kept. The only byte-literal suppressions that remain are on genuine 1024-scale byte arithmetic. No change to any exported API, error code, wire format, or runtime behavior.
12
+
13
+ - v0.14.4 (2026-05-30) — **Removed three pieces of dead code from the SAML, TLS, and JMAP surfaces; no API or behavior changes.** Cleanup of unreachable code. A reverse signature-algorithm lookup in the SAML verifier was never called — the actual verification path resolves the algorithm through the supported-signature table — so it is removed and a stale comment that referenced it is corrected. A leftover no-op placeholder in the TLS certificate re-encode path (a zero-length slice that was assigned and discarded) is removed, leaving the verbatim extension re-encode it sat next to. An unused JMAP well-known-path constant that existed only to be discarded is removed. None of this changes any exported API, error code, wire format, or runtime behavior. **Removed:** *Unreachable code in SAML, TLS, and JMAP* — Removed `_sigAlgFromUri` from the SAML module (a reverse alg lookup that was never called — the embedded XML-DSig verifier resolves the algorithm via the supported-signature table, and the redirect-binding path uses the forward `_sigAlgUrn`), a discarded zero-length-slice placeholder in the TLS certificate extension re-encode path, and an unused well-known-path constant in the JMAP server. Internal cleanup only — no change to any exported API, error code, wire format, or runtime behavior.
14
+
15
+ - v0.14.3 (2026-05-30) — **A codebase check now ensures every lint-suppression marker names a real check, so a typo can't silently disable a guard.** Source files suppress an individual lint with an `// allow:<class>` comment. If the class is mistyped or stale, the comment suppresses nothing — the check it names does not exist — so the issue it was meant to explain ships unflagged. A new codebase check now verifies every `// allow:<class>` marker names a registered check class and fails if it does not, with the full set of valid classes maintained as an explicit registry. Two markers that named a non-kebab class were corrected as part of this. No runtime, API, or wire-format changes. **Detectors:** *Lint-suppression markers must name a registered check* — A new check flags any `// allow:<class>` suppression comment whose class is not one of the registered check classes — catching typos and stale markers (for example a marker that named a check which was later renamed) that would otherwise silently disable the guard they appear to explain. The valid classes are kept as an explicit registry, so adding a check with a new allow-class is a one-line registration. Source-comment hygiene only — no change to any exported API, error code, wire format, or runtime behavior.
16
+
17
+ - v0.14.2 (2026-05-29) — **Internal lint hygiene: the byte-literal check now flags only genuine byte-scale arithmetic, with no API or behavior changes.** A no-behavior-change cleanup of the source tree's internal lint markers. The byte-literal lint previously flagged every integer that was a multiple of 8 — which is most numbers — so the source carried a large number of suppression comments on values that were not byte sizes at all (status codes, counts, lengths, radixes, opcodes). The lint now flags only 1024-scale byte arithmetic (the case the C.BYTES.kib/mib/gib helpers exist to replace), and the now-unnecessary suppression comments have been removed while keeping their explanatory text. Several lint-suppression markers that named a check that does not exist were also corrected. None of this changes any API, wire format, or runtime behavior. **Changed:** *Source-tree lint markers cleaned up* — The internal byte-literal lint was tightened to flag only genuine byte-scale (`* 1024`) arithmetic, and the suppression comments it previously required on non-byte integers were removed (their explanatory text is retained as plain comments). A handful of suppression markers that referenced a non-existent check were pointed at the correct one or removed. This is source-comment hygiene only — there is no change to any exported API, error code, wire format, or runtime behavior.
18
+
19
+ - v0.14.1 (2026-05-29) — **Correctness fixes: JAR request-object typ enforcement, byte-faithful PGP multipart/signed, and SAML InResponseTo binding.** A set of correctness fixes across the auth, mail-crypto, TLS, and encoder surfaces. The most important: JWT-secured authorization requests (RFC 9101) now require the request object to carry the registered `oauth-authz-req+jwt` typ, closing a cross-JWT-confusion vector; the PGP multipart/signed wrapper is now assembled byte-faithfully so non-ASCII signed content can't be corrupted; and SAML response verification now returns the InResponseTo of the SubjectConfirmation that actually validated. Two of these change behavior — see Changed — and are bug fixes rather than new features. **Changed:** *JAR parsing rejects untyped request objects (breaking)* — Following the typ enforcement above, a request object whose header omits `typ` is now refused. An authorization server whose clients sign request objects without the `oauth-authz-req+jwt` typ must update those clients to set it. · *PGP sign() returns multipartSigned as a Buffer (breaking)* — `b.mail.crypto.pgp.sign(...).multipartSigned` is now a Buffer instead of a string. The OpenPGP signature covers the signed-part bytes exactly, and a JS-string round trip through latin1/utf8 could corrupt non-ASCII signed content and break verification, so the RFC 3156 multipart/signed wrapper is now assembled as bytes. Code that wrote the previous string to the wire works unchanged when it writes the Buffer; code that did string operations on the value should treat it as a Buffer (its `indexOf` / `toString` still work). **Fixed:** *SAML response verification binds InResponseTo to the validated confirmation* — `verifyResponse` returned the InResponseTo of the first SubjectConfirmationData in the assertion rather than of the SubjectConfirmation that actually passed bearer validation. When a response carried more than one SubjectConfirmation, the returned value could come from a non-validated confirmation. It is now the InResponseTo of the confirmation that validated. · *checkServerIdentity9525 emits the documented CN-fallback audit code* — A CN-only legacy certificate (a Common Name present, no subjectAltName) is now refused by the exported `b.network.tls.checkServerIdentity9525` with the distinct `tls/pkix-cn-fallback-refused` code its documentation promised, so audit logs can tell a CN-only certificate apart from one carrying neither a SAN nor a CN (which still yields `tls/pkix-san-required`). The accept/refuse outcome is unchanged — both are refused; only the audit granularity improved. · *OIDC back-channel logout / JARM no longer accept dead override parameters* — `verifyBackchannelLogoutToken` and `parseJarmResponse` passed `acceptedAlgs` / `jwksUri` / `maxClockSkewMs` through to the ID-token verifier, which ignored them and applied the configured (create()-time) values. The pass-throughs are removed so the code no longer reads as if those can be overridden per call; the configured trust anchor was — and remains — what applies. · *Queue lease failures are logged* — The consumer loop's lease-acquisition error path swallowed the backend error silently; it now logs at debug so a flapping backend that has not yet tripped the circuit breaker is visible. · *Protobuf and ASN.1 encoders reject out-of-range tags* — The protobuf tag encoder rejected nothing and would have emitted a wrong tag for field numbers at or above 2^28 (where the 32-bit shift overflows); the ASN.1 context-tag writers silently truncated tag numbers above 30 (which require the multi-byte high-tag-number form). Both now throw a RangeError rather than encode silently-wrong output. The values these encoders serve are well within range, so no current caller is affected. · *oid4vci proofAlgorithms default documented accurately* — The documented default proof-algorithm list now matches the code (`["ES256", "ES384", "EdDSA"]`); the doc previously omitted EdDSA, which the runtime has always accepted by default. **Security:** *JAR request objects must carry the registered typ (RFC 9101)* — `b.auth.jar.parse` now requires the request-object JWS header to carry `typ: "oauth-authz-req+jwt"` (with or without the `application/` prefix); a request object with an absent or different typ is refused with `auth-jar/bad-typ`. RFC 9101 §10.8 specifies this media type precisely to stop a JWT minted for another purpose (an ID token, an access token, a logout token) and signed by the same client key from being replayed as a request object. The existing `iss` / `aud` / `client_id` bindings already constrained that; this restores the explicit type check as well. This is stricter than before — see Changed.
20
+
21
+ - v0.14.0 (2026-05-29) — **Operator-configurable header and field names across SSE, request-id, rate-limit, age-gate, AI-Act disclosure, GraphQL federation, and the HTTP cache.** This release makes operator-facing identifiers that were hardcoded configurable. The framework already let operators rename most names (CSRF cookie/field, cookie parser, i18n header/query/cookie, mTLS CA name, and so on); this closes the remaining gaps so a custom or framework-specific name is never frozen. Every new option defaults to the value emitted today, so upgrading changes no behavior — these are additive knobs. It also fixes a request-id asymmetry (the response header is now written on the same name the inbound id is read from) and wires an SSE proxy-buffering option whose escape hatch was documented but never implemented. **Added:** *Configurable cache-status header on the HTTP client* — The outbound HTTP client annotated every cached response with a hardcoded `x-blamejs-cache: HIT|MISS|STALE|REVALIDATED` header. `b.httpClient.cache.create` now takes `statusHeader` (default "x-blamejs-cache") — pass a custom name (e.g. "x-cache") to rename it, or null/false to suppress it entirely. The decision remains available programmatically on `res.cacheStatus`. · *Configurable rate-limit header names* — `b.middleware.rateLimit` emitted the de-facto `X-RateLimit-Limit` / `X-RateLimit-Remaining` headers (which are not RFC-pinned). It now accepts `headerPrefix` (default "X-RateLimit-") so operators can match the unprefixed IETF-draft `RateLimit-*` names or an upstream gateway's convention; the limit/remaining pair is always built from the same prefix. · *Configurable age-gate and AI-Act disclosure header names* — `b.middleware.ageGate` now takes `privacyPostureHeader` (default "X-Privacy-Posture"; null/false to suppress), and `b.middleware.aiActDisclosure` takes `headerPrefix` (default "AI-Act-") that prefixes the emitted Notice / Article / Policy headers. The EU AI Act mandates the disclosure, not the HTTP spelling, so operators matching a downstream convention can rename these. · *Configurable GraphQL-federation replay-nonce header* — `b.graphqlFederation.guardSdl` read the replay nonce from the Apollo-vendor `x-apollographql-router-nonce` header with no override. It now accepts `nonceHeader` (default unchanged) so an operator fronting the gateway with a non-Apollo router can point the replay check at their own header. · *SSE proxy-buffering opt-out* — `b.sse.create` and `b.middleware.sse` set `X-Accel-Buffering: no` (the nginx hint that disables proxy buffering). They now accept `proxyBuffer` (default true) — pass false when not behind nginx, or when buffering is controlled at the load balancer, to suppress the nginx-specific header. The opt-out was previously referenced in the documentation but not implemented. **Fixed:** *Request-id middleware reflects the configured header name* — `b.log.middleware` read the inbound request id from a configurable `headerName` but always wrote the response on the literal `X-Request-Id`. An operator who set a custom `headerName` (e.g. `X-Correlation-Id`) therefore read from one header and emitted another. The response is now written on the same configured name; the default remains `X-Request-Id`, so deployments that did not set `headerName` are unaffected.
22
+
9
23
  ## v0.13.x
10
24
 
11
25
  - v0.13.46 (2026-05-29) — **`createApp` now wires the documented security middleware ON by default — CSRF, CSP nonce, cookie parser, fetch-metadata, and body parser.** The README has long described a security middleware stack as "wired by createApp", but createApp only mounted request-ID, security-headers, and bot-guard by default — CSRF protection, the CSP nonce, the threat-aware cookie parser, the fetch-metadata guard, and the body parser were documented but not actually wired. This release closes that gap: createApp now mounts all of them by default, in dependency order (cookies, CSP nonce, fetch-metadata, then body parser, then CSRF last so it can read a body-field token). This is a behavior change — apps built with createApp now enforce CSRF on state-changing requests by default. Each layer is configurable via opts.middleware.<name> (operator cookie and field names flow straight through — nothing is hardcoded) or can be turned off with false, and disabling a security default now emits an app.middleware.disabled audit event. Every layer is idempotent: an operator who also mounts one of these inside opts.routes gets a no-op second mount rather than a double-apply. The default CSRF is a double-submit cookie that auto-skips requests carrying an Authorization header or no cookies at all, which are not CSRF-able, so token-authenticated API clients are not rejected. The README middleware list is now an accurate description of what createApp wires. **Added:** *Idempotent security middleware* — The cookie parser, CSP nonce, fetch-metadata, and CSRF middleware are now idempotent within a request: if one has already run (because createApp wired it and an operator also mounted it), the second instance is a no-op rather than re-parsing, re-generating a nonce, or issuing a second CSRF cookie. This lets an application compose its own middleware order on top of createApp's defaults without double-applying. The body parser already had this behavior. **Changed:** *createApp wires CSRF, CSP nonce, cookie parser, fetch-metadata, and body parser by default (breaking)* — Applications constructed with b.createApp now mount, in order: the threat-aware cookie parser, the CSP nonce generator, the fetch-metadata resource-isolation guard, the body parser (JSON / urlencoded / text / multipart), and CSRF protection — in addition to the request-ID, security-headers, and bot-guard layers already wired. The ordering guarantees CSRF runs after the body parser so a body-field token is available. This is a behavior change: state-changing requests (POST / PUT / DELETE / PATCH) that carry a session cookie are now CSRF-validated by default. Each layer is configured through opts.middleware.<name> (an object passes operator options straight through; cookie and field names are not hardcoded) or disabled with false. Operators who were mounting these middleware themselves inside opts.routes do not need to change anything — the second mount is now a no-op (see idempotency below). · *Default CSRF auto-skips token-authenticated and cookieless requests* — The CSRF middleware gains a skipStateless option (default false; createApp's default wiring sets it true). When on, token validation is skipped for requests that carry an Authorization header or no Cookie header at all — such requests are not CSRF-able, because CSRF abuses a victim's ambient cookie credential and these have none. The token is still issued on safe methods so a later cookie-authenticated browser flow works. Cross-site form CSRF is unaffected: the browser auto-sends the victim's cookies, so an attack request always carries a Cookie header and is validated. · *Disabling a default security middleware is audited* — Passing false for one of the security-on-by-default middleware (for example middleware: { csrf: false }) now emits an app.middleware.disabled audit event naming the middleware, so a weakened posture leaves a trace in the audit chain rather than being silent.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 1,
3
- "frameworkVersion": "0.13.46",
4
- "createdAt": "2026-05-30T02:15:44.237Z",
3
+ "frameworkVersion": "0.14.5",
4
+ "createdAt": "2026-05-30T14:33:33.657Z",
5
5
  "exports": {
6
6
  "a2a": {
7
7
  "type": "object",
@@ -47,15 +47,15 @@ function mintLegacyEnvelope0xE1(plaintext, recipient) {
47
47
  var nonce = bCrypto.generateBytes(C.BYTES.bytes(24));
48
48
  // Legacy 0xE1 envelope header — 4 bytes: magic, kemId, cipherId, kdfId.
49
49
  var headerAad = Buffer.from([
50
- 0xE1, // allow:raw-byte-literal — legacy 0xE1 envelope magic byte
50
+ 0xE1, // legacy 0xE1 envelope magic byte
51
51
  C.KEM_IDS.ML_KEM_1024_P384,
52
52
  C.CIPHER_IDS.XCHACHA20_POLY1305,
53
53
  C.KDF_IDS.SHAKE256,
54
54
  ]);
55
55
  var ct = xchacha20poly1305(key, nonce, headerAad).encrypt(Buffer.from(plaintext, "utf8"));
56
- var kemCtLen = Buffer.alloc(2); kemCtLen.writeUInt16BE(kem.ciphertext.length); // allow:raw-byte-literal — 16-bit length-prefix field
56
+ var kemCtLen = Buffer.alloc(2); kemCtLen.writeUInt16BE(kem.ciphertext.length); // 16-bit length-prefix field
57
57
  var ecEphDer = ephEc.publicKey;
58
- var ecEphLen = Buffer.alloc(2); ecEphLen.writeUInt16BE(ecEphDer.length); // allow:raw-byte-literal — 16-bit length-prefix field
58
+ var ecEphLen = Buffer.alloc(2); ecEphLen.writeUInt16BE(ecEphDer.length); // 16-bit length-prefix field
59
59
  return Buffer.concat([
60
60
  headerAad,
61
61
  kemCtLen, kem.ciphertext, ecEphLen, ecEphDer, nonce, Buffer.from(ct),