@blamejs/blamejs-shop 0.4.121 → 0.4.123

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 (33) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/loyalty-earn-rules.js +7 -1
  4. package/lib/order.js +23 -10
  5. package/lib/vendor/MANIFEST.json +30 -28
  6. package/lib/vendor/blamejs/CHANGELOG.md +2 -0
  7. package/lib/vendor/blamejs/api-snapshot.json +2 -2
  8. package/lib/vendor/blamejs/examples/wiki/lib/opts-resolver.js +1 -1
  9. package/lib/vendor/blamejs/examples/wiki/server.js +1 -1
  10. package/lib/vendor/blamejs/examples/wiki/src/wiki.js +1 -1
  11. package/lib/vendor/blamejs/examples/wiki/test/codebase-patterns.test.js +9 -9
  12. package/lib/vendor/blamejs/lib/acme.js +1 -1
  13. package/lib/vendor/blamejs/lib/agent-trace.js +1 -1
  14. package/lib/vendor/blamejs/lib/auth/oauth.js +2 -2
  15. package/lib/vendor/blamejs/lib/cli.js +2 -2
  16. package/lib/vendor/blamejs/lib/cluster.js +1 -1
  17. package/lib/vendor/blamejs/lib/db-schema.js +1 -1
  18. package/lib/vendor/blamejs/lib/gate-contract.js +1 -1
  19. package/lib/vendor/blamejs/lib/json-schema.js +2 -2
  20. package/lib/vendor/blamejs/lib/mcp.js +1 -1
  21. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +1 -1
  22. package/lib/vendor/blamejs/lib/module-loader.js +2 -2
  23. package/lib/vendor/blamejs/lib/retry.js +1 -1
  24. package/lib/vendor/blamejs/lib/safe-url.js +1 -1
  25. package/lib/vendor/blamejs/lib/ssrf-guard.js +1 -1
  26. package/lib/vendor/blamejs/lib/vendor-data.js +2 -2
  27. package/lib/vendor/blamejs/lib/websocket.js +1 -1
  28. package/lib/vendor/blamejs/lib/ws-client.js +1 -1
  29. package/lib/vendor/blamejs/package.json +1 -1
  30. package/lib/vendor/blamejs/release-notes/v0.15.33.json +18 -0
  31. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +74 -6
  32. package/lib/vendor/blamejs/test/layer-0-primitives/source-comment-blocks.test.js +1 -1
  33. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -8,6 +8,10 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.4.x
10
10
 
11
+ - v0.4.123 (2026-06-26) — **Vendored framework refreshed to 0.15.33.** Updates the vendored blamejs framework to 0.15.33. The upstream release is internal test-suite tooling only: it re-verifies three more of the framework's guard-suite suppression classes from scratch and renames their markers to descriptive tokens, recording the old names as retired so a re-verified class cannot inherit a stale approval. No runtime code, public API, or wire format changed upstream, so there is no runtime or behavior change for this storefront and no operator action is required. **Changed:** *Vendored framework refreshed to 0.15.33* — Refreshes the vendored blamejs framework to 0.15.33, an upstream release scoped to test-suite tooling — three more guard-suite suppression classes re-verified and their markers renamed to descriptive tokens, with the old names retired. The shipped framework runtime, public API, and wire format are unchanged, so no operator action is required.
12
+
13
+ - v0.4.122 (2026-06-26) — **Loyalty points are clawed back against the goods subtotal they were earned on, not the order's grand total.** Loyalty points are earned on an order's goods value. When an order was refunded, the points clawback was computed as a proportion of the GRAND total instead — so refunding the full goods value while keeping non-refundable shipping or tax clawed back less than all of the earned points, letting a customer keep loyalty points on goods they had fully returned (a buy-then-return rewards-farming gap). The clawback now ratios against the DISCOUNTED goods value (the subtotal minus any order discount — the cash the customer actually paid for the goods), so returning the full goods value reverses all earned points even when shipping or tax is retained; the refund is applied goods-first (capped at the goods value). Separately, the clawback's points-times-amount product is now computed in BigInt, so a very large order can no longer drift the floored result by a point. Loyalty-tender restoration (returning points that were spent at checkout) still ratios against the cash refund and is unchanged. **Fixed:** *Earned-points clawback ratios against the discounted goods value, not the grand total* — Points are awarded on an order's goods value, but the refund clawback divided the refunded amount by the order's grand total. On an order carrying tax or shipping the grand total is larger than the goods value, so refunding the full goods value never reached a 100% clawback — the customer kept a slice of points on goods they fully returned. The refund path now passes the DISCOUNTED goods value — the subtotal minus any order discount, i.e. the cash actually paid for the goods — as the clawback base (the refund is treated goods-first and capped at that value), so a full goods return reverses all earned points even when non-refundable shipping or tax is kept, and a discounted order is no longer under-clawed. The terminal full-refund edge still claws 100%, and loyalty points spent as a checkout tender are still restored against the cash refunded. · *The proportional clawback computes points-times-amount in BigInt* — The clawback's points-awarded times refunded-amount product was computed with floating-point arithmetic. On a sufficiently large order the product can exceed the exact-integer range and drift the floored clawback by a point. It is now computed in BigInt — matching the framework's convention for money-by-quantity products — so the clawed amount is exact at any order size.
14
+
11
15
  - v0.4.121 (2026-06-26) — **Vendor-invoice reconciliation values each PO line at its own cost, and a vendor's invoices must share one currency.** Two fixes to vendor-invoice reconciliation and reporting. When the same SKU appeared on more than one purchase order at different unit costs, reconcileAgainstPOs summed the received quantity across the POs but valued all of it at the LAST PO's unit cost, inflating the PO received value and corrupting the over-billing variance the operator relies on to catch a vendor over-bill before paying. Each PO line is now valued at its own unit cost and accumulated, so the received value and the variance are exact, and the per-unit figure shown in the line variance is a true weighted mean. Separately, a vendor's invoices may now only be recorded in one currency: the accounts-payable aging report and the vendor scorecard sum amounts per vendor into a single figure, which is meaningless across currencies, so an invoice whose currency differs from the vendor's existing invoices is refused at write time rather than silently producing an incommensurable total. **Fixed:** *PO reconciliation values each purchase-order line at its own unit cost* — reconcileAgainstPOs aggregated purchase-order lines per SKU, accumulating the received quantity across POs but overwriting the unit cost with each successive PO's — so when the same SKU was received on two POs at different prices, the received value was computed as the combined quantity times the last PO's cost. That inflated po_received_value_minor and the variance the operator uses to spot a vendor over-bill before payment. Each PO line is now valued at its own unit cost and the values accumulated, so the received value and variance are exact; the line-variance's per-unit cost is reported as the true weighted mean of the received value. · *A vendor's invoices must all be recorded in the same currency* — The accounts-payable aging report and the vendor scorecard sum each vendor's invoice amounts into a single figure, which is only meaningful within one currency — mixing currencies produced an incommensurable total with no currency tag to unwind it. Recording an invoice whose currency differs from the vendor's existing invoices is now refused with a clear error, so those per-vendor totals stay within a single currency by construction.
12
16
 
13
17
  - v0.4.120 (2026-06-26) — **Splitting a discount across order lines no longer rounds a line's share negative.** When an order-level discount is allocated across the order's lines (proportionally, equally, or by quantity), each line's share was rounded independently with half-even rounding. Independently rounded shares can sum to MORE than the discount, which drove the leftover remainder negative and produced a negative discount on one line — and the checkout recorder, which rejects a negative share, then dropped the whole allocation breakdown, leaving nothing for a later per-line partial refund to draw on. Reversing an allocation for a refund had the same flaw and could persist a negative per-line refund (a charge-back on that line). The split now composes the framework's largest-remainder allocator: it floors each share and hands out the non-negative leftover one minor unit at a time, so every line's share is non-negative, the shares sum to the discount (or the refund) exactly, and no breakdown is dropped. The only visible change is which line absorbs a leftover cent — now the line with the largest fractional remainder rather than the highest subtotal. **Fixed:** *Per-line discount and refund shares are floored and distributed, never rounded negative* — The per-line discount split rounded each share half-even and independently, so the rounded shares could sum above the discount, send the remainder negative, and assign a negative discount to one line; the checkout path then dropped the breakdown (its recorder refuses a negative share), so a subsequent per-line refund had no recorded allocation to subtract. The reverse path likewise could persist a negative per-line refund. Both now compose the framework's largest-remainder allocator, which floors each share and distributes the non-negative leftover one minor unit at a time to the largest remainders — every share is non-negative, the shares sum exactly to the total, and the allocation is recorded. The leftover cent now lands on the largest-remainder line instead of the highest-subtotal line.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.4.121",
2
+ "version": "0.4.123",
3
3
  "assets": {
4
4
  "css/admin.css": {
5
5
  "integrity": "sha384-imfe0otYErcB8rr2h6KLSGTtStirysptpXETSPY4zLv3bZoIT75Lo1dOvkOav+xL",
@@ -808,7 +808,13 @@ function create(opts) {
808
808
  var awarded = Number(row.points_awarded || 0);
809
809
  if (awarded <= 0) continue;
810
810
  var already = Number(row.clawed_points || 0);
811
- var target = Math.floor((awarded * effRefunded) / orderTotalMinor);
811
+ // BigInt math — awarded (up to the 1e9 per-event cap) times effRefunded
812
+ // (minor units, unbounded) can exceed 2^53 on a large order, where a
813
+ // float multiply drifts and the floored claw is off by a point. BigInt
814
+ // division floors toward zero, matching Math.floor for these
815
+ // non-negative operands; the quotient is < awarded so it returns to a
816
+ // safe Number.
817
+ var target = Number((BigInt(awarded) * BigInt(effRefunded)) / BigInt(orderTotalMinor));
812
818
  if (target > awarded) target = awarded;
813
819
  var delta = target - already;
814
820
  if (delta <= 0) continue;
package/lib/order.js CHANGED
@@ -839,16 +839,24 @@ function create(opts) {
839
839
  });
840
840
  }).catch(function () { /* drop-silent — loyalty ledger holds its own audit trail */ });
841
841
  }
842
- // Loyalty points EARNED on the purchase — clawed back proportionally
843
- // (full, on a death edge). Detached + drop-silent; clawed_points
844
- // makes the claw idempotent and convergent across partial slices.
845
- if (loyaltyEarnRules && typeof loyaltyEarnRules.reverseForEventProRata === "function") {
842
+ // Loyalty points EARNED on the purchase — clawed back proportionally.
843
+ // The claw ratios against the DISCOUNTED goods value (subtotal minus
844
+ // any order discount) — the cash the customer actually paid for the
845
+ // goods the points were earned on, and the most a goods refund can
846
+ // return. A full-refund death edge refunds the whole order, so
847
+ // effRefunded (capped at the goods value) reaches it and the claw is
848
+ // 100% even when non-refundable shipping/tax is kept. Ratioing
849
+ // against the raw (pre-discount) subtotal would under-claw a
850
+ // discounted order. Detached + drop-silent; clawed_points makes the
851
+ // claw idempotent and convergent across partial slices.
852
+ var _revGoods = (Number(refreshed.subtotal_minor) || 0) - (Number(refreshed.discount_minor) || 0);
853
+ if (_revGoods > 0 && loyaltyEarnRules && typeof loyaltyEarnRules.reverseForEventProRata === "function") {
846
854
  Promise.resolve().then(function () {
847
855
  return loyaltyEarnRules.reverseForEventProRata({
848
856
  customer_id: _revCustomer,
849
857
  trigger_event_ref: "order:" + _revOrderId,
850
858
  refunded_minor: _refTotal,
851
- order_total_minor: _refTotal,
859
+ order_total_minor: _revGoods,
852
860
  });
853
861
  }).catch(function () { /* drop-silent — loyalty ledger holds its own audit trail */ });
854
862
  }
@@ -1079,9 +1087,13 @@ function create(opts) {
1079
1087
  // the customer back more than the operator refunded. The provider can
1080
1088
  // never refund more than the cash it captured, so a cash-only partial
1081
1089
  // refund leaves the non-cash tenders untouched here; they are returned
1082
- // by the terminal full-refund edge. Earned-loyalty clawback stays
1083
- // proportional to the FULL order total points were earned on the whole
1084
- // order, and clawing them back is not part of the value-return path.
1090
+ // by the terminal full-refund edge. Earned-loyalty clawback ratios
1091
+ // against the DISCOUNTED goods value (subtotal minus any order discount)
1092
+ // the cash paid for the goods the points were earned on — NOT the
1093
+ // grand total: refunding the full goods value claws all earned points
1094
+ // even when non-refundable shipping/tax is kept (the refund is
1095
+ // goods-first, capped at the goods value). Clawing is not part of the
1096
+ // value-return path above.
1085
1097
  var _ptTotal = Number(current.grand_total_minor) || 0;
1086
1098
  if (_ptTotal > 0) {
1087
1099
  var _ptRefunded = await this.refundedTotalMinor(orderId);
@@ -1108,13 +1120,14 @@ function create(opts) {
1108
1120
  });
1109
1121
  }).catch(function () { /* drop-silent — loyalty ledger holds its own audit trail */ });
1110
1122
  }
1111
- if (loyaltyEarnRules && typeof loyaltyEarnRules.reverseForEventProRata === "function") {
1123
+ var _ptGoods = (Number(current.subtotal_minor) || 0) - (Number(current.discount_minor) || 0);
1124
+ if (_ptGoods > 0 && loyaltyEarnRules && typeof loyaltyEarnRules.reverseForEventProRata === "function") {
1112
1125
  Promise.resolve().then(function () {
1113
1126
  return loyaltyEarnRules.reverseForEventProRata({
1114
1127
  customer_id: _ptCust,
1115
1128
  trigger_event_ref: "order:" + orderId,
1116
1129
  refunded_minor: _ptRefunded,
1117
- order_total_minor: _ptTotal,
1130
+ order_total_minor: _ptGoods,
1118
1131
  });
1119
1132
  }).catch(function () { /* drop-silent — loyalty ledger holds its own audit trail */ });
1120
1133
  }
@@ -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.15.32",
7
- "tag": "v0.15.32",
6
+ "version": "0.15.33",
7
+ "tag": "v0.15.33",
8
8
  "license": "Apache-2.0",
9
9
  "author": "blamejs contributors",
10
10
  "source": "https://github.com/blamejs/blamejs",
@@ -855,6 +855,7 @@
855
855
  "release-notes/v0.15.30.json": "lib/vendor/blamejs/release-notes/v0.15.30.json",
856
856
  "release-notes/v0.15.31.json": "lib/vendor/blamejs/release-notes/v0.15.31.json",
857
857
  "release-notes/v0.15.32.json": "lib/vendor/blamejs/release-notes/v0.15.32.json",
858
+ "release-notes/v0.15.33.json": "lib/vendor/blamejs/release-notes/v0.15.33.json",
858
859
  "release-notes/v0.15.4.json": "lib/vendor/blamejs/release-notes/v0.15.4.json",
859
860
  "release-notes/v0.15.5.json": "lib/vendor/blamejs/release-notes/v0.15.5.json",
860
861
  "release-notes/v0.15.6.json": "lib/vendor/blamejs/release-notes/v0.15.6.json",
@@ -1563,7 +1564,7 @@
1563
1564
  ".npmrc": "sha256:66f104e7d07c496d2d0409988225e8c0e4ceb8d247dbcac3be75b2128d20ce66",
1564
1565
  ".pinact.yaml": "sha256:0213ffda55961dc49b64c0a5dfa3c0567419633b1499d57eaf7c8d842d7da6c7",
1565
1566
  "ARCHITECTURE.md": "sha256:9b1c8d2b1b7a41838eb348b0a008e4b4369718fd72bfe2974b37155f7536d35b",
1566
- "CHANGELOG.md": "sha256:e0c814dcd62903cdd67f2a50fa6667692956a4695459b9178ac239257be847ff",
1567
+ "CHANGELOG.md": "sha256:a72d9034e3821cdcb1694eb030baccc80cffd00140c7c4ab13af2aea868db641",
1567
1568
  "CODE_OF_CONDUCT.md": "sha256:148a281960fff7c2fe6554dab66da572c72245ddeb00b0d14811558397bff386",
1568
1569
  "CONTRIBUTING.md": "sha256:bb4dbdbc8598da31dbce653a8ed322e08ff46560173f2eb67a4d684653948332",
1569
1570
  "GOVERNANCE.md": "sha256:906df6afb1f552b27b9acb50f7f96c47b917a2f1021cd4e987dbf4ee0e0a821b",
@@ -1573,7 +1574,7 @@
1573
1574
  "NOTICE": "sha256:f487fa47a11aca0f89e2615cdd3c713e9842abf7a30d8d328eeeae1c864aa774",
1574
1575
  "README.md": "sha256:3ddcc197b003da0b02db8bdd1aef1e943c94f7eab613c633d6a45bb11d0a80e9",
1575
1576
  "SECURITY.md": "sha256:77d8c2bcc04b425a08ef30e51204cebddbd48954b028a259c7a8412dbfeab40a",
1576
- "api-snapshot.json": "sha256:27f70007fec3539fc97ecef20f681e774a0dec98d359be47de412e3f19d5c1cf",
1577
+ "api-snapshot.json": "sha256:1458bc7368fc7d15cdd62fe3740e383939c54230b9107ed46b790a2fd266c797",
1577
1578
  "assets/BlameJS_Logo.png": "sha256:3c65699753c771b48ef9ac7f45bb40815ec19a23afcdd0cd30ef4601bbbe293e",
1578
1579
  "assets/BlameJS_Logo.svg": "sha256:dda44f3fb1343d5de9db6b1fcdb75fc649c57e7a99a8e8239fcf852e3841e1a8",
1579
1580
  "bench/README.md": "sha256:74202f2507fd840bfc1ac6c681975d9273cf36cca6e0f72655f138337304033c",
@@ -1625,7 +1626,7 @@
1625
1626
  "examples/wiki/lib/harvest-vendored-deps.js": "sha256:11fc8f1b3359d9e49e92a037b9ef8051516cb8e74bf5dbda34fd2c6293d2e513",
1626
1627
  "examples/wiki/lib/html-entities.js": "sha256:1afa873a5eba49a9206530868ffdccdd2cf67d00afdb53ea88ae585526caeee8",
1627
1628
  "examples/wiki/lib/nav.js": "sha256:d56f262733ff72e80c24b121fe244dff4a827cb2f24698b0fe63b8edae582d28",
1628
- "examples/wiki/lib/opts-resolver.js": "sha256:d5a7f1153e265a267b899515a42726afad6ecd8921f22fe5f3d17e9b81783c05",
1629
+ "examples/wiki/lib/opts-resolver.js": "sha256:16fcfc5006ad9687a6b10fceb7bedea815d394a0391f1c45f4afa345f16d5ef1",
1629
1630
  "examples/wiki/lib/page-generator.js": "sha256:056cf57ad85ff89f3708e5eec54ceda40ff7fccd7ee074d9553ed74788f4eceb",
1630
1631
  "examples/wiki/lib/section.js": "sha256:373d86c66fbd20ad086c3929fffca5da1fd1fb4ca43bc969c43bc5f826f67eb9",
1631
1632
  "examples/wiki/lib/source-comment-block-validator.js": "sha256:96df385db028c4d9c3e9157a878ff340dfbf38d35a229317494c70313792d135",
@@ -1647,14 +1648,14 @@
1647
1648
  "examples/wiki/seeders/prod/0001-default-pages.js": "sha256:e435490715cb1b620816aca0e3f256dbfffd3316a133b5b2bb62bde76e9e4f05",
1648
1649
  "examples/wiki/seeders/prod/pages/_index.js": "sha256:fb4d2ebe288f9928fa2a63006946eabcd4f7144b29b36c3ecaca6cd4b9e16e12",
1649
1650
  "examples/wiki/seeders/prod/pages/api.js": "sha256:ba564a5cf62cf40db37cafe872e1c9ab00ec9b8f1ed107cb85cef56d1355216c",
1650
- "examples/wiki/server.js": "sha256:3171dc66b9373583ee6872bcec0471d34a0442044c99853a3fff5860a0800f1e",
1651
+ "examples/wiki/server.js": "sha256:761d1e03a9f1ccaf99dca9a7985ff7e2ad2ff9c3c30d6c6a3d53b93bdebd84fc",
1651
1652
  "examples/wiki/site.config.js": "sha256:9345ce551f25416023b85edfd83907fe7ffba46cca4cb38fb6e5117929f2d400",
1652
1653
  "examples/wiki/snippets/README.md": "sha256:cde9a330207a087bbfd06480a641ae1dcd704c5a28d0274c0bf6cefc9e61a86d",
1653
1654
  "examples/wiki/snippets/auth/password-hash.example.js": "sha256:88c55a37bb7ebf76dff945d49138b6f2b2fa05db9acc3355ae483f702f3d8ebe",
1654
1655
  "examples/wiki/src/editor.js": "sha256:92ec81b8fe090dde49d348e91cec9472ffad4d122898e257b61d2d45b3b69b72",
1655
- "examples/wiki/src/wiki.js": "sha256:d27db30436ce441f13ff91cc8f7c4fa59a115b644748cd1fdfd855a8f910a797",
1656
+ "examples/wiki/src/wiki.js": "sha256:ab3b9b94e6b45f7ad99f9448bd4d2e002f205862745a0f90a7e8c14158dce584",
1656
1657
  "examples/wiki/test/AUDIT.md": "sha256:28868e102852aa5c0981421035066a1da6676ec5ed8d0f4b88571614dc3301ab",
1657
- "examples/wiki/test/codebase-patterns.test.js": "sha256:2973f4c766dd038eff4054a8a5f0fd4df4ba7577f23b1cf52f885cc5d1be6a67",
1658
+ "examples/wiki/test/codebase-patterns.test.js": "sha256:9af250738f2888bb4a67a7b9509d241b490a6e032a7211e9a68b72e7876b49b9",
1658
1659
  "examples/wiki/test/e2e.js": "sha256:705ee3158a1ef64ae85d026c02f8b868ca7b7f733e1a69ed76370345c989a723",
1659
1660
  "examples/wiki/test/find-missing-pages.js": "sha256:092c92b400d8f528df47ab4400f83834dd7a561269bd602e57f05eb740d9126a",
1660
1661
  "examples/wiki/test/integration.js": "sha256:a917fc9cb71d922f8796a426e7defe0d978878e29ce03f4f0db795ed544abc73",
@@ -1775,7 +1776,7 @@
1775
1776
  "lib/_test/crypto-fixtures.js": "sha256:91470fc813e41eeed06dee1e8fbb92d179af77eb01109c1256f7330cb2fc0980",
1776
1777
  "lib/a2a-tasks.js": "sha256:d027609ce0688a307ba7c42e52fb6054b1b076fe4d1f62ccf89373ba73f4df3c",
1777
1778
  "lib/a2a.js": "sha256:2d11b818fb32fac0bfb25e92720d22a46840b9b209ecc5d76c2254496b037cca",
1778
- "lib/acme.js": "sha256:22939f9dca7dbe99e475bba10bdfc057b553b3ba05798e14fbf724ae0d52eb3d",
1779
+ "lib/acme.js": "sha256:5010654b7f6c8be491be6ee6d1c075bdc8f36a7c28765ad92467a2b0318e071a",
1779
1780
  "lib/agent-audit.js": "sha256:e75baecca3146dfda7070704b0a2c25ffb0aca4f58119c9b50975f1c2f141b22",
1780
1781
  "lib/agent-envelope-mac.js": "sha256:2909c3d7a090c444478f122c657a66046f021afd75caf218e7ff7de09871be61",
1781
1782
  "lib/agent-event-bus.js": "sha256:c8b21e11f0b6596ddfc36cd87a7ee26185e41ff59e3bb65c0fb4b02e525ee1e4",
@@ -1786,7 +1787,7 @@
1786
1787
  "lib/agent-snapshot.js": "sha256:eac77c6c771b31ced5ce01937ee0cab301bc97a5b96d9db949471296029da769",
1787
1788
  "lib/agent-stream.js": "sha256:8e519cba5505ad8e89bfe827483c16fe577ad39742e17f8f01d30b430a4bbf0b",
1788
1789
  "lib/agent-tenant.js": "sha256:811d483e210b6dabf98aff873d63600cc1971e04b15259077fec81f9b84445e5",
1789
- "lib/agent-trace.js": "sha256:46b90274a48c7602789991dea990f967172e324eb1e71877ac0842f06cfe75bf",
1790
+ "lib/agent-trace.js": "sha256:ccffe830ddbd25b8acc6aea26ffeddedd2d0e27a88dff84a77252bfdf34bb4ea",
1790
1791
  "lib/ai-adverse-decision.js": "sha256:145e0f8789332b39a8c06ac93cfd63f317b043937a6bd395cd40c0d3baf3ed25",
1791
1792
  "lib/ai-aedt-bias-audit.js": "sha256:4dcbbaf1aacbe981d5792ef732cdf39db378cc5c650e8e2efb3d4c7ea1378958",
1792
1793
  "lib/ai-capability.js": "sha256:4e625db5a0eec3f07746df094168ab38319436c8de8961fec816a46853f1beab",
@@ -1842,7 +1843,7 @@
1842
1843
  "lib/auth/jwt-external.js": "sha256:4b0073de3b72e3215534613781f16892736b4433f7c9b4fd9f5968a106bb777d",
1843
1844
  "lib/auth/jwt.js": "sha256:e018192d8578c4b1d549fdb14a93852d153f75ecf0443301d6227b6fd72d7d31",
1844
1845
  "lib/auth/lockout.js": "sha256:c765cc891ef6c8ce34ba31d4d6044b7c99d529d72ce369a28f1b588bee6829cb",
1845
- "lib/auth/oauth.js": "sha256:9a1e2f1db05a339bfe620f4d7bb20819db85c0eda647bc9a551617beea89be6b",
1846
+ "lib/auth/oauth.js": "sha256:f19d2df441b1a0d081cdd5ccbeed2d21746430e008e6a82b0a9b6c49f94fc9e8",
1846
1847
  "lib/auth/oid4vci.js": "sha256:8f3f5ae5722ef00d7c5885eb49084820e6b8409aa564a52b0c48b1d334d3e49c",
1847
1848
  "lib/auth/oid4vp.js": "sha256:96aee801f9e47491c8eb47f50f21d395aacabbf948cafe2477f876051ac1ef3d",
1848
1849
  "lib/auth/openid-federation.js": "sha256:2644424c3802382c2922dd018d6674790263d77bf0e7b6c80502d8e1e6535e4f",
@@ -1878,12 +1879,12 @@
1878
1879
  "lib/chain-writer.js": "sha256:e067e2ecf1088a0fb334f512b95025685bff9a3fc648b3522d20f33ad0e613a2",
1879
1880
  "lib/circuit-breaker.js": "sha256:54244401ef17e588341176cece113b39f42c55ac3cfefe8f46b5172835b26f8c",
1880
1881
  "lib/cli-helpers.js": "sha256:ab292718a0076b66c32fc4a19a8150c25030cb7cff4bef9363612c29cb66f119",
1881
- "lib/cli.js": "sha256:70f7b74582b4643d0a8192049698c63d096db18d864753799bbddba14587a4b6",
1882
+ "lib/cli.js": "sha256:4d8a205b2b636b7388c0461309817e0c3e7a35faacdf91d5bf82145ae974fa40",
1882
1883
  "lib/client-hints.js": "sha256:fc571db42faa28fc2d36db24754ce486e2b0161c32e0a580095ece8dcd1c3de1",
1883
1884
  "lib/cloud-events.js": "sha256:9a067389255b6d05e8cb61b1f2cc6b9f31e56d13a5e8c3d625d5403470ecf5de",
1884
1885
  "lib/cluster-provider-db.js": "sha256:d480a0afe22b5a083b4bfbdcf337d08a3a4a79307f35fb819c4e9a75f03bd02e",
1885
1886
  "lib/cluster-storage.js": "sha256:b0c9d150ab05d71254d74f65eb0f1dece3aa9a4d94a7292912422588f843eafd",
1886
- "lib/cluster.js": "sha256:7a9263639fcccf72dd528e9ab5fd4b2ae893bf16ea0ab2b57b4b4dd45c336fbe",
1887
+ "lib/cluster.js": "sha256:8dfa14227c6bc971e88f23cfed9735d09e1aefba96394be0997d4a2bc2469a8c",
1887
1888
  "lib/cms-codec.js": "sha256:fcc9583c18e7262033e972940a4d6a3ef5a2c0ab93b744b6dcef551250cff56b",
1888
1889
  "lib/codepoint-class.js": "sha256:20b63ddff5d25398164e96aeb3a4e96ac51573427108219b761de375190ed1f6",
1889
1890
  "lib/compliance-ai-act-logging.js": "sha256:acf27602fcee00315e8245942e9a7247f35b75320c2d80d7263ec48ac5da02fa",
@@ -1926,7 +1927,7 @@
1926
1927
  "lib/db-file-lifecycle.js": "sha256:c2dfbe775869da8828f7898b9f97b6977ba39eecdf1ce0827c200cb28850577c",
1927
1928
  "lib/db-query.js": "sha256:1f8ebfb7481b58cacb689fe87e92cb5574bd42f2665da5f4d27febb1010e45f2",
1928
1929
  "lib/db-role-context.js": "sha256:fa97dd17a8de1278a76a01d7979c3c847295c5efe1f14ab90701ca0e98f9bd3b",
1929
- "lib/db-schema.js": "sha256:5aaef5f61f16dc0913225cb3f134e9ef6d05bf917d15ea35360c8cfbb81de1cd",
1930
+ "lib/db-schema.js": "sha256:d77648de0488e39a27e1995b7478081fd1892e4dc4dcc12ec528f9fe1e854bb7",
1930
1931
  "lib/db.js": "sha256:0b932ee8c055aec8369f195a1bfc774e380bb019dfc338d84e759db0f687cfa9",
1931
1932
  "lib/dbsc.js": "sha256:403ae5ef5fe57397ad36326223197fd379d72d100c22f89bc637e291fd42b850",
1932
1933
  "lib/ddl-change-control.js": "sha256:75265cda0b214a878786c2bded05769b29ddb566b122524311d94490877e18ec",
@@ -1961,7 +1962,7 @@
1961
1962
  "lib/framework-schema.js": "sha256:5d515f0b5ba47f851ffa6d458d69268205aedd7d09a343f52dd943055f3df56c",
1962
1963
  "lib/framework-sha1-hibp.js": "sha256:07f0e4032c988e3543872ab03a0898e3d1c0791b02a2089686da9d0032b5ffeb",
1963
1964
  "lib/fsm.js": "sha256:57bfdc6d8f7727248b40cc0169d1ad025ab5fdf16f06f71f8e53258d9c99050a",
1964
- "lib/gate-contract.js": "sha256:ae5551c721867d51656559181c4bbcc91051b5cfad09d51f76d772d531c1cf74",
1965
+ "lib/gate-contract.js": "sha256:cbfcfedd7188ea009eef28eb67b09146868b06cedccc2c5879e83465da4f29f2",
1965
1966
  "lib/gdpr-ropa.js": "sha256:d0fb72fc7a68186f233832965afa1ffc7c4ce3c514894656c04c327a88f54925",
1966
1967
  "lib/graphql-federation.js": "sha256:ce625ea629850a8e2bb2e6139e078c3b0f20c281c2fac00a631672b252504898",
1967
1968
  "lib/guard-agent-registry.js": "sha256:ea4330c2b2af5975ec01b5e704827e5ba1abbcf23b39425c9e15e241ee20d713",
@@ -2045,7 +2046,7 @@
2045
2046
  "lib/json-patch.js": "sha256:04a724f69068befe8ac48aeb5fe1a44fe5c81bb5022218377511870ca797a2b7",
2046
2047
  "lib/json-path.js": "sha256:174bf52b289a152717bc3103bbab9174aa965534e0ed67b59f48cd319f0b5c63",
2047
2048
  "lib/json-pointer.js": "sha256:840b0c95de55a61479fa70f3f717f3ea8173e0199e6aacedce0a155cfaea2f59",
2048
- "lib/json-schema.js": "sha256:bf35f4c7b3e9e87237e8116752fbbea654810de53487844e72b5385804bb8273",
2049
+ "lib/json-schema.js": "sha256:2e824e4e120c22fda5027d527cfed441e444f84de25049bbb5efb2da6a722175",
2049
2050
  "lib/jsonapi.js": "sha256:0579684952b15bb699033f7ff186b655a75d45a01dc6ca9f769bd51f749c2f0c",
2050
2051
  "lib/jtd.js": "sha256:d34de661aefcdf8ccb902434e3a6343c9693edf9546710e8726dc36e3f3127f6",
2051
2052
  "lib/jwk.js": "sha256:1545b15542b4aded0cbe66a02f2eea90aca8ed0b78e8770ebe565e8d95822cf0",
@@ -2103,7 +2104,7 @@
2103
2104
  "lib/markup-escape.js": "sha256:a76e8c77f30ae456caa53c33afeb2dd0b27f7b8799ac857beac86ea038f17d9a",
2104
2105
  "lib/markup-tokenizer.js": "sha256:8aa91d3e173c8d3d4df4dac00e892a359863be7295c5b1846cf322bc7bfc9510",
2105
2106
  "lib/mcp-tool-registry.js": "sha256:df3480e6a0d29a9734bdb19d322f83bff5ebfdd756620f947cf593878dea8776",
2106
- "lib/mcp.js": "sha256:6c7ec4b631cbcc21ff9ac429ec6e42d41e1ffbda38a05722c521c6cec46085fd",
2107
+ "lib/mcp.js": "sha256:c65af74fdb3cf30436699aba5051c4d6e8cb972887cbaaecc46250d557599953",
2107
2108
  "lib/mdoc.js": "sha256:bc31d38d6fdfac8db8f040dfa4d33ab40405f56340bb4ec978f3ba98e93f6433",
2108
2109
  "lib/metrics.js": "sha256:edc2a3f08a48ab67c9e805cb75839cc9d326ac334478b0f30db0423102ee5713",
2109
2110
  "lib/middleware/age-gate.js": "sha256:dc8c61a4d41f4a781220c9c97eb475fb2867f5ee444eb2756badcbc5b8411795",
@@ -2123,7 +2124,7 @@
2123
2124
  "lib/middleware/cors.js": "sha256:7ef687c8c681886838858b65c59d51061f6b70730460470c7173a8210690f1bb",
2124
2125
  "lib/middleware/csp-nonce.js": "sha256:d568d5c8c1e1176142614719ec6944b7e1a79e363e2101fb5be3b122797f3e3b",
2125
2126
  "lib/middleware/csp-report.js": "sha256:7e74756f85654547e9e5275c9452200e8a446d053db873f9ba3f9bf2c8e81339",
2126
- "lib/middleware/csrf-protect.js": "sha256:28c5bf60b8dddd9cc387a77d6d113ade0598dadf680c0a1c2437f67e25601efb",
2127
+ "lib/middleware/csrf-protect.js": "sha256:ac83505bcd24bd7c6fae4dec6b726c6d7aab38d98c1e9d0b06d9f49d5fa31926",
2127
2128
  "lib/middleware/daily-byte-quota.js": "sha256:204b0535b9ebee864118be4407d67a3dd09802c93cde4f4e9ede1ac0ee64111d",
2128
2129
  "lib/middleware/db-role-for.js": "sha256:b9879c17dbf7fa3d299f402043592a133176a74ac1bcb49b0b717253d4ad1d3a",
2129
2130
  "lib/middleware/deny-response.js": "sha256:073d78a1b64f18a846ab0162c7797d88eda56f3de1b8239664464e3fde8aceea",
@@ -2165,7 +2166,7 @@
2165
2166
  "lib/migration-files.js": "sha256:f3f23597b58e1d215cf676411e0b2ec96e968f4b0c238a72cd795f375239509b",
2166
2167
  "lib/migrations.js": "sha256:4c5614707b4d18a571d6b5f7aa6c0891850bf60150f7408dc1568041aef500f8",
2167
2168
  "lib/mime-parse.js": "sha256:f36fa6e1b5ffa3695699cdbc6bce5be168ac445331f602b8c8af3228c574a748",
2168
- "lib/module-loader.js": "sha256:fcd2027815c17c66aa570bc4077a76689bf1cd7393b97553f1185c2c3f9043de",
2169
+ "lib/module-loader.js": "sha256:b217c64dc72826b56684f9f15a8a40ef0a9eaacce7630326e19fece392883935",
2169
2170
  "lib/money.js": "sha256:0af40305b125b01b87ffd0aa4541a09b2975460507c96402b7d877ad72b15865",
2170
2171
  "lib/mtls-ca.js": "sha256:55ac3df43e5e3c4664bab51d5ab3505fe83a7598705280c4dbdd2fd8cc318898",
2171
2172
  "lib/mtls-engine-default.js": "sha256:bb2e47de5b8a6fa03f433c4c8ecc02fc7e7841f9eff97a36e7a4379880c81cd7",
@@ -2245,7 +2246,7 @@
2245
2246
  "lib/restore-rollback.js": "sha256:f00e2f40e2e6a14bc6687afe8c112e367d83314eb04592d9ba399cb699fb0e03",
2246
2247
  "lib/restore.js": "sha256:7137ebb01175e0a238f4f76ad6a26297af3daff3103bbec8386b73357d9d3465",
2247
2248
  "lib/retention.js": "sha256:a02c58871864073ae8031db0523cfbb71cb9e6dc7650dc943b79244cbb2b13d2",
2248
- "lib/retry.js": "sha256:785a4e7bad551354b8b84d5c01092fcfde88b49bf8ff646557b28fbb3d25302e",
2249
+ "lib/retry.js": "sha256:59f7588894aaf54dfe117af971b29d87e5b89f0ce68c24df805af4b6c5308983",
2249
2250
  "lib/rfc3339.js": "sha256:b318c45be3834ccbcddfa5d4773d88c6a558cd184e21c15a4021d1b5693c55f6",
2250
2251
  "lib/router.js": "sha256:b87d81ffc8398d440a0911dfd63a777dc244fc9479249ec2b64d872a52fb7961",
2251
2252
  "lib/safe-archive.js": "sha256:48a8c985ff590220d69341fb7251e7c477ea2c43c1bdab43c62e2dcb58c0a9d4",
@@ -2265,7 +2266,7 @@
2265
2266
  "lib/safe-sieve.js": "sha256:2925300c6a6d973178a7cdc73983520fa764847e104551e1c52a20fbd9ab760d",
2266
2267
  "lib/safe-smtp.js": "sha256:887e24088859d8ec95a307956fc747c14f31141bed2fa08a0e473beb07141785",
2267
2268
  "lib/safe-sql.js": "sha256:2d05221d5dce9ff5244b93aec082c9021dbaa090b8bed6e887131e3834da17b2",
2268
- "lib/safe-url.js": "sha256:36e3d2c72e7adc5c90cce7f80e469cf50451ccadd3791a1e3aa406754a4ce6e1",
2269
+ "lib/safe-url.js": "sha256:29d4f25254a47ac26b5b2ff703bfb4f0c51d60afd8cb8a5f0b398ef4158e4554",
2269
2270
  "lib/safe-vcard.js": "sha256:be2964d302b9317206fab1740ebbd0acff00258b138810aa6d64ad6cc1797ce5",
2270
2271
  "lib/sandbox-worker.js": "sha256:eefe4e76b2a736208f2e2e90347fc1ff2c2018a98e06bca3103aeb6f96298c6b",
2271
2272
  "lib/sandbox.js": "sha256:0fa2d3c7d52afa3091826083ec5b08fd8273e0a6fd33b207e714fd16b734d5b5",
@@ -2284,7 +2285,7 @@
2284
2285
  "lib/slug.js": "sha256:bcebb078559528e6bb50a6244633d425ffdd861bb7a708c2b201eae3b3c44b35",
2285
2286
  "lib/sql.js": "sha256:8de2d3f1be989cc07a465ee205e0c5ece854240c7f7d7b3757613edb93ee049c",
2286
2287
  "lib/sse.js": "sha256:5e4fca52ddb92ab1c13ad7434c6b13d5c4ef0f7fc3845b003f8c3603c1629dbf",
2287
- "lib/ssrf-guard.js": "sha256:65d3d1bf6841064cdf9b9e7ffb5a0a3ac9358e462943f5de09087640353dfac4",
2288
+ "lib/ssrf-guard.js": "sha256:db61826b3b9b30787636160071d9799e949b35b1c28c4d98ac8806b93f705738",
2288
2289
  "lib/standard-webhooks.js": "sha256:e604534d48202a41f2c9f6954a990731db80d0693794d3a80f371f843490ff57",
2289
2290
  "lib/static.js": "sha256:09b63860428beef3117d7b8e59954857eb27a612064f4f083a597c0428865341",
2290
2291
  "lib/storage.js": "sha256:0f6d4acbcd6709e0117ae2a7d9f8cea250ea4f28da8d1acdc2bbd3dea46b2668",
@@ -2312,7 +2313,7 @@
2312
2313
  "lib/vault/seal-pem-file.js": "sha256:0eaaa19af92cea39a5849591c71a7c3c0be81c4c463f133dcfa365f6efe3480a",
2313
2314
  "lib/vault/wrap.js": "sha256:5d8d748c6eb603c018a9f5f5581f4d3270da34ea69dee6d6ef0e5199c727b800",
2314
2315
  "lib/vc.js": "sha256:554cf29ea712b231256e1eaa75f6b1f1d39c392aac86b33e818d52e956ea83ae",
2315
- "lib/vendor-data.js": "sha256:137b493f0eae8a94ac6722134624cc2041b38aa84717db9fbb6ac43078b16eee",
2316
+ "lib/vendor-data.js": "sha256:89f27188bd2054286196f588bbecf125c500f1ae484555afa6082357237157c8",
2316
2317
  "lib/vendor/.vendor-data-pubkey": "sha256:73a935b8c72f55d821c22ddb8188453bab324f80d229d033a0a1549819a1f096",
2317
2318
  "lib/vendor/MANIFEST.json": "sha256:c2b9e40fb993db0f92c49154a5ac078e01324ccd02a19985e38186da06dd7338",
2318
2319
  "lib/vendor/bimi-trust-anchors.data.js": "sha256:aa7a4d33b65a68422a2a2c1670177689f66fdcaa08bd2514d78798b827bd1608",
@@ -2333,18 +2334,18 @@
2333
2334
  "lib/webhook-dispatcher.js": "sha256:3a8517f6dd3bbc37c1fa2e5e23e81ce60b8488aec75ab4598ec57df743d186db",
2334
2335
  "lib/webhook.js": "sha256:0db5e3aed7b1f10eeeb15b5fd94424f2cb44e443fbfdc6029800ac89b2f8dad1",
2335
2336
  "lib/websocket-channels.js": "sha256:d8f39368acc3ff17d8aaa7f0ef5bb5e64b6b406154e314c21833dce0415aea14",
2336
- "lib/websocket.js": "sha256:a8d4dfa48de0100de0ade5ae0db7d67f99e1564d4587a8d4e56c82a6b36137f8",
2337
+ "lib/websocket.js": "sha256:c64c20149136195b127ed1b4e378d6b6166d53cf4e1db1c451f0c370f1c4decf",
2337
2338
  "lib/wiki-concepts.js": "sha256:54789790b950d926cbd0657dd51b32435c4988012b520819615df93673680de5",
2338
2339
  "lib/worker-pool.js": "sha256:fc35b3c9f83a4c72be0981400f5294b566472bfe187df0500775e37dd71afa4c",
2339
2340
  "lib/worm.js": "sha256:f17e24f8ca39295f396f40bd0c4ad1c946f5e41ff646ef1b33e8d50dc8b9435e",
2340
- "lib/ws-client.js": "sha256:4e66a26e94438c4d6bea31b69ada0f6fb14a8b1f8914b81607db493ae483e375",
2341
+ "lib/ws-client.js": "sha256:5a854921c96500d504c731d302a7d338d93400b41bbe12056aa1c38494ac7497",
2341
2342
  "lib/x509-chain.js": "sha256:fdc0ecd264d9de0e039f348e819675fdf3838d61097a97a0e3e119def338722a",
2342
2343
  "lib/xml-c14n.js": "sha256:01a27d20df99ebd6eaefbff0aad933a2231049f65a54ae994236694d4146ce5d",
2343
2344
  "oss-fuzz/projects/blamejs/Dockerfile": "sha256:6c48ec4d81f4b1836a6b43701a2497cf737002413dd0da6a10892be1498b0766",
2344
2345
  "oss-fuzz/projects/blamejs/README.md": "sha256:ae13b7bb79ed8d69b1b3276e5562807a0349fb6e6b7d11cf1f683aad1eafdb4b",
2345
2346
  "oss-fuzz/projects/blamejs/build.sh": "sha256:0ced1cf21782c97be7f8d74faf5e27a308b60b2f858836fb5ca3b8c4e939a8f7",
2346
2347
  "oss-fuzz/projects/blamejs/project.yaml": "sha256:59f2cb83aa622325a175b77416fe155be15b70a9c798bd1a78bba05763b1b03d",
2347
- "package.json": "sha256:82e87499ed49c5957bc6c22da3dddd25c8ccb7d5bea1bb38cee2e7d8f6973e60",
2348
+ "package.json": "sha256:69f5a0b0cfc8dc14380bd8ccec1c5517680ae98de4bb3fe8de04ad2eb8637d64",
2348
2349
  "release-notes/v0.0.x.json": "sha256:7a49819f30068ee119000cad7010194882bb8bfaa12acbdab4dfc066efb7982f",
2349
2350
  "release-notes/v0.1.x.json": "sha256:6742a8c17f947c5cb76f69dead7eea86b942d80621d914b774ba5488e09937e5",
2350
2351
  "release-notes/v0.10.x.json": "sha256:fe498045daf88337bd3d987e5964aa42c99a50e1685b6f09e51f698b8687726f",
@@ -2379,6 +2380,7 @@
2379
2380
  "release-notes/v0.15.30.json": "sha256:d40ce2c5ffb7ae5a2b501ea0f949bd29510d8544a5f588f136a37ce4981d50ad",
2380
2381
  "release-notes/v0.15.31.json": "sha256:f1d259dcee41503588b9c54060e56e436eb5fa7db502872a895c84ebb96627a9",
2381
2382
  "release-notes/v0.15.32.json": "sha256:af99a8a782dcc30aff3a135c27179b064d63181fc4c302c31da632c1615b68ce",
2383
+ "release-notes/v0.15.33.json": "sha256:295ea9939b74498c7f0be6afdc8bc511f97cb2383a436c3040c58b0600598b19",
2382
2384
  "release-notes/v0.15.4.json": "sha256:6ac7fa0ef1728c27e71b2050d1b07a810f9b4b1440ccddbf28ad56e2f54d8585",
2383
2385
  "release-notes/v0.15.5.json": "sha256:cca1d0edd5d6fc41b512d19d98be224b990dcab41478622c11962f0fcb1bb09a",
2384
2386
  "release-notes/v0.15.6.json": "sha256:0e3b9e5e43b70b61dd258c3003d1b8729cd3c26c62a34dedcca81bbec5d31077",
@@ -2625,7 +2627,7 @@
2625
2627
  "test/layer-0-primitives/cluster-storage.test.js": "sha256:238b3b3db0eba3e6312a863710533178f566347b90e161e564481aa826707647",
2626
2628
  "test/layer-0-primitives/cluster-vault-rotation.test.js": "sha256:3514e9e71d6c39e805248f58ad2f41528d091e196c0f3766a032675677161b2d",
2627
2629
  "test/layer-0-primitives/cms-codec.test.js": "sha256:7e46078ed82be5b69d22c48f22dba37ea5015371c2a8cf5f94fb1a792fb7bb78",
2628
- "test/layer-0-primitives/codebase-patterns.test.js": "sha256:6520fb495c58a1979fd8e47af2eb8a2daefc7d4eed93877b19c3477b288736ac",
2630
+ "test/layer-0-primitives/codebase-patterns.test.js": "sha256:323ee48a6e6c4cce47f48155cb059e4bc6115af7a01283b30d89592367bb6198",
2629
2631
  "test/layer-0-primitives/codepoint-class.test.js": "sha256:19d1b69efa7e0e9f7ef2392ca264167767a5ec5890ee339b2cfd8a7818035d27",
2630
2632
  "test/layer-0-primitives/compliance-ai-act.test.js": "sha256:5ee4ad05d12233cb3c5457ef10a727833710bbc1ce1318838f9f9ef5d2cb8d4b",
2631
2633
  "test/layer-0-primitives/compliance-cascade.test.js": "sha256:ee02cf14541a837a9d7977c6ea6bf7f9210bed293925d93c976e31f270aebec4",
@@ -2993,7 +2995,7 @@
2993
2995
  "test/layer-0-primitives/sigv4-multipart-sse.test.js": "sha256:964c4a854e258103f8a11e9140368e825155b4934fc8bf130802fb1e133e2b29",
2994
2996
  "test/layer-0-primitives/slug.test.js": "sha256:15590eb5da4a54144e5c68756119d4c453bb1cd871c67c7d7732250b650928da",
2995
2997
  "test/layer-0-primitives/smtp-policy.test.js": "sha256:184fee03f15e5b607ded9ae034143c00561030830cdf7b96a70b3fcc2cb8d419",
2996
- "test/layer-0-primitives/source-comment-blocks.test.js": "sha256:83f8fdfc46fd384515932d120e00f76cd5fa041cb6f52e706c43cd5c56592309",
2998
+ "test/layer-0-primitives/source-comment-blocks.test.js": "sha256:0fdc77c482b72e3e65a0e11bef94b050dffd6c77bdac9e52a17f3334b4d0c2d8",
2997
2999
  "test/layer-0-primitives/speculation-rules.test.js": "sha256:aa6a5b52d01832fd90db008220c861a412c61a1a5e90bb179f393359e6579598",
2998
3000
  "test/layer-0-primitives/sql.test.js": "sha256:948c78941cae9ff706f7dacaad15b516514693b58eb56c2bc64e94c06cd1f323",
2999
3001
  "test/layer-0-primitives/sse-backpressure.test.js": "sha256:a435f5ca7e4b37f80c41da40d20d152cc2ad78d9e57fa020a054474b1feb8050",
@@ -8,6 +8,8 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.15.x
10
10
 
11
+ - v0.15.33 (2026-06-26) — **Internal test-suite hardening only — the published library's runtime behavior and public API are unchanged (source-comment marker text aside).** Three more suppression classes in the codebase-patterns guard suite were re-verified from scratch and renamed to descriptive tokens, with their old names recorded as retired and their in-source marker comments updated to match. No runtime code, public API, or wire format changed. **Detectors:** *Three more suppression-marker classes re-verified and their tokens retired* — Continuing the re-verification pass: each marked site for the math-random-noncrypto, raw-new-url, and dynamic-require guard classes was re-read and confirmed (non-security jitter/sampling; URL parsing for shape/origin inspection or behind the safe wrapper; operator-supplied module loads), then the class was renamed to a descriptive token and its old name added to the retired-token set. This is test-suite tooling; no shipped framework behavior changed.
12
+
11
13
  - v0.15.32 (2026-06-26) — **Internal test-suite hardening only — the published library's runtime behavior and public API are unchanged (source-comment marker text aside).** Three more suppression classes in the codebase-patterns guard suite were re-verified from scratch and renamed to descriptive tokens, with their old names recorded as retired so the prior approval cannot be silently resurrected and their in-source marker comments updated to match. No runtime code, public API, or wire format changed. **Detectors:** *Three more suppression-marker classes re-verified and their tokens retired* — Continuing the re-verification pass: each marked site for the process-exit, hand-rolled buffer-collect, and raw-outbound-http guard classes was re-read and confirmed (operator-opt-in exits; bounded protocol-framing / TLV assembly; framework-routed outbound calls), then the class was renamed to a descriptive token and its old name added to the retired-token set. This is test-suite tooling; no shipped framework behavior changed.
12
14
 
13
15
  - v0.15.31 (2026-06-26) — **Internal test-suite hardening only — the published library's runtime behavior and public API are unchanged (source-comment marker text aside).** The codebase-patterns guard suite gains a gate that retires a renamed suppression-marker token: once a suppression class is re-verified and renamed, its old token cannot be silently re-registered, so a later suppression has to be re-examined under the new name instead of inheriting a stale approval. Eight suppression classes were re-verified and renamed to descriptive tokens this release, and their in-source marker comments were updated to match. No runtime code, public API, or wire format changed. **Detectors:** *Re-verification gate retires a renamed suppression-marker token* — A new guard refuses to re-register a retired suppression-marker token, and the orphan check points a stale marker at its current name. When a suppression class is re-verified, it is renamed to a descriptive token and the old name is recorded as retired, so the old approval cannot be quietly resurrected — a future suppression must be re-examined and re-stamped under the new name. This is test-suite tooling; no shipped framework behavior changed.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 1,
3
- "frameworkVersion": "0.15.32",
4
- "createdAt": "2026-06-26T19:50:16.827Z",
3
+ "frameworkVersion": "0.15.33",
4
+ "createdAt": "2026-06-26T20:59:47.809Z",
5
5
  "exports": {
6
6
  "a2a": {
7
7
  "type": "object",
@@ -34,7 +34,7 @@ function probeAllowList(fn) {
34
34
  if (typeof fn !== "function") {
35
35
  return { ok: false, reason: "not-a-function" };
36
36
  }
37
- var probeKey = "__opts_resolver_probe_" + Date.now() + "_" + Math.random().toString(36).slice(2); // allow:math-random-noncrypto — probe-key uniqueness only; never reaches a security boundary
37
+ var probeKey = "__opts_resolver_probe_" + Date.now() + "_" + Math.random().toString(36).slice(2); // allow:math-random-noncrypto-jitter-sampling — probe-key uniqueness only; never reaches a security boundary
38
38
  var probeOpts = {};
39
39
  probeOpts[probeKey] = true;
40
40
  var thrown = null;
@@ -86,7 +86,7 @@ function _resolveAdminPassword() {
86
86
  function _terminate(code, reason, err) {
87
87
  if (err) log.error(reason, { err: (err && err.stack) || String(err), exitCode: code });
88
88
  else if (reason) log.info(reason, { exitCode: code });
89
- process.exit(code); // allow:process-exit — wiki app entrypoint terminator
89
+ process.exit(code); // allow:process-exit-operator-optin — wiki app entrypoint terminator
90
90
  }
91
91
 
92
92
  (async function main() {
@@ -202,7 +202,7 @@
202
202
  function loadManifest() {
203
203
  if (manifest) return Promise.resolve(manifest);
204
204
  if (loadPromise) return loadPromise;
205
- loadPromise = fetch("/symbols.json", { credentials: "same-origin" }) // allow:raw-outbound-http — browser-side script; b.httpClient is Node-server-only
205
+ loadPromise = fetch("/symbols.json", { credentials: "same-origin" }) // allow:raw-outbound-http-framework-internal — browser-side script; b.httpClient is Node-server-only
206
206
  .then(function (r) { return r.ok ? r.json() : []; })
207
207
  .then(function (data) { manifest = Array.isArray(data) ? data : []; return manifest; })
208
208
  .catch(function () { manifest = []; return manifest; });
@@ -317,13 +317,13 @@ function testNoInlineRequires() {
317
317
 
318
318
  function testNoMathRandomForSecurity() {
319
319
  var matches = _scan(/\bMath\.random\(/);
320
- matches = _filterMarkers(matches, "math-random-noncrypto");
320
+ matches = _filterMarkers(matches, "math-random-noncrypto-jitter-sampling");
321
321
  _report("Math.random() has explicit non-crypto allow marker", matches);
322
322
  }
323
323
 
324
324
  function testRawNewURL() {
325
325
  var matches = _scan(/\bnew URL\(/);
326
- matches = _filterMarkers(matches, "raw-new-url");
326
+ matches = _filterMarkers(matches, "raw-new-url-parse-only");
327
327
  _report("new URL(...) routes through b.safeUrl.parse", matches);
328
328
  }
329
329
 
@@ -369,14 +369,14 @@ function testFormatValidatorLengthCap() {
369
369
 
370
370
  function testNoProcessExit() {
371
371
  var matches = _scan(/\bprocess\.exit\(/);
372
- matches = _filterMarkers(matches, "process-exit");
372
+ matches = _filterMarkers(matches, "process-exit-operator-optin");
373
373
  _report("no process.exit() (server.js entry needs an allow marker)",
374
374
  matches);
375
375
  }
376
376
 
377
377
  function testNoSilentCatchSwallow() {
378
378
  var matches = _scan(/catch\s*\(\s*_\w*\s*\)\s*\{\s*\}/);
379
- matches = _filterMarkers(matches, "silent-catch");
379
+ matches = _filterMarkers(matches, "silent-catch-stream-teardown");
380
380
  _report("empty catch(_e) {} blocks have explicit silent-catch allow marker",
381
381
  matches);
382
382
  }
@@ -404,14 +404,14 @@ function testNoRawRemoteAddress() {
404
404
 
405
405
  function testNoRawProcessEnv() {
406
406
  var matches = _scan(/\bprocess\.env\.\w+/);
407
- matches = _filterMarkers(matches, "raw-process-env");
407
+ matches = _filterMarkers(matches, "raw-process-env-bootstrap");
408
408
  _report("process.env reads route through b.safeEnv.readVar (or have allow marker)",
409
409
  matches);
410
410
  }
411
411
 
412
412
  function testNoRawTimingSafeEqual() {
413
413
  var matches = _scan(/\b(nodeCrypto|crypto)\.timingSafeEqual\(/);
414
- matches = _filterMarkers(matches, "raw-timing-safe-equal");
414
+ matches = _filterMarkers(matches, "raw-timing-safe-equal-boot-prechecked");
415
415
  _report("crypto.timingSafeEqual routes through b.crypto.timingSafeEqual",
416
416
  matches);
417
417
  }
@@ -512,13 +512,13 @@ function testTimersUnref() {
512
512
  });
513
513
  }
514
514
  }
515
- bad = _filterMarkers(bad, "timer-no-unref");
515
+ bad = _filterMarkers(bad, "timer-no-unref-unrefed-below");
516
516
  _report("setInterval timers call .unref() (or have allow marker)", bad);
517
517
  }
518
518
 
519
519
  function testNoRawRandomBytesToken() {
520
520
  var matches = _scan(/\b(nodeCrypto|crypto)\.randomBytes\([^)]+\)\s*\.\s*toString\s*\(/);
521
- matches = _filterMarkers(matches, "raw-randombytes-token");
521
+ matches = _filterMarkers(matches, "raw-randombytes-token-mime-boundary");
522
522
  _report("nodeCrypto.randomBytes(n).toString routes through b.crypto.generateToken",
523
523
  matches);
524
524
  }
@@ -531,7 +531,7 @@ function testNoHandrolledSleep() {
531
531
 
532
532
  function testNoRawOutboundHttp() {
533
533
  var matches = _scan(/\b(http|https)\.(request|get)\s*\(|^[^/]*\bfetch\s*\(/);
534
- matches = _filterMarkers(matches, "raw-outbound-http");
534
+ matches = _filterMarkers(matches, "raw-outbound-http-framework-internal");
535
535
  _report("http(s).request / fetch route through b.httpClient", matches);
536
536
  }
537
537
 
@@ -1026,7 +1026,7 @@ function create(opts) {
1026
1026
  // Non-crypto: RFC 9773 §4.2 fleet-scheduling jitter inside the
1027
1027
  // CA-suggested renewal window. Predictability is not a threat
1028
1028
  // here; uniform distribution across the window is the goal.
1029
- renewAtMs = jLo + Math.floor(Math.random() * (jHi - jLo + 1)); // allow:math-random-noncrypto — RFC 9773 fleet jitter, predictability not a threat
1029
+ renewAtMs = jLo + Math.floor(Math.random() * (jHi - jLo + 1)); // allow:math-random-noncrypto-jitter-sampling — RFC 9773 fleet jitter, predictability not a threat
1030
1030
  } else {
1031
1031
  // Past-window — renew immediately, no jitter.
1032
1032
  renewAtMs = nowMs;
@@ -256,7 +256,7 @@ function _shouldSample(globalRate, perMethod, method, traceId) {
256
256
  // No trace-id supplied — start of a new trace. Operators wire
257
257
  // shouldSample(method, ctx.traceId) on every downstream hop so
258
258
  // children inherit the decision deterministically.
259
- return Math.random() < rate; // allow:math-random-noncrypto — start-of-trace seed only; downstream hops pass traceId for deterministic propagation
259
+ return Math.random() < rate; // allow:math-random-noncrypto-jitter-sampling — start-of-trace seed only; downstream hops pass traceId for deterministic propagation
260
260
  }
261
261
 
262
262
  function _formatAttributes(info) {
@@ -282,7 +282,7 @@ function _validateUrl(url, allowHttp, label) {
282
282
  // global flag.
283
283
  var isLocalhostHttp = false;
284
284
  try {
285
- var parsed = new URL(url); // allow:raw-new-url — RFC 9700 §4.1.1 localhost-exception lookup; safeUrl re-validates below for non-localhost paths
285
+ var parsed = new URL(url); // allow:raw-new-url-parse-only — RFC 9700 §4.1.1 localhost-exception lookup; safeUrl re-validates below for non-localhost paths
286
286
  // Strip trailing root-zone dot before the localhost compare.
287
287
  // RFC 1034 §3.1 — `localhost.` resolves identically to `localhost`;
288
288
  // without the strip, an attacker who registers `evil.com` as a
@@ -2168,7 +2168,7 @@ function create(opts) {
2168
2168
  "parseFrontchannelLogoutRequest: req with url required");
2169
2169
  }
2170
2170
  var u;
2171
- try { u = new URL(req.url, "http://placeholder.invalid"); } // allow:raw-new-url — req.url is the framework-normalized path; placeholder base provides a synthetic origin for relative-path parse
2171
+ try { u = new URL(req.url, "http://placeholder.invalid"); } // allow:raw-new-url-parse-only — req.url is the framework-normalized path; placeholder base provides a synthetic origin for relative-path parse
2172
2172
  catch (_e) {
2173
2173
  throw new OAuthError("auth-oauth/bad-frontchannel-logout-url",
2174
2174
  "parseFrontchannelLogoutRequest: malformed request URL");
@@ -455,11 +455,11 @@ function _resolveTargetModule(modulePath, ctx) {
455
455
  // code never reaches this nodePath.
456
456
  if (!modulePath) {
457
457
  var root = nodePath.resolve(__dirname, "..");
458
- return require(nodePath.join(root, "index.js")); // allow:dynamic-require — operator-extensibility entry point
458
+ return require(nodePath.join(root, "index.js")); // allow:dynamic-require-operator-module — operator-extensibility entry point
459
459
  }
460
460
  var abs = nodePath.isAbsolute(modulePath) ? modulePath : nodePath.resolve(ctx.cwd, modulePath);
461
461
  delete require.cache[require.resolve(abs)];
462
- return require(abs); // allow:dynamic-require — operator-extensibility entry point
462
+ return require(abs); // allow:dynamic-require-operator-module — operator-extensibility entry point
463
463
  }
464
464
 
465
465
  function _runApiSnapshot(args, ctx) {
@@ -750,7 +750,7 @@ async function _heartbeat() {
750
750
  // budget is in `leaseTtl - heartbeatMs`, not in the jitter
751
751
  // window).
752
752
  if (!lease) {
753
- var jitterMs = Math.floor(Math.random() * (heartbeatMs * 0.4)); // allow:math-random-noncrypto — heartbeat jitter, not security-bearing
753
+ var jitterMs = Math.floor(Math.random() * (heartbeatMs * 0.4)); // allow:math-random-noncrypto-jitter-sampling — heartbeat jitter, not security-bearing
754
754
  if (jitterMs > 0) {
755
755
  await safeAsync.sleep(jitterMs);
756
756
  }
@@ -605,7 +605,7 @@ function runMigrations(database, migrationDir) {
605
605
  // Operator-supplied migration file — by definition not statically
606
606
  // require-able by a bundler. Anyone bundling this surface into SEA
607
607
  // accepts that runtime migration loading won't resolve.
608
- mig = require(fullPath); // allow:dynamic-require — operator-supplied migration
608
+ mig = require(fullPath); // allow:dynamic-require-operator-module — operator-supplied migration
609
609
  } catch (e) {
610
610
  throw new Error("migration '" + file + "' failed to load: " + e.message);
611
611
  }
@@ -940,7 +940,7 @@ function canaryGate(gate, opts) {
940
940
  name: opts.name || "canary",
941
941
  check: async function (ctx) {
942
942
  var d = await gate.check(ctx);
943
- if (d.action === "refuse" && Math.random() > rate) { // allow:math-random-noncrypto — canary sampling, non-security
943
+ if (d.action === "refuse" && Math.random() > rate) { // allow:math-random-noncrypto-jitter-sampling — canary sampling, non-security
944
944
  return Object.assign({}, d, { ok: true, action: "warn" });
945
945
  }
946
946
  return d;
@@ -104,7 +104,7 @@ function _resolveUri(ref, base) {
104
104
  // RFC 3986 relative→absolute resolution of a schema $id/$ref (operator-
105
105
  // trusted schema text, not request data); safeUrl.parse intentionally
106
106
  // rejects the relative refs and non-http schemes schemas legitimately use.
107
- try { return new URL(ref, base).href; } // allow:raw-new-url — schema $id/$ref URI resolution, not request-data URL handling
107
+ try { return new URL(ref, base).href; } // allow:raw-new-url-parse-only — schema $id/$ref URI resolution, not request-data URL handling
108
108
  catch (_e) {
109
109
  // Relative resolution against a non-URL base (e.g. "urn:..." or a
110
110
  // bare name). Fall back to fragment-aware concatenation.
@@ -730,7 +730,7 @@ function _checkFormat(format, value, type) {
730
730
  if (/\s/.test(value)) return false; // raw whitespace is not a valid URI
731
731
  if (/%(?![0-9A-Fa-f]{2})/.test(value)) return false; // malformed percent-escape
732
732
  if (!/^[A-Za-z][A-Za-z0-9+.-]*:/.test(value)) return false; // absolute URI requires a scheme // allow:regex-no-length-cap — linear scheme prefix
733
- try { new URL(value); return true; } catch (_e) { return false; } // allow:raw-new-url — string-shape check, no fetch / SSRF surface
733
+ try { new URL(value); return true; } catch (_e) { return false; } // allow:raw-new-url-parse-only — string-shape check, no fetch / SSRF surface
734
734
  }
735
735
  case "uuid": return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(value); // allow:regex-no-length-cap — fixed-width UUID
736
736
  case "ipv4": return /^(\d{1,3}\.){3}\d{1,3}$/.test(value) && value.split(".").every(function (o) { return Number(o) <= 255; }); // allow:regex-no-length-cap — bounded dotted-quad
@@ -510,7 +510,7 @@ function _toolResultSanitize(result, opts) {
510
510
  } else if (block.type === "image" || block.type === "resource_link" || block.type === "audio") {
511
511
  var url = block.url || (block.resource && block.resource.uri);
512
512
  if (typeof url === "string" && url.length > 0 && allowedHosts.length > 0) {
513
- var u; try { u = new URL(url); } catch (_e) { u = null; } // allow:raw-new-url — operator-supplied tool URL; allowlist enforced below
513
+ var u; try { u = new URL(url); } catch (_e) { u = null; } // allow:raw-new-url-parse-only — operator-supplied tool URL; allowlist enforced below
514
514
  if (!u || allowedHosts.indexOf(u.host) === -1) {
515
515
  issues.push({ kind: "off-allowlist-url", index: i, url: url });
516
516
  if (posture === "sanitize") continue; // drop the block in sanitize mode
@@ -194,7 +194,7 @@ function _checkOriginAllowed(req, allowedOrigins, isHttpsFn, requireOrigin) {
194
194
 
195
195
  function _originOf(rawUrl) {
196
196
  try {
197
- var u = new URL(rawUrl); // allow:raw-new-url — origin-shape inspection (NOT outbound). Intentionally tolerates file:// / data: which safeUrl.parse refuses.
197
+ var u = new URL(rawUrl); // allow:raw-new-url-parse-only — origin-shape inspection (NOT outbound). Intentionally tolerates file:// / data: which safeUrl.parse refuses.
198
198
  return u.origin; // "https://host:port" — no path / query / fragment
199
199
  } catch (_e) { return null; }
200
200
  }
@@ -4,7 +4,7 @@
4
4
  * operator-supplied module file (a migration or a seed) by path.
5
5
  *
6
6
  * Operator modules execute arbitrary code on `require`, so the dynamic
7
- * `require()` lives here behind ONE `allow:dynamic-require` marker rather
7
+ * `require()` lives here behind ONE `allow:dynamic-require-operator-module` marker rather
8
8
  * than scattered across every host-CLI loader (`b.migrations`,
9
9
  * `b.seeders`, `b.externalDb.migrate`). The require cache is busted first
10
10
  * so a dev / test rewriting a fixture between calls picks up the new
@@ -33,7 +33,7 @@
33
33
  function requireFresh(absPath, onLoadError) {
34
34
  try { delete require.cache[require.resolve(absPath)]; } catch (_e) { /* not yet cached */ }
35
35
  try {
36
- return require(absPath); // allow:dynamic-require — operator-supplied module (migration / seed)
36
+ return require(absPath); // allow:dynamic-require-operator-module — operator-supplied module (migration / seed)
37
37
  } catch (e) {
38
38
  throw onLoadError(e);
39
39
  }
@@ -284,7 +284,7 @@ function backoffDelay(attempt, opts) {
284
284
  // 30-50K randomInt/sec under a retry storm without any security
285
285
  // payoff. Math.random's PRNG is the right tool for
286
286
  // thundering-herd avoidance.
287
- var jitter = capped * opts.jitterFactor * Math.random(); // allow:math-random-noncrypto — jitter for thundering-herd, not a confidentiality primitive
287
+ var jitter = capped * opts.jitterFactor * Math.random(); // allow:math-random-noncrypto-jitter-sampling — jitter for thundering-herd, not a confidentiality primitive
288
288
  return Math.floor(capped - jitter);
289
289
  }
290
290
 
@@ -444,7 +444,7 @@ function format(url) {
444
444
  }
445
445
  // Constructing URL() is the path that surfaces the IDN-crash on
446
446
  // older Node — wrap so the listener never crashes.
447
- var u = new URL(url); // allow:raw-new-url — safeUrl.format wraps URL ctor for CVE-2026-21712; this IS the safe wrapper.
447
+ var u = new URL(url); // allow:raw-new-url-parse-only — safeUrl.format wraps URL ctor for CVE-2026-21712; this IS the safe wrapper.
448
448
  return u.href;
449
449
  } catch (e) {
450
450
  if (e && e.isSafeUrlError) throw e;
@@ -754,7 +754,7 @@ function createAllowlist(opts) {
754
754
  }
755
755
  async function assertUrl(url) {
756
756
  var parsed;
757
- try { parsed = new URL(url); } // allow:raw-new-url — local URL parse for hostname extraction
757
+ try { parsed = new URL(url); } // allow:raw-new-url-parse-only — local URL parse for hostname extraction
758
758
  catch (_e) {
759
759
  throw new SsrfError("invalid URL", "ssrf-guard/bad-url", { url: url });
760
760
  }
@@ -176,8 +176,8 @@ function _loadAndVerify(name) {
176
176
  throw new VendorDataError("vendor-data/module-missing",
177
177
  "vendorData: '" + name + "' .data.js module not statically " +
178
178
  "require'd by lib/vendor-data.js. Add the literal-string require " +
179
- "to the _MODULES table at the top of the file — dynamic " + // allow:dynamic-require — diagnostic message text
180
- "require(variable) breaks SEA / esbuild bundling."); // allow:dynamic-require — diagnostic message text
179
+ "to the _MODULES table at the top of the file — dynamic " + // allow:dynamic-require-operator-module — diagnostic message text
180
+ "require(variable) breaks SEA / esbuild bundling."); // allow:dynamic-require-operator-module — diagnostic message text
181
181
  }
182
182
 
183
183
  // Module-shape gate
@@ -460,7 +460,7 @@ function isOriginAllowed(req, origins) {
460
460
  var host = (req.headers || {}).host;
461
461
  if (!host) return false;
462
462
  var originHost;
463
- try { originHost = new URL(origin).host; } // allow:raw-new-url — comparing browser-supplied Origin header against Host; safeUrl.parse adds policy filtering that isn't appropriate for exact host comparison
463
+ try { originHost = new URL(origin).host; } // allow:raw-new-url-parse-only — comparing browser-supplied Origin header against Host; safeUrl.parse adds policy filtering that isn't appropriate for exact host comparison
464
464
  catch (_e) { return false; }
465
465
  return originHost === host;
466
466
  }
@@ -964,7 +964,7 @@ class WsClient extends EventEmitter {
964
964
  this._reconnectAttempt += 1;
965
965
  var attempt = Math.min(this._reconnectAttempt, 30); // clamp 2^attempt overflow
966
966
  var ceiling = Math.min(rOpts.maxMs, rOpts.baseMs * Math.pow(2, attempt - 1));
967
- var delay = Math.floor(Math.random() * ceiling); // allow:math-random-noncrypto — backoff jitter, not security
967
+ var delay = Math.floor(Math.random() * ceiling); // allow:math-random-noncrypto-jitter-sampling — backoff jitter, not security
968
968
  var self = this;
969
969
  this._reconnectTimer = setTimeout(function () {
970
970
  self._reconnectTimer = null;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.15.32",
3
+ "version": "0.15.33",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.15.33",
4
+ "date": "2026-06-26",
5
+ "headline": "Internal test-suite hardening only — the published library's runtime behavior and public API are unchanged (source-comment marker text aside)",
6
+ "summary": "Three more suppression classes in the codebase-patterns guard suite were re-verified from scratch and renamed to descriptive tokens, with their old names recorded as retired and their in-source marker comments updated to match. No runtime code, public API, or wire format changed.",
7
+ "sections": [
8
+ {
9
+ "heading": "Detectors",
10
+ "items": [
11
+ {
12
+ "title": "Three more suppression-marker classes re-verified and their tokens retired",
13
+ "body": "Continuing the re-verification pass: each marked site for the math-random-noncrypto, raw-new-url, and dynamic-require guard classes was re-read and confirmed (non-security jitter/sampling; URL parsing for shape/origin inspection or behind the safe wrapper; operator-supplied module loads), then the class was renamed to a descriptive token and its old name added to the retired-token set. This is test-suite tooling; no shipped framework behavior changed."
14
+ }
15
+ ]
16
+ }
17
+ ]
18
+ }
@@ -125,6 +125,26 @@ function _walk(dir, files) {
125
125
  return files;
126
126
  }
127
127
 
128
+ // Like _walk but also prunes node_modules / .test-output — used to scan the
129
+ // FULL repo surface (incl operator-shipped examples/*/lib app code) for retired
130
+ // allow-tokens, without descending into vendored example dependencies.
131
+ function _walkAllSource(dir, files) {
132
+ files = files || [];
133
+ var base = path.basename(dir);
134
+ if (base === "vendor" || base === "node_modules" || base === ".test-output" ||
135
+ base === ".git" || base === "dist" || base === "build" || base === "coverage") return files;
136
+ var entries;
137
+ try { entries = fs.readdirSync(dir, { withFileTypes: true }); }
138
+ catch (_e) { return files; }
139
+ for (var i = 0; i < entries.length; i++) {
140
+ var e = entries[i];
141
+ var full = path.join(dir, e.name);
142
+ if (e.isDirectory()) _walkAllSource(full, files);
143
+ else if (e.isFile() && e.name.endsWith(".js")) files.push(full);
144
+ }
145
+ return files;
146
+ }
147
+
128
148
  function _libFiles() { return _walk(LIB_ROOT); }
129
149
 
130
150
  // Test-tree walker. Excludes infra: test/helpers/_*.js (shape-matcher,
@@ -304,7 +324,7 @@ var VALID_ALLOW_CLASSES = {
304
324
  "deny-path-hardcoded-response": 1,
305
325
  "duplicate-regex": 1,
306
326
  "dynamic-regex": 1,
307
- "dynamic-require": 1,
327
+ "dynamic-require-operator-module": 1,
308
328
  "from-base64url-untrapped": 1,
309
329
  "hand-rolled-sql": 1,
310
330
  "fs-path-from-operator-identifier-without-traversal-refusal": 1,
@@ -318,14 +338,14 @@ var VALID_ALLOW_CLASSES = {
318
338
  "internal-binding-in-prose": 1,
319
339
  "internal-narrative-comment": 1,
320
340
  "list-without-pagination": 1,
321
- "math-random-noncrypto": 1,
341
+ "math-random-noncrypto-jitter-sampling": 1,
322
342
  "no-number-money-arithmetic": 1,
323
343
  "numeric-opt-Infinity": 1,
324
344
  "primitive-unreachable": 1,
325
345
  "process-exit-operator-optin": 1,
326
346
  "raw-byte-literal": 1,
327
347
  "raw-hash-compare": 1,
328
- "raw-new-url": 1,
348
+ "raw-new-url-parse-only": 1,
329
349
  "raw-outbound-http-framework-internal": 1,
330
350
  "raw-process-env-bootstrap": 1,
331
351
  "raw-randombytes-token-mime-boundary": 1,
@@ -364,6 +384,9 @@ var RETIRED_ALLOW_TOKENS = {
364
384
  "handrolled-buffer-collect": "renamed to 'handrolled-buffer-collect-bounded-framing' (2026-06-26 re-verify pass) — every site is a bounded protocol-framing / TLV-serialization assembly, not a collect-to-end stream; re-verify before reusing",
365
385
  "process-exit": "renamed to 'process-exit-operator-optin' (2026-06-26 re-verify pass) — every site exits only on an explicit operator opt-in (exitAfterPhases / { exit: true } bin shim / watchdog); re-verify before reusing",
366
386
  "raw-outbound-http": "renamed to 'raw-outbound-http-framework-internal' (2026-06-26 re-verify pass) — every site routes through b.httpClient / a framework wrapper, or is the documented DoH cycle exception; re-verify before reusing",
387
+ "math-random-noncrypto": "renamed to 'math-random-noncrypto-jitter-sampling' (2026-06-26 re-verify pass) — every site is jitter / sampling / backoff where predictability is not a threat; re-verify before reusing",
388
+ "raw-new-url": "renamed to 'raw-new-url-parse-only' (2026-06-26 re-verify pass) — every site parses for shape/origin inspection, is the safeUrl wrapper itself, or is re-validated downstream — none is an unguarded outbound-fetch target; re-verify before reusing",
389
+ "dynamic-require": "renamed to 'dynamic-require-operator-module' (2026-06-26 re-verify pass) — every site loads an operator-supplied path (migration / seed / extensibility entry, centralized in module-loader.js) or is diagnostic message text; re-verify before reusing",
367
390
  };
368
391
 
369
392
  function testNoRetiredAllowTokenReRegistered() {
@@ -384,6 +407,50 @@ function testNoRetiredAllowTokenReRegistered() {
384
407
  _report("no retired allow-token is re-registered in VALID_ALLOW_CLASSES", bad);
385
408
  }
386
409
 
410
+ function testNoRetiredTokenUsedAnywhere() {
411
+ // A retired token must appear NOWHERE in the repo — not as an `// allow:<token>`
412
+ // suppression marker AND not as a `_filterMarkers(..., "<token>")` detector arg.
413
+ // testNoOrphanAllowClass only covers lib + test/ markers; it misses (a) operator-
414
+ // shipped example app code under examples/*/lib, and (b) a DUPLICATED detector suite
415
+ // (examples/wiki/test/codebase-patterns.test.js) whose filter still references the
416
+ // old class. Renaming a class in one suite but leaving a copy on the old name keeps
417
+ // the retired approval silently reusable in that suite's CI path (Codex P2, PR #384).
418
+ // This scans the FULL source surface (lib + test + all examples, minus node_modules).
419
+ var retired = Object.keys(RETIRED_ALLOW_TOKENS);
420
+ if (retired.length === 0) { check("no retired allow-token used anywhere (none retired)", true); return; }
421
+ var alt = retired.map(function (t) { return t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }).join("|");
422
+ // The new name is always `<old>-<suffix>`, so a trailing `-`/word char means it is the
423
+ // NEW token (exempt); a non-identifier boundary means the bare retired token is in use.
424
+ var markerRe = new RegExp("\\ballow:(" + alt + ")(?![-\\w])");
425
+ var filterRe = new RegExp("_filterMarkers\\([^,]+,\\s*[\"'](" + alt + ")[\"']");
426
+ var examplesRoot = path.resolve(__dirname, "..", "..", "examples");
427
+ var seen = {};
428
+ var files = _libFiles().concat(_walk(TEST_ROOT)).concat(_walkAllSource(examplesRoot));
429
+ var bad = [];
430
+ for (var fi = 0; fi < files.length; fi++) {
431
+ var rel = _relPath(files[fi]);
432
+ // Skip THIS file: it holds RETIRED_ALLOW_TOKENS + the regexes that name retired tokens.
433
+ if (rel === "test/layer-0-primitives/codebase-patterns.test.js") continue;
434
+ if (seen[rel]) continue; seen[rel] = true;
435
+ if (/\/node_modules\//.test(rel) || /\/\.test-output\//.test(rel)) continue;
436
+ var content;
437
+ try { content = fs.readFileSync(files[fi], "utf8"); }
438
+ catch (_e) { continue; }
439
+ var lines = content.split(/\r?\n/);
440
+ for (var li = 0; li < lines.length; li++) {
441
+ var m = markerRe.exec(lines[li]) || filterRe.exec(lines[li]);
442
+ if (m) {
443
+ bad.push({
444
+ file: rel,
445
+ line: li + 1,
446
+ content: "retired allow-token '" + m[1] + "' still used here — " + RETIRED_ALLOW_TOKENS[m[1]],
447
+ });
448
+ }
449
+ }
450
+ }
451
+ _report("no retired allow-token is used as a marker or detector arg anywhere (lib + test + examples)", bad);
452
+ }
453
+
387
454
  function testNoOrphanAllowClass() {
388
455
  // scanScope: lib + test (every shipped + test source).
389
456
  var files = _libFiles().concat(_testFiles());
@@ -1572,7 +1639,7 @@ function testNoDynamicRequires() {
1572
1639
  // interpolation is rare in require()). Skip require.resolve too —
1573
1640
  // distinct API.
1574
1641
  var matches = _scan(/\brequire\(\s*[^"'`)]/);
1575
- matches = _filterMarkers(matches, "dynamic-require");
1642
+ matches = _filterMarkers(matches, "dynamic-require-operator-module");
1576
1643
  _report("require() argument must be a string literal " +
1577
1644
  "(or has dynamic-require allow marker)",
1578
1645
  matches);
@@ -1586,7 +1653,7 @@ function testNoMathRandomForSecurity() {
1586
1653
  // Math.random has legitimate uses (jitter, non-security IDs); those
1587
1654
  // get an allow marker.
1588
1655
  var matches = _scan(/\bMath\.random\(/);
1589
- matches = _filterMarkers(matches, "math-random-noncrypto");
1656
+ matches = _filterMarkers(matches, "math-random-noncrypto-jitter-sampling");
1590
1657
  _report("Math.random() in lib/ has an explicit non-crypto allow marker",
1591
1658
  matches);
1592
1659
  }
@@ -1611,7 +1678,7 @@ function testRawNewURL() {
1611
1678
  // protocol allowlist + length cap + userinfo block apply. Internal
1612
1679
  // URL building (test fixtures, sigv4 canonical query) is fine.
1613
1680
  var matches = _scan(/\bnew URL\(/);
1614
- matches = _filterMarkers(matches, "raw-new-url");
1681
+ matches = _filterMarkers(matches, "raw-new-url-parse-only");
1615
1682
  _report("new URL(...) routes through safeUrl.parse (or has allow marker)",
1616
1683
  matches);
1617
1684
  }
@@ -13173,6 +13240,7 @@ async function run() {
13173
13240
  testNoInternalNarrativeComments();
13174
13241
  testNoOrphanAllowClass();
13175
13242
  testNoRetiredAllowTokenReRegistered();
13243
+ testNoRetiredTokenUsedAnywhere();
13176
13244
  testNoRawByteLiterals();
13177
13245
  testNoRawTimeLiterals();
13178
13246
  testNumericOptsValidate();
@@ -43,7 +43,7 @@ function _buildLocalOptsResolver() {
43
43
  }
44
44
  function _probe(fn) {
45
45
  if (typeof fn !== "function") return { ok: false, reason: "not-a-function" };
46
- var probeKey = "__opts_smoke_probe_" + Date.now() + "_" + Math.random().toString(36).slice(2); // allow:math-random-noncrypto — probe-key uniqueness only
46
+ var probeKey = "__opts_smoke_probe_" + Date.now() + "_" + Math.random().toString(36).slice(2); // allow:math-random-noncrypto-jitter-sampling — probe-key uniqueness only
47
47
  var probeOpts = {}; probeOpts[probeKey] = true;
48
48
  var caught = null;
49
49
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/blamejs-shop",
3
- "version": "0.4.121",
3
+ "version": "0.4.123",
4
4
  "description": "Open-source framework built on blamejs. Vendored stack, zero npm runtime deps, PQC-first crypto, security-on by default.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {