@blamejs/blamejs-shop 0.4.91 → 0.4.93
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/security-middleware.js +21 -3
- package/lib/vendor/MANIFEST.json +49 -41
- package/lib/vendor/blamejs/CHANGELOG.md +6 -0
- package/lib/vendor/blamejs/SECURITY.md +1 -0
- package/lib/vendor/blamejs/api-snapshot.json +208 -2
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +7 -4
- package/lib/vendor/blamejs/examples/wiki/test/integration.js +15 -12
- package/lib/vendor/blamejs/index.js +2 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +34 -1
- package/lib/vendor/blamejs/lib/backup/manifest.js +191 -44
- package/lib/vendor/blamejs/lib/codepoint-class.js +284 -77
- package/lib/vendor/blamejs/lib/framework-error.js +14 -0
- package/lib/vendor/blamejs/lib/fsm.js +80 -24
- package/lib/vendor/blamejs/lib/log.js +32 -0
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +18 -2
- package/lib/vendor/blamejs/lib/middleware/request-id.js +24 -4
- package/lib/vendor/blamejs/lib/request-helpers.js +50 -0
- package/lib/vendor/blamejs/lib/safe-path.js +24 -10
- package/lib/vendor/blamejs/lib/sql.js +133 -0
- package/lib/vendor/blamejs/lib/totp.js +98 -33
- package/lib/vendor/blamejs/lib/ws-client.js +39 -28
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.15.21.json +51 -0
- package/lib/vendor/blamejs/release-notes/v0.15.22.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.15.23.json +22 -0
- package/lib/vendor/blamejs/test/00-primitives.js +80 -0
- package/lib/vendor/blamejs/test/_smoke-worker.js +81 -0
- package/lib/vendor/blamejs/test/integration/federation-auth.test.js +7 -4
- package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +7 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +91 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-default-gate-posture-caps.test.js +5 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-replaystore-required.test.js +9 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/fsm.test.js +99 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +9 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +33 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-id-async-context.test.js +117 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +64 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +55 -0
- package/lib/vendor/blamejs/test/smoke.js +93 -10
- 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.93 (2026-06-25) — **Per-IP rate limits now key an IPv6 client by its /64 prefix, closing an address-rotation bypass of the login, checkout, and webhook throttles.** The request-throttling layer derived its per-client key from the full client IP address. For an IPv4 client that is one host, but an IPv6 end-site is allocated an entire /64 prefix (RFC 6177 / RFC 4291) and can freely rotate the low 64 bits, presenting a fresh address — and therefore a brand-new rate-limit bucket — on every request. That let a single IPv6 site walk straight through every per-IP ceiling: the global request limiter, the tight per-IP limiter on login / register / passkey / checkout, the PayPal webhook verification budget, and the per-IP captcha budget. The client key now collapses an IPv6 address to its routing-significant /64 (an IPv4 address is still keyed verbatim, and an IPv4-mapped IPv6 keys as its dotted host), so one end-site shares one bucket while distinct sites stay distinct. A value that is not a parseable IP falls back to itself, so two unidentifiable clients never collapse into one shared bucket. No configuration changes. **Fixed:** *IPv6 clients can no longer rotate addresses to bypass per-IP rate limits* — Every per-IP throttle — the global request limiter, the tight limiter on authentication and checkout routes, the PayPal webhook verification budget, and the captcha budget — keyed off the full client IP. An IPv6 client controls a whole /64 and could rotate the low 64 bits to mint an unlimited supply of fresh buckets, defeating each ceiling. The per-client key now masks an IPv6 address to its /64 prefix (IPv4 is unchanged), so a single end-site is held to one bucket. The fix lives in the client-key derivation itself, because the framework's rate-limit key mode is bypassed whenever a custom key function is supplied — as every limiter here does.
|
|
12
|
+
|
|
13
|
+
- v0.4.92 (2026-06-25) — **Refresh the vendored framework to 0.15.23 — a state transition whose entry hook throws is now always recorded in the audit trail.** Updates the vendored blamejs framework from 0.15.20 to 0.15.23. The behavioural change operators will notice is in the order, return, redemption, and dropship state machines, which compose the framework's finite-state-machine primitive: previously, if a destination state's entry hook threw, the state change committed but no audit record was written — leaving a privileged transition unaudited. The framework now always records the transition (stamped with a failure outcome and the hook error) and still re-raises the error, so a state change can never be silently unaudited. The refresh also carries upstream correctness and hardening work in primitives the storefront does not currently reach (a websocket-client reconnect fix, a cross-platform path-containment fix), plus additive primitives the application will adopt in follow-up changes. No configuration changes. **Changed:** *State transitions are always audited, even when an entry hook fails* — The order, return, redemption, and dropship-forwarding state machines record every transition on the framework's tamper-evident audit chain. A transition whose destination entry hook threw previously committed the state change without emitting that record. The refreshed framework always writes the audit record — stamped with a failure outcome and the entry-hook error — and still re-raises the error to the caller, so a privileged state change is never left unaudited.
|
|
14
|
+
|
|
11
15
|
- v0.4.91 (2026-06-24) — **A gift-card refund is now linked to the order it reverses, so an order's gift-card settlement history is complete.** When a refund returns money to a gift card (a cancelled or refunded order that had been paid with the card), the ledger credit now records the order it reverses in the structured order field, not only as a free-text reference. Previously a query for a given order's gift-card movements returned the debits that spent the card but not the refund credits that returned money to it, so the order's gift-card settlement history read as one-sided. The refund credit now carries the order link, so the order's gift-card history shows both the spend and the matching refund. No configuration changes, and existing gift-card behavior — balances, overdraft refusal, and the per-card tamper-evident hash chain — is unchanged. **Fixed:** *Refund-to-gift-card credits carry the order they reverse* — giftCardLedger.credit now accepts an optional order_id, and the order-cancellation/refund path that returns a redeemed amount to a gift card passes the order it reverses. The ledger's transactionsForOrder(order_id) lookup keys on that structured field, so it now returns the refund credits flowing back to a card alongside the debits that drained it for the order — previously the credits were keyed only by a free-text reference and were absent from the lookup. Each refund credit still participates in the per-card hash chain (the order link is covered by the row hash), and credits with no associated order (promotional or manual top-ups) are unaffected.
|
|
12
16
|
|
|
13
17
|
- v0.4.90 (2026-06-24) — **Credit-account releases and aging now attribute payments to orders correctly, so cancelling a paid order can't erase another order's debt.** Two related accounting fixes for B2B credit accounts, no configuration or schema changes. On a credit account, payments are revolving — they pay down the oldest outstanding charge first across all of a customer's orders. Releasing the hold on a cancelled or returned order previously reduced the balance by that order's full charge without accounting for payments already applied to it, so on an account with more than one order, cancelling an order that a payment had effectively settled drove the balance below what was genuinely owed and silently erased another order's debt from the outstanding total and the aging report. A release now reduces the balance only by the order's still-unpaid amount (its charges minus the payments attributed to it, oldest-first), so a cancelled-but-paid order is a no-op and every other order's genuine debt is preserved. Separately, the aging report was pooling order-scoped releases together with order-agnostic payments into a single oldest-first settlement, so releasing a recent order could settle the oldest charge and report a genuinely past-due balance as current; the report now nets each order's releases against that order's own charges before applying payments oldest-first, so the past-due buckets reflect reality. The outstanding total is unchanged in every case — only the misattribution is corrected. Upgrade to pick it up. **Changed:** *Vendored blamejs framework refreshed to 0.15.20* — The vendored framework moves from 0.15.19 to 0.15.20, with no API or configuration change. It refreshes the bundled Mozilla public-suffix list (used for cookie-scope, same-site, and DMARC/BIMI domain classification), updates the bundled WebAuthn server library to 13.3.2 (improved passkey attestation certificate-path validation), and corrects the vendored-dependency SBOM version metadata so CVE scanners match advisories against the versions actually shipped. **Fixed:** *Releasing a credit-account order caps at its unpaid amount, not its full charge* — creditLimits.releaseHold now reduces the outstanding balance only by the target order's unpaid exposure — its charges and holds, minus its own prior releases, minus the revolving payments attributed to it under an oldest-order-first allocation — capped at the live balance. Previously it reduced the balance by the order's full net charge and ignored payments entirely (payments carry no order reference), so on a multi-order account, cancelling an order that a payment had already settled released credit that was never owed and erased another order's genuine debt from the outstanding total. A cancelled order whose charge has effectively been paid now releases nothing (the request is refused as having no outstanding amount); a genuinely unpaid order still releases its full exposure. The check is a single atomic statement, so it stays correct under concurrent releases and payments. · *Aging report nets order releases against their own order before applying payments* — creditLimits.agingReport no longer pools order-scoped releases with order-agnostic payments into one oldest-first drain. It first nets each order's releases against that order's own charges (a release reverses its own order's charge, never another's), then applies the revolving payment pool oldest-charge-first across what remains. Previously, releasing a recent order could settle the oldest charge in the pooled drain, masking a genuinely past-due balance as current and inverting the aging buckets that drive dunning and collections. The total outstanding is identical to before — only the bucket distribution is corrected — and it uses the same payment-attribution model as the release cap, so a release and the report can never disagree on an order's unpaid amount.
|
package/lib/asset-manifest.json
CHANGED
|
@@ -283,15 +283,33 @@ var PUBLIC_ORIGINS = (process.env.SHOP_PUBLIC_ORIGINS || "https://blamejs.shop")
|
|
|
283
283
|
* non-empty string so two un-identifiable clients never collapse into
|
|
284
284
|
* the same bucket as a real IP — request-shape reader, returns a
|
|
285
285
|
* default, never throws.
|
|
286
|
+
*
|
|
287
|
+
* The resolved address is collapsed to its rate-limit-significant key via
|
|
288
|
+
* `b.requestHelpers.ipKey`: an IPv4 host is kept verbatim, but an IPv6
|
|
289
|
+
* client is masked to its /64 prefix. A single end-site is allocated a
|
|
290
|
+
* whole IPv6 /64 (RFC 6177 / RFC 4291) and freely rotates the low 64 bits,
|
|
291
|
+
* so keying on the full 128-bit address would let one site present a fresh
|
|
292
|
+
* source on every request and mint unlimited buckets — walking every
|
|
293
|
+
* per-IP limiter (and the captcha-IP budget) that keys off this value.
|
|
294
|
+
* Keying on the /64 closes that while still distinguishing real end-sites.
|
|
286
295
|
*/
|
|
287
296
|
function clientKey(req) {
|
|
288
297
|
var headers = (req && req.headers) || {};
|
|
289
298
|
var cf = headers["cf-connecting-ip"];
|
|
290
|
-
if (typeof cf === "string" && cf.length > 0) return cf.trim();
|
|
299
|
+
if (typeof cf === "string" && cf.length > 0) return _ipBucket(cf.trim());
|
|
291
300
|
var real = headers["x-real-ip"];
|
|
292
|
-
if (typeof real === "string" && real.length > 0) return real.trim();
|
|
301
|
+
if (typeof real === "string" && real.length > 0) return _ipBucket(real.trim());
|
|
293
302
|
var sock = b.requestHelpers.clientIp(req);
|
|
294
|
-
return sock
|
|
303
|
+
return sock ? _ipBucket(sock) : "unknown";
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Collapse one resolved client IP to its per-IP bucket key. ipKey returns
|
|
307
|
+
// "" for a value that isn't a parseable IP (a malformed header, "unknown"),
|
|
308
|
+
// so we fall back to the original non-empty string — keeping two
|
|
309
|
+
// un-identifiable clients in distinct buckets rather than collapsing every
|
|
310
|
+
// garbage value into one shared bucket.
|
|
311
|
+
function _ipBucket(ip) {
|
|
312
|
+
return b.requestHelpers.ipKey(ip, { ipv6Bits: 64 }) || ip;
|
|
295
313
|
}
|
|
296
314
|
|
|
297
315
|
/**
|
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.23",
|
|
7
|
+
"tag": "v0.15.23",
|
|
8
8
|
"license": "Apache-2.0",
|
|
9
9
|
"author": "blamejs contributors",
|
|
10
10
|
"source": "https://github.com/blamejs/blamejs",
|
|
@@ -842,6 +842,9 @@
|
|
|
842
842
|
"release-notes/v0.15.19.json": "lib/vendor/blamejs/release-notes/v0.15.19.json",
|
|
843
843
|
"release-notes/v0.15.2.json": "lib/vendor/blamejs/release-notes/v0.15.2.json",
|
|
844
844
|
"release-notes/v0.15.20.json": "lib/vendor/blamejs/release-notes/v0.15.20.json",
|
|
845
|
+
"release-notes/v0.15.21.json": "lib/vendor/blamejs/release-notes/v0.15.21.json",
|
|
846
|
+
"release-notes/v0.15.22.json": "lib/vendor/blamejs/release-notes/v0.15.22.json",
|
|
847
|
+
"release-notes/v0.15.23.json": "lib/vendor/blamejs/release-notes/v0.15.23.json",
|
|
845
848
|
"release-notes/v0.15.3.json": "lib/vendor/blamejs/release-notes/v0.15.3.json",
|
|
846
849
|
"release-notes/v0.15.4.json": "lib/vendor/blamejs/release-notes/v0.15.4.json",
|
|
847
850
|
"release-notes/v0.15.5.json": "lib/vendor/blamejs/release-notes/v0.15.5.json",
|
|
@@ -1389,6 +1392,7 @@
|
|
|
1389
1392
|
"test/layer-0-primitives/redact-dlp.test.js": "lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js",
|
|
1390
1393
|
"test/layer-0-primitives/redis-client.test.js": "lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js",
|
|
1391
1394
|
"test/layer-0-primitives/request-helpers.test.js": "lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js",
|
|
1395
|
+
"test/layer-0-primitives/request-id-async-context.test.js": "lib/vendor/blamejs/test/layer-0-primitives/request-id-async-context.test.js",
|
|
1392
1396
|
"test/layer-0-primitives/request-log.test.js": "lib/vendor/blamejs/test/layer-0-primitives/request-log.test.js",
|
|
1393
1397
|
"test/layer-0-primitives/require-auth-cache-control.test.js": "lib/vendor/blamejs/test/layer-0-primitives/require-auth-cache-control.test.js",
|
|
1394
1398
|
"test/layer-0-primitives/require-mtls.test.js": "lib/vendor/blamejs/test/layer-0-primitives/require-mtls.test.js",
|
|
@@ -1517,7 +1521,7 @@
|
|
|
1517
1521
|
"test/smoke.js": "lib/vendor/blamejs/test/smoke.js"
|
|
1518
1522
|
},
|
|
1519
1523
|
"bundler": "shallow git clone of release tag from github.com/blamejs/blamejs",
|
|
1520
|
-
"bundledAt": "2026-06-
|
|
1524
|
+
"bundledAt": "2026-06-25",
|
|
1521
1525
|
"hashes": {
|
|
1522
1526
|
".clusterfuzzlite/Dockerfile": "sha256:1eed98fcc49172efc1c1a7740dba20ce6cfcb3830cccd9f28cf114b4b39794f3",
|
|
1523
1527
|
".clusterfuzzlite/build.sh": "sha256:b9f5a627272c65f6569fa20dcbb32c383ca3a1183ce2562d481408a2fbaf9881",
|
|
@@ -1548,7 +1552,7 @@
|
|
|
1548
1552
|
".npmrc": "sha256:66f104e7d07c496d2d0409988225e8c0e4ceb8d247dbcac3be75b2128d20ce66",
|
|
1549
1553
|
".pinact.yaml": "sha256:0213ffda55961dc49b64c0a5dfa3c0567419633b1499d57eaf7c8d842d7da6c7",
|
|
1550
1554
|
"ARCHITECTURE.md": "sha256:9b1c8d2b1b7a41838eb348b0a008e4b4369718fd72bfe2974b37155f7536d35b",
|
|
1551
|
-
"CHANGELOG.md": "sha256:
|
|
1555
|
+
"CHANGELOG.md": "sha256:40391649edd980766aa2b417436b582587ec4a7cfd9a136886e459b5992cc25b",
|
|
1552
1556
|
"CODE_OF_CONDUCT.md": "sha256:148a281960fff7c2fe6554dab66da572c72245ddeb00b0d14811558397bff386",
|
|
1553
1557
|
"CONTRIBUTING.md": "sha256:bb4dbdbc8598da31dbce653a8ed322e08ff46560173f2eb67a4d684653948332",
|
|
1554
1558
|
"GOVERNANCE.md": "sha256:906df6afb1f552b27b9acb50f7f96c47b917a2f1021cd4e987dbf4ee0e0a821b",
|
|
@@ -1557,8 +1561,8 @@
|
|
|
1557
1561
|
"MIGRATING.md": "sha256:3dcc952a3d4a77d53ff60fb67cb5eb5c3a3db2449d7c71f9c4dc7f868097153c",
|
|
1558
1562
|
"NOTICE": "sha256:f487fa47a11aca0f89e2615cdd3c713e9842abf7a30d8d328eeeae1c864aa774",
|
|
1559
1563
|
"README.md": "sha256:3ddcc197b003da0b02db8bdd1aef1e943c94f7eab613c633d6a45bb11d0a80e9",
|
|
1560
|
-
"SECURITY.md": "sha256:
|
|
1561
|
-
"api-snapshot.json": "sha256:
|
|
1564
|
+
"SECURITY.md": "sha256:77d8c2bcc04b425a08ef30e51204cebddbd48954b028a259c7a8412dbfeab40a",
|
|
1565
|
+
"api-snapshot.json": "sha256:ff683e612e56b48ef7f90928f4981e144ad63739583b409d516fba414f9c5349",
|
|
1562
1566
|
"assets/BlameJS_Logo.png": "sha256:3c65699753c771b48ef9ac7f45bb40815ec19a23afcdd0cd30ef4601bbbe293e",
|
|
1563
1567
|
"assets/BlameJS_Logo.svg": "sha256:dda44f3fb1343d5de9db6b1fcdb75fc649c57e7a99a8e8239fcf852e3841e1a8",
|
|
1564
1568
|
"bench/README.md": "sha256:74202f2507fd840bfc1ac6c681975d9273cf36cca6e0f72655f138337304033c",
|
|
@@ -1640,9 +1644,9 @@
|
|
|
1640
1644
|
"examples/wiki/src/wiki.js": "sha256:d27db30436ce441f13ff91cc8f7c4fa59a115b644748cd1fdfd855a8f910a797",
|
|
1641
1645
|
"examples/wiki/test/AUDIT.md": "sha256:28868e102852aa5c0981421035066a1da6676ec5ed8d0f4b88571614dc3301ab",
|
|
1642
1646
|
"examples/wiki/test/codebase-patterns.test.js": "sha256:2973f4c766dd038eff4054a8a5f0fd4df4ba7577f23b1cf52f885cc5d1be6a67",
|
|
1643
|
-
"examples/wiki/test/e2e.js": "sha256:
|
|
1647
|
+
"examples/wiki/test/e2e.js": "sha256:705ee3158a1ef64ae85d026c02f8b868ca7b7f733e1a69ed76370345c989a723",
|
|
1644
1648
|
"examples/wiki/test/find-missing-pages.js": "sha256:092c92b400d8f528df47ab4400f83834dd7a561269bd602e57f05eb740d9126a",
|
|
1645
|
-
"examples/wiki/test/integration.js": "sha256:
|
|
1649
|
+
"examples/wiki/test/integration.js": "sha256:a917fc9cb71d922f8796a426e7defe0d978878e29ce03f4f0db795ed544abc73",
|
|
1646
1650
|
"examples/wiki/test/validate-cli-snapshot.js": "sha256:2986efd62acdf6bc1e98e883457aa8a59dd2ccde6910a5d3b6d3a0e4fbfcfe44",
|
|
1647
1651
|
"examples/wiki/test/validate-env-snapshot.js": "sha256:dd00c689731446fc60fb2a7b6f04d220f92f402ed832e903f605107e1f3d7a4c",
|
|
1648
1652
|
"examples/wiki/test/validate-nav-coverage.js": "sha256:71816ec8b1f46f74bbfadd3e8bb03c2aacd8ec690993b4627b9cdaad8d5aeb17",
|
|
@@ -1755,7 +1759,7 @@
|
|
|
1755
1759
|
"fuzz/safe-url_seed_corpus/05-ipv6.txt": "sha256:b210575d6e9f91b70d1616c89a38bf81e66e4356dcf204a3d40f1932961d01cc",
|
|
1756
1760
|
"fuzz/safe-url_seed_corpus/06-idn.txt": "sha256:9f163641afe7046491b09f95684e30aac38b3cbf243afb115c556ae4fc0339f0",
|
|
1757
1761
|
"fuzz/safe-vcard.fuzz.js": "sha256:20ef167055ea75b6138bc6dc9d8cbdcf108d92be2792571a0162b849671354bd",
|
|
1758
|
-
"index.js": "sha256:
|
|
1762
|
+
"index.js": "sha256:72eb86bf6f3065d8c869b11a019a92bbd87ec2c38dcff67549e50fb3767f5cc0",
|
|
1759
1763
|
"keys/release-pqc-pub.json": "sha256:38fb7f580ccc06c5682c5c3f12b43441d4fdd3e79cf57afb8b3dab3a73af290d",
|
|
1760
1764
|
"lib/_test/crypto-fixtures.js": "sha256:91470fc813e41eeed06dee1e8fbb92d179af77eb01109c1256f7330cb2fc0980",
|
|
1761
1765
|
"lib/a2a-tasks.js": "sha256:d027609ce0688a307ba7c42e52fb6054b1b076fe4d1f62ccf89373ba73f4df3c",
|
|
@@ -1807,7 +1811,7 @@
|
|
|
1807
1811
|
"lib/audit-chain.js": "sha256:1c9895a2bbf6ce3b4c546b1b3c95ac9d5ed55d82a2b58c0de4e3ecc1947c3c31",
|
|
1808
1812
|
"lib/audit-daily-review.js": "sha256:61cebe47d6e5eeeedcab45515473acfaab623217810a7ab3629b3aeca5028519",
|
|
1809
1813
|
"lib/audit-emit.js": "sha256:1171699027269e154fd247141a549e65bcdb566e52ed00b993c7dfb9a293ba0f",
|
|
1810
|
-
"lib/audit-sign.js": "sha256:
|
|
1814
|
+
"lib/audit-sign.js": "sha256:b8ddef053fca28c1e6cf265f73ecd254290a9c2e0759250342e926280205342f",
|
|
1811
1815
|
"lib/audit-tools.js": "sha256:d446ea8de44a70ba1155f30251201ad6787d8ba9c86dd985cd581ee344e459e9",
|
|
1812
1816
|
"lib/audit.js": "sha256:a8a149b4d42605e54b6cdae2dbf6c9840c3162f8e3e254cd47630b665b45d00b",
|
|
1813
1817
|
"lib/auth-bot-challenge.js": "sha256:53084ed4eb6cf18de37e0d60c5e4de2ea40c1100ebb6769b2695db4fe57f11a6",
|
|
@@ -1844,7 +1848,7 @@
|
|
|
1844
1848
|
"lib/backup/bundle.js": "sha256:7c7c7329cbd7240a4793ee04b3d9ec3d2a4620fdd82e84494298791a02567b0f",
|
|
1845
1849
|
"lib/backup/crypto.js": "sha256:a83ff69d25e4c30d7a84ed4754653706b786b3594a38a879f3f7ff6899625f67",
|
|
1846
1850
|
"lib/backup/index.js": "sha256:929b173e19b3b4fb58e7acae281b652d3ae322602ab41aa67f9f8c1c3582a066",
|
|
1847
|
-
"lib/backup/manifest.js": "sha256:
|
|
1851
|
+
"lib/backup/manifest.js": "sha256:797b8e192a1e5b70e980c7394005a3570ea64d792491c2a0f9ffafcf88f2a6a5",
|
|
1848
1852
|
"lib/base32.js": "sha256:9e3f7c0262b0d442d5c92eef15a8a15dad60b034fe3c7c0a16cfdd5c307c3782",
|
|
1849
1853
|
"lib/boot-gates.js": "sha256:ff6ee110476002445093de97b3654cec6f2465039242cea5df8756429f8e9e67",
|
|
1850
1854
|
"lib/bounded-map.js": "sha256:bc7365632665aeb4ca6b256e14cbde25b6002a9992e00211c8df3d54572cf4ca",
|
|
@@ -1870,7 +1874,7 @@
|
|
|
1870
1874
|
"lib/cluster-storage.js": "sha256:b0c9d150ab05d71254d74f65eb0f1dece3aa9a4d94a7292912422588f843eafd",
|
|
1871
1875
|
"lib/cluster.js": "sha256:7a9263639fcccf72dd528e9ab5fd4b2ae893bf16ea0ab2b57b4b4dd45c336fbe",
|
|
1872
1876
|
"lib/cms-codec.js": "sha256:fcc9583c18e7262033e972940a4d6a3ef5a2c0ab93b744b6dcef551250cff56b",
|
|
1873
|
-
"lib/codepoint-class.js": "sha256:
|
|
1877
|
+
"lib/codepoint-class.js": "sha256:20b63ddff5d25398164e96aeb3a4e96ac51573427108219b761de375190ed1f6",
|
|
1874
1878
|
"lib/compliance-ai-act-logging.js": "sha256:acf27602fcee00315e8245942e9a7247f35b75320c2d80d7263ec48ac5da02fa",
|
|
1875
1879
|
"lib/compliance-ai-act-prohibited.js": "sha256:c4d0f404274441c065f93400034edf28daf6c56a9cfdaf25158488e490547c80",
|
|
1876
1880
|
"lib/compliance-ai-act-risk.js": "sha256:cf30214a34b0bbcb66a5e7c9fbfb0c8f4b33fb52786ed2be0d5f9ad58943bfa4",
|
|
@@ -1941,11 +1945,11 @@
|
|
|
1941
1945
|
"lib/flag-targeting.js": "sha256:c2b5096e04dcaa98435c66cfa6b1aae02d0da708ca7e96f810627ef38e669309",
|
|
1942
1946
|
"lib/flag.js": "sha256:3eab2c7e2f86fdf0a099d4ba287ec69486ee985c5496077ce79167979f6fccaf",
|
|
1943
1947
|
"lib/forms.js": "sha256:e8a90aee2497da53d62fed67a674aefda3b4665c75dcee284334ec762753b692",
|
|
1944
|
-
"lib/framework-error.js": "sha256:
|
|
1948
|
+
"lib/framework-error.js": "sha256:6b707ad3cb0c1f180671165381ef228fa9ceb7187bd7202ff6eec0af03304a28",
|
|
1945
1949
|
"lib/framework-files.js": "sha256:689fb8e65ef70633c8ab40f874346fd5f818bdc182690f362545667bf9b5e607",
|
|
1946
1950
|
"lib/framework-schema.js": "sha256:5d515f0b5ba47f851ffa6d458d69268205aedd7d09a343f52dd943055f3df56c",
|
|
1947
1951
|
"lib/framework-sha1-hibp.js": "sha256:07f0e4032c988e3543872ab03a0898e3d1c0791b02a2089686da9d0032b5ffeb",
|
|
1948
|
-
"lib/fsm.js": "sha256:
|
|
1952
|
+
"lib/fsm.js": "sha256:57bfdc6d8f7727248b40cc0169d1ad025ab5fdf16f06f71f8e53258d9c99050a",
|
|
1949
1953
|
"lib/gate-contract.js": "sha256:ae5551c721867d51656559181c4bbcc91051b5cfad09d51f76d772d531c1cf74",
|
|
1950
1954
|
"lib/gdpr-ropa.js": "sha256:d0fb72fc7a68186f233832965afa1ffc7c4ce3c514894656c04c327a88f54925",
|
|
1951
1955
|
"lib/graphql-federation.js": "sha256:ce625ea629850a8e2bb2e6139e078c3b0f20c281c2fac00a631672b252504898",
|
|
@@ -2046,7 +2050,7 @@
|
|
|
2046
2050
|
"lib/log-stream-syslog.js": "sha256:da9648a760c35a609a673419ead08b3f21daf72749ef6365f0c40256304e9bfc",
|
|
2047
2051
|
"lib/log-stream-webhook.js": "sha256:aaec51da99ec52b62c217ff589558bdb73f7f1439a2d1f750e4ee1826be99a19",
|
|
2048
2052
|
"lib/log-stream.js": "sha256:9ffda79044835670fba447876b617b1d5cef0592abf08b52167e2ae7b6bcdba7",
|
|
2049
|
-
"lib/log.js": "sha256:
|
|
2053
|
+
"lib/log.js": "sha256:c95d8850a1c7064be20a1aab448078375643410f5cc9a6bb22cd2598811f9bc6",
|
|
2050
2054
|
"lib/lro.js": "sha256:da9baf47f27c422c32d51495b2896c887ec3ac283875712efcd7528fd396868b",
|
|
2051
2055
|
"lib/mail-agent.js": "sha256:4ca93408c03873796d285d002067ffa54fa70859ad5437215d6001d90c0f76ea",
|
|
2052
2056
|
"lib/mail-arc-sign.js": "sha256:872f31e16321f8629e3af3cac31d3deb460804748b25a7fbb427164a2ad88f84",
|
|
@@ -2127,8 +2131,8 @@
|
|
|
2127
2131
|
"lib/middleware/no-cache.js": "sha256:7ff93c1462595514dd1d9ac7676c683f076347640208998194843fa2d9adba85",
|
|
2128
2132
|
"lib/middleware/openapi-serve.js": "sha256:8fdef819a7b0330d81856e090fecad87ca0e8de269460ba8564dfaa6569d79b5",
|
|
2129
2133
|
"lib/middleware/protected-resource-metadata.js": "sha256:9c1d82fbe360eeed8ea812d441aba8fb88890954b4b0558e4e6e1d744f532856",
|
|
2130
|
-
"lib/middleware/rate-limit.js": "sha256:
|
|
2131
|
-
"lib/middleware/request-id.js": "sha256:
|
|
2134
|
+
"lib/middleware/rate-limit.js": "sha256:7239ecf662fa4ffd983e6678ad1244c152544e838bbfeb04468b6ef819c9cff5",
|
|
2135
|
+
"lib/middleware/request-id.js": "sha256:f9f0cd49ea5090a72c5239af049ea774b99c883ec40083c7f73e5c65c231eae5",
|
|
2132
2136
|
"lib/middleware/request-log.js": "sha256:388a33778a4984dc27cdeb22e73fa95115af2aad587ae37de080bcf5d7f2b834",
|
|
2133
2137
|
"lib/middleware/require-aal.js": "sha256:85d5e53b6bce640df13b8faa96c5498cdab1b2f2ab26b96652ca5935e58eefcb",
|
|
2134
2138
|
"lib/middleware/require-auth.js": "sha256:526b964565eae3296b9bc2ddf02152794507efeb84ca5a38a822a5439170906e",
|
|
@@ -2224,7 +2228,7 @@
|
|
|
2224
2228
|
"lib/redact.js": "sha256:1cd102db31eb48ffbc677c39013ddc1b829db7597d808785a7b202a5e0dc691d",
|
|
2225
2229
|
"lib/redis-client.js": "sha256:9f8168b11b81ce7b649b2e0658ceeb7134a257435b611f4917d36e1ed178a3e5",
|
|
2226
2230
|
"lib/render.js": "sha256:1890c0cce371ea93c1820f70ea544dee25d8d9bd427fdfd6688d7cb17720ed8b",
|
|
2227
|
-
"lib/request-helpers.js": "sha256:
|
|
2231
|
+
"lib/request-helpers.js": "sha256:74f2361c3e5250bfc5dd04d4f3b17401daeba8135152221597d3d94efab54f07",
|
|
2228
2232
|
"lib/resource-access-lock.js": "sha256:868d2c0a59d2ca2757a334858779d23e0cde9c18bf63c535350d8ebd6ae20b53",
|
|
2229
2233
|
"lib/restore-bundle.js": "sha256:c2a9c3af19434a2072ea4cc721211119f71ba363bbbad9df7ac34a3ff03e43e2",
|
|
2230
2234
|
"lib/restore-rollback.js": "sha256:f00e2f40e2e6a14bc6687afe8c112e367d83314eb04592d9ba399cb699fb0e03",
|
|
@@ -2244,7 +2248,7 @@
|
|
|
2244
2248
|
"lib/safe-jsonpath.js": "sha256:0d5a0191de5cba7564847d6419a63c9949fb310f6a77c5637d2ad7b8ca30623c",
|
|
2245
2249
|
"lib/safe-mime.js": "sha256:885bf0b2932d5ad492ec981f21068e1f85bb6738383a140b27e33659b690931e",
|
|
2246
2250
|
"lib/safe-mount-info.js": "sha256:790d047481e0a2c04d3dd1f6f1645e2d6fada2f1dd1efde93ca647d2177ca7d4",
|
|
2247
|
-
"lib/safe-path.js": "sha256:
|
|
2251
|
+
"lib/safe-path.js": "sha256:b7c73576e4540bc9b3d5b91768c9ae5980d8c1cac72d5f12bf823d5a7f36706e",
|
|
2248
2252
|
"lib/safe-redirect.js": "sha256:fdbec66fbc6747f98f0f3145c7166fc5f980d520fa9d1cda063577aedec85052",
|
|
2249
2253
|
"lib/safe-schema.js": "sha256:a5cfab85ced62a38417f3fa09ac6b7e52bdc7b6b1e16567192462c552ff7da58",
|
|
2250
2254
|
"lib/safe-sieve.js": "sha256:2925300c6a6d973178a7cdc73983520fa764847e104551e1c52a20fbd9ab760d",
|
|
@@ -2267,7 +2271,7 @@
|
|
|
2267
2271
|
"lib/session-stores.js": "sha256:b79de919061a2bfeb090185bcc511919fb01d3e7a495fe0a7c711cf6cf65137b",
|
|
2268
2272
|
"lib/session.js": "sha256:dc3fcfd31edb04f25ce128ca8eb7106978f6b985c6558c6e1179613b8771930f",
|
|
2269
2273
|
"lib/slug.js": "sha256:bcebb078559528e6bb50a6244633d425ffdd861bb7a708c2b201eae3b3c44b35",
|
|
2270
|
-
"lib/sql.js": "sha256:
|
|
2274
|
+
"lib/sql.js": "sha256:8de2d3f1be989cc07a465ee205e0c5ece854240c7f7d7b3757613edb93ee049c",
|
|
2271
2275
|
"lib/sse.js": "sha256:5e4fca52ddb92ab1c13ad7434c6b13d5c4ef0f7fc3845b003f8c3603c1629dbf",
|
|
2272
2276
|
"lib/ssrf-guard.js": "sha256:65d3d1bf6841064cdf9b9e7ffb5a0a3ac9358e462943f5de09087640353dfac4",
|
|
2273
2277
|
"lib/standard-webhooks.js": "sha256:e604534d48202a41f2c9f6954a990731db80d0693794d3a80f371f843490ff57",
|
|
@@ -2283,7 +2287,7 @@
|
|
|
2283
2287
|
"lib/testing.js": "sha256:12a03fe09ca1b048a9f6ef1b871533befa79efd9bb8bd037e154dbed75cb35a8",
|
|
2284
2288
|
"lib/time.js": "sha256:e20e65af3acdfcfd593b15e11d5cc11fa692f94520da98cfe7ef679a4cb57941",
|
|
2285
2289
|
"lib/tls-exporter.js": "sha256:b53bb42848b35f6b4ee6c4cbe72fd901c00921cd35a5fc6b0e827b0917e1ca72",
|
|
2286
|
-
"lib/totp.js": "sha256:
|
|
2290
|
+
"lib/totp.js": "sha256:92e31489267990f4b8d00abb550c5ba5aacc95208f5a19dc85c3dfdb30ba7d0b",
|
|
2287
2291
|
"lib/tracing.js": "sha256:9cf50be329ce320ecd2064ee4112749e9b0258f60cef2d99ff487f152a2e1393",
|
|
2288
2292
|
"lib/tsa.js": "sha256:7b5a0844c7f8fdc75d65556819015233ac3f3f5cef95f2abd4ca52deb6a52d66",
|
|
2289
2293
|
"lib/uri-template.js": "sha256:9b7252fce4a8245ee1ad51b3ce4dadd42d08080ddded961dafad2330a1a6cd8d",
|
|
@@ -2322,14 +2326,14 @@
|
|
|
2322
2326
|
"lib/wiki-concepts.js": "sha256:54789790b950d926cbd0657dd51b32435c4988012b520819615df93673680de5",
|
|
2323
2327
|
"lib/worker-pool.js": "sha256:fc35b3c9f83a4c72be0981400f5294b566472bfe187df0500775e37dd71afa4c",
|
|
2324
2328
|
"lib/worm.js": "sha256:f17e24f8ca39295f396f40bd0c4ad1c946f5e41ff646ef1b33e8d50dc8b9435e",
|
|
2325
|
-
"lib/ws-client.js": "sha256:
|
|
2329
|
+
"lib/ws-client.js": "sha256:66d615ad9d57099afd281e3b4f32666fc2981207b084e9eb46444d67b2a8fe19",
|
|
2326
2330
|
"lib/x509-chain.js": "sha256:fdc0ecd264d9de0e039f348e819675fdf3838d61097a97a0e3e119def338722a",
|
|
2327
2331
|
"lib/xml-c14n.js": "sha256:01a27d20df99ebd6eaefbff0aad933a2231049f65a54ae994236694d4146ce5d",
|
|
2328
2332
|
"oss-fuzz/projects/blamejs/Dockerfile": "sha256:6c48ec4d81f4b1836a6b43701a2497cf737002413dd0da6a10892be1498b0766",
|
|
2329
2333
|
"oss-fuzz/projects/blamejs/README.md": "sha256:ae13b7bb79ed8d69b1b3276e5562807a0349fb6e6b7d11cf1f683aad1eafdb4b",
|
|
2330
2334
|
"oss-fuzz/projects/blamejs/build.sh": "sha256:0ced1cf21782c97be7f8d74faf5e27a308b60b2f858836fb5ca3b8c4e939a8f7",
|
|
2331
2335
|
"oss-fuzz/projects/blamejs/project.yaml": "sha256:59f2cb83aa622325a175b77416fe155be15b70a9c798bd1a78bba05763b1b03d",
|
|
2332
|
-
"package.json": "sha256:
|
|
2336
|
+
"package.json": "sha256:f6b218899ddd351231d447c0f072d8800614317baf5496c30d1f0bfd56c955e0",
|
|
2333
2337
|
"release-notes/v0.0.x.json": "sha256:7a49819f30068ee119000cad7010194882bb8bfaa12acbdab4dfc066efb7982f",
|
|
2334
2338
|
"release-notes/v0.1.x.json": "sha256:6742a8c17f947c5cb76f69dead7eea86b942d80621d914b774ba5488e09937e5",
|
|
2335
2339
|
"release-notes/v0.10.x.json": "sha256:fe498045daf88337bd3d987e5964aa42c99a50e1685b6f09e51f698b8687726f",
|
|
@@ -2351,6 +2355,9 @@
|
|
|
2351
2355
|
"release-notes/v0.15.19.json": "sha256:8c6a745accd2c551953464991bb23547e8cf87286d57938c57080755785e58b5",
|
|
2352
2356
|
"release-notes/v0.15.2.json": "sha256:36e1423dda94ed4e55c660e0fae882019005d8de3ee5e3b6ac4f38ccf8e744a2",
|
|
2353
2357
|
"release-notes/v0.15.20.json": "sha256:bc469d136c909f94d89d2816a5a4c7b08ae93380d812e837d4f1c554eae1ce2b",
|
|
2358
|
+
"release-notes/v0.15.21.json": "sha256:02b6e86d81f4d3ab5785ccdb2b0d2623c3ba406232dd9a5b9fbf8e3287c22c69",
|
|
2359
|
+
"release-notes/v0.15.22.json": "sha256:3e794d767699e38d06ac3566117009e104fde8623f64ffd8f7ce682105d25341",
|
|
2360
|
+
"release-notes/v0.15.23.json": "sha256:bb25738ab9701fb90a287e0b0370fe28f06396481664922450d1178c2a191b19",
|
|
2354
2361
|
"release-notes/v0.15.3.json": "sha256:19a0074c445545468ca3cc411b21ec8bdb27be2669ae1950347cc244f6aa348c",
|
|
2355
2362
|
"release-notes/v0.15.4.json": "sha256:6ac7fa0ef1728c27e71b2050d1b07a810f9b4b1440ccddbf28ad56e2f54d8585",
|
|
2356
2363
|
"release-notes/v0.15.5.json": "sha256:cca1d0edd5d6fc41b512d19d98be224b990dcab41478622c11962f0fcb1bb09a",
|
|
@@ -2390,14 +2397,14 @@
|
|
|
2390
2397
|
"scripts/vendor-data-gen.js": "sha256:76b627bc6e19b4a122edfca6f514bcb8ca11af02902f0957e641f503337a8a0f",
|
|
2391
2398
|
"scripts/vendor-data-keygen.js": "sha256:94eaa4d8f832b4aac9ccbcb2a07e6b99cd35cf7b044e1412079cebdefc1f4c0e",
|
|
2392
2399
|
"scripts/vendor-update.sh": "sha256:373d7f024b7caa3345a3598fa3a586078dd842f0071e6fdad00a473f48a3a929",
|
|
2393
|
-
"test/00-primitives.js": "sha256:
|
|
2400
|
+
"test/00-primitives.js": "sha256:a3b45127578d453428a2afc10724a0c7dc7cd4963b32dd2a965453ab517f481f",
|
|
2394
2401
|
"test/10-state.js": "sha256:7f286e00fda002ccf50ccc59d658b6dce9a4bccee304232984a932a2ceb31c49",
|
|
2395
2402
|
"test/20-db.js": "sha256:241ef6b7ef305d077aeafb22ee3bcc75b6b549a8fa9b1a6b5d6d5fba43b48d7d",
|
|
2396
2403
|
"test/30-chain.js": "sha256:5aec1fb27d1a87ac74fb3613192b0d6b9cb8bb1dbf5cefdd0fc04eceb9fc3d35",
|
|
2397
2404
|
"test/40-consumers.js": "sha256:b652384ea357532ecec289dcf2c624caf1b50b8ac1600b11f5ed08acba3e1992",
|
|
2398
2405
|
"test/50-integration.js": "sha256:a016825cc3d954f9e2c65c8f74e9fc23e180c470645adefc8b8b17c2229aedca",
|
|
2399
2406
|
"test/_helpers.js": "sha256:9769ddf6d7eb1c4ef7d461036ba47835ef5ef2a86d64704ffd85d49b3ccbaf20",
|
|
2400
|
-
"test/_smoke-worker.js": "sha256:
|
|
2407
|
+
"test/_smoke-worker.js": "sha256:502a4cb77dcec473b44b60a28ddccce6a4e424de78f053293e75d1d6333eea7a",
|
|
2401
2408
|
"test/fixtures/exploit-corpus/corpus.json": "sha256:83bf3878cbadd7097698fd6292f19b981d139d56eeafdff242292451ff7a4afc",
|
|
2402
2409
|
"test/fixtures/http-client-stream-payload.txt": "sha256:4f2855f401f5883f26da53848fb78f7b8f9f31194282025523c5d15297bbf4fa",
|
|
2403
2410
|
"test/fixtures/worker-pool/echo.js": "sha256:42995cb27a3d510468558db916cab189fb85efe1a52a4941fde8c9230f8f338a",
|
|
@@ -2433,12 +2440,12 @@
|
|
|
2433
2440
|
"test/integration/db-layer-postgres.test.js": "sha256:cfcca6540004699adcaf2d11aca5a7dab36203a67a438ee527167d22231af63e",
|
|
2434
2441
|
"test/integration/distributed-scheduler-fencing-pg.test.js": "sha256:7f61080d79414749d64a576d2af3153e85032dd133e583292e9a8cdb70d2d075",
|
|
2435
2442
|
"test/integration/external-db-postgres.test.js": "sha256:bf339af851d42418d7e4e76b2c0585d12e41fcd5c2e061a269cc6febd07d5bfd",
|
|
2436
|
-
"test/integration/federation-auth.test.js": "sha256:
|
|
2443
|
+
"test/integration/federation-auth.test.js": "sha256:00b9f81699ed116cac61608e1d3cc64d24a3aa044e221afb89fe0682a0b509a9",
|
|
2437
2444
|
"test/integration/framework-schema-mysql.test.js": "sha256:aade2c58eb5694d93533188cf38a27d52cc6749417f19a21e37f6d85dc447a00",
|
|
2438
2445
|
"test/integration/http-client.test.js": "sha256:fb667e279fa47dcdaca2ad24fa08d11ab4322a86283e19d9b1cc2b607bab29cc",
|
|
2439
2446
|
"test/integration/log-stream-cloudwatch.test.js": "sha256:c55b4434db449e4b39809c2d7af61f47af470164cf547c69f09a5de8a764d676",
|
|
2440
2447
|
"test/integration/log-stream.test.js": "sha256:9b69a9cc30be81f3353be15247f2d90bd06afa2cf970178598793b7d1fecdd81",
|
|
2441
|
-
"test/integration/mail-crypto-smime.test.js": "sha256:
|
|
2448
|
+
"test/integration/mail-crypto-smime.test.js": "sha256:21661d212c0e9c9b780265266a0ded4fee0f097948bfc7c6d5e99a3e74d2d89f",
|
|
2442
2449
|
"test/integration/mail-dkim.test.js": "sha256:bdf8e25e0b0a566ddbafef863b65a4b98634aa7b23bfed9a2ed2e0e29e6722d2",
|
|
2443
2450
|
"test/integration/mail-smtp.test.js": "sha256:ac93642ca28716ccecfee4d02509fb9f234be443b5a91c47c0b852c5dad3a9fa",
|
|
2444
2451
|
"test/integration/mtls-ca.test.js": "sha256:d475c0f6f72e2ea4f161ce7c6b5527e74ebff26401ebbf39043c2cbd97fe434e",
|
|
@@ -2546,7 +2553,7 @@
|
|
|
2546
2553
|
"test/layer-0-primitives/backup-clone-bundle.test.js": "sha256:b6f8dd251177e1d5cc7d4b764fa66597140d9060a0226b0a082ded3f864b0e56",
|
|
2547
2554
|
"test/layer-0-primitives/backup-find-bundles.test.js": "sha256:bf34b6a1b92415187a537813d9ca83a0a934999012610f7d403867f2f4a82c98",
|
|
2548
2555
|
"test/layer-0-primitives/backup-key-rotation.test.js": "sha256:61c789bf78c00723356b5b61f5853bbcb0b930f0c07ea2a30d9d60c23055f612",
|
|
2549
|
-
"test/layer-0-primitives/backup-manifest-signature.test.js": "sha256:
|
|
2556
|
+
"test/layer-0-primitives/backup-manifest-signature.test.js": "sha256:2b6899f8cb83d6a257cab74c430ffb95e2943b9d6c0bfb897d4dfa33952c1046",
|
|
2550
2557
|
"test/layer-0-primitives/backup-object-store-adapter.test.js": "sha256:15683a337c2fa883c0be198019846198df63e19a063b16170e33bdad16d395c3",
|
|
2551
2558
|
"test/layer-0-primitives/backup-residency-posture.test.js": "sha256:cd9a03fae204f58930780737fe50e38f936f95fb4b2a89733af48af5fd7eaf97",
|
|
2552
2559
|
"test/layer-0-primitives/backup-rewrap-all.test.js": "sha256:bd70e4fbf0b8b4ffdd56546a4ede4ff84f2ec870d93c995db704829ef599ebb7",
|
|
@@ -2596,8 +2603,8 @@
|
|
|
2596
2603
|
"test/layer-0-primitives/cluster-storage.test.js": "sha256:238b3b3db0eba3e6312a863710533178f566347b90e161e564481aa826707647",
|
|
2597
2604
|
"test/layer-0-primitives/cluster-vault-rotation.test.js": "sha256:3514e9e71d6c39e805248f58ad2f41528d091e196c0f3766a032675677161b2d",
|
|
2598
2605
|
"test/layer-0-primitives/cms-codec.test.js": "sha256:7e46078ed82be5b69d22c48f22dba37ea5015371c2a8cf5f94fb1a792fb7bb78",
|
|
2599
|
-
"test/layer-0-primitives/codebase-patterns.test.js": "sha256:
|
|
2600
|
-
"test/layer-0-primitives/codepoint-class.test.js": "sha256:
|
|
2606
|
+
"test/layer-0-primitives/codebase-patterns.test.js": "sha256:b3e942c8f91682437dfb023f7bb2bdda06036b3d2d47111015d4c5db8cea36c7",
|
|
2607
|
+
"test/layer-0-primitives/codepoint-class.test.js": "sha256:19d1b69efa7e0e9f7ef2392ca264167767a5ec5890ee339b2cfd8a7818035d27",
|
|
2601
2608
|
"test/layer-0-primitives/compliance-ai-act.test.js": "sha256:5ee4ad05d12233cb3c5457ef10a727833710bbc1ce1318838f9f9ef5d2cb8d4b",
|
|
2602
2609
|
"test/layer-0-primitives/compliance-cascade.test.js": "sha256:ee02cf14541a837a9d7977c6ea6bf7f9210bed293925d93c976e31f270aebec4",
|
|
2603
2610
|
"test/layer-0-primitives/compliance-eaa.test.js": "sha256:8afb3fa66f3f9452592995e77f5e0644d8c82de2321c551c6f5be6002b2c27a4",
|
|
@@ -2664,7 +2671,7 @@
|
|
|
2664
2671
|
"test/layer-0-primitives/ddl-change-control.test.js": "sha256:f9e7c97f75c8aa98a4723d43d15690dc54a562ca7e91fb181fb633926d346ac8",
|
|
2665
2672
|
"test/layer-0-primitives/declare-row-policy.test.js": "sha256:e263a6a3b3ba9ba6c551dad41200f3559d4ef8c9093618d91f4569e35393fcd8",
|
|
2666
2673
|
"test/layer-0-primitives/declare-view.test.js": "sha256:43bf4ec78c6ad4dd003ad2c29fb2607f6b63a26dc1207641ae13bf43c35b52f7",
|
|
2667
|
-
"test/layer-0-primitives/defineguard-default-gate-posture-caps.test.js": "sha256:
|
|
2674
|
+
"test/layer-0-primitives/defineguard-default-gate-posture-caps.test.js": "sha256:c94b446d8e6043c4d6e76c69b8a262d1412aba6a5a0b69fb8fe4e85605113b6b",
|
|
2668
2675
|
"test/layer-0-primitives/defineguard-resolve-opts.test.js": "sha256:9a48ff0777feaca789f434947296449610a1f6ad8d5abe729ac92e897391adce",
|
|
2669
2676
|
"test/layer-0-primitives/deny-response.test.js": "sha256:603a8694cbc557e9023d824c54976fef535f2028c39c4155ac180f7ffb35686c",
|
|
2670
2677
|
"test/layer-0-primitives/did.test.js": "sha256:41e59ef91bd3431475d29beae8f3de7f8b916e50b3971d0b51809f4f76006813",
|
|
@@ -2674,7 +2681,7 @@
|
|
|
2674
2681
|
"test/layer-0-primitives/dora.test.js": "sha256:e046e66ad07fe7b69e8763c53cc7514956362b161500977548bdc47964813fc2",
|
|
2675
2682
|
"test/layer-0-primitives/dpop-alg-kty.test.js": "sha256:64d7c85ae95d49b82a29bec74d81ce134025917c25a21992bcdf6645b48e19be",
|
|
2676
2683
|
"test/layer-0-primitives/dpop-htu-peergating.test.js": "sha256:a328ebe9c97d272de9f4cf15368b03764e75f5afd3d38e1ee59b69aaf089eb87",
|
|
2677
|
-
"test/layer-0-primitives/dpop-middleware-replaystore-required.test.js": "sha256:
|
|
2684
|
+
"test/layer-0-primitives/dpop-middleware-replaystore-required.test.js": "sha256:e6172e4c90a33b7002f99514b8b3810788b1c7da94e426f38ecd86bf6e550e71",
|
|
2678
2685
|
"test/layer-0-primitives/dr-runbook.test.js": "sha256:9665caaa90f356d0237e0e6c6889c56a3467b20c7eaf78d2e2afa51c4b3af2cb",
|
|
2679
2686
|
"test/layer-0-primitives/dsa.test.js": "sha256:2cdbdd29b9c58d738920bb4f82f73492eab56e7d7f8111f1cdb14838de3a3ab3",
|
|
2680
2687
|
"test/layer-0-primitives/dsr-state-rules.test.js": "sha256:0ddc7fd6d5d3f8817d8f4aad7bb66c6bf6e64eafe61fdedaafa8f60957d20bd0",
|
|
@@ -2702,7 +2709,7 @@
|
|
|
2702
2709
|
"test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js": "sha256:ad13f7f84a33899b4f4e66b74c896f606e070bfe5df769b0acd109cfb7ab38c7",
|
|
2703
2710
|
"test/layer-0-primitives/flag.test.js": "sha256:8b58826342b8c28d90e11e4cfe1a7e266c2296615a90558221cad12e9f6ecb4e",
|
|
2704
2711
|
"test/layer-0-primitives/forensic-snapshot.test.js": "sha256:629a8af1ccd0396e2b30f8e46d76fe19eab9f33c156c0db78e3e76649e21030c",
|
|
2705
|
-
"test/layer-0-primitives/fsm.test.js": "sha256:
|
|
2712
|
+
"test/layer-0-primitives/fsm.test.js": "sha256:7037831083426478ed4efd7d1c17d4b96c3609816a41819b5c9da71d2b6187e8",
|
|
2706
2713
|
"test/layer-0-primitives/gate-contract-content-gate.test.js": "sha256:d9f8b94231efb0e02a94b7934bf58a3f8e343829ce11346b7302e69e13efd551",
|
|
2707
2714
|
"test/layer-0-primitives/gcs-bucket-ops.test.js": "sha256:2261e3ac2d66d48e4e436d2f43f9f48f45822930824fa48888f0fc9cfabcf908",
|
|
2708
2715
|
"test/layer-0-primitives/gdpr-ropa.test.js": "sha256:ebed2f001ddc79e42a9cd0ee5319536662dcb4c601b3eb65077161ab81e243a4",
|
|
@@ -2833,7 +2840,7 @@
|
|
|
2833
2840
|
"test/layer-0-primitives/metrics-snapshot.test.js": "sha256:aa405be22acb6680b062d1de1aa7ce00029e414218a0e4e521e10a14b2254851",
|
|
2834
2841
|
"test/layer-0-primitives/middleware-compose-pipeline.test.js": "sha256:a779468bde043b6de4add5d4405a33973163890ee667b833e3330373ee64f77d",
|
|
2835
2842
|
"test/layer-0-primitives/mime-parse.test.js": "sha256:73ccfea7d08b0c3b5fb899215806d4f430c02bf63e21835024a4cdcfc4254b31",
|
|
2836
|
-
"test/layer-0-primitives/money.test.js": "sha256:
|
|
2843
|
+
"test/layer-0-primitives/money.test.js": "sha256:d4c6d830d94badf24242f2ba3a9f4c2ffe13e214d6c6e56bcf73dc026f0dc380",
|
|
2837
2844
|
"test/layer-0-primitives/mtls-ca-paths.test.js": "sha256:71518f55b516c202021f62e720af710aa98c86be8aca33bda1decac6afa1218b",
|
|
2838
2845
|
"test/layer-0-primitives/mtls-ca-revocation.test.js": "sha256:27e3e909cd2fc0b6dfb8276a2a182c3bf948dccc65f601c670204a324d792e36",
|
|
2839
2846
|
"test/layer-0-primitives/nel.test.js": "sha256:1b074316a1172d23da880ee6c9fa99b5548ae28322ea43a7f91adbdb260375ca",
|
|
@@ -2863,7 +2870,7 @@
|
|
|
2863
2870
|
"test/layer-0-primitives/observability.test.js": "sha256:29e0e41b05a358b53053dd696e48dd17827d903e6eb59dad08a183ac932376a5",
|
|
2864
2871
|
"test/layer-0-primitives/openapi.test.js": "sha256:2e552cbb27b70ac28688632364defc9d063b3b26ff45788012e656bce8ba31e3",
|
|
2865
2872
|
"test/layer-0-primitives/otel-export.test.js": "sha256:78c0103b69f04270b35f1d4f14471c4aa085bdad0b55667e2f182f94c2a3f7b6",
|
|
2866
|
-
"test/layer-0-primitives/otlp-attr-redaction.test.js": "sha256:
|
|
2873
|
+
"test/layer-0-primitives/otlp-attr-redaction.test.js": "sha256:8cc7e45ca183b3b940688d19dd38141463836ced32c396f157dc5cf916eb8d84",
|
|
2867
2874
|
"test/layer-0-primitives/outbox-inflight-reaper.test.js": "sha256:b4d65c14c7d8aa7712424f2a685fd7bc44b306650c14e3ff5047b2f021ac81f4",
|
|
2868
2875
|
"test/layer-0-primitives/output-header-hardening.test.js": "sha256:4792ef56abc48e96833bdaf0019c5a61b21789cf62062fd74c48f3a969bf2db3",
|
|
2869
2876
|
"test/layer-0-primitives/pagination.test.js": "sha256:432bbead37b57079f91429c2f3998aed28eb947086f8b0b8ebbd111fa3abdb07",
|
|
@@ -2894,10 +2901,11 @@
|
|
|
2894
2901
|
"test/layer-0-primitives/rate-limit-cluster.test.js": "sha256:732f28a7737c6696c02f554b5b7e5d4328a3eacb84ab1491b8b058c2ba603ee7",
|
|
2895
2902
|
"test/layer-0-primitives/rate-limit-memory-getorinsert.test.js": "sha256:6e113f7643f0de46975f5ca37d87cc16f7bf97c2c4513fd8f09b09c224e4622f",
|
|
2896
2903
|
"test/layer-0-primitives/rate-limit-registry.test.js": "sha256:bb8a7081398aadfd8e8ecf8665863a2b28136b9dddf438022bfd5de0b2f05956",
|
|
2897
|
-
"test/layer-0-primitives/rate-limit-xff-spoofing.test.js": "sha256:
|
|
2904
|
+
"test/layer-0-primitives/rate-limit-xff-spoofing.test.js": "sha256:aa85f9aff582227ff7c2db29b33c24d62e73b95ace13398d2e27ded345298e1c",
|
|
2898
2905
|
"test/layer-0-primitives/redact-dlp.test.js": "sha256:42b80cd22185ce81e8caf71243e6f6bc2f3185a091ebe5fbb776bfab7bab37c3",
|
|
2899
2906
|
"test/layer-0-primitives/redis-client.test.js": "sha256:bb1f192c78311b7f3fededcf90a3e5bc3492fc31c001f64c642dd3eb9b631dd4",
|
|
2900
|
-
"test/layer-0-primitives/request-helpers.test.js": "sha256:
|
|
2907
|
+
"test/layer-0-primitives/request-helpers.test.js": "sha256:0c4a5f689c3553e22835152d58c127239dbd8bfe2cc538b5a540f9d359b06bc8",
|
|
2908
|
+
"test/layer-0-primitives/request-id-async-context.test.js": "sha256:7c61b217c94105ee513b5b467fbf8df8ad695a275673c1b9a47dfaccf9ad7ceb",
|
|
2901
2909
|
"test/layer-0-primitives/request-log.test.js": "sha256:31479f63311b31a74aa7f636b7f9ef04c2f6bcb152b8b8c465a40d08461cc03f",
|
|
2902
2910
|
"test/layer-0-primitives/require-auth-cache-control.test.js": "sha256:36b9d77791285e2b2606a5d2f8f8c8536a46e7ec1f4f2c5e54ee1b17a3dece3d",
|
|
2903
2911
|
"test/layer-0-primitives/require-mtls.test.js": "sha256:ba041e00d098090b4ffa578bb8b3f01927043842a5057069502dc69ade2dc23d",
|
|
@@ -2924,7 +2932,7 @@
|
|
|
2924
2932
|
"test/layer-0-primitives/safe-jsonpath.test.js": "sha256:d7a161d928d0d45621568479f8b80ab27603cfdb0dbb644695b4eedd3849a2b5",
|
|
2925
2933
|
"test/layer-0-primitives/safe-mime.test.js": "sha256:ba8af559611c30897f3d00f26d9dbd85a56ca66a1fdeef0fb84a3ca4a8fd2dc9",
|
|
2926
2934
|
"test/layer-0-primitives/safe-mount-info.test.js": "sha256:eae629afda908036b9d9f4ba175c53a7a65f678c98ce5c8c96e41bbfab5e0e88",
|
|
2927
|
-
"test/layer-0-primitives/safe-path.test.js": "sha256:
|
|
2935
|
+
"test/layer-0-primitives/safe-path.test.js": "sha256:0d41d24a5409dfd6026efdcfbdfe18f9aa0d5406f6831400043615857f778070",
|
|
2928
2936
|
"test/layer-0-primitives/safe-redirect.test.js": "sha256:3435b29c5fed535442e71f9801c24805a5f35aef0f3b4972ed253a9163dd4802",
|
|
2929
2937
|
"test/layer-0-primitives/safe-sieve.test.js": "sha256:55351060c1cefc55adbba060d5cad75c75a07e5735ce70f94458d7f6deabf49c",
|
|
2930
2938
|
"test/layer-0-primitives/safe-smtp.test.js": "sha256:c0969bc61e66744e672df89740f9c09ab0d955d946f12648cb936d1bf2a31d70",
|
|
@@ -2965,7 +2973,7 @@
|
|
|
2965
2973
|
"test/layer-0-primitives/smtp-policy.test.js": "sha256:184fee03f15e5b607ded9ae034143c00561030830cdf7b96a70b3fcc2cb8d419",
|
|
2966
2974
|
"test/layer-0-primitives/source-comment-blocks.test.js": "sha256:83f8fdfc46fd384515932d120e00f76cd5fa041cb6f52e706c43cd5c56592309",
|
|
2967
2975
|
"test/layer-0-primitives/speculation-rules.test.js": "sha256:aa6a5b52d01832fd90db008220c861a412c61a1a5e90bb179f393359e6579598",
|
|
2968
|
-
"test/layer-0-primitives/sql.test.js": "sha256:
|
|
2976
|
+
"test/layer-0-primitives/sql.test.js": "sha256:948c78941cae9ff706f7dacaad15b516514693b58eb56c2bc64e94c06cd1f323",
|
|
2969
2977
|
"test/layer-0-primitives/sse-backpressure.test.js": "sha256:a435f5ca7e4b37f80c41da40d20d152cc2ad78d9e57fa020a054474b1feb8050",
|
|
2970
2978
|
"test/layer-0-primitives/sse.test.js": "sha256:ca58bd0149a2b62b7b08aa5003d81edcb9cc14e38cbc5fade1e6a2639a84cfe0",
|
|
2971
2979
|
"test/layer-0-primitives/ssrf-guard.test.js": "sha256:323f48e6ad057ea9977f6b798619ee8f7c74fa2d404a496086a9f61eb2cbd75b",
|
|
@@ -3016,14 +3024,14 @@
|
|
|
3016
3024
|
"test/layer-0-primitives/worker-pool-recycle-race.test.js": "sha256:84f02fb349ac9b10470271a16214b8fc08d4a89757c2958f296e6bd11307e394",
|
|
3017
3025
|
"test/layer-0-primitives/worker-pool.test.js": "sha256:0a3698d862346f64f98eb1c954694ad6a6b4cedbfc569a1f4d93233b7bfa733a",
|
|
3018
3026
|
"test/layer-0-primitives/worm.test.js": "sha256:0908cfbf7228de39ab68796505c29071d3117571b8a6c07cef7d1fa27d0380b8",
|
|
3019
|
-
"test/layer-0-primitives/ws-client.test.js": "sha256:
|
|
3027
|
+
"test/layer-0-primitives/ws-client.test.js": "sha256:e08ee87dc913390dd2f099e5677806a89e9c7f36701265a31212446dedac9753",
|
|
3020
3028
|
"test/layer-0-primitives/x509-chain-ca-enforcement.test.js": "sha256:8d68ffe4f8655af99682927524ae5a6c5336f32a57eb7c5c78fef5f2d1b2e6e3",
|
|
3021
3029
|
"test/layer-1-state/api-key.test.js": "sha256:48d641b673a181746adf80dfa995f0ca29187af17aa4735590557fda4350dcb8",
|
|
3022
3030
|
"test/layer-5-integration/bundler-output.test.js": "sha256:d54ea7e86cdeb0241d49df70e5c5962ad8a35e3a0a57ff0026361597c4785b0b",
|
|
3023
3031
|
"test/layer-5-integration/external-db-residency.test.js": "sha256:3ff1de115d465f1f35decf207d9263bb1bb5327892662bd992adddb8af9e0f49",
|
|
3024
3032
|
"test/layer-5-integration/guard-host-integration.test.js": "sha256:5c57da239285ebf04ee34cb5ab2bc000e61e7b13a91fc15750ca1db49c431808",
|
|
3025
3033
|
"test/layer-5-integration/security-chaos.test.js": "sha256:7459c282a2169b54afb1f6fe36649116553f3f62b6acb454fb4f90cb3b02aa87",
|
|
3026
|
-
"test/smoke.js": "sha256:
|
|
3034
|
+
"test/smoke.js": "sha256:869ffd58acde24418af1b8ae834c8f65635602fbf8622c37cc19d13295a279a9"
|
|
3027
3035
|
}
|
|
3028
3036
|
}
|
|
3029
3037
|
}
|
|
@@ -8,6 +8,12 @@ upgrading across more than a few patches at a time.
|
|
|
8
8
|
|
|
9
9
|
## v0.15.x
|
|
10
10
|
|
|
11
|
+
- v0.15.23 (2026-06-24) — **`b.wsClient` error objects now carry a usable terminal-vs-transient signal (and the client's auto-reconnect, previously dead, works again), and `b.safePath` resolves cross-platform containment with the target platform's path semantics — fixing both a false refusal of in-base paths and a backslash-traversal escape when validating for Windows on a POSIX host.** Two correctness fixes. b.wsClient marked every WsClientError permanent, so a consumer driving its own reconnect loop could not tell a terminal handshake failure (a bad URL, a 4xx rejection, an accept-mismatch, a protocol-violation frame) from a transient one (a 5xx handshake rejection, a pong/handshake timeout, a dropped socket) and had to re-derive the taxonomy from error codes. err.permanent now reflects the actual transience of each error, the single bad-status code is split by the carried HTTP status (4xx terminal, 5xx transient) with the status exposed as err.statusCode, and — because the client's own auto-reconnect keyed off the same always-true flag — auto-reconnect was silently disabled for every transient failure and now fires correctly. Separately, b.safePath.resolve / resolveOrNull / validate performed its lexical containment with the runtime path module while the per-segment naming walk used opts.platform. The two disagreeing broke cross-platform validation both ways: every legitimate in-base path was refused with safe-path/escapes-base when opts.platform differed from the host, and — more seriously — a POSIX host validating opts.platform: "windows" accepted a backslash traversal (ok\..\..\outside), because the runtime resolver treats \ as an ordinary filename character and never collapsed the .. segments, so the path escaped the base once a Windows consumer read the backslashes. The lexical resolve and containment boundary now use the target platform's path module (node:path.win32 / node:path.posix), matching the segment walk, so in-base paths resolve and cross-platform traversals are refused under any opts.platform override; the realpath check, which touches the live filesystem, keeps its runtime resolve. **Fixed:** *b.wsClient: WsClientError carries a real terminal/transient signal, and auto-reconnect works again* — WsClientError was declared always-permanent, so err.permanent was true for every error — a consumer's reconnect loop could not distinguish a terminal handshake failure (bad URL, bad subprotocol, malformed handshake header, accept-mismatch, bad upgrade, bad status line, a 4xx rejection, an oversized/protocol-violation frame) from a transient one (a 5xx handshake rejection, a pong- or handshake-timeout, a dropped socket) and had to maintain its own error-code list tracking the framework's taxonomy. err.permanent now reflects each error's actual transience, derived from its code (a new/unknown code defaults to terminal, so it fails closed rather than redialing a hopeless target forever); the single ws-client/bad-status code is split by the response status (4xx terminal, 5xx transient) and the status is exposed as err.statusCode (the existing err.status alias is preserved). The same always-permanent flag also drove the client's built-in auto-reconnect, which therefore never retried any framework-surfaced transient failure (a 5xx handshake or a keepalive timeout); reconnect now fires for transient failures and still skips terminal ones. · *b.safePath: cross-platform containment resolves with the target platform's path semantics* — b.safePath.resolve / resolveOrNull / validate performed its lexical containment (resolve rel under base, then bound the result with a separator slice) using the runtime path module, while the per-segment naming walk used opts.platform. When the two disagreed, validation broke both ways. Benign direction: a Linux service validating server-origin names against the stricter Windows ruleset (the recommended cross-platform pattern) had every legitimate in-base path refused with safe-path/escapes-base, because the runtime-separated resolved path could never match a Windows-separator boundary. Security direction: a POSIX host validating opts.platform: "windows" accepted a backslash traversal such as ok\..\..\outside — the segment walk splits on \ for Windows, but the runtime resolver on POSIX treats \ as an ordinary filename character and never collapsed the .. segments, so the path passed containment and resolved to <base>/ok\..\..\outside, which escapes the base once a Windows consumer interprets the backslashes. The lexical resolve and the containment boundary now use the target platform's path module (node:path.win32 when validating for Windows, node:path.posix otherwise), matching the segment walk, so in-base paths resolve correctly and a genuine traversal is refused under any opts.platform override. The realpath check, which resolves symlinks on the live filesystem, keeps a separate runtime resolve because a foreign-platform path cannot be symlink-resolved on the host. opts.platform continues to gate the per-segment naming rules (reserved names, trailing dot/space, NTFS ADS colon).
|
|
12
|
+
|
|
13
|
+
- v0.15.22 (2026-06-24) — **Internal test-harness reliability only — the published library is byte-for-byte identical to 0.15.21.** This release changes only the repository's own test harness and test files; nothing under the shipped tarball (index.js, bin/, lib/) is touched, so the API, behavior, and published files are identical to 0.15.21 and operators have nothing to do. The smoke worker now attributes a fire-and-forget failure — an unawaited promise or an unreleased handle (a retry timer, a shutdown wait, a watcher/reload restart) that throws AFTER a test's assertions already passed — to the exact test that caused it and retries it once, instead of the prior unattributable, intermittent failure that only surfaced on a resource-starved CI runner. Five test files that invoked their run() at module scope (re-running and, in some cases, exiting the worker before it could report a result) are corrected to run only under require.main === module, and a test-discipline check keeps the pattern from returning. An opt-in handle-leak audit (SMOKE_AUDIT_HANDLES) surfaces tests that hold a timer / socket / server / worker past completion, for a follow-up cleanup pass. **Changed:** *Smoke test harness attributes late-async-error failures and fixes module-level test self-execution* — The forked smoke worker installs unhandledRejection / uncaughtException handlers and a settle tick so a failure that fires after a test's assertions pass — a leaked handle's callback or an unawaited promise from retry / shutdown / reload logic — is reported against the test that caused it and retried once (a transient passes, a persistent one fails again and names the bug), replacing the prior intermittent, unattributable 'fork failed' that only appeared on a starved CI runner. Five test files (two integration, three layer-0, plus two wiki-suite harnesses) that called run() at module scope are corrected to execute only under require.main === module so they no longer double-run or exit the worker prematurely when required, and a codebase-patterns test-discipline detector prevents the unguarded-module-level-run shape from recurring. A SMOKE_AUDIT_HANDLES opt-in reports per-file handle leaks for a tracked cleanup. None of this is in the published package.
|
|
14
|
+
|
|
15
|
+
- v0.15.21 (2026-06-24) — **Adds a portable compare-and-swap UPDATE, an IPv6 /64 rate-limit key, a verify-only legacy-TOTP path, request-id AsyncLocalStorage scoping, schema-agnostic backup signing, side-effect-free FSM transition resolution, and the public codepoint-threat catalog — and fixes an FSM state transition that committed without an audit record when its entry hook threw.** A batch of additive primitives that close gaps operators hit composing the framework: b.sql.guardedUpdate builds the cross-instance-safe compare-and-swap UPDATE (the conditional-INSERT sibling) with b.sql.casWon reading the won/lost result; b.requestHelpers.ipKey (and a rateLimit ipKeyMode) key an IPv6 client by its routing-significant /64 so one end-site can't rotate the low 64 bits to evade a per-IP limit; b.auth.totp gains an opt-in verify-only SHA-1 path for one-final-login legacy-secret migration while generation stays SHA-512-only; b.middleware.requestId can bind the id into an AsyncLocalStorage scope that survives the awaited route chain; b.backupManifest.signBytes/verifyBytes authenticate a consumer's own canonical bytes with the framework signing key; b.fsm gains a side-effect-free instance.target() and a way to defer its transition audit when composed with an external claim; and the codepoint-threat catalog the guard family composes is exposed as b.codepointClass. A correctness fix: an FSM transition whose onEnter hook threw left the state committed but emitted no audit record — the record now always fires (stamped a failure outcome with the hook error) so a state change is never unaudited. **Added:** *b.sql.guardedUpdate + b.sql.casWon — portable compare-and-swap UPDATE* — b.sql.guardedUpdate(table) builds an UPDATE whose required guardWhere(col, expected) fence makes it land only when the row is still in the expected value — the cross-instance-safe way to advance a status or version on a single-statement-per-request backend (a D1-over-HTTP bridge or any autocommit-only adapter without interactive transactions), and the conditional-UPDATE sibling of b.sql.insertSelectWhere. It refuses to render without a fence (an unfenced guardedUpdate is just a plain update). b.sql.casWon(result) reads the won/lost verdict from the affected-row count, normalizing the rowCount / changes / affectedRows field-name divergence across adapters and throwing on an indeterminate result so a phantom win can't ship. Standard SQL across SQLite / Postgres / MySQL; guardWhereOp(col, op, expected) supports a non-equality fence (an optimistic-version or balance guard), and a null fence renders IS NULL. · *b.requestHelpers.ipKey + rateLimit ipKeyMode — IPv6 /64 keying* — b.requestHelpers.ipKey(ip, { ipv6Bits }) derives a stable rate-limit / blocklist key: an IPv4 address verbatim (one IPv4 is one host) but an IPv6 address collapsed to its routing-significant /64 prefix. A single IPv6 end-site is allocated a whole /64 (RFC 6177 / RFC 4291) and freely rotates the low 64 bits, so keying on the full 128-bit address lets one site mint unlimited fresh keys and walk a per-IP throttle or evade an exact-address block; keying on the /64 closes that while still distinguishing real end-sites. b.middleware.rateLimit gains ipKeyMode: "prefix64" to apply this to its default key (the audit record still logs the full client IP). · *b.auth.totp verify-only SHA-1 path for legacy-secret migration* — b.auth.totp.verify(secret, code, { algorithm: "sha1", verifyOnly: true }) authenticates a single legacy code during a re-enrollment flow, so a consumer migrating pre-existing RFC-6238-default (SHA-1) secrets can reuse the maintained verifier — separator stripping, 64-bit counter, drift / replay semantics — instead of hand-rolling a parallel HOTP. SHA-1 is still refused on every generation path (compute / generate / uri), so new-enrollment posture stays SHA-512-only, and the flag is honored only by verify(); each such verification emits an auth.totp.legacy_sha1_verify audit signal. · *b.middleware.requestId AsyncLocalStorage scoping* — b.middleware.requestId({ asyncContext: true }) binds the request id into the framework's AsyncLocalStorage scope so b.log.getRequestId() (and every b.log.create-built logger) returns it inside awaited route-handler code, not just on req.requestId. Because the b.router dispatch model runs the route handler after the middleware returns, the binding uses AsyncLocalStorage.enterWith (which persists forward across the awaited chain) rather than a callback wrap that would close before the handler runs; each request runs in its own async context so the binding stays request-scoped. The underlying b.log.enterRequestId(id) is exposed for callers wiring their own middleware. · *b.backupManifest.signBytes / verifyBytes — schema-agnostic signing* — b.backupManifest.signBytes(canonicalBytes) and verifyBytes(canonicalBytes, signatureBlock, { expectedFingerprint }) sign and verify a consumer's own canonical bytes with the same audit-sign keypair and fingerprint pinning as the v1-manifest sign() / verifySignature(), without adopting the framework's manifest schema — so a bespoke backup-header format can authenticate itself against the framework signing key. Fingerprint pinning is bound to the key the signature actually verifies under: the pin is checked against the fingerprint recomputed from the signature block's own public key (the new b.auditSign.fingerprintOf(publicKeyPem) helper), not the block's self-asserted fingerprint field, so a block can't claim a trusted fingerprint while being signed by a different key. The same binding now also applies to the v1-manifest verifySignature(). b.auditSign.verify additionally no longer requires init() when given an explicit public key, so a downstream verifier that holds only a trusted public key can check a detached signature. · *b.fsm side-effect-free transition resolution + deferrable audit* — instance.target(event) resolves a transition's destination state side-effect-free — the same edge and guard check as can() but returning the to-state (or null when the edge is illegal or guard-refused) — so a consumer composing an external compare-and-swap (b.sql.guardedUpdate on an autocommit-only substrate) can build the SET status = <to> claim without calling transition(), which would mutate state and emit an audit before the cross-instance claim is known to land. transition(event, { audit: false }) suppresses the built-in emit so that composition can emit its own enriched record once the claim resolves. · *b.codepointClass — the codepoint-threat catalog on the public surface* — The Unicode bidi-override / C0-control / zero-width / null-byte / Unicode-Tags tables and the UTS #39 confusable-script detector that the b.guard* family composes internally are now exposed as b.codepointClass, so a consumer can build a custom unconstrained-free-text screen — detectCharThreats / assertNoCharThreats / applyCharStripPolicies / scriptFor / detectMixedScripts plus the compiled regexes — without re-rolling the regexes (where the zero-width class is mistyped and the astral Unicode-Tags block forgotten) or coupling to an internal module path. For a ready-made free-text guard, b.guardText remains the first-class entry point. **Fixed:** *An FSM transition committed its state change without an audit record when the entry hook threw* — b.fsm commits the new state and pushes the history entry before running the destination state's onEnter hook. When that hook threw, control skipped the audit emission entirely — leaving a committed state transition with no audit record, a compliance gap for any regime that requires state changes to be auditable. The transition audit now always fires even when onEnter throws: it records the committed transition stamped with a failure outcome and the hook error, and still re-raises the error to the caller (the documented contract that an onEnter throw surfaces so the operator can roll back is unchanged).
|
|
16
|
+
|
|
11
17
|
- v0.15.20 (2026-06-24) — **Vendored SBOM version fields are derived from the bundle so they cannot drift, and the Public Suffix List + @simplewebauthn/server bundles are refreshed.** The vendor manifest recorded each bundled package's version in two scanner-facing places that were hand-maintained and could drift from the code actually shipped — the structured components[].version (the CycloneDX component versions) and the cpe string. Two had drifted: peculiar-pki's @peculiar/x509 component read 1.13.0 while the bundle shipped 2.0.0, and @noble/curves' cpe read 0.0.0 while the bundle shipped 2.2.0. A CVE scanner (Trivy / Grype / a CycloneDX export, or a consumer mirroring the manifest into its own SBOM) keys on those structured fields, so an advisory was matched against the wrong version — a false negative on a real fix or a false positive on a patched one. Both fields are corrected, the vendor-bundle script now derives them from the actually-installed package versions at bundle time so they cannot drift again, and a manifest gate fails the build if they ever disagree. Separately, the vendored Mozilla Public Suffix List is refreshed to the current upstream revision and @simplewebauthn/server is refreshed to 13.3.2. **Changed:** *Vendored Public Suffix List and @simplewebauthn/server refreshed* — The vendored Mozilla Public Suffix List is refreshed to the current upstream revision (used by b.publicSuffix for DMARC / BIMI / cookie-scope / same-site domain classification). @simplewebauthn/server is refreshed from 13.3.1 to 13.3.2, which improves WebAuthn attestation certificate-path validation; the published-tarball diff was reviewed (no install scripts, no network/eval, a self-contained code change) before re-vendoring. **Fixed:** *Vendored SBOM version metadata is bundle-derived, not hand-maintained* — lib/vendor/MANIFEST.json recorded each package's version in two places a CVE/SBOM scanner reads — the structured components[].version sub-object and the cpe string — both hand-maintained alongside the human version string, so they could (and did) drift from the bundled code. @peculiar/x509's component version read 1.13.0 while the bundle shipped 2.0.0; @noble/curves' cpe read 0.0.0 while the bundle shipped 2.2.0. Either drift makes a scanner match advisories against the wrong version. Both are corrected to the shipped versions, and the durable fix is structural: scripts/vendor-update.sh now writes both the structured component versions and the cpe version from the ACTUALLY-INSTALLED package versions captured at bundle time, so a maintainer can no longer update one field and forget the other. A smoke-time manifest gate additionally fails the build if any component or cpe version disagrees with the package version, catching a manual drift before it ships.
|
|
12
18
|
|
|
13
19
|
- v0.15.19 (2026-06-22) — **Restores the wiki container build by keeping its base image on the continuously-patched rolling tag.** A follow-up to 0.15.18. The framework code is unchanged from 0.15.18 — this patch reverts one part of that release's supply-chain pass: the example wiki container's Chainguard base images had been pinned to specific digests, but Chainguard rebuilds those images continuously to ship CVE fixes, so the frozen digest fell behind an upstream fix within hours and the container's Trivy CRITICAL/HIGH release gate rejected the build (a fixed npm/undici denial-of-service the rolling tag already carried). For a deployed, Trivy-gated image, tracking the rolling, always-patched tag is the correct posture; the wiki Dockerfile is back on it. The ClusterFuzzLite fuzz base (not deployed, not release-gated) stays digest-pinned with Dependabot keeping it current. **Fixed:** *Wiki container builds again on a continuously-patched base* — 0.15.18 digest-pinned the example wiki container's Chainguard base images (runtime + builder). Because Chainguard rebuilds those images continuously to ship CVE fixes, the pinned digest went stale within hours and the container's Trivy CRITICAL/HIGH release gate rejected the build over an already-fixed npm/undici DoS (CVE-2026-12151) the rolling tag carried. The wiki Dockerfile tracks the rolling tag again, so the deployed image is always CVE-current and the build passes the release gate. To keep the Trivy-scanned image identical to the multi-arch image that is published (they are built separately), the release workflow resolves the rolling tag to a digest once at build time and feeds it to both builds via build-args — scan-equals-publish without a committed pin that goes stale. (This trades the OSSF Scorecard PinnedDependencies signal for CVE currency on a deployed, gate-scanned image — the right call here; the non-deployed ClusterFuzzLite fuzz base remains digest-pinned with Dependabot bumping it.) The framework package itself is identical to 0.15.18.
|
|
@@ -341,6 +341,7 @@ This is the minimum-viable security posture for a production deployment. The fra
|
|
|
341
341
|
- [ ] For session security: pass `{ req }` to `b.session.create()` and `b.session.verify()` so the IP / UA fingerprint is captured and checked; for high-value sessions (admin, finance) set `requireFingerprintMatch: true` OR `maxAnomalyScore: 0.7` with an operator-supplied `scorer(input)` function (impossible-travel detection, geo-distance, etc.). When rotating a session at a privilege boundary (login, MFA, role change), pass the same `{ req, fingerprintFields }` to `b.session.rotate()` so the device binding re-keys to the new session id — a fingerprint-bound session rotated without `req` is refused, because the binding cannot follow the new id and would otherwise silently break or false-drift the user out on the next request
|
|
342
342
|
- [ ] For RFC 9449 DPoP proof-of-possession deployments: wire `b.middleware.dpop` with a `replayStore` (a `b.nonceStore`-shaped `{ checkAndInsert }`, e.g. `b.nonceStore.create({ backend })`) — it is required at mount time, so single-use jti-replay defense is always enforced. Mounting the middleware without the store (or with one lacking `checkAndInsert`) throws at config time rather than failing open at request time with no replay defense (RFC 9449 §11.1)
|
|
343
343
|
- [ ] For inbound admin paths reachable on the public network: mount `b.middleware.networkAllowlist({ paths: ["/admin"], allowedCidrs: [...] })` as the in-process CIDR fence above the application-layer auth gate
|
|
344
|
+
- [ ] For IPv6-reachable deployments, set `ipKeyMode: "prefix64"` on `b.middleware.rateLimit` so the per-IP key buckets an IPv6 client by its routing-significant `/64` — a single end-site is allocated a whole `/64` (RFC 6177 / RFC 4291) and can otherwise rotate the low 64 bits to mint unlimited fresh keys and walk the limit; IPv4 stays per-host. `b.requestHelpers.ipKey(ip)` exposes the same keying for blocklists. Behind a reverse proxy, still declare `trustedProxies` (CIDRs) so the forwarded client IP is peer-gated, not forgeable
|
|
344
345
|
- [ ] For outbound integrations: pin destination hosts via `b.httpClient.request({ allowedHosts: ["api.partner.com", ".internal.example.com"] })` so a compromised process can't reach arbitrary upstreams
|
|
345
346
|
- [ ] For test suites that mount a mock server on `127.0.0.1` to exercise `b.httpClient` / `b.wsClient` against deterministic fixtures: keep the SSRF gate ON in production code, then in tests inject an explicit `allowInternal: true` (per-call) alongside the mock-server URL. The opt-in is loud and audited, the production posture is unchanged, and operators reviewing the test grep see exactly which call sites talk to internal addresses. Cloud-metadata IPs (`169.254.169.254` etc.) stay hard-deny under any `allowInternal` value
|
|
346
347
|
- [ ] Before comparing a URL against an allowlist/denylist, building a cache/dedup key from one, or deciding whether a host is internal: canonicalize it with `b.safeUrl.canonicalize(url)` (or `b.ssrfGuard.canonicalizeHost(host)` for the host alone) first. It collapses obfuscated host + IP spellings — decimal / octal / hex / dotted IPv4, zero-compressed IPv6, IDN → punycode (rejecting confusable hosts), default ports, trailing-dot hosts (every count), path percent-encoding — to one comparable string, so `0177.0.0.1`, `0x7f.1`, `2130706433`, and `127.0.0.1` can't slip past a check that only string-matched the literal. An IPv4-mapped IPv6 host (`::ffff:1.2.3.4`) folds to its embedded IPv4 so a dual-stack peer unifies with a dotted-IPv4 entry, and credentials are dropped from the canonical form (NAT64 / 6to4 stay IPv6 so canonicalize-then-classify agrees with the SSRF classifier). Pair it with the `b.ssrfGuard` DNS-resolving gate, which still runs at fetch time
|