@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.
- package/CHANGELOG.md +4 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/loyalty-earn-rules.js +7 -1
- package/lib/order.js +23 -10
- package/lib/vendor/MANIFEST.json +30 -28
- package/lib/vendor/blamejs/CHANGELOG.md +2 -0
- package/lib/vendor/blamejs/api-snapshot.json +2 -2
- package/lib/vendor/blamejs/examples/wiki/lib/opts-resolver.js +1 -1
- package/lib/vendor/blamejs/examples/wiki/server.js +1 -1
- package/lib/vendor/blamejs/examples/wiki/src/wiki.js +1 -1
- package/lib/vendor/blamejs/examples/wiki/test/codebase-patterns.test.js +9 -9
- package/lib/vendor/blamejs/lib/acme.js +1 -1
- package/lib/vendor/blamejs/lib/agent-trace.js +1 -1
- package/lib/vendor/blamejs/lib/auth/oauth.js +2 -2
- package/lib/vendor/blamejs/lib/cli.js +2 -2
- package/lib/vendor/blamejs/lib/cluster.js +1 -1
- package/lib/vendor/blamejs/lib/db-schema.js +1 -1
- package/lib/vendor/blamejs/lib/gate-contract.js +1 -1
- package/lib/vendor/blamejs/lib/json-schema.js +2 -2
- package/lib/vendor/blamejs/lib/mcp.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +1 -1
- package/lib/vendor/blamejs/lib/module-loader.js +2 -2
- package/lib/vendor/blamejs/lib/retry.js +1 -1
- package/lib/vendor/blamejs/lib/safe-url.js +1 -1
- package/lib/vendor/blamejs/lib/ssrf-guard.js +1 -1
- package/lib/vendor/blamejs/lib/vendor-data.js +2 -2
- package/lib/vendor/blamejs/lib/websocket.js +1 -1
- package/lib/vendor/blamejs/lib/ws-client.js +1 -1
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.15.33.json +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +74 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/source-comment-blocks.test.js +1 -1
- 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.
|
package/lib/asset-manifest.json
CHANGED
|
@@ -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
|
-
|
|
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
|
-
//
|
|
844
|
-
//
|
|
845
|
-
|
|
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:
|
|
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
|
|
1083
|
-
//
|
|
1084
|
-
//
|
|
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
|
-
|
|
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:
|
|
1130
|
+
order_total_minor: _ptGoods,
|
|
1118
1131
|
});
|
|
1119
1132
|
}).catch(function () { /* drop-silent — loyalty ledger holds its own audit trail */ });
|
|
1120
1133
|
}
|
package/lib/vendor/MANIFEST.json
CHANGED
|
@@ -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.
|
|
7
|
-
"tag": "v0.15.
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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.
|
|
@@ -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;
|
|
@@ -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