@blamejs/blamejs-shop 0.2.2 → 0.2.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 +4 -0
- package/lib/admin.js +171 -5
- package/lib/asset-manifest.json +9 -5
- package/lib/storefront.js +193 -0
- package/lib/vendor/MANIFEST.json +2 -2
- package/lib/vendor/blamejs/CHANGELOG.md +6 -0
- package/lib/vendor/blamejs/SECURITY.md +1 -1
- package/lib/vendor/blamejs/api-snapshot.json +54 -58
- package/lib/vendor/blamejs/lib/acme.js +8 -5
- package/lib/vendor/blamejs/lib/archive-read.js +24 -20
- package/lib/vendor/blamejs/lib/break-glass.js +4 -5
- package/lib/vendor/blamejs/lib/crypto.js +8 -5
- package/lib/vendor/blamejs/lib/guard-dsn.js +3 -2
- package/lib/vendor/blamejs/lib/guard-list-id.js +3 -2
- package/lib/vendor/blamejs/lib/guard-regex.js +4 -4
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +1 -2
- package/lib/vendor/blamejs/lib/mail-agent.js +47 -37
- package/lib/vendor/blamejs/lib/network-dnssec.js +98 -5
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +8 -0
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.13.14.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.13.15.json +27 -0
- package/lib/vendor/blamejs/release-notes/v0.13.16.json +27 -0
- package/lib/vendor/blamejs/test/00-primitives.js +9 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +4 -8
- package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +6 -0
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"frameworkVersion": "0.13.
|
|
4
|
-
"createdAt": "2026-05-
|
|
3
|
+
"frameworkVersion": "0.13.16",
|
|
4
|
+
"createdAt": "2026-05-27T16:55:42.429Z",
|
|
5
5
|
"exports": {
|
|
6
6
|
"a2a": {
|
|
7
7
|
"type": "object",
|
|
@@ -37552,54 +37552,17 @@
|
|
|
37552
37552
|
"agent": {
|
|
37553
37553
|
"type": "object",
|
|
37554
37554
|
"members": {
|
|
37555
|
-
"
|
|
37556
|
-
"type": "object",
|
|
37557
|
-
"members": {
|
|
37558
|
-
"export": {
|
|
37559
|
-
"type": "primitive",
|
|
37560
|
-
"valueType": "boolean"
|
|
37561
|
-
},
|
|
37562
|
-
"search": {
|
|
37563
|
-
"type": "primitive",
|
|
37564
|
-
"valueType": "boolean"
|
|
37565
|
-
}
|
|
37566
|
-
}
|
|
37567
|
-
},
|
|
37568
|
-
"MailAgentError": {
|
|
37569
|
-
"type": "function",
|
|
37570
|
-
"arity": 4
|
|
37571
|
-
},
|
|
37572
|
-
"SCOPE_FOR_METHOD": {
|
|
37555
|
+
"COMPOSE_HINT": {
|
|
37573
37556
|
"type": "object",
|
|
37574
37557
|
"members": {
|
|
37575
37558
|
"compose": {
|
|
37576
37559
|
"type": "primitive",
|
|
37577
37560
|
"valueType": "string"
|
|
37578
37561
|
},
|
|
37579
|
-
"delete": {
|
|
37580
|
-
"type": "primitive",
|
|
37581
|
-
"valueType": "string"
|
|
37582
|
-
},
|
|
37583
37562
|
"export": {
|
|
37584
37563
|
"type": "primitive",
|
|
37585
37564
|
"valueType": "string"
|
|
37586
37565
|
},
|
|
37587
|
-
"expunge": {
|
|
37588
|
-
"type": "primitive",
|
|
37589
|
-
"valueType": "string"
|
|
37590
|
-
},
|
|
37591
|
-
"fetch": {
|
|
37592
|
-
"type": "primitive",
|
|
37593
|
-
"valueType": "string"
|
|
37594
|
-
},
|
|
37595
|
-
"flag": {
|
|
37596
|
-
"type": "primitive",
|
|
37597
|
-
"valueType": "string"
|
|
37598
|
-
},
|
|
37599
|
-
"folders": {
|
|
37600
|
-
"type": "primitive",
|
|
37601
|
-
"valueType": "string"
|
|
37602
|
-
},
|
|
37603
37566
|
"forward": {
|
|
37604
37567
|
"type": "primitive",
|
|
37605
37568
|
"valueType": "string"
|
|
@@ -37628,56 +37591,73 @@
|
|
|
37628
37591
|
"type": "primitive",
|
|
37629
37592
|
"valueType": "string"
|
|
37630
37593
|
},
|
|
37631
|
-
"
|
|
37594
|
+
"reply": {
|
|
37632
37595
|
"type": "primitive",
|
|
37633
37596
|
"valueType": "string"
|
|
37634
37597
|
},
|
|
37635
|
-
"
|
|
37598
|
+
"send": {
|
|
37636
37599
|
"type": "primitive",
|
|
37637
37600
|
"valueType": "string"
|
|
37638
37601
|
},
|
|
37639
|
-
"
|
|
37602
|
+
"sieve.activate": {
|
|
37640
37603
|
"type": "primitive",
|
|
37641
37604
|
"valueType": "string"
|
|
37642
37605
|
},
|
|
37643
|
-
"
|
|
37606
|
+
"sieve.list": {
|
|
37644
37607
|
"type": "primitive",
|
|
37645
37608
|
"valueType": "string"
|
|
37646
37609
|
},
|
|
37647
|
-
"
|
|
37610
|
+
"vacation.set": {
|
|
37648
37611
|
"type": "primitive",
|
|
37649
37612
|
"valueType": "string"
|
|
37613
|
+
}
|
|
37614
|
+
}
|
|
37615
|
+
},
|
|
37616
|
+
"HEAVY_METHODS": {
|
|
37617
|
+
"type": "object",
|
|
37618
|
+
"members": {
|
|
37619
|
+
"export": {
|
|
37620
|
+
"type": "primitive",
|
|
37621
|
+
"valueType": "boolean"
|
|
37650
37622
|
},
|
|
37651
|
-
"
|
|
37623
|
+
"search": {
|
|
37624
|
+
"type": "primitive",
|
|
37625
|
+
"valueType": "boolean"
|
|
37626
|
+
}
|
|
37627
|
+
}
|
|
37628
|
+
},
|
|
37629
|
+
"MailAgentError": {
|
|
37630
|
+
"type": "function",
|
|
37631
|
+
"arity": 4
|
|
37632
|
+
},
|
|
37633
|
+
"SCOPE_FOR_METHOD": {
|
|
37634
|
+
"type": "object",
|
|
37635
|
+
"members": {
|
|
37636
|
+
"compose": {
|
|
37652
37637
|
"type": "primitive",
|
|
37653
37638
|
"valueType": "string"
|
|
37654
37639
|
},
|
|
37655
|
-
"
|
|
37640
|
+
"delete": {
|
|
37656
37641
|
"type": "primitive",
|
|
37657
37642
|
"valueType": "string"
|
|
37658
37643
|
},
|
|
37659
|
-
"
|
|
37644
|
+
"export": {
|
|
37660
37645
|
"type": "primitive",
|
|
37661
37646
|
"valueType": "string"
|
|
37662
37647
|
},
|
|
37663
|
-
"
|
|
37648
|
+
"expunge": {
|
|
37664
37649
|
"type": "primitive",
|
|
37665
37650
|
"valueType": "string"
|
|
37666
37651
|
},
|
|
37667
|
-
"
|
|
37652
|
+
"fetch": {
|
|
37668
37653
|
"type": "primitive",
|
|
37669
37654
|
"valueType": "string"
|
|
37670
|
-
}
|
|
37671
|
-
|
|
37672
|
-
},
|
|
37673
|
-
"WIRED_AT": {
|
|
37674
|
-
"type": "object",
|
|
37675
|
-
"members": {
|
|
37676
|
-
"compose": {
|
|
37655
|
+
},
|
|
37656
|
+
"flag": {
|
|
37677
37657
|
"type": "primitive",
|
|
37678
37658
|
"valueType": "string"
|
|
37679
37659
|
},
|
|
37680
|
-
"
|
|
37660
|
+
"folders": {
|
|
37681
37661
|
"type": "primitive",
|
|
37682
37662
|
"valueType": "string"
|
|
37683
37663
|
},
|
|
@@ -37709,10 +37689,22 @@
|
|
|
37709
37689
|
"type": "primitive",
|
|
37710
37690
|
"valueType": "string"
|
|
37711
37691
|
},
|
|
37692
|
+
"move": {
|
|
37693
|
+
"type": "primitive",
|
|
37694
|
+
"valueType": "string"
|
|
37695
|
+
},
|
|
37696
|
+
"quota": {
|
|
37697
|
+
"type": "primitive",
|
|
37698
|
+
"valueType": "string"
|
|
37699
|
+
},
|
|
37712
37700
|
"reply": {
|
|
37713
37701
|
"type": "primitive",
|
|
37714
37702
|
"valueType": "string"
|
|
37715
37703
|
},
|
|
37704
|
+
"search": {
|
|
37705
|
+
"type": "primitive",
|
|
37706
|
+
"valueType": "string"
|
|
37707
|
+
},
|
|
37716
37708
|
"send": {
|
|
37717
37709
|
"type": "primitive",
|
|
37718
37710
|
"valueType": "string"
|
|
@@ -37729,6 +37721,10 @@
|
|
|
37729
37721
|
"type": "primitive",
|
|
37730
37722
|
"valueType": "string"
|
|
37731
37723
|
},
|
|
37724
|
+
"thread": {
|
|
37725
|
+
"type": "primitive",
|
|
37726
|
+
"valueType": "string"
|
|
37727
|
+
},
|
|
37732
37728
|
"vacation.set": {
|
|
37733
37729
|
"type": "primitive",
|
|
37734
37730
|
"valueType": "string"
|
|
@@ -1079,14 +1079,17 @@ function create(opts) {
|
|
|
1079
1079
|
* the DER-encoded cert (base64url-encoded automatically) plus an
|
|
1080
1080
|
* optional `reason` code per RFC 5280 §5.3.1 (0=unspecified,
|
|
1081
1081
|
* 1=keyCompromise, 3=affiliationChanged, 4=superseded, 5=cessationOfOperation).
|
|
1082
|
-
* Signs with the account key
|
|
1083
|
-
*
|
|
1084
|
-
*
|
|
1082
|
+
* Signs with the account key — the only supported path today, and
|
|
1083
|
+
* sufficient for mainstream CAs. (The cert-key-signed variant —
|
|
1084
|
+
* `useCertKey` / `certPrivateKey` — is reserved and not yet
|
|
1085
|
+
* implemented; passing `useCertKey:true` throws.)
|
|
1085
1086
|
*
|
|
1086
1087
|
* @opts
|
|
1087
1088
|
* reason: number, // RFC 5280 §5.3.1 reason code; default 0 (unspecified)
|
|
1088
|
-
* useCertKey: boolean, //
|
|
1089
|
-
*
|
|
1089
|
+
* useCertKey: boolean, // RESERVED — cert-key-signed revocation is not yet
|
|
1090
|
+
* // implemented; account-key signing (the default)
|
|
1091
|
+
* // covers mainstream CAs. Passing true throws.
|
|
1092
|
+
* certPrivateKey: KeyObject, // RESERVED — consumed only by the cert-key path above
|
|
1090
1093
|
*
|
|
1091
1094
|
* @example
|
|
1092
1095
|
* await acme.revokeCert(certDerBuffer, { reason: 4 }); // 4 = superseded
|
|
@@ -772,7 +772,7 @@ function zip(adapter, opts) {
|
|
|
772
772
|
* @primitive b.archive.read.zip.fromTrustedStream
|
|
773
773
|
* @signature b.archive.read.zip.fromTrustedStream(adapter, opts?)
|
|
774
774
|
* @since 0.12.7
|
|
775
|
-
* @status
|
|
775
|
+
* @status experimental
|
|
776
776
|
* @related b.archive.read.zip, b.archive.adapters.trustedStream
|
|
777
777
|
*
|
|
778
778
|
* Forward-scan-only ZIP reader for trusted Readable sources. No
|
|
@@ -781,20 +781,23 @@ function zip(adapter, opts) {
|
|
|
781
781
|
* `b.archive.zip().toStream()` output back into a reader for round-trip
|
|
782
782
|
* verification).
|
|
783
783
|
*
|
|
784
|
-
*
|
|
785
|
-
* `
|
|
784
|
+
* NOT YET IMPLEMENTED: the streaming LFH walker is not built —
|
|
785
|
+
* `inspect()` / `entries()` / `extract()` throw
|
|
786
|
+
* `archive-read/trusted-stream-*-deferred`, and `bombPolicy` / `audit`
|
|
787
|
+
* are accepted but not yet honored. Re-opens when a streaming
|
|
788
|
+
* consumer needs it. Until then, collect the stream into a buffer and
|
|
789
|
+
* use the random-access reader, which is the supported path for both
|
|
790
|
+
* trusted round-trip verification and adversarial input.
|
|
786
791
|
*
|
|
787
792
|
* @opts
|
|
788
|
-
* bombPolicy: {
|
|
789
|
-
*
|
|
790
|
-
* audit: b.audit,
|
|
793
|
+
* bombPolicy: { ... }, // reserved — not yet honored
|
|
794
|
+
* audit: b.audit, // reserved — not yet honored
|
|
791
795
|
*
|
|
792
796
|
* @example
|
|
793
|
-
*
|
|
794
|
-
* var
|
|
795
|
-
*
|
|
796
|
-
* );
|
|
797
|
-
* for await (var e of reader.entries()) console.log(e.name, e.size);
|
|
797
|
+
* // Supported path: buffer the stream, then read random-access.
|
|
798
|
+
* var bytes = await someStreamToBuffer(producedZipStream);
|
|
799
|
+
* var reader = b.archive.read.zip(b.archive.adapters.buffer(bytes));
|
|
800
|
+
* var entries = await reader.inspect();
|
|
798
801
|
*/
|
|
799
802
|
function fromTrustedStream(adapter, opts) {
|
|
800
803
|
if (!adapter || adapter.kind !== "trusted-sequential") {
|
|
@@ -805,25 +808,26 @@ function fromTrustedStream(adapter, opts) {
|
|
|
805
808
|
var bombPolicy = _normalizeBombPolicy(opts.bombPolicy);
|
|
806
809
|
void bombPolicy;
|
|
807
810
|
|
|
808
|
-
//
|
|
809
|
-
//
|
|
810
|
-
//
|
|
811
|
-
//
|
|
812
|
-
//
|
|
811
|
+
// The streaming LFH walker is not built — only the API surface +
|
|
812
|
+
// adapter validation exist. Extraction via streaming inflate +
|
|
813
|
+
// data-descriptor scanning re-opens when a streaming consumer needs
|
|
814
|
+
// it; until then the supported path is to buffer the stream and use
|
|
815
|
+
// the random-access reader (which handles both trusted round-trip
|
|
816
|
+
// verification and adversarial input).
|
|
813
817
|
async function inspect() {
|
|
814
818
|
throw new ArchiveReadError("archive-read/trusted-stream-inspect-deferred",
|
|
815
|
-
"fromTrustedStream.inspect() is
|
|
816
|
-
"
|
|
819
|
+
"fromTrustedStream.inspect() is not implemented — collect the stream into a buffer and " +
|
|
820
|
+
"use b.archive.read.zip(b.archive.adapters.buffer(bytes))");
|
|
817
821
|
}
|
|
818
822
|
|
|
819
823
|
async function* entries() {
|
|
820
824
|
throw new ArchiveReadError("archive-read/trusted-stream-entries-deferred",
|
|
821
|
-
"fromTrustedStream.entries() is
|
|
825
|
+
"fromTrustedStream.entries() is not implemented — collect into a buffer and use the random-access reader");
|
|
822
826
|
}
|
|
823
827
|
|
|
824
828
|
async function extract() {
|
|
825
829
|
throw new ArchiveReadError("archive-read/trusted-stream-extract-deferred",
|
|
826
|
-
"fromTrustedStream.extract() is
|
|
830
|
+
"fromTrustedStream.extract() is not implemented — collect into a buffer and use the random-access reader");
|
|
827
831
|
}
|
|
828
832
|
|
|
829
833
|
return {
|
|
@@ -130,9 +130,9 @@ function _ensureFactorLockout() {
|
|
|
130
130
|
// keys + encryption-context binding (cross-cell tampering / accidental
|
|
131
131
|
// row-swap fails closed). It does NOT defend against vault-key
|
|
132
132
|
// compromise alone — the DEK is still vault-recoverable. True
|
|
133
|
-
// second-factor cryptographic gating
|
|
134
|
-
//
|
|
135
|
-
//
|
|
133
|
+
// second-factor cryptographic gating uses passkey integration (the
|
|
134
|
+
// passkey private key lives on the YubiKey, not in the framework, so a
|
|
135
|
+
// vault leak alone can't unwrap).
|
|
136
136
|
|
|
137
137
|
// In-memory DEK cache. Keyed by table name. Cleared on _resetForTest.
|
|
138
138
|
var dekCache = new Map();
|
|
@@ -520,8 +520,7 @@ function _validatePolicySet(table, opts) {
|
|
|
520
520
|
if (ALLOWED_FACTORS.indexOf(opts.factors[j]) === -1) {
|
|
521
521
|
throw new BreakGlassError("breakglass/bad-policy",
|
|
522
522
|
"policy.set: factors[" + j + "] '" + opts.factors[j] +
|
|
523
|
-
"' not in
|
|
524
|
-
" (passkey lands in v0.5.2)");
|
|
523
|
+
"' not in allowed factors [" + ALLOWED_FACTORS.join(",") + "]");
|
|
525
524
|
}
|
|
526
525
|
}
|
|
527
526
|
// Model B (cryptographic mode) ships in v0.5.1. When enabled,
|
|
@@ -789,10 +789,12 @@ function toBase64Url(buf) {
|
|
|
789
789
|
*
|
|
790
790
|
* Strict mode (default) refuses non-canonical input — chars outside
|
|
791
791
|
* the RFC 4648 §5 alphabet, length-mod-4-of-1, mixed `+/` from
|
|
792
|
-
* standard base64, trailing garbage. Defends
|
|
793
|
-
* footgun where
|
|
794
|
-
*
|
|
795
|
-
*
|
|
792
|
+
* standard base64, trailing garbage. Defends the CWE-347 /
|
|
793
|
+
* CWE-1286 signature-canonicalization footgun where a permissive
|
|
794
|
+
* base64url decoder silently tolerates a tampered JWS / JWT signature
|
|
795
|
+
* (non-canonical bytes decoding to the same buffer). Operators with a
|
|
796
|
+
* documented lossy legacy payload opt out per call via
|
|
797
|
+
* `{ strict: false }`.
|
|
796
798
|
*
|
|
797
799
|
* @opts
|
|
798
800
|
* strict: boolean // default: true — refuse non-canonical input
|
|
@@ -817,7 +819,8 @@ function fromBase64Url(s, opts) {
|
|
|
817
819
|
// OAuth `state` round-tripping) MUST reject non-canonical / malformed
|
|
818
820
|
// input. The Node base64url decoder silently tolerates trailing
|
|
819
821
|
// garbage, mixed `+/` from standard base64, missing padding errors,
|
|
820
|
-
// and length-mod-4 shapes —
|
|
822
|
+
// and length-mod-4 shapes — the CWE-347 / CWE-1286 signature-
|
|
823
|
+
// canonicalization footgun. Strict mode
|
|
821
824
|
// (the default) refuses anything outside the RFC 4648 §5 alphabet +
|
|
822
825
|
// length rules. Operators with a known-lossy legacy payload pass
|
|
823
826
|
// `{ strict: false }` to opt out per call.
|
|
@@ -84,8 +84,9 @@
|
|
|
84
84
|
* generating a DSN (the existing `b.mail.bounce` primitive does
|
|
85
85
|
* this); this guard parses INBOUND DSNs and gates the parse
|
|
86
86
|
* surface bounds, not the bounce-generation policy.
|
|
87
|
-
* - **DSN header-injection class** (CVE-2026-32178 .NET
|
|
88
|
-
* System.Net.Mail
|
|
87
|
+
* - **DSN header-injection class** (CVE-2026-32178 — .NET CWE-138
|
|
88
|
+
* special-element / header-injection spoofing, the System.Net.Mail
|
|
89
|
+
* vector per MSRC, at outbound; the inbound parse path here)
|
|
89
90
|
* — refuses CR/LF/NUL/C0 in header lines.
|
|
90
91
|
* - **CSAF / iSchedule prose tampering** — operator inspecting
|
|
91
92
|
* the prose part for the original recipient runs into the
|
|
@@ -37,8 +37,9 @@
|
|
|
37
37
|
* octets. Total header value capped at 998 bytes per RFC 5322
|
|
38
38
|
* §2.1.1 line cap.
|
|
39
39
|
* - **CRLF + control-char refusal** — header-injection defense
|
|
40
|
-
* (CVE-2026-32178 .NET
|
|
41
|
-
*
|
|
40
|
+
* (CVE-2026-32178 — .NET CWE-138 header-injection spoofing, the
|
|
41
|
+
* System.Net.Mail vector per MSRC, on the wire-protocol surface;
|
|
42
|
+
* this primitive's job is the SEMANTIC shape).
|
|
42
43
|
* - **Phrase-injection refusal** — Operator-supplied display
|
|
43
44
|
* phrase mustn't carry CRLF / `<` / `>` outside the angle
|
|
44
45
|
* brackets (a separate Bcc/Cc header smuggled into the phrase
|
|
@@ -248,14 +248,14 @@ function _detectIssues(input, opts) {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
// Consecutive-star wildcard cap (CVE-2026-26996). Operator-supplied
|
|
251
|
-
// glob fragments compile to picomatch / RegExp; a long run
|
|
252
|
-
// against a non-matching literal walks O(4^N). Three-or-more
|
|
251
|
+
// glob fragments compile to minimatch / picomatch / RegExp; a long run
|
|
252
|
+
// of `*` against a non-matching literal walks O(4^N). Three-or-more
|
|
253
253
|
// consecutive `*` is the canonical bad shape; `**` (recursive glob)
|
|
254
254
|
// stays permitted, gated by the profile's `maxConsecutiveStars`.
|
|
255
255
|
function _detectConsecutiveStar(input, opts, issues) {
|
|
256
256
|
if (opts.consecutiveStarPolicy === "allow") return;
|
|
257
|
-
// CVE-2026-26996 is a
|
|
258
|
-
// `***+literal` walks O(4^N) when
|
|
257
|
+
// CVE-2026-26996 is a minimatch glob-shape backtracking class —
|
|
258
|
+
// `***+literal` walks O(4^N) when minimatch translates the run to a
|
|
259
259
|
// backtracking-heavy regex. Native ECMAScript regex syntax cannot
|
|
260
260
|
// produce three consecutive `*` quantifiers (it's a SyntaxError),
|
|
261
261
|
// so applying this detector to `inputKind: "regex"` strings only
|
|
@@ -15,8 +15,7 @@
|
|
|
15
15
|
* ## Smuggling defense — bare-CR / bare-LF refusal
|
|
16
16
|
*
|
|
17
17
|
* The SMTP smuggling class (`CVE-2023-51764` Postfix, `CVE-2023-51765`
|
|
18
|
-
* Sendmail, `CVE-2023-51766` Exim
|
|
19
|
-
* `System.Net.Mail`) exploits implementations that accept the
|
|
18
|
+
* Sendmail, `CVE-2023-51766` Exim) exploits implementations that accept the
|
|
20
19
|
* non-standard end-of-data sequence `<LF>.<LF>` or `<LF>.<CR><LF>`
|
|
21
20
|
* instead of the standard `<CR><LF>.<CR><LF>`. The introduced break-
|
|
22
21
|
* out lets a malicious peer inject a second message past SPF / DMARC
|
|
@@ -7,19 +7,26 @@
|
|
|
7
7
|
* @featured true
|
|
8
8
|
*
|
|
9
9
|
* @intro
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
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
|
|
19
|
-
* `b.mailStore`
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
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
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
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
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
"sieve.
|
|
131
|
-
"sieve.activate": "
|
|
132
|
-
"identity.set": "
|
|
133
|
-
"vacation.set": "
|
|
134
|
-
"mdn.send": "
|
|
135
|
-
"mdn.parse": "
|
|
136
|
-
"mdn.allowList": "
|
|
137
|
-
export: "
|
|
138
|
-
job: "
|
|
139
|
-
import: "
|
|
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,
|
|
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 + "
|
|
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
|
-
|
|
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.
|