@blamejs/core 0.13.15 → 0.13.16

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,8 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.13.x
10
10
 
11
+ - v0.13.16 (2026-05-27) — **`b.mail.agent` docs now describe the facade accurately, and not-yet-wired verbs point to the primitive to use.** b.mail.agent's module documentation claimed it was "the standardization contract for every mail protocol" that JMAP / IMAP / POP3 all route through — but no protocol server actually dispatches through the agent (the framework's own JMAP EmailSubmission handler composes b.mail.send.deliver directly), and the compose / send / reply / forward, sieve.list / sieve.activate, identity / vacation / mdn.* and export / job / import verbs throw mail-agent/not-implemented. The docs are corrected to describe what the agent is: a mailbox-access facade (RBAC + posture + audit + dispatch around a mail store) whose read surface plus the mailbox-mutation and Sieve-upload methods are wired, with the remaining verbs not yet routed through it. Those verbs' error message now names the underlying primitive to compose directly (b.mail.send.deliver, b.mail.sieve, b.mailMdn, …) instead of citing a version tag that had long passed. The public WIRED_AT export (a method→version map that no longer reflected reality) is replaced by COMPOSE_HINT (a method→primitive-to-compose map). No behaviour change: the same methods are wired or throw exactly as before. **Changed:** *`b.mail.agent` documentation corrected; not-implemented errors point to the primitive to compose* — The `@module` / `@card` no longer claim the agent is the universal protocol-dispatch contract — it's documented as a mailbox-access facade with a wired read + mutation + Sieve-upload surface, and the compose/send/identity/vacation/MDN/export verbs documented as not yet routed through it (compose the underlying primitive directly until a protocol server adopts the agent). The `mail-agent/not-implemented` error now names that primitive (e.g. `b.mail.send.deliver`) rather than a passed version tag. **Removed:** *`b.mail.agent.WIRED_AT` export replaced by `COMPOSE_HINT`* — The `WIRED_AT` export mapped each method to a framework version that was supposed to "light it up" — versions that have all shipped without the wiring, so the map was misleading. It is replaced by `COMPOSE_HINT`, mapping each not-yet-wired method to the primitive an operator composes directly. Operators reading `b.mail.agent.WIRED_AT` should read `b.mail.agent.COMPOSE_HINT` instead (pre-1.0: no compatibility shim).
12
+
11
13
  - v0.13.15 (2026-05-27) — **Corrected more source citations and made deferred/reserved options honest in their docs.** A second accuracy pass over source threat-annotations and option docs. Three citation corrections: the base64url strict-decode guard cited CVE-2022-0235 (which is actually a node-fetch cookie-leak, unrelated) — it now names the weakness class it defends (CWE-347 / CWE-1286 signature canonicalization); the glob consecutive-wildcard ReDoS cap cited the wrong library (the CVE-2026-26996 ReDoS is minimatch, not picomatch — the adjacent picomatch one is CVE-2026-33671); and CVE-2026-32178 is reframed to the CWE-138 header-injection-spoofing class the public record actually documents (and dropped from the end-of-data SMTP-smuggling list, which is a different class). Several options/statuses are now honest about not-yet-implemented surface: b.archive.read.zip.fromTrustedStream is marked experimental (its methods throw and its options aren't honored yet — the example now shows the supported buffer-then-random-access path); b.acme revokeCert's useCertKey / certPrivateKey are marked reserved (the cert-key path throws; account-key signing is the supported default); and a stale message claiming passkey break-glass factors were a future feature is removed (passkeys are a live allowed factor). No runtime behaviour changes beyond message/doc text. **Changed:** *Deferred / reserved surface now documented honestly* — `b.archive.read.zip.fromTrustedStream` is marked `experimental` — its `inspect`/`entries`/`extract` throw and its `bombPolicy`/`audit` options aren't honored yet; the documented example now shows the supported path (buffer the stream, then use the random-access reader). `b.acme` `revokeCert`'s `useCertKey` / `certPrivateKey` options are marked reserved (the cert-key-signed-revocation path throws; account-key signing, the default, covers mainstream CAs). A `b.breakGlass` policy error and comment that called passkey factors a future feature are corrected — passkeys are a live allowed factor. **Fixed:** *Corrected misattributed CVE citations in source threat-annotations* — `b.crypto.fromBase64Url`'s strict-decode guard cited CVE-2022-0235 (a node-fetch header-leak, unrelated to base64/JWT decoding); it now cites the weakness class it actually defends — CWE-347 / CWE-1286 signature canonicalization. `b.guardRegex`'s consecutive-`*` cap attributed CVE-2026-26996 to picomatch; that ReDoS is in minimatch (the picomatch ReDoS it also defends is CVE-2026-33671) — the library name is corrected. CVE-2026-32178 is reframed to the CWE-138 header-injection spoofing class the public advisory documents, and removed from the end-of-data SMTP-smuggling trio (a distinct class). No behaviour change — the defenses are unchanged.
12
14
 
13
15
  - v0.13.14 (2026-05-27) — **DNSSEC chain validation now bounds KeyTrap (CVE-2023-50387) amplification with hard caps.** b.network.dns.dnssec.verifyChain tried every DNSKEY whose 16-bit key tag matched an RRSIG, with no cap on how many candidates or total signature verifications a single response could drive. A hostile zone publishing many DNSKEYs sharing one key tag (plus matching RRSIGs) could force O(keys x signatures) full public-key verifications from one query — the KeyTrap denial-of-service (CVE-2023-50387). Validation is now bounded by non-configurable caps that match the BIND / Unbound mitigations: at most 4 same-tag candidate keys are tried per RRSIG, at most 64 DNSKEYs per zone link and 16 DS records per delegation are accepted, the chain is at most 128 links deep, and the whole response is held to a signature-validation budget that scales with chain depth (so a legitimate deep delegation is never false-rejected while bounded collisions stay bounded); exceeding any of these refuses the response rather than performing the work. Separately, a domain name that encodes to more than 255 octets is now refused at canonicalization (RFC 1035 §2.3.4), which also bounds the NSEC3 closest-encloser label enumeration, and the NSEC3 iteration ceiling is lowered from 500 to 150 to match the BIND 9.16.33+ / Unbound 1.17.1 fix for the sibling CVE-2023-50868. **Security:** *`verifyChain` caps colliding-key fan-out and total signature validations (KeyTrap / CVE-2023-50387)* — A zone advertising many same-key-tag DNSKEYs and RRSIGs can no longer drive unbounded public-key verifications. New refusals: `dnssec/too-many-colliding-keys` (>4 same-tag candidates per RRSIG), `dnssec/too-many-dnskeys` (>64 DNSKEYs per zone link), `dnssec/too-many-ds` (>16 DS records per delegation), `dnssec/too-many-links` (chain deeper than 128), and `dnssec/validation-budget-exceeded` (signature validations beyond the depth-scaled budget). The caps are intentionally non-configurable — they sit well above any legitimate zone, and the budget scales with chain depth so deep delegations validate normally. · *Domain-name octet cap + lower NSEC3 iteration ceiling* — A name that canonicalizes to more than 255 octets is refused (`dnssec/bad-name`, RFC 1035 §2.3.4), which bounds the per-label NSEC3 closest-encloser enumeration (CVE-2023-50868 class). The default NSEC3 iteration ceiling drops from 500 to 150, matching the BIND 9.16.33+ / Unbound 1.17.1 post-CVE defaults (RFC 9276 recommends 0).
package/lib/mail-agent.js CHANGED
@@ -7,19 +7,26 @@
7
7
  * @featured true
8
8
  *
9
9
  * @intro
10
- * The standardization contract for every mail protocol blamejs ships.
11
- * JMAP (v0.9.27), IMAP (v0.9.28), POP3 (v0.9.29), ManageSieve (v0.9.30),
12
- * the inbound MX listener (v0.9.24), and the submission listener
13
- * (v0.9.25) all translate their protocol calls into `agent.X(args)`.
14
- * The agent owns RBAC, posture enforcement, audit emission,
15
- * dispatch, and worker isolation; every protocol on top is a thin
16
- * shell.
10
+ * A mailbox-access facade that owns RBAC, posture enforcement, audit
11
+ * emission, dispatch (local / worker-pool / queue), and worker
12
+ * isolation around a mail store, so a protocol server built on top
13
+ * can stay a thin shell. It is designed to be the shared dispatch
14
+ * layer mail-protocol servers route through; today the read surface
15
+ * and the mailbox-mutation + Sieve-upload methods are wired, while the
16
+ * compose/send and identity/vacation/MDN/export verbs are not yet
17
+ * wired into the facade (see below).
17
18
  *
18
- * `agent.create()` returns the facade. Methods backed by v0.9.19's
19
- * `b.mailStore` run immediately; methods that depend on later slices
20
- * throw `mail-agent/not-implemented` with a `wiredAt` tag naming the
21
- * version that lights them up (defer-with-condition operator can
22
- * match against the tag to scope their integration).
19
+ * `agent.create()` returns the facade. Methods backed by
20
+ * `b.mailStore` (folders / fetch / search / move / flag / delete /
21
+ * expunge, plus `sieve.put`) run immediately. The remaining verbs
22
+ * compose / send / reply / forward, sieve.list / sieve.activate,
23
+ * identity / vacation / mdn.*, export / job / import — throw
24
+ * `mail-agent/not-implemented`: they are not yet routed through the
25
+ * agent. Until they are, compose the underlying primitive directly
26
+ * (`b.mail.send.deliver` for outbound, `b.mail.sieve` for Sieve,
27
+ * `b.mailMdn` for MDN, etc.) — which is what the framework's own JMAP
28
+ * `emailSubmissionSet` handler does. They wire into the facade when a
29
+ * protocol server adopts the agent as its dispatch layer.
23
30
  *
24
31
  * ```js
25
32
  * var agent = b.mail.agent.create({
@@ -58,9 +65,11 @@
58
65
  * on every entrypoint.
59
66
  *
60
67
  * @card
61
- * The standardization contract for every mail protocol JMAP / IMAP /
62
- * POP3 all translate into `agent.X(args)`. RBAC + posture + audit +
63
- * dispatch owned here; protocols on top are thin shells.
68
+ * Mailbox-access facade RBAC + posture + audit + dispatch around a
69
+ * mail store, so a protocol server on top stays a thin shell. Read +
70
+ * mailbox-mutation + Sieve-upload methods are wired; compose/send and
71
+ * identity/vacation/MDN/export verbs compose the underlying primitive
72
+ * directly until a protocol server routes them through the agent.
64
73
  */
65
74
 
66
75
  var lazyRequire = require("./lazy-require");
@@ -118,25 +127,25 @@ var SCOPE_FOR_METHOD = Object.freeze({
118
127
  import: "mail:import",
119
128
  });
120
129
 
121
- // Methods deferred behind a `wiredAt` version. Operator gets a clear
122
- // error pointing at the slice that lights them up — defer-with-
123
- // condition per the v1-defensible-scope rule.
124
- var WIRED_AT = Object.freeze({
125
- compose: "v0.9.25",
126
- send: "v0.9.25",
127
- reply: "v0.9.25",
128
- forward: "v0.9.25",
129
- "sieve.list": "v0.9.26",
130
- "sieve.put": "v0.9.26",
131
- "sieve.activate": "v0.9.26",
132
- "identity.set": "v0.9.25",
133
- "vacation.set": "v0.9.25",
134
- "mdn.send": "v0.9.25",
135
- "mdn.parse": "v0.9.25",
136
- "mdn.allowList": "v0.9.25",
137
- export: "v0.9.34a",
138
- job: "v0.9.34a",
139
- import: "v0.9.34",
130
+ // Verbs not yet routed through the agent facade. The error points the
131
+ // operator at the underlying primitive to compose directly (the
132
+ // escape hatch) defer-with-condition: these wire into the agent when
133
+ // a protocol server adopts it as its dispatch layer.
134
+ var COMPOSE_HINT = Object.freeze({
135
+ compose: "b.mail.send.deliver",
136
+ send: "b.mail.send.deliver",
137
+ reply: "b.mail.send.deliver",
138
+ forward: "b.mail.send.deliver",
139
+ "sieve.list": "b.mail.sieve",
140
+ "sieve.activate": "b.mail.sieve",
141
+ "identity.set": "your identity store + b.mail.sieve",
142
+ "vacation.set": "b.mail.sieve (vacation extension)",
143
+ "mdn.send": "b.mailMdn",
144
+ "mdn.parse": "b.mailMdn",
145
+ "mdn.allowList": "b.mailMdn",
146
+ export: "b.mailStore / b.auditTools",
147
+ job: "the dispatch queue directly",
148
+ import: "b.mailStore",
140
149
  });
141
150
 
142
151
  /**
@@ -653,9 +662,10 @@ function _notImplemented(ctx, method, args) {
653
662
  // the slice lights up.
654
663
  if (ctx.posture) guardMailQuery.validateActor(args && args.actor, ctx.posture);
655
664
  _checkPermission(ctx, method, args);
656
- ctx.auditEmit("mail.agent.not_implemented", args && args.actor, { method: method, wiredAt: WIRED_AT[method] });
665
+ ctx.auditEmit("mail.agent.not_implemented", args && args.actor, { method: method, composeDirectly: COMPOSE_HINT[method] });
657
666
  return Promise.reject(new MailAgentError("mail-agent/not-implemented",
658
- "agent." + method + ": wired at " + WIRED_AT[method] + " (defer-with-condition)"));
667
+ "agent." + method + " is not yet routed through the agent facade — compose " +
668
+ COMPOSE_HINT[method] + " directly"));
659
669
  }
660
670
 
661
671
  // ---- Internals ------------------------------------------------------------
@@ -771,7 +781,7 @@ module.exports = {
771
781
  consumer: consumer,
772
782
  MailAgentError: MailAgentError,
773
783
  SCOPE_FOR_METHOD: SCOPE_FOR_METHOD,
774
- WIRED_AT: WIRED_AT,
784
+ COMPOSE_HINT: COMPOSE_HINT,
775
785
  HEAVY_METHODS: HEAVY_METHODS,
776
786
  // Re-export the guard family so callers can introspect without
777
787
  // separate requires.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.13.15",
3
+ "version": "0.13.16",
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:f4f503eb-ba54-47ab-8286-d7c3e006249e",
5
+ "serialNumber": "urn:uuid:cd0375e1-7520-4024-b6eb-d8c708fc00db",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-05-27T16:53:17.354Z",
8
+ "timestamp": "2026-05-27T17:24:50.447Z",
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.13.15",
22
+ "bom-ref": "@blamejs/core@0.13.16",
23
23
  "type": "application",
24
24
  "name": "blamejs",
25
- "version": "0.13.15",
25
+ "version": "0.13.16",
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.13.15",
29
+ "purl": "pkg:npm/%40blamejs/core@0.13.16",
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.13.15",
57
+ "ref": "@blamejs/core@0.13.16",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]