@bobfrankston/rmfmail 1.2.322 → 1.2.324

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.
Files changed (35) hide show
  1. package/.commitmsg +21 -24
  2. package/.llm/trusted-lists.md +2 -0
  3. package/client/android-bootstrap.bundle.js +5 -2
  4. package/client/android-bootstrap.bundle.js.map +2 -2
  5. package/client/app.bundle.js +9 -4
  6. package/client/app.bundle.js.map +2 -2
  7. package/client/components/calendar-sidebar.js +14 -2
  8. package/client/components/calendar-sidebar.js.map +1 -1
  9. package/client/components/calendar-sidebar.ts +17 -2
  10. package/client/components/message-viewer.js +12 -2
  11. package/client/components/message-viewer.js.map +1 -1
  12. package/client/components/message-viewer.ts +13 -3
  13. package/docs/allowlist.md +1 -0
  14. package/npmchanges.md +50 -0
  15. package/package.json +7 -7
  16. package/packages/mailx-imap/package-lock.json +2 -2
  17. package/packages/mailx-imap/package.json +1 -1
  18. package/packages/mailx-service/index.d.ts.map +1 -1
  19. package/packages/mailx-service/index.js +8 -2
  20. package/packages/mailx-service/index.js.map +1 -1
  21. package/packages/mailx-service/index.ts +8 -2
  22. package/packages/mailx-service/package.json +1 -1
  23. package/packages/mailx-settings/docs/allowlist.md +1 -0
  24. package/packages/mailx-settings/package.json +1 -1
  25. package/packages/mailx-store/package.json +1 -1
  26. package/packages/mailx-store-web/package.json +1 -1
  27. package/packages/mailx-types/mailx-api.d.ts +1 -0
  28. package/packages/mailx-types/mailx-api.d.ts.map +1 -1
  29. package/packages/mailx-types/mailx-api.ts +1 -1
  30. package/packages/mailx-types/package.json +1 -1
  31. package/packages/mailx-types/trust.d.ts +4 -0
  32. package/packages/mailx-types/trust.d.ts.map +1 -1
  33. package/packages/mailx-types/trust.js +17 -1
  34. package/packages/mailx-types/trust.js.map +1 -1
  35. package/packages/mailx-types/trust.ts +20 -1
package/.commitmsg CHANGED
@@ -1,27 +1,24 @@
1
- Trust a sender via the relay that signs for it ("groundnews.email via amazonses.com")
1
+ A proved, trusted sender vouches for its own links; the trust button appears whenever trust would clear the banner
2
2
 
3
- Bob 2026-09-10, Ground News: "another valid site. How do I approve it?"
4
- The banner read "This claims to be a sender you trust, but nothing proves
5
- it is" — groundnews.email is on his list, but Ground News sends through
6
- Amazon SES, the message is signed only as amazonses.com, and the domain
7
- publishes no DMARC record, so the sender can never be proved and the list
8
- was ignored, correctly, with no way forward. Trusting amazonses.com as an
9
- intermediary was not offered (no Sender: header) and would be too broad.
3
+ Bob 2026-09-11, a Toast receipt: "Another message to flag as safe because
4
+ I trust toasttakeout.com. There should be a trust button."
10
5
 
11
- New allowlist.jsonc `trustedSendersVia`: "‹sender domain› via ‹relay
12
- domain›" pairs. An entry counts only when the From domain matches AND the
13
- named relay's DKIM signature verified at the receiving server — a relay
14
- like SES lets a customer send only From identities it has verified, so
15
- the pair is evidence a forger's own relay account cannot supply, and a
16
- message without the relay's signature matches nothing. Never silences
17
- forgery evidence. The trusted-but-unproved caution now names the relay
18
- that signed and the action; the banner offers "Trust ‹sender› via
19
- ‹relay›". trustSenderOrDomain type "via", TRUST_LIST_KEYS carries the
20
- key for desktop and Android; getAllowlist returns it.
6
+ The mail is dmarc=pass toasttab.com, toasttab.com is on his list, so the
7
+ server's 19.9 spam verdict was already silent what remained was the
8
+ redirector warning: every link runs through toasttakeout.page.link
9
+ (Firebase's per-app redirector) to toasttakeout.com. Two organisations by
10
+ hostname, nobody signed for page.link, the sender is neither, so rules 1
11
+ to 4 all missed, and the finding's own text said "only the sender could
12
+ vouch for the link". Rule 5: when the proved sender is one the reader
13
+ trusts, it has. Proof stays mandatory trust without the server's pass
14
+ clears nothing (tested), so a forger typing a trusted domain into From
15
+ gets no vouching.
21
16
 
22
- Tests: Ground News headers; pair silences only with that relay's
23
- signature (not unsigned, not another relay, not another From through the
24
- same relay); a phishing listing stays red. Verified on the live message:
25
- caution with the offer before, silent after. mailx-types 0.1.97,
26
- mailx-settings 0.1.89, mailx-store 0.1.124, mailx-service 0.1.38,
27
- mailx-store-web 0.1.117.
17
+ The banner's "Stop warning about" buttons used to appear only when the
18
+ server's verdict was the single finding. They now appear whenever every
19
+ finding is one trust clears (the verdict, the redirector warning) and the
20
+ sender is proved — the Toast receipt carried both and so had no button
21
+ on the one message that needed it. A proved-but-untrusted sender's
22
+ redirector warning now names the action; an unproved one says plainly
23
+ that nothing proves who the sender is. mailx-types 0.1.99. Verified on
24
+ the live receipt: two cautions before, nothing after.
@@ -68,3 +68,5 @@ tests/trust.test.ts, .commitmsg, TODO.md C165, root version 1.2.311. Then rebuil
68
68
  - v1.2.321: signature block uses a 3cm <hr> instead of '-- ' (compose.ts sigBlock).
69
69
  - Bob confirmed 2026-09-10: 'quill worked' (v1.2.320 placeCaretAfterLink).
70
70
  - v1.2.322: trustedSendersVia ('sender via relay' pairs) — Ground News via amazonses.com. Banner offers 'Trust ‹sender› via ‹relay›' on the trusted-but-unproved caution; counts only when the relay DKIM-signed. 45/45 trust tests.
71
+ - v1.2.323: New event picker always shown (disabled + explanatory tooltip when only one writable calendar); getCalendars returns all calendars with selected flag; daemon logs roles.
72
+ - v1.2.324: redirector rule 5 — proved + trusted sender vouches for its own links (Toast via toasttakeout.page.link). Banner 'Stop warning about' now offered when every finding is verdict/redirector and sender proved. 48/48.
@@ -2589,6 +2589,8 @@ function provedSenderDomain(input) {
2589
2589
  function redirectorLink(input) {
2590
2590
  const bodyHtml = input.bodyHtml || "";
2591
2591
  const senderDomain = provedSenderDomain(input);
2592
+ if (senderDomain && input.senderTrusted)
2593
+ return null;
2592
2594
  const intermediary = provedIntermediary(input);
2593
2595
  const signers = dkimSigners(input);
2594
2596
  for (const m of bodyHtml.matchAll(/href\s*=\s*["']([^"']+)["']/gi)) {
@@ -2618,13 +2620,14 @@ function redirectorLink(input) {
2618
2620
  if (senderDomain && sameOrg(target.hostname, senderDomain))
2619
2621
  continue;
2620
2622
  const signer = signers.find((s) => sameOrg(s, url.hostname));
2621
- const how = signer ? ` ${signer} signed this message; "Trust ${signer} as an intermediary" stops this warning for links through ${signer} in mail it signs.` : ` Nobody signed this message for ${url.hostname}, so there is no intermediary to trust; only the sender could vouch for the link.`;
2623
+ const how = signer ? ` ${signer} signed this message; "Trust ${signer} as an intermediary" stops this warning for links through ${signer} in mail it signs.` : senderDomain ? ` Nobody signed this message for ${url.hostname}, so there is no intermediary to trust; ${senderDomain} proved it sent this, and "Stop warning about *@${senderDomain}" lets it vouch for its own links.` : ` Nobody signed this message for ${url.hostname}, so there is no intermediary to trust; only the sender could vouch for the link, and nothing proves who the sender is.`;
2622
2624
  return {
2623
2625
  id: "redirector-link",
2624
2626
  severity: "caution",
2625
2627
  text: `A link hides where it goes: it passes through ${url.hostname} and ends at ${target.hostname}.`,
2626
2628
  detail: `${url.hostname} -> ${target.hostname}.${how}`,
2627
- ...signer ? { via: signer } : {}
2629
+ ...signer ? { via: signer } : {},
2630
+ ...senderDomain && !signer ? { sender: senderDomain } : {}
2628
2631
  };
2629
2632
  }
2630
2633
  }