@blamejs/core 0.14.2 → 0.14.4

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 CHANGED
@@ -8,6 +8,10 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.14.x
10
10
 
11
+ - v0.14.4 (2026-05-30) — **Removed three pieces of dead code from the SAML, TLS, and JMAP surfaces; no API or behavior changes.** Cleanup of unreachable code. A reverse signature-algorithm lookup in the SAML verifier was never called — the actual verification path resolves the algorithm through the supported-signature table — so it is removed and a stale comment that referenced it is corrected. A leftover no-op placeholder in the TLS certificate re-encode path (a zero-length slice that was assigned and discarded) is removed, leaving the verbatim extension re-encode it sat next to. An unused JMAP well-known-path constant that existed only to be discarded is removed. None of this changes any exported API, error code, wire format, or runtime behavior. **Removed:** *Unreachable code in SAML, TLS, and JMAP* — Removed `_sigAlgFromUri` from the SAML module (a reverse alg lookup that was never called — the embedded XML-DSig verifier resolves the algorithm via the supported-signature table, and the redirect-binding path uses the forward `_sigAlgUrn`), a discarded zero-length-slice placeholder in the TLS certificate extension re-encode path, and an unused well-known-path constant in the JMAP server. Internal cleanup only — no change to any exported API, error code, wire format, or runtime behavior.
12
+
13
+ - v0.14.3 (2026-05-30) — **A codebase check now ensures every lint-suppression marker names a real check, so a typo can't silently disable a guard.** Source files suppress an individual lint with an `// allow:<class>` comment. If the class is mistyped or stale, the comment suppresses nothing — the check it names does not exist — so the issue it was meant to explain ships unflagged. A new codebase check now verifies every `// allow:<class>` marker names a registered check class and fails if it does not, with the full set of valid classes maintained as an explicit registry. Two markers that named a non-kebab class were corrected as part of this. No runtime, API, or wire-format changes. **Detectors:** *Lint-suppression markers must name a registered check* — A new check flags any `// allow:<class>` suppression comment whose class is not one of the registered check classes — catching typos and stale markers (for example a marker that named a check which was later renamed) that would otherwise silently disable the guard they appear to explain. The valid classes are kept as an explicit registry, so adding a check with a new allow-class is a one-line registration. Source-comment hygiene only — no change to any exported API, error code, wire format, or runtime behavior.
14
+
11
15
  - v0.14.2 (2026-05-29) — **Internal lint hygiene: the byte-literal check now flags only genuine byte-scale arithmetic, with no API or behavior changes.** A no-behavior-change cleanup of the source tree's internal lint markers. The byte-literal lint previously flagged every integer that was a multiple of 8 — which is most numbers — so the source carried a large number of suppression comments on values that were not byte sizes at all (status codes, counts, lengths, radixes, opcodes). The lint now flags only 1024-scale byte arithmetic (the case the C.BYTES.kib/mib/gib helpers exist to replace), and the now-unnecessary suppression comments have been removed while keeping their explanatory text. Several lint-suppression markers that named a check that does not exist were also corrected. None of this changes any API, wire format, or runtime behavior. **Changed:** *Source-tree lint markers cleaned up* — The internal byte-literal lint was tightened to flag only genuine byte-scale (`* 1024`) arithmetic, and the suppression comments it previously required on non-byte integers were removed (their explanatory text is retained as plain comments). A handful of suppression markers that referenced a non-existent check were pointed at the correct one or removed. This is source-comment hygiene only — there is no change to any exported API, error code, wire format, or runtime behavior.
12
16
 
13
17
  - v0.14.1 (2026-05-29) — **Correctness fixes: JAR request-object typ enforcement, byte-faithful PGP multipart/signed, and SAML InResponseTo binding.** A set of correctness fixes across the auth, mail-crypto, TLS, and encoder surfaces. The most important: JWT-secured authorization requests (RFC 9101) now require the request object to carry the registered `oauth-authz-req+jwt` typ, closing a cross-JWT-confusion vector; the PGP multipart/signed wrapper is now assembled byte-faithfully so non-ASCII signed content can't be corrupted; and SAML response verification now returns the InResponseTo of the SubjectConfirmation that actually validated. Two of these change behavior — see Changed — and are bug fixes rather than new features. **Changed:** *JAR parsing rejects untyped request objects (breaking)* — Following the typ enforcement above, a request object whose header omits `typ` is now refused. An authorization server whose clients sign request objects without the `oauth-authz-req+jwt` typ must update those clients to set it. · *PGP sign() returns multipartSigned as a Buffer (breaking)* — `b.mail.crypto.pgp.sign(...).multipartSigned` is now a Buffer instead of a string. The OpenPGP signature covers the signed-part bytes exactly, and a JS-string round trip through latin1/utf8 could corrupt non-ASCII signed content and break verification, so the RFC 3156 multipart/signed wrapper is now assembled as bytes. Code that wrote the previous string to the wire works unchanged when it writes the Buffer; code that did string operations on the value should treat it as a Buffer (its `indexOf` / `toString` still work). **Fixed:** *SAML response verification binds InResponseTo to the validated confirmation* — `verifyResponse` returned the InResponseTo of the first SubjectConfirmationData in the assertion rather than of the SubjectConfirmation that actually passed bearer validation. When a response carried more than one SubjectConfirmation, the returned value could come from a non-validated confirmation. It is now the InResponseTo of the confirmation that validated. · *checkServerIdentity9525 emits the documented CN-fallback audit code* — A CN-only legacy certificate (a Common Name present, no subjectAltName) is now refused by the exported `b.network.tls.checkServerIdentity9525` with the distinct `tls/pkix-cn-fallback-refused` code its documentation promised, so audit logs can tell a CN-only certificate apart from one carrying neither a SAN nor a CN (which still yields `tls/pkix-san-required`). The accept/refuse outcome is unchanged — both are refused; only the audit granularity improved. · *OIDC back-channel logout / JARM no longer accept dead override parameters* — `verifyBackchannelLogoutToken` and `parseJarmResponse` passed `acceptedAlgs` / `jwksUri` / `maxClockSkewMs` through to the ID-token verifier, which ignored them and applied the configured (create()-time) values. The pass-throughs are removed so the code no longer reads as if those can be overridden per call; the configured trust anchor was — and remains — what applies. · *Queue lease failures are logged* — The consumer loop's lease-acquisition error path swallowed the backend error silently; it now logs at debug so a flapping backend that has not yet tripped the circuit breaker is visible. · *Protobuf and ASN.1 encoders reject out-of-range tags* — The protobuf tag encoder rejected nothing and would have emitted a wrong tag for field numbers at or above 2^28 (where the 32-bit shift overflows); the ASN.1 context-tag writers silently truncated tag numbers above 30 (which require the multi-byte high-tag-number form). Both now throw a RangeError rather than encode silently-wrong output. The values these encoders serve are well within range, so no current caller is affected. · *oid4vci proofAlgorithms default documented accurately* — The documented default proof-algorithm list now matches the code (`["ES256", "ES384", "EdDSA"]`); the doc previously omitted EdDSA, which the runtime has always accepted by default. **Security:** *JAR request objects must carry the registered typ (RFC 9101)* — `b.auth.jar.parse` now requires the request-object JWS header to carry `typ: "oauth-authz-req+jwt"` (with or without the `application/` prefix); a request object with an absent or different typ is refused with `auth-jar/bad-typ`. RFC 9101 §10.8 specifies this media type precisely to stop a JWT minted for another purpose (an ID token, an access token, a logout token) and signed by the same client key from being replayed as a request object. The existing `iss` / `aud` / `client_id` bindings already constrained that; this restores the explicit type check as well. This is stricter than before — see Changed.
package/lib/auth/saml.js CHANGED
@@ -1726,8 +1726,8 @@ function _decryptEncryptedAssertion(encAssertion, spPrivateKeyPem) {
1726
1726
 
1727
1727
  // PQC SignatureMethod URIs used by the embedded XMLDSig signatures.
1728
1728
  // Standard XMLDSig vocabulary classical signing URIs (W3C XMLDSig
1729
- // Core 1.1 + RFC 9231 for Ed25519) are dispatched via _sigAlgUrn /
1730
- // _sigAlgFromUri. The framework adds two non-standard URNs for
1729
+ // Core 1.1 + RFC 9231 for Ed25519) are dispatched via _sigAlgUrn (sign
1730
+ // side) and the SUPPORTED_SIG table (verify side). The framework adds two non-standard URNs for
1731
1731
  // ML-DSA because no W3C/IETF XMLDSig URI registration exists for
1732
1732
  // post-quantum signers yet (LAMPS WG has open drafts but none final).
1733
1733
  // Operators integrating with PQC-aware IdPs that exchange those URNs
@@ -2027,22 +2027,6 @@ function _sigAlgUrn(alg) {
2027
2027
  return null;
2028
2028
  }
2029
2029
 
2030
- // Reverse lookup — SignatureMethod URI on the inbound wire → alg
2031
- // shorthand for _sigAlgUrn dispatch. Used by _verifyEmbeddedXmlDsig
2032
- // to pick the right verifier when an IdP signs with a classical alg.
2033
- function _sigAlgFromUri(uri) {
2034
- if (uri === "urn:blamejs:experimental:saml-sig-alg:ml-dsa-65") return "ml-dsa-65";
2035
- if (uri === "urn:blamejs:experimental:saml-sig-alg:ml-dsa-87") return "ml-dsa-87";
2036
- if (uri === "http://www.w3.org/2021/04/xmldsig-more#ed25519") return "ed25519";
2037
- if (uri === "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") return "rsa-sha256";
2038
- if (uri === "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384") return "rsa-sha384";
2039
- if (uri === "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512") return "rsa-sha512";
2040
- if (uri === "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256") return "ecdsa-sha256";
2041
- if (uri === "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384") return "ecdsa-sha384";
2042
- if (uri === "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512") return "ecdsa-sha512";
2043
- return null;
2044
- }
2045
-
2046
2030
  /**
2047
2031
  * @primitive b.auth.saml.fetchMdq
2048
2032
  * @signature b.auth.saml.fetchMdq(opts)
@@ -175,7 +175,7 @@ function guardSdl(opts) {
175
175
  return _readBody(req, errorClass).then(function (rawBody) {
176
176
  var query = null;
177
177
  try {
178
- var parsed = typeof rawBody === "string" ? safeJson.parse(rawBody, { maxBytes: C.BYTES.mib(1) }) : rawBody; // allow:JSON.parse — routed via safeJson.parse
178
+ var parsed = typeof rawBody === "string" ? safeJson.parse(rawBody, { maxBytes: C.BYTES.mib(1) }) : rawBody; // routed via safeJson.parse
179
179
  query = parsed && typeof parsed === "object" ? parsed.query : null;
180
180
  } catch (_e) { /* not JSON; pass through */ }
181
181
  if (req.body === undefined) req.body = rawBody;
@@ -133,9 +133,7 @@ var audit = lazyRequire(function () { return require("./audit"); });
133
133
  var MailServerJmapError = defineClass("MailServerJmapError", { alwaysPermanent: true });
134
134
 
135
135
  var DEFAULT_PROFILE = "strict";
136
- var WELL_KNOWN_PATH = "/.well-known/jmap";
137
136
  void C; // reserved for future cap constants
138
- void WELL_KNOWN_PATH;
139
137
 
140
138
  /**
141
139
  * @primitive b.mail.server.jmap.create
package/lib/mcp.js CHANGED
@@ -79,7 +79,7 @@ function parseRequest(body, opts) {
79
79
  var errorClass = opts.errorClass || McpError;
80
80
  var parsed;
81
81
  try {
82
- parsed = typeof body === "string" ? safeJson.parse(body, { maxBytes: C.BYTES.mib(1) }) : body; // allow:JSON.parse — routed via safeJson.parse
82
+ parsed = typeof body === "string" ? safeJson.parse(body, { maxBytes: C.BYTES.mib(1) }) : body; // routed via safeJson.parse
83
83
  } catch (_e) {
84
84
  throw errorClass.factory("mcp/bad-json",
85
85
  "mcp.parseRequest: body is not valid JSON");
@@ -1797,11 +1797,8 @@ function _stripSctExtensionFromCert(certDer) {
1797
1797
  if (oid === OID_CT_SCT_LIST) continue; // drop the SCT extension
1798
1798
  } catch (_e) { /* not an OID — keep the extension as-is */ }
1799
1799
  }
1800
- // Re-encode this extension verbatim (we have the original bytes).
1801
- var origExt = certDer.slice(0, 0); // placeholder; we rebuild from the parsed node below
1802
- void origExt;
1800
+ // Re-encode this extension verbatim from its parsed bytes.
1803
1801
  keptExtBytes.push(_encodeAsn1(asn1.TAG.SEQUENCE, true, extBytes));
1804
- void extBytes;
1805
1802
  }
1806
1803
  var newExtSeq = _encodeAsn1(asn1.TAG.SEQUENCE, true, Buffer.concat(keptExtBytes));
1807
1804
  var newExplicit3 = _encodeContextExplicit(3, newExtSeq);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.14.2",
3
+ "version": "0.14.4",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
package/sbom.cdx.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.5",
5
- "serialNumber": "urn:uuid:95f2c7cc-00a1-4b32-bc6e-c58843b25ec2",
5
+ "serialNumber": "urn:uuid:3b6688f8-8f17-4d81-9bad-f0e6166a53c7",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-05-30T07:09:18.952Z",
8
+ "timestamp": "2026-05-30T08:50:20.572Z",
9
9
  "lifecycles": [
10
10
  {
11
11
  "phase": "build"
@@ -19,14 +19,14 @@
19
19
  }
20
20
  ],
21
21
  "component": {
22
- "bom-ref": "@blamejs/core@0.14.2",
22
+ "bom-ref": "@blamejs/core@0.14.4",
23
23
  "type": "application",
24
24
  "name": "blamejs",
25
- "version": "0.14.2",
25
+ "version": "0.14.4",
26
26
  "scope": "required",
27
27
  "author": "blamejs contributors",
28
28
  "description": "The Node framework that owns its stack.",
29
- "purl": "pkg:npm/%40blamejs/core@0.14.2",
29
+ "purl": "pkg:npm/%40blamejs/core@0.14.4",
30
30
  "properties": [],
31
31
  "externalReferences": [
32
32
  {
@@ -54,7 +54,7 @@
54
54
  "components": [],
55
55
  "dependencies": [
56
56
  {
57
- "ref": "@blamejs/core@0.14.2",
57
+ "ref": "@blamejs/core@0.14.4",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]