@blamejs/blamejs-shop 0.1.31 → 0.1.33
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/README.md +4 -0
- package/lib/admin.js +18 -10
- package/lib/asset-manifest.json +17 -5
- package/lib/bundles.js +28 -0
- package/lib/checkout.js +48 -2
- package/lib/storefront.js +792 -45
- package/lib/vendor/MANIFEST.json +2 -2
- package/lib/vendor/blamejs/CHANGELOG.md +8 -0
- package/lib/vendor/blamejs/README.md +3 -1
- package/lib/vendor/blamejs/api-snapshot.json +99 -2
- package/lib/vendor/blamejs/index.js +3 -0
- package/lib/vendor/blamejs/lib/crypto-oprf.js +110 -0
- package/lib/vendor/blamejs/lib/network-tsig.js +404 -0
- package/lib/vendor/blamejs/lib/network.js +1 -0
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +44 -9
- package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +19 -0
- package/lib/vendor/blamejs/lib/worm.js +246 -0
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.12.x.json +1844 -0
- package/lib/vendor/blamejs/release-notes/v0.13.0.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.13.1.json +18 -0
- package/lib/vendor/blamejs/scripts/vendor-update.sh +11 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +3 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +101 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tsig.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/testing.test.js +3 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/worm.test.js +126 -0
- package/package.json +2 -2
- package/lib/vendor/blamejs/release-notes/v0.12.0.json +0 -64
- package/lib/vendor/blamejs/release-notes/v0.12.1.json +0 -32
- package/lib/vendor/blamejs/release-notes/v0.12.10.json +0 -65
- package/lib/vendor/blamejs/release-notes/v0.12.11.json +0 -39
- package/lib/vendor/blamejs/release-notes/v0.12.12.json +0 -48
- package/lib/vendor/blamejs/release-notes/v0.12.13.json +0 -31
- package/lib/vendor/blamejs/release-notes/v0.12.14.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.15.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.12.16.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.17.json +0 -22
- package/lib/vendor/blamejs/release-notes/v0.12.18.json +0 -22
- package/lib/vendor/blamejs/release-notes/v0.12.19.json +0 -22
- package/lib/vendor/blamejs/release-notes/v0.12.2.json +0 -45
- package/lib/vendor/blamejs/release-notes/v0.12.20.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.21.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.12.22.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.23.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.24.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.25.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.26.json +0 -30
- package/lib/vendor/blamejs/release-notes/v0.12.27.json +0 -26
- package/lib/vendor/blamejs/release-notes/v0.12.28.json +0 -26
- package/lib/vendor/blamejs/release-notes/v0.12.29.json +0 -31
- package/lib/vendor/blamejs/release-notes/v0.12.3.json +0 -23
- package/lib/vendor/blamejs/release-notes/v0.12.30.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.31.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.32.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.12.33.json +0 -31
- package/lib/vendor/blamejs/release-notes/v0.12.34.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.35.json +0 -22
- package/lib/vendor/blamejs/release-notes/v0.12.36.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.37.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.12.38.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.39.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.4.json +0 -19
- package/lib/vendor/blamejs/release-notes/v0.12.40.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.41.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.42.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.43.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.44.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.45.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.46.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.47.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.48.json +0 -22
- package/lib/vendor/blamejs/release-notes/v0.12.49.json +0 -31
- package/lib/vendor/blamejs/release-notes/v0.12.5.json +0 -40
- package/lib/vendor/blamejs/release-notes/v0.12.50.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.51.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.52.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.53.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.54.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.55.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.56.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.12.57.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.58.json +0 -22
- package/lib/vendor/blamejs/release-notes/v0.12.6.json +0 -45
- package/lib/vendor/blamejs/release-notes/v0.12.60.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.61.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.62.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.63.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.12.64.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.65.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.12.66.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.12.68.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.12.69.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.12.7.json +0 -86
- package/lib/vendor/blamejs/release-notes/v0.12.8.json +0 -81
- package/lib/vendor/blamejs/release-notes/v0.12.9.json +0 -61
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.
|
|
7
|
-
"tag": "v0.
|
|
6
|
+
"version": "0.13.1",
|
|
7
|
+
"tag": "v0.13.1",
|
|
8
8
|
"license": "Apache-2.0",
|
|
9
9
|
"author": "blamejs contributors",
|
|
10
10
|
"source": "https://github.com/blamejs/blamejs",
|
|
@@ -6,8 +6,16 @@ Pre-1.0 the surface is intentionally evolving — every release may
|
|
|
6
6
|
change something operators depend on. Read each entry before
|
|
7
7
|
upgrading across more than a few patches at a time.
|
|
8
8
|
|
|
9
|
+
## v0.13.x
|
|
10
|
+
|
|
11
|
+
- v0.13.1 (2026-05-26) — **`b.worm` — write-once-read-many retention.** Store records that cannot be altered or deleted before a retention period elapses — the immutable-storage discipline regulators require (SEC 17a-4(f), CFTC 1.31, FINRA 4511). b.worm.create(opts) returns a WORM store that enforces, on every mutating call, that a record is not overwritten or deleted while it is within its retainUntil window or under a legal hold. Two modes mirror cloud Object-Lock: compliance (the default — no one, including the operator, can delete before expiry) and governance (a privileged caller may override with an audited reason). Retention can only be extended, never shortened; every record carries a SHA3-512 digest that get verifies, so tampering with the underlying bytes is detected on read; every allow/refuse decision is audited. Storage is pluggable via a synchronous store adapter, so the policy layer sits over a sealed DB table, a filesystem, or any non-S3 backend — the store-agnostic, application-level companion to b.objectStore's S3 Object Lock, with content-integrity verification that native Object Lock does not provide. **Added:** *`b.worm.create` — write-once-read-many retention* — Returns a store with `put` / `get` / `delete` / `extendRetention` / `placeLegalHold` / `releaseLegalHold` / `list`. `put` is write-once (an overwrite of a retained or held record is refused); `delete` is gated by the retention window, legal holds, and the mode (`compliance` refuses any early delete; `governance` allows a privileged override with a required, audited reason); `extendRetention` is extend-only; `get` verifies the stored SHA3-512 digest and throws `worm/tampered` on a mismatch. Storage is a pluggable synchronous adapter (`get` / `set` / `delete` / `has` / `keys`), defaulting to in-memory for tests. Use it for SEC 17a-4 / CFTC / FINRA immutable records on backends without native Object Lock; `b.objectStore` remains the path for S3 Object Lock.
|
|
12
|
+
|
|
13
|
+
- v0.13.0 (2026-05-26) — **`b.crypto.oprf` — RFC 9497 Oblivious PRFs.** Compute F(serverKey, input) without the server learning the input and without the client learning the key — the Oblivious PRF primitive behind password hardening (the server peppers a password it never sees), private set intersection, and Privacy Pass. b.crypto.oprf.suite(name) returns an RFC 9497 ciphersuite — ristretto255-sha512, p256-sha256, p384-sha384, or p521-sha512 — each exposing the base oprf mode and the verifiable voprf mode (a DLEQ proof lets the client confirm the server used the key committed in its public key). The client blinds its input, the server blind-evaluates with its secret key, and the client finalizes by un-blinding and hashing; because un-blinding cancels the blind, the output depends only on key and input. Validated byte-for-byte against the RFC 9497 Appendix-A test vectors. Group and hash-to-curve operations come from the newly vendored @noble/curves (Paul Miller, MIT) — the same maintainer as the framework's existing vendored @noble/post-quantum and @noble/ciphers, with no added npm runtime dependency. **Added:** *`b.crypto.oprf` — RFC 9497 OPRF / VOPRF* — `suite(name)` returns `{ name, oprf, voprf }` for one of the four RFC 9497 ciphersuites (ristretto255-SHA512 / P-256-SHA256 / P-384-SHA384 / P-521-SHA512). The `oprf` (base) mode provides `deriveKeyPair` / `generateKeyPair` / `blind` / `blindEvaluate` / `finalize` / `evaluate`; `voprf` (verifiable) adds a DLEQ proof so the client can prove the server used the committed key. Use it for password hardening, private set intersection, and OPRF-based tokens. Verified against the RFC 9497 Appendix-A vectors. The partially-oblivious `poprf` mode is not yet exposed (the vendored `@noble/curves` does not implement it) and will follow upstream. · *Vendored `@noble/curves`* — `@noble/curves` 2.2.0 (Paul Miller, MIT) is vendored under `lib/vendor/` (no npm runtime dependency), supplying the ristretto255 / NIST-curve group and hash-to-curve operations behind `b.crypto.oprf`. It joins the existing vendored `@noble/post-quantum` and `@noble/ciphers` from the same maintainer; tracked in the SBOM and the vendor-currency gate.
|
|
14
|
+
|
|
9
15
|
## v0.12.x
|
|
10
16
|
|
|
17
|
+
- v0.12.70 (2026-05-26) — **`b.network.dns.tsig` — RFC 8945 DNS transaction signatures.** Sign and verify DNS messages with RFC 8945 TSIG — the shared-key HMAC that authenticates a DNS transaction (zone transfers, dynamic updates, query/response pairs) and proves it was not altered in flight. b.network.dns.tsig.sign(message, opts) appends a TSIG resource record and returns the signed wire; b.network.dns.tsig.verify(message, opts) locates the TSIG record, recomputes the HMAC over the RFC 8945 §4.3.3 digest, compares it in constant time, and checks the time window (valid only within `fudge` seconds of `timeSigned`). HMAC-SHA-256 is the default; SHA-384 / SHA-512 are available and the broken HMAC-MD5 / HMAC-SHA-1 algorithms are refused unless allowLegacy is set. Signing a response chains the request MAC into the digest. Verified byte-for-byte against dnspython 2.8.0 reference signatures. TSIG completes the DNS-trust set alongside the existing DNSSEC (zone-data authentication) and DANE primitives — DNSSEC authenticates the data end-to-end, TSIG authenticates a single hop's transaction with a pre-shared key. **Added:** *`b.network.dns.tsig.sign` / `b.network.dns.tsig.verify`* — RFC 8945 TSIG transaction authentication. `sign(message, { keyName, secret, algorithm, fudge, time, requestMac })` appends a TSIG RR to a DNS wire message and returns `{ wire, mac }`; `verify(message, { keys, now, requestMac })` returns `{ valid, keyName, algorithm, timeSigned, error, macValid, timeValid, reason }`, with a constant-time MAC compare (via `b.crypto.timingSafeEqual`), a `fudge`-second time-window check, truncated-MAC handling per §5.2.2.1, and request-MAC chaining for responses (§5.4.1). HMAC-SHA-256 default; HMAC-SHA-384 / SHA-512 supported; HMAC-MD5 / HMAC-SHA-1 refused unless `allowLegacy: true`. The transaction-level companion to `b.network.dns.dnssec` and `b.network.dns.dane`.
|
|
18
|
+
|
|
11
19
|
- v0.12.69 (2026-05-26) — **`b.middleware.botGuard` no longer blocks browsers that omit Sec-Fetch-Mode.** b.middleware.botGuard treated a missing Sec-Fetch-Mode header as a bot signal and returned 403 Forbidden, which refused legitimate browsers on any origin where the browser does not emit Fetch Metadata: every plain-HTTP non-localhost origin (Umbrel apps, LAN and *.local reverse-proxy deployments) and Safari before 16.4 even over HTTPS. Browsers only send Sec-Fetch-* in a secure context, so its absence is normal there — not a bot. Sec-Fetch-Mode is now advisory only: it never blocks, and it sets req.suspectedBot in mode:"tag" only on a secure-context HTML GET where a modern browser would have sent it. Drive-by bots are still blocked by the missing-Accept-Language and User-Agent heuristics. No configuration change is needed; if you had widened skipPaths or disabled bot-guard to work around this, you can revert that. **Fixed:** *`b.middleware.botGuard` no longer 403s browsers over plain HTTP or older Safari* — A missing `Sec-Fetch-Mode` was a blocking heuristic, but browsers omit Fetch Metadata outside a secure context (every plain-HTTP non-localhost origin — Umbrel, LAN, `*.local` proxies) and Safari < 16.4 omits it even over HTTPS. Those legitimate browsers were refused with `403 Forbidden`. `Sec-Fetch-Mode` is now advisory: it never blocks, and only sets `req.suspectedBot` in `mode: "tag"` on a secure-context HTML GET. The `Accept-Language` and User-Agent heuristics (which catch the same bots) are unchanged. **Detectors:** *reserved-hostname trailing-dot detector recognizes regex strips* — The codebase-patterns gate that requires stripping the RFC 1034 trailing root-zone dot before a reserved-hostname comparison now also recognizes end-anchored regex strips (`.replace(/\.$/, …)`), not only the `charAt` / `while`-loop forms.
|
|
12
20
|
|
|
13
21
|
- v0.12.68 (2026-05-26) — **`b.jwk` — RFC 7638 JWK thumbprint.** Compute the RFC 7638 thumbprint of a JSON Web Key — the canonical base64url(SHA-256(canonical-JSON)) identifier used to name a key (DPoP jkt bindings, ACME account-key thumbprints, DBSC session pins, kid derivation). b.jwk.thumbprint(jwk) returns the digest; b.jwk.canonicalize(jwk) returns the exact JSON that is hashed — only the key-type's required members, member names in lexicographic order, no whitespace, so the same key always yields the same thumbprint regardless of how its JWK was serialized. The standard key types are supported (EC, RSA, oct, OKP per RFC 8037) plus AKP, the IANA key type Node uses for ML-DSA / SLH-DSA post-quantum public keys; SHA-256 is the default, with hash: "sha384" | "sha512" for RFC 9278 thumbprint-with-hash. Verified against the RFC 7638 §3.1 worked example. b.auth.dpop, b.acme, and b.dbsc now compute their thumbprints through this primitive. **Added:** *`b.jwk.thumbprint` / `b.jwk.canonicalize`* — RFC 7638 JWK thumbprint. `thumbprint(jwk, opts)` returns `base64url(hash(canonical-JSON))` — only the key-type's required members feed the hash, so optional fields (`kid`, `use`, `alg`, …) never change the result. `canonicalize(jwk)` returns the canonical JSON string itself. Supports EC / RSA / oct / OKP and the AKP post-quantum key type; SHA-256 default, `hash` selects SHA-384 / SHA-512. Throws `JwkError` on an invalid key or unknown hash. **Changed:** *DPoP, ACME, and DBSC compose `b.jwk`* — `b.auth.dpop` (the `jkt` proof-key thumbprint), `b.acme` (the RFC 8555 account-key authorization), and `b.dbsc` (the session-pin thumbprint) now compute RFC 7638 thumbprints through `b.jwk` instead of carrying their own implementations. Behavior is unchanged — DPoP still refuses symmetric key types, and each surface keeps its own error codes.
|
|
@@ -89,8 +89,10 @@ The framework bundles the surface a typical Node app reaches for. Every primitiv
|
|
|
89
89
|
- **Workflow gates** — break-glass column gates with second-factor + audit (`b.breakGlass`); two-person-rule m-of-n approval with cooling-off lock + cancellation (`b.dualControl`)
|
|
90
90
|
- **Financial / Open Banking** — FAPI 2.0 Final composite posture (PAR + PKCE-S256 + DPoP-or-mTLS + RFC 9207); runtime enforcement helpers `b.fapi2.assertCallback` (refuses missing iss + bare-param under message-signing) and `b.fapi2.assertAuthzRequest` (refuses non-JAR); CFPB §1033 / FDX 6.0 consumer-financial-data-sharing wrapper (`b.fdx`)
|
|
91
91
|
- **Data-subject coordination** — cross-table export / rectify / erase / restrict / objection (`b.subject`, `b.subject.eraseHard`); subject-level legal-hold registry consulted by erase + retention paths (FRCP Rule 26/37(e), GDPR Art 17(3)(e), SEC Rule 17a-4, HIPAA §164.530(j)(2)) (`b.legalHold`)
|
|
92
|
+
- **WORM retention** — write-once-read-many records over any backing store (`b.worm.create`): `compliance` / `governance` Object-Lock modes, extend-only `retainUntil`, legal holds, and a tamper-evident SHA3-512 digest verified on read — the store-agnostic application-level companion to `b.objectStore`'s S3 Object Lock, for sealed-DB / filesystem / non-S3 backends (SEC 17a-4(f), CFTC 1.31, FINRA 4511)
|
|
92
93
|
- **Account safety** — adaptive bot-challenge staircase (`b.authBotChallenge`); session-to-device-posture binding with fail-closed verify (`b.sessionDeviceBinding`)
|
|
93
94
|
- **Anonymous authorization** — Privacy Pass origin side (RFC 9577/9578 — `b.privacyPass`): issue a `WWW-Authenticate: PrivateToken` challenge and verify a presented Blind-RSA (type 0x0002) token against the issuer public key, with no issuer callback and no client identity
|
|
95
|
+
- **Oblivious PRF** — RFC 9497 OPRF / VOPRF (`b.crypto.oprf.suite`): learn `F(serverKey, input)` without the server seeing the input — the primitive behind password hardening (pepper a password the server never sees), private set intersection, and Privacy Pass; `oprf` (base) + `voprf` (verifiable, DLEQ-proof) modes over ristretto255-SHA512 / P-256 / P-384 / P-521; validated against the RFC 9497 Appendix-A vectors
|
|
94
96
|
### Crypto
|
|
95
97
|
|
|
96
98
|
- **At-rest envelope** — envelope-versioned PQC (ML-KEM-1024 + P-384 hybrid, XChaCha20-Poly1305, SHAKE256); vault sealing (`b.crypto`, `b.vault`)
|
|
@@ -131,7 +133,7 @@ The framework bundles the surface a typical Node app reaches for. Every primitiv
|
|
|
131
133
|
- In-process CIDR fence (`b.middleware.networkAllowlist`)
|
|
132
134
|
- `Cache-Control: no-store` on every 401 from `requireAuth` / `requireAal` / `requireStepUp` per RFC 9111 §5.2.2.5
|
|
133
135
|
- **Outbound HTTP client** — HTTP/1.1 + HTTP/2 with SSRF gate (cloud-metadata IPs hard-denied; private / loopback / link-local overridable per call); scheme + userinfo + per-host destination allowlist; redirects, multipart, interceptors, progress, encrypted cookie jar (`b.httpClient`, `b.ssrfGuard`, `b.safeUrl`)
|
|
134
|
-
- **Network configurability (`b.network`)** — env-driven NTP / NTS (RFC 8915), IPv4/IPv6 NTP, DNS with IPv6 / DoH / DoT (private-CA pinning) / cache / lookup timeout; local DNSSEC signature verification (RFC 4035 — `b.network.dns.dnssec.verifyRrset` over a canonicalised RRset against RSA / ECDSA P-256·P-384 / Ed25519 DNSKEYs, plus DS-digest + key-tag, plus `verifyDenial` for NSEC / NSEC3 (RFC 5155) NXDOMAIN / NODATA proofs with iteration caps + Opt-Out handling, plus `verifyChain` to validate a full root→TLD→zone delegation chain against the pinned IANA root anchors) so a resolver client can verify both positive and negative answers instead of trusting the upstream AD bit; DANE / TLSA certificate matching (RFC 6698/7671 — `b.network.dns.dane.matchCertificate`) to pin a service's key through DNSSEC instead of a public CA; outbound HTTP proxy (`HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY`); runtime DPI trust-store CA additions; application-level heartbeats; TCP socket defaults
|
|
136
|
+
- **Network configurability (`b.network`)** — env-driven NTP / NTS (RFC 8915), IPv4/IPv6 NTP, DNS with IPv6 / DoH / DoT (private-CA pinning) / cache / lookup timeout; local DNSSEC signature verification (RFC 4035 — `b.network.dns.dnssec.verifyRrset` over a canonicalised RRset against RSA / ECDSA P-256·P-384 / Ed25519 DNSKEYs, plus DS-digest + key-tag, plus `verifyDenial` for NSEC / NSEC3 (RFC 5155) NXDOMAIN / NODATA proofs with iteration caps + Opt-Out handling, plus `verifyChain` to validate a full root→TLD→zone delegation chain against the pinned IANA root anchors) so a resolver client can verify both positive and negative answers instead of trusting the upstream AD bit; DANE / TLSA certificate matching (RFC 6698/7671 — `b.network.dns.dane.matchCertificate`) to pin a service's key through DNSSEC instead of a public CA; TSIG transaction signatures (RFC 8945 — `b.network.dns.tsig.sign` / `verify`) for shared-key HMAC authentication of zone transfers, dynamic updates, and query/response pairs, with constant-time MAC compare + fudge-window check (verified against dnspython); outbound HTTP proxy (`HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY`); runtime DPI trust-store CA additions; application-level heartbeats; TCP socket defaults
|
|
135
137
|
- **Error pages** — operator-rendered, no app-frame leakage (`b.errorPage`)
|
|
136
138
|
### Defensive parsers
|
|
137
139
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"frameworkVersion": "0.
|
|
4
|
-
"createdAt": "2026-05-
|
|
3
|
+
"frameworkVersion": "0.13.1",
|
|
4
|
+
"createdAt": "2026-05-26T20:56:45.702Z",
|
|
5
5
|
"exports": {
|
|
6
6
|
"a2a": {
|
|
7
7
|
"type": "object",
|
|
@@ -13951,6 +13951,23 @@
|
|
|
13951
13951
|
"type": "function",
|
|
13952
13952
|
"arity": 3
|
|
13953
13953
|
},
|
|
13954
|
+
"oprf": {
|
|
13955
|
+
"type": "object",
|
|
13956
|
+
"members": {
|
|
13957
|
+
"OprfError": {
|
|
13958
|
+
"type": "function",
|
|
13959
|
+
"arity": 4
|
|
13960
|
+
},
|
|
13961
|
+
"SUITES": {
|
|
13962
|
+
"type": "instance",
|
|
13963
|
+
"ctorName": "Array"
|
|
13964
|
+
},
|
|
13965
|
+
"suite": {
|
|
13966
|
+
"type": "function",
|
|
13967
|
+
"arity": 1
|
|
13968
|
+
}
|
|
13969
|
+
}
|
|
13970
|
+
},
|
|
13954
13971
|
"randomInt": {
|
|
13955
13972
|
"type": "function",
|
|
13956
13973
|
"arity": 2
|
|
@@ -42208,6 +42225,69 @@
|
|
|
42208
42225
|
"type": "function",
|
|
42209
42226
|
"arity": 1
|
|
42210
42227
|
},
|
|
42228
|
+
"tsig": {
|
|
42229
|
+
"type": "object",
|
|
42230
|
+
"members": {
|
|
42231
|
+
"ALGORITHMS": {
|
|
42232
|
+
"type": "object",
|
|
42233
|
+
"members": {
|
|
42234
|
+
"hmac-sha224": {
|
|
42235
|
+
"type": "primitive",
|
|
42236
|
+
"valueType": "string"
|
|
42237
|
+
},
|
|
42238
|
+
"hmac-sha256": {
|
|
42239
|
+
"type": "primitive",
|
|
42240
|
+
"valueType": "string"
|
|
42241
|
+
},
|
|
42242
|
+
"hmac-sha384": {
|
|
42243
|
+
"type": "primitive",
|
|
42244
|
+
"valueType": "string"
|
|
42245
|
+
},
|
|
42246
|
+
"hmac-sha512": {
|
|
42247
|
+
"type": "primitive",
|
|
42248
|
+
"valueType": "string"
|
|
42249
|
+
}
|
|
42250
|
+
}
|
|
42251
|
+
},
|
|
42252
|
+
"ERROR": {
|
|
42253
|
+
"type": "object",
|
|
42254
|
+
"members": {
|
|
42255
|
+
"BADKEY": {
|
|
42256
|
+
"type": "primitive",
|
|
42257
|
+
"valueType": "number"
|
|
42258
|
+
},
|
|
42259
|
+
"BADSIG": {
|
|
42260
|
+
"type": "primitive",
|
|
42261
|
+
"valueType": "number"
|
|
42262
|
+
},
|
|
42263
|
+
"BADTIME": {
|
|
42264
|
+
"type": "primitive",
|
|
42265
|
+
"valueType": "number"
|
|
42266
|
+
},
|
|
42267
|
+
"BADTRUNC": {
|
|
42268
|
+
"type": "primitive",
|
|
42269
|
+
"valueType": "number"
|
|
42270
|
+
},
|
|
42271
|
+
"NOERROR": {
|
|
42272
|
+
"type": "primitive",
|
|
42273
|
+
"valueType": "number"
|
|
42274
|
+
}
|
|
42275
|
+
}
|
|
42276
|
+
},
|
|
42277
|
+
"TsigError": {
|
|
42278
|
+
"type": "function",
|
|
42279
|
+
"arity": 4
|
|
42280
|
+
},
|
|
42281
|
+
"sign": {
|
|
42282
|
+
"type": "function",
|
|
42283
|
+
"arity": 2
|
|
42284
|
+
},
|
|
42285
|
+
"verify": {
|
|
42286
|
+
"type": "function",
|
|
42287
|
+
"arity": 2
|
|
42288
|
+
}
|
|
42289
|
+
}
|
|
42290
|
+
},
|
|
42211
42291
|
"useDesignatedResolvers": {
|
|
42212
42292
|
"type": "function",
|
|
42213
42293
|
"arity": 1
|
|
@@ -50270,6 +50350,23 @@
|
|
|
50270
50350
|
}
|
|
50271
50351
|
}
|
|
50272
50352
|
},
|
|
50353
|
+
"worm": {
|
|
50354
|
+
"type": "object",
|
|
50355
|
+
"members": {
|
|
50356
|
+
"MODES": {
|
|
50357
|
+
"type": "instance",
|
|
50358
|
+
"ctorName": "Array"
|
|
50359
|
+
},
|
|
50360
|
+
"WormError": {
|
|
50361
|
+
"type": "function",
|
|
50362
|
+
"arity": 4
|
|
50363
|
+
},
|
|
50364
|
+
"create": {
|
|
50365
|
+
"type": "function",
|
|
50366
|
+
"arity": 1
|
|
50367
|
+
}
|
|
50368
|
+
}
|
|
50369
|
+
},
|
|
50273
50370
|
"wsClient": {
|
|
50274
50371
|
"type": "object",
|
|
50275
50372
|
"members": {
|
|
@@ -57,6 +57,7 @@ var crypto = require("./lib/crypto");
|
|
|
57
57
|
// remembering separate top-level namespaces. Implementations live in
|
|
58
58
|
// the dedicated lib files; these are thin aliases.
|
|
59
59
|
crypto.hpke = require("./lib/crypto-hpke");
|
|
60
|
+
crypto.oprf = require("./lib/crypto-oprf");
|
|
60
61
|
// Both PQ-HPKE drafts behind one opt-in sub-namespace — see
|
|
61
62
|
// lib/crypto-hpke-pq.js. Operators that need a draft-codepoint
|
|
62
63
|
// shape reach for b.crypto.hpke.pq.connolly / .wg explicitly; the
|
|
@@ -371,6 +372,7 @@ var fileUpload = require("./lib/file-upload");
|
|
|
371
372
|
var dualControl = require("./lib/dual-control");
|
|
372
373
|
var retention = require("./lib/retention");
|
|
373
374
|
var legalHold = require("./lib/legal-hold");
|
|
375
|
+
var worm = require("./lib/worm");
|
|
374
376
|
var network = require("./lib/network");
|
|
375
377
|
var cloudEvents = require("./lib/cloud-events");
|
|
376
378
|
var dsr = require("./lib/dsr");
|
|
@@ -709,6 +711,7 @@ module.exports = {
|
|
|
709
711
|
dualControl: dualControl,
|
|
710
712
|
retention: retention,
|
|
711
713
|
legalHold: legalHold,
|
|
714
|
+
worm: worm,
|
|
712
715
|
network: network,
|
|
713
716
|
cloudEvents: cloudEvents,
|
|
714
717
|
dsr: dsr,
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module b.crypto.oprf
|
|
4
|
+
* @nav Crypto
|
|
5
|
+
* @title OPRF
|
|
6
|
+
*
|
|
7
|
+
* @intro
|
|
8
|
+
* Oblivious Pseudorandom Functions per <a
|
|
9
|
+
* href="https://www.rfc-editor.org/rfc/rfc9497">RFC 9497</a>. An OPRF lets
|
|
10
|
+
* a client learn <code>F(serverKey, input)</code> — a keyed pseudorandom
|
|
11
|
+
* value — <em>without</em> the server learning the input and without the
|
|
12
|
+
* client learning the key. It is the primitive behind Privacy Pass
|
|
13
|
+
* tokens, password-breach checks and password hardening (the server can
|
|
14
|
+
* pepper a password without ever seeing it), and private set
|
|
15
|
+
* intersection.
|
|
16
|
+
*
|
|
17
|
+
* Two modes are provided per RFC 9497: <code>oprf</code> (base) and
|
|
18
|
+
* <code>voprf</code> (verifiable — the client can prove the server used
|
|
19
|
+
* the committed key, via a DLEQ proof carried in the evaluation). The
|
|
20
|
+
* partially-oblivious <code>poprf</code> mode is not yet exposed: the
|
|
21
|
+
* vendored <code>@noble/curves</code> does not implement it, so it will
|
|
22
|
+
* be added when upstream ships it rather than stubbed here.
|
|
23
|
+
* The base protocol is: the client <code>blind</code>s its input to a
|
|
24
|
+
* group element, the server <code>blindEvaluate</code>s it with its
|
|
25
|
+
* secret key, and the client <code>finalize</code>s by un-blinding and
|
|
26
|
+
* hashing. Because un-blinding cancels the blind, the output depends only
|
|
27
|
+
* on the key and the input — a server-side <code>evaluate</code> produces
|
|
28
|
+
* the same value directly.
|
|
29
|
+
*
|
|
30
|
+
* <code>suite(name)</code> returns the suite for one of the RFC 9497
|
|
31
|
+
* ciphersuites — <code>ristretto255-sha512</code> (the Privacy Pass
|
|
32
|
+
* default), <code>p256-sha256</code>, <code>p384-sha384</code>, or
|
|
33
|
+
* <code>p521-sha512</code> — each exposing the three modes. Group and
|
|
34
|
+
* hash-to-curve operations come from the vendored <code>@noble/curves</code>.
|
|
35
|
+
* Byte arguments are <code>Uint8Array</code> / <code>Buffer</code>;
|
|
36
|
+
* returned elements and outputs are <code>Uint8Array</code>.
|
|
37
|
+
*
|
|
38
|
+
* @card
|
|
39
|
+
* RFC 9497 Oblivious PRFs — learn <code>F(key, input)</code> without the
|
|
40
|
+
* server seeing the input (oprf / voprf / poprf modes; ristretto255 / P-256
|
|
41
|
+
* / P-384 / P-521 suites). The primitive behind Privacy Pass, password
|
|
42
|
+
* hardening, and private set intersection.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
var nobleCurves = require("./vendor/noble-curves.cjs");
|
|
46
|
+
var { defineClass } = require("./framework-error");
|
|
47
|
+
|
|
48
|
+
var OprfError = defineClass("OprfError", { alwaysPermanent: true });
|
|
49
|
+
|
|
50
|
+
// RFC 9497 ciphersuite name → vendored @noble/curves OPRF implementation.
|
|
51
|
+
var SUITE_IMPL = {
|
|
52
|
+
"ristretto255-sha512": nobleCurves.ristretto255_oprf,
|
|
53
|
+
"p256-sha256": nobleCurves.p256_oprf,
|
|
54
|
+
"p384-sha384": nobleCurves.p384_oprf,
|
|
55
|
+
"p521-sha512": nobleCurves.p521_oprf,
|
|
56
|
+
};
|
|
57
|
+
var SUITES = Object.keys(SUITE_IMPL);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @primitive b.crypto.oprf.suite
|
|
61
|
+
* @signature b.crypto.oprf.suite(name)
|
|
62
|
+
* @since 0.13.0
|
|
63
|
+
* @status stable
|
|
64
|
+
*
|
|
65
|
+
* Return the RFC 9497 OPRF suite for <code>name</code> — one of
|
|
66
|
+
* <code>"ristretto255-sha512"</code>, <code>"p256-sha256"</code>,
|
|
67
|
+
* <code>"p384-sha384"</code>, or <code>"p521-sha512"</code> (case
|
|
68
|
+
* insensitive). The result is <code>{ name, oprf, voprf }</code>; each mode
|
|
69
|
+
* object has the protocol functions:
|
|
70
|
+
*
|
|
71
|
+
* <ul>
|
|
72
|
+
* <li><code>deriveKeyPair(seed, info)</code> / <code>generateKeyPair()</code>
|
|
73
|
+
* → <code>{ secretKey, publicKey }</code></li>
|
|
74
|
+
* <li><code>blind(input)</code> → <code>{ blind, blinded }</code> (client)</li>
|
|
75
|
+
* <li><code>oprf.blindEvaluate(secretKey, blinded)</code> → evaluation
|
|
76
|
+
* element; <code>voprf.blindEvaluate(secretKey, publicKey, blinded)</code>
|
|
77
|
+
* → <code>{ evaluated, proof }</code> (server)</li>
|
|
78
|
+
* <li><code>oprf.finalize(input, blind, evaluation)</code> /
|
|
79
|
+
* <code>voprf.finalize(input, blind, evaluated, blinded, publicKey, proof)</code>
|
|
80
|
+
* → output bytes (client; <code>voprf</code> verifies the proof and
|
|
81
|
+
* throws if it does not match <code>publicKey</code>)</li>
|
|
82
|
+
* <li><code>evaluate(secretKey, input)</code> → output bytes (server-side,
|
|
83
|
+
* non-oblivious — equals the client's <code>finalize</code> output)</li>
|
|
84
|
+
* </ul>
|
|
85
|
+
*
|
|
86
|
+
* The partially-oblivious <code>poprf</code> mode is intentionally absent
|
|
87
|
+
* (not implemented by the vendored <code>@noble/curves</code>). Throws
|
|
88
|
+
* <code>OprfError</code> for an unknown suite name.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* var s = b.crypto.oprf.suite("ristretto255-sha512");
|
|
92
|
+
* var kp = s.oprf.deriveKeyPair(seed, Buffer.from("my-app"));
|
|
93
|
+
* var c = s.oprf.blind(Buffer.from("user@example.com")); // client
|
|
94
|
+
* var ev = s.oprf.blindEvaluate(kp.secretKey, c.blinded); // server
|
|
95
|
+
* var out = s.oprf.finalize(Buffer.from("user@example.com"), c.blind, ev);
|
|
96
|
+
* // out === s.oprf.evaluate(kp.secretKey, Buffer.from("user@example.com"))
|
|
97
|
+
*/
|
|
98
|
+
function suite(name) {
|
|
99
|
+
var impl = SUITE_IMPL[String(name).toLowerCase()];
|
|
100
|
+
if (!impl) throw new OprfError("oprf/bad-suite", "crypto.oprf.suite: unknown suite '" + name + "'; expected one of " + SUITES.join(", "));
|
|
101
|
+
// Expose only the modes the vendored @noble/curves implements (base +
|
|
102
|
+
// verifiable). poprf is omitted rather than surfaced as an empty stub.
|
|
103
|
+
return { name: impl.name, oprf: impl.oprf, voprf: impl.voprf };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = {
|
|
107
|
+
suite: suite,
|
|
108
|
+
SUITES: SUITES,
|
|
109
|
+
OprfError: OprfError,
|
|
110
|
+
};
|