RFC-updates recon — 2026-08
Scope: the shared recon artifact for the RFC-updates adoption program. For every base RFC the stack implements, the RFC Editor lists published update RFCs; this page maps each update onto every repo surface it touches, records an audited status (with the method used to reach it), and closes each row with an adopt/decline recommendation. The recommendations are inputs to future planning decisions, not decisions — nothing on this page changes code, and no update is adopted by appearing here.
The cluster inventory (which updates exist per base) comes from the updated-by graph verified against rfc-editor.org metadata on 2026-08-05; it is not re-derived here. Ten clusters exist in total — SMTP core, enhanced status codes, email TLS, DSN/MDN, SPF, DKIM, ARF, IMAP, POP3, and message format/MIME — and all ten are audited below. The page closes with the cross-cluster overlap map (which clusters can never run as concurrent lanes) and the decision inventory (the adopt/decline questions each future cluster wave must put to the user at its planning).
Method: every “audited status” was established by reading this repo’s sources
and, where a behavior lives in an adopted dependency, the vendored crate
sources under the local cargo registry (~/.cargo/registry/src): mail-auth
0.11.1, smtp-proto 0.2.1, imap-types 2.0.0-alpha.7, mail-parser 0.11.5,
mail-builder 0.4.4, and reqwest 0.13.4. Each row names its grep target or
the function read, plus file:line cites as of 2026-08-05 — line numbers
drift, so the function names are the durable half of each cite. Audit depth is
deliberately prose-with-cites: executable fences (tests asserting an update’s
behavior) ride each future adopting-cluster wave, not this page.
Wired into
SUMMARY.mdunder Appendix: Reference in wave-set #47 (alongsidedependency-audit-2026-07.md, this page’s structural sibling).
The coverage-assertion sync sites. Whenever a cluster wave adopts an
update, three places assert RFC coverage and must move together:
Standards and RFC coverage, the
protocol-conformance appendix, and the
owning server crate’s lib.rs “RFCs implemented” block.
Verdict legend
- done — the update’s behavior is already implemented and credited; no action.
- adopted in-flight — being adopted by a wave currently running; the row records the fact, not an open question.
- adopt (citation/fence) — the behavior is already present (natively or via an adopted dependency); the remaining work is citing the RFC and fencing the behavior with a test or doc assertion, not implementing it.
- adopt (implement) — the behavior is absent and adoption is recommended; the row scopes the (small) implementation.
- decision required — adoption turns on a question the owning cluster wave must put to the user at its planning; the row records evidence only, and the question is stated — not answered — in the user decision inventory closing this page.
- decline — recommend not adopting; the rationale rides the row.
- defer (EAI) — only meaningful if the stack ever adopts internationalized email (RFC 6530–6533); park behind that decision. That decision is now recorded (wave-set #51 lane C): deferred with criteria — the EAI program stays unopened until a concrete demand signal arrives (an operator or user needing non-ASCII addresses, or interop with an EAI sender); no implementation now. The rows keep this verdict tag, with decision-inventory entry 7 as their governing record.
Cluster 1 — SMTP core (RFC 5321)
Owning surfaces: the sans-io smtp_session state machine (wire grammar over
the adopted smtp-proto 0.2.1) driven by smtp_server; outbound, the relay’s
SMTP client (smtp_session::client used by mail_spooler). Coverage
assertions: the SMTP table in standards.md and
smtp_session/src/lib.rs’s RFC block.
| Update | What it adds to 5321 | Audited status | Verdict |
|---|---|---|---|
| RFC 7504 | 521 (host never accepts mail) / 556 (domain publishes null MX) reply codes | already implemented, previously uncredited | adopted in-flight (wave-set #47 lane B) |
- RFC 7504 — adopted in wave-set #47 lane B, running concurrently with
this recon, as a citation/fence pass rather than an implementation: the
behavior was found already present but uncredited. The relay’s
null_mx_outcome()(mail_spooler/src/pipeline/relay.rs:923) already produced the 556 / 5.1.10 outcome — RFC 7504 §2.2’s prescribed use of the code in the failure DSN for a null-MX domain — while citing only RFC 7505; and the client outcome classifieris_permanent()(smtp_session/src/client/outcome.rs:50) treats anycode >= 500generically, so an inbound 521/556 from a remote server already terminates retries as 7504 intends. There is deliberately no live 521/556 emission path on the server side: SithBit’s posture is “don’t run the server if you don’t want mail”, so a mode that answers every connection with 521 has no product meaning here. Lane B’s pass adds the citations and fences; no behavior changes.
Cluster 2 — Enhanced status codes (RFC 3463)
Owning surfaces: smtp_session/src/reply.rs — EnhancedCode (reply.rs:18)
and Reply::enhanced (reply.rs:48), where the class digit is derived from
the reply code so a class mismatch is unrepresentable (fenced by the inline
test at reply.rs:131); advertised via ENHANCEDSTATUSCODES (RFC 2034).
Three of this cluster’s updaters are SMTP extensions that merely register
new codes, so each needed an adopt/decline verdict on the extension itself,
not just on code strings.
| Update | What it is | Audited status | Verdict |
|---|---|---|---|
| RFC 3886 | message/tracking-status (MTRK companion) | absent; MTRK param structurally refused | decline |
| RFC 4468 | BURL submission extension | absent; command falls to the catch-all | decline |
| RFC 4865 | FUTURERELEASE (scheduled send) | absent; HOLDFOR/HOLDUNTIL structurally refused | decline |
| RFC 4954 | SMTP AUTH | implemented and credited | done |
| RFC 5248 | the enhanced-status-code IANA registry (BCP) | no code surface; emitted codes are registry-listed; credit landed | adopted (wave-set #48 lane A) |
- RFC 3886 (with RFC 3885, cluster 4). The adopted
smtp-protogrammar parses theMTRKMAIL parameter (MailFrom.mtrk, vendoredsmtp-proto-0.2.1/src/lib.rs:120), butunsupported_mail_param(smtp_session/src/session/ready.rs:300-302) refuses it with555 5.5.4because the extension is never advertised — the deliberate pattern for every extension the config does not enable. Method: grep forMTRK/Mtrkacrosssmtp_session,smtp_server,mail_spooler, and the vendoredsmtp-proto. Recommendation: decline — the MTRK family (RFC 3885/3886/3887) saw effectively no real-world deployment, and SithBit’s message tracking already lives a layer down: on-chain message accounts give senders a stronger delivery record than MTRK ever specified. - RFC 4468 (BURL).
smtp-protoparsesRequest::Burl(vendoredlib.rs:37), but no session state handles it: the dispatch catch-all (ready.rs:92) answers500 5.5.1(unknown_command,session/mod.rs:524-526), andEXT_BURLis never advertised. BURL also requires IMAP URLAUTH (RFC 4467) on the access side, and the adoptedimap-types2.0.0-alpha.7 has no URLAUTH types at all (method: grep forurlauth/GenUrlAuthin the vendored source — zero hits), so the prerequisite is unbuildable without the already-deferredimap-typesfork. Recommendation: decline — near-zero client deployment, a blocked prerequisite, and the compose-without-reupload problem it solves is served by the account API compose endpoint (mail_submit) instead. - RFC 4865 (FUTURERELEASE). Parsed by
smtp-proto(MailFrom.hold_for/hold_until), structurally refused with555 5.5.4atready.rs:303-305; never advertised. It also updates RFC 3464 (DSN wording for held mail — see cluster 4). Recommendation: decline — scheduled send belongs in the composing client or the account API, where the user can still see and cancel the message, not in an SMTP queue extension; the DSN-side changes fall away with it. - RFC 4954 — done. Implemented and credited:
smtp_session/src/lib.rs:19, the standards.md SMTP table, and the §6-conformant failure replies (failure_reply,ready.rs, e.g.535 5.7.8). No action. - RFC 5248. A BCP that turns 3463’s code lists into a living IANA
registry — there is no implementable behavior. Audit: inventoried every
Reply::enhancedcall site insmtp_session/smtp_server(method: grep- sed extraction of the code triples) and spot-checked the notable ones
against the registry: all emitted codes are registry-listed, including the
post-3463 registrations
5.7.8(RFC 4954),5.7.23(RFC 7372), and the DSN-side5.1.10(RFC 7505). Adopted in wave-set #48 lane A exactly as recommended — the wave that next touched standards.md folded the one-line credit onto its enhanced-status-codes row (“every emitted code is listed in the RFC 5248 IANA registry”); nothing was implemented.
- sed extraction of the code triples) and spot-checked the notable ones
against the registry: all emitted codes are registry-listed, including the
post-3463 registrations
Cluster 3 — Email TLS (bases: RFC 3207, 2595, 8314, 4616)
Owning surfaces: the shared server-side acceptors in
server_common/src/tls.rs (tls_acceptor at tls.rs:174 and
tls_acceptor_with_client_auth at tls.rs:197 — all three protocol servers
ride these); the single outbound client config connector() in
mail_spooler/src/smtp_out.rs:214 (covering TlsVerify::Strict,
Permissive, and Dane); and — for the residual finding below — the two
HTTPS fetchers in the spooler. Policy gates (RFC 8314) are documented in
the protocol-conformance appendix.
| Update | What it is | Audited status | Verdict |
|---|---|---|---|
| RFC 7817 | updated TLS server-identity check for email protocols | already satisfied where it applies; now cited at the handshake and credited | adopted (wave-set #48 lane A) |
| RFC 8996 | deprecates TLS 1.0/1.1 | floor held at every rustls site; now fenced, and the two reqwest sites pinned | adopted (wave-set #48 lane A) |
| RFC 8997 | TLS 1.2+ floor for email (updates 8314) | same evidence and fences as 8996 | adopted (wave-set #48 lane A) |
| RFC 4616 | SASL PLAIN (base, updated by 8996) | implemented and credited (server_common auth) | done |
| RFC 8314 | TLS before credentials (base, updated by 8997) | implemented and credited | done |
- RFC 7817 — adopted in wave-set #48 lane A, as the recommended
citation pass: the audit found the behavior already satisfied where it
applies, and no behavior changed. The only email-protocol TLS client in
this repo is the outbound SMTP path — there is no IMAP or POP client — so
7817’s 2595-side duties bind third-party clients, not these servers.
Audited evidence (unchanged by adoption):
TlsVerify::Strict(smarthost and MTA-STS enforce) hands the MX or smarthost hostname to rustls and verifies via rustls-webpki, which matches DNS-ID SANs only, supports single-label wildcards, and has no CN fallback at all — a strict subset of what 7817 permits, satisfying its MUSTs.TlsVerify::Permissiveis opportunistic RFC 7435 (identity checking out of scope by design), andTlsVerify::Danereplaces the identity check per RFC 7672 §3.1.1, which post-dates 7817 and governs its own case. What landed: the RFC 7817 citation athandshake()(mail_spooler/src/smtp_out.rs), recording that underStrictthe verified name is the MX target or configured smarthost, never the recipient domain; and the credit row in standards.md’s transport-hardening table. - RFC 8996 / 8997 — adopted in wave-set #48 lane A, as the recommended
verify-and-fence pass; nothing was implemented. The audited base fact
stands: the three production rustls builder sites all call
with_safe_default_protocol_versions()— the two shared acceptors inserver_common/src/tls.rsand the outboundconnector()inmail_spooler/src/smtp_out.rs(the repo’s fourth builder is a#[cfg(test)]loopback helper) — and rustls has never shipped TLS ≤ 1.1, so no acceptor or connector can negotiate the deprecated versions. What landed: the fencesafe_default_versions_enforce_the_tls12_floornow rides both choke points (server_common/src/tls.rstests for the acceptors, A-P1;mail_spooler/src/smtp_out.rstests for the connector, A-P2), pinning rustlsDEFAULT_VERSIONSto exactly {TLS 1.3, TLS 1.2};server_common’slib.rsRFC block gained the 8996/8997 lines; and the docs credits ride standards.md plus the conformance appendix’s version-floor note. The recorded residual is closed too: the MTA-STS policy fetcher (HttpsPolicyFetcher::production_builder,mail_spooler/src/mta_sts.rs) and the TLS-RPT submitter (TlsRptReportWorker::new,mail_spooler/src/pipeline/tlsrpt_report.rs) now pin the rustls backend via.tls_backend_rustls()— reqwest 0.13.4’s current name foruse_rustls_tls— so the 8996/8997 floor at those two sites is asserted in code rather than inherited from reqwest’sdefault-tls = ["rustls"]feature defaults plus the lockfile; the MTA-STS real-HTTPS smoke tests exercise the pinned builder. That closes decision-inventory entry 6 as option (a) — see below. - RFC 4616 and RFC 8314 — done as bases (SASL PLAIN in
server_common::auth; the TLS-before-credentials gates and their per-protocol cites in the conformance appendix); their respective updaters 8996/8997 are the rows above.
Cluster 4 — DSN / MDN (bases: RFC 3461, 3464, 6522)
Owning surfaces: envelope DSN parameters in smtp_session
(RET/ENVID in session/ready.rs, NOTIFY/ORCPT in
session/mail_txn.rs); DSN generation in mail_spooler/src/pipeline/dsn.rs
(the RFC 3464 worker) fed by the relay (pipeline/relay.rs); the
multipart/report container built via the adopted mail-builder
(dsn.rs:220).
All five verdicts below are recorded (wave-set #50 lane C, decision-recording only — nothing was implemented): every row closes as declined, deferred, or done, so no adopting wave will ever own this cluster. Per the recording’s convention call, declined RFCs get no standards.md rows — this page is the record.
The RFC 6533 deferral is now itself a recorded decision (wave-set #51 lane C): the EAI program is deferred with criteria — parked until a concrete demand signal (an operator or user needing non-ASCII addresses, or interop with an EAI sender); no implementation now. Decision-inventory entry 7 is the governing record for this row and its four sibling rows in clusters 5, 6, 8, and 10.
| Update | What it is | Audited status | Verdict |
|---|---|---|---|
| RFC 8098 | Message Disposition Notifications (obsoletes 3798) | absent everywhere | declined (wave-set #50 lane C) |
| RFC 3885 | MTRK ESMTP extension | absent; structurally refused | declined (with 3886; wave-set #50 lane C) |
| RFC 6533 | internationalized DSN/MDN (via 5337 → 6533) | absent, and out of scope while SMTPUTF8 is off | deferred (EAI) (wave-set #50 lane C) |
| RFC 4865 | FUTURERELEASE’s DSN-side updates to 3464 | falls with the extension | declined (falls with cluster 2, settled there) |
| RFC 6522 | multipart/report (base, updated by 6533) | implemented and credited | done |
- RFC 8098 (MDN). Fully absent, and confirmed absent at every layer:
repo-wide grep for
Disposition-Notification(Rust and webclients) — zero hits; the vendoredmail-parser0.11.5 andmail-builder0.4.4 have no MDN-specific types either (method: grep the vendored sources; the generic MIME builder could of course construct one). Declined at the server layer (wave-set #50 lane C), exactly as recommended — an MDN is generated by the recipient’s mail client on display, never by the MTA, so the server-side stack has no conformant role to add; if read receipts are ever wanted they are a webmail/client feature with real privacy trade-offs, to be decided there. The decline is reinforced by the workspace’s standing “inbound DSN/MDN processing — dropped (no surviving consumer)” record in HANDOFF.md’s deliberate design choices: the stack already deliberately retired the inbound half of the same MDN/DSN surface, so generating what it will never consume would be a one-armed feature. - RFC 3885 (MTRK) — declined (wave-set #50 lane C). Same audited
status and verdict as its 3886 companion in cluster 2: parsed by
smtp-proto, refused555 5.5.4atready.rs:300-302, never advertised — and the cluster-2 rationale carries here unchanged (the MTRK family saw effectively no real-world deployment, and on-chain message accounts already give senders a stronger delivery record). - RFC 6533 (internationalized DSN). The DSN worker emits the ASCII forms
exclusively:
message/delivery-status(dsn.rs:223) andOriginal-Recipient: rfc822; …(dsn.rs:282) — nevermessage/global-delivery-statusor theutf-8;address types (method: grepdsn.rsforglobal/utf8; readrenderand the per-recipient status block). But this is not a gap today, because no UTF-8 envelope can reach the spool: SMTPUTF8 is deliberately disabled — the driver pinssmtputf8: false(smtp_server/src/driver.rs:168) and the session refuses theSMTPUTF8MAIL parameter with555 5.5.4(ready.rs:291-293). Deferred behind the EAI program (wave-set #50 lane C) — 6533 only becomes implementable (or needed) if the stack adopts RFC 6530–6533 internationalized email wholesale; it rides that decision together with cluster 10’s 6532 row and cluster 5’s 8616 row, never alone. - RFC 4865 — declined (falls with cluster 2, where the FUTURERELEASE extension itself was declined and the decision settled): scheduled send stays out of the SMTP queue, so 4865’s DSN-wording updates to 3464 have nothing to attach to. The cluster-2 row carries the rationale; this row records only that the DSN side falls with it.
- RFC 6522 — done as a base (
multipart/reportwraps both DSN and ARF reports; standards.md row); its updater 6533 is the row above.
Cluster 5 — SPF (RFC 7208)
Owning surfaces: SPF evaluation is fully delegated to the adopted mail-auth
0.11.1 (verify_spf, vendored spf/verify.rs:33, TXT lookup at
spf/verify.rs:112), called from smtp_server/src/policy.rs — the v1 Spf
policy (check_envelope, policy.rs:352-368) and the DMARC-family policies
(policy.rs:447, policy.rs:604). Coverage assertion:
standards.md’s RFC 7208 row.
As planned, this cluster’s wave shape is verify the dependency and fence.
The one adoptable row below landed (wave-set #50 lane B): RFC 7372 is cited and fenced at its
5.7.23emission site, exactly as recommended. The 8553 decline (genuinely nothing to do) and the 8616 EAI deferral stand as recorded, so nothing in this cluster remains open.
The RFC 8616 deferral is now itself a recorded decision (wave-set #51 lane C): the EAI program is deferred with criteria — parked until a concrete demand signal (an operator or user needing non-ASCII addresses, or interop with an EAI sender); no implementation now. Decision-inventory entry 7 is the governing record.
The
5.7.26deferred candidate is now taken (wave-set #51 lane A): the DMARC bounce is re-coded from the conventional550 5.7.1to554 5.7.26, the “multiple authentication checks failed” code RFC 7372 §3.3 registers for a DMARC rejection — following the in-repo precise-code idiom the5.7.23SPF-hardfail reply set. The reply still names the offending From domain.
| Update | What it is | Audited status | Verdict |
|---|---|---|---|
| RFC 7372 | email-auth enhanced status codes | the one code with an emission path was already emitted; now cited and fenced | adopted (wave-set #50 lane B; DMARC bounce re-coded to 5.7.26, wave-set #51 lane A) |
| RFC 8553 | DNS AttrLeaf (underscored node names) | no SPF-side code surface | decline (nothing to do) |
| RFC 8616 | email auth for internationalized mail | absent in mail-auth; out of scope while SMTPUTF8 is off | defer (EAI) |
- RFC 7372 — adopted in wave-set #50 lane B, as the recommended
citation/fence pass; no behavior changed. The audited base fact stands:
the SPF hardfail rejection already used 7372 §3.2’s code —
554 5.7.23 SPF validation failed…— and the remaining 7372 codes have no emission site by policy design, not by omission: SPF temperror/permerror never reject — they land inAuthentication-Resultsinstead (the deliberate-softness comment atpolicy.rs:357-359); DKIM failures never reject standalone in anySenderAuthmode (smtp_server/src/config.rs:274-286); and the DMARC bounce then used the conventional550 5.7.1naming the offending From domain (dmarc_reject_reply), which that pass did not disturb. Method: greppolicy.rs/driver.rsforReply::enhancedand read the two reply sites. What landed: the rejection site became the free helperspf_hardfail_rejection(smtp_server/src/policy.rs) carrying the in-code §3.2 cite, fenced bypublished_spf_hardfail_rejects_with_5_7_23(a publishedv=spf1 -allover the offline resolver must reject 554 with enhanced status5.7.23, plus the softfail pass-through half); the credit rides the standards.md RFC 7208 row and the conformance appendix, andsmtp_server’slib.rsRFC block cites 7372. Re-coding the DMARC bounce as5.7.26“multiple authentication checks failed” was considered and initially not taken (5.7.1being the widely-recognized convention) — recorded as a deferred candidate, and since taken (wave-set #51 lane A):dmarc_reject_replynow emits554 5.7.26with the in-code §3.3 cite, still carrying the actionable domain name. - RFC 8553. The AttrLeaf BCP standardizes the global underscored-name
registry. SPF’s record lives at the bare domain —
mail-authqueries TXT at the domain itself (spf/verify.rs:112) — so no underscored node name is involved anywhere in this repo’s SPF path (method: read the lookup path in the vendored source). The underscored names the stack does use (_mta-sts,_smtp._tls,_dmarc,_domainkey,_25._tcp,_solana.authority) are already the registry forms and belong to other features’ surfaces. Recommendation: decline for this cluster — genuinely nothing to change or even cite; revisit only in cluster 6, where 8553 appears again on the DKIM side. - RFC 8616. Absent in the dependency:
mail-auth0.11.1 performs no U-label→A-label conversion — noidnadependency in itsCargo.toml, and noidna/punycode/u_labelhits anywhere in its source (method: grep the vendored crate) — so an internationalized domain would go to DNS unconverted. As with 6533, this cannot bite today: SMTPUTF8 is disabled (driver.rs:168), so no EAI identity ever reaches the verifiers. Recommendation: defer (EAI) — and note that if EAI is ever adopted, 8616 becomes an upstreammail-authquestion first (the same verify-the-dependency shape as this cluster), not repo code.
Cluster 6 — DKIM (RFC 6376)
Owning surfaces: signing in mail_submit/src/dkim.rs — rsa-sha256 with
relaxed/relaxed canonicalization, the signer type pinned to
DkimSigner<RsaKey<Sha256>, …> (dkim.rs:16, dkim.rs:39), one signer per
sending domain, signing once at spool entry; verification fully delegated to
the adopted mail-auth 0.11.1 (verify_dkim) from smtp_server/src/policy.rs
(policy.rs:385, policy.rs:474, policy.rs:629), where a DKIM failure
never rejects standalone in any SenderAuth mode
(smtp_server/src/config.rs:274-286). Coverage assertion:
standards.md’s RFC 6376 row. As planned, the wave
shape is verify the dependency and fence.
Both adoptable rows below landed (wave-set #50 lane B): 8301’s verify-side gap is closed by a repo post-filter, and 8463 is verified and optionally dual-signed — the owning-surfaces snapshot above predates the landing (the signer now also holds an optional
Ed25519Key, and everyverify_dkimresult is post-filtered); the rows and bullets record the current state. The 8553 decline (nothing to do) and the 8616 EAI deferral stand as recorded, so nothing in this cluster remains open.
The RFC 8616 deferral is now itself a recorded decision (wave-set #51 lane C), identically to the cluster-5 note: the EAI program is deferred with criteria — parked until a concrete demand signal (an operator or user needing non-ASCII addresses, or interop with an EAI sender); no implementation now. Decision-inventory entry 7 is the governing record.
| Update | What it is | Audited status | Verdict |
|---|---|---|---|
| RFC 8301 | SHA-1 deprecation, RSA key-size floors | signing side conformant by construction; the verify-side gap is now closed by a repo post-filter | adopted (wave-set #50 lane B) |
| RFC 8463 | Ed25519-SHA256 signatures | verify side fenced; signing side now opt-in dual-signing, default off | adopted (wave-set #50 lane B) |
| RFC 8553 | DNS AttrLeaf (underscored node names) | already the registry forms | decline (nothing to do) |
| RFC 8616 | email auth for internationalized mail | absent in mail-auth; out of scope while SMTPUTF8 is off | defer (EAI) |
- RFC 8301 — adopted in wave-set #50 lane B, going one step past the
recommended citation/fence: the decision-inventory question the audit
raised was answered as option (a), so the verify side gained a small
implementation too. The audited base facts stand: the signing side
conforms by construction — the mandatory signer is
RsaKey<Sha256>(mail_submit/src/dkim.rs), so norsa-sha1signature can ever be emitted (8301 §3.1’s signer MUST); the key-size floors are operational (operator-supplied PEM; the test fixture is 2048-bit, matching §3.2’s SHOULD); andmail-auth0.11.1 still parses (dkim/parse.rs:221) and verifiesrsa-sha1— under the repo’sringfeature viaRSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY(common/crypto/ring_impls.rs:266,ring_impls.rs:284), whose1024_8192range does enforce §3.2’s 1024-bit verifier floor. Method: read the vendored parse/verify/crypto paths; grepSha1acrossmail-authand the repo. What landed: the post-filterdowngrade_rsa_sha1(smtp_server/src/policy.rs) runs immediately after everyverify_dkimcall in all three sender policies, rewriting a verifiedrsa-sha1pass into a failure before the outputs feedAuthentication-Resultsor DMARC alignment (signature evidence kept so reporting still names the signing domain); fenced both ways, including the deliberate assert thatmail-authstill verifiesrsa-sha1— a future dependency bump that stops doing so reddens it, the signal the filter and fences can retire. The 8301 cite rides the signer’s module doc,smtp_server’slib.rs, the standards.md RFC 6376 row, and the conformance appendix. Decision-inventory entry 3 below records the answer. - RFC 8463 — adopted in wave-set #50 lane B, both halves: the verify
side as the recommended citation/fence, the signing side as the
decision-inventory question answered as option (a) — opt-in
dual-signing. The audited base facts stand:
mail-authparsesa=ed25519-sha256(dkim/parse.rs:230) andk=ed25519key records (dkim/parse.rs:273), verifies via ring’s Ed25519 public key type (Ed25519PublicKey,ring_impls.rs:299-313), and can sign (dkim/sign.rs:106). Method: grepEd25519across the vendored crate; readDkim::from_key_pem. What landed: the verify fencean_ed25519_sha256_signature_verifies_to_pass(smtp_server/src/policy.rs) live-signs with the RFC 8463 appendix-A test keypair (= RFC 8032 §7.1’s TEST 1 vectors), publishes thek=ed25519record shape (p=is the raw 32-byte key base64, not DER SPKI), and pins the pass toEd25519Sha256; and[spooler.dkim]entries gained the optionaled25519_selector+ed25519_key_filepair (both-or-neither, validated at load; default off = rsa-only unchanged), emitting a second ed25519-sha256DKIM-Signatureover the same headers alongside the rsa one — RSA-only verifiers simply keep honoring the RSA signature. Credits ride the standards.md RFC 6376 row, the conformance appendix, and the configuration reference. Decision-inventory entry 4 below records the answer. - RFC 8553. Same shape as the cluster-5 row: DKIM’s lookup names are
already the registered AttrLeaf forms, and they live in the dependency —
mail-authqueries{selector}._domainkey.{domain}(dkim/verify.rs:105) and_report._domainkey.{d}for reporting (dkim/verify.rs:204). No repo code hand-rolls the names. Recommendation: decline — nothing to change or cite; this reconciles with cluster 5’s identical verdict, closing the 8553 overlap. - RFC 8616. Identical evidence to the cluster-5 row, which audited the
same dependency:
mail-auth0.11.1 has noidnadependency and performs no U-label→A-label conversion anywhere, and SMTPUTF8 is disabled (driver.rs:168) so no EAI identity reaches the DKIM verifier either. Recommendation: defer (EAI) — decided with the whole EAI family, never alone.
Cluster 7 — ARF (bases: RFC 5965, 6591)
Owning surfaces: generation only. The DMARC forensic (RUF) path builds one
RFC 6591 auth-failure ARF report per DMARC failure —
build_forensic_report (mail_spooler/src/pipeline/dmarc_forensic.rs:56)
over mail_auth::report::Feedback, serialized by the dependency’s
to_rfc5322 into the RFC 6522 multipart/report container. There is no
ARF ingestion path: nothing in the repo calls Feedback::parse (the
aggregate-report ingester, adapters/dmarc_rua.rs, consumes DMARC XML, not
ARF). Coverage assertions: standards.md’s RFC 5965 and 6591
rows.
| Update | What it is | Audited status | Verdict |
|---|---|---|---|
| RFC 6650 | ARF applicability statement (when reports may be sent) | satisfied by construction — the only generation path is solicited-by-publication; now cited and credited | adopted (wave-set #49 lane B) |
| RFC 6692 | Source-Port report field | implemented — the peer port now threads from the driver seam into with_source_port | adopted (wave-set #49 lane B) |
| RFC 9991 | DMARC failure reporting (updates 6591) | adopted at #44/#45 (DMARCbis) | done |
- RFC 6650 — adopted in wave-set #49 lane B, as the recommended
citation/fence. Its core normative addition to 5965 is consent: feedback
reports go only where the receiving party has asked for them. The repo’s
single generation path satisfies that by construction —
ruf=targets are addresses the policy domain itself published, and out-of-domain targets additionally pass the RFC 9991 §5 external-destination gate (authorized_report_uris,dmarc_forensic.rs:133) before any report is sent. No abuse-type feedback loop exists to regulate, and no reports are received. Method: read the forensic module’s gate; grep for otherFeedbackTypeconstruction sites (there are none). The credit now rides the standards.md RFC 6591 row and the conformance appendix, and the forensic module doc names 6650 as the applicability statement governing theauth-failureARF usage — no behavior change. - RFC 6692 — adopted in wave-set #49 lane B, as the recommended small
implementation. It registers the optional
Source-Portfield so auth-failure reports can attribute a connection behind carrier-grade NAT. The dependency was ready:Feedback.source_portexists (vendoredreport/mod.rs:338),with_source_portsets it (report/arf/mod.rs:202), and the ARF serializer emits it whenever it is nonzero (report/arf/generate.rs:228-229). The missing seam is now threaded: the driver captures the peer’s TCP source port inSenderContext(peer_port,smtp_server/src/driver.rs:606), the forensic datum carries it (DmarcForensicInput::source_port,smtp_server/src/policy.rs:261), andbuild_forensic_reporthands it towith_source_port. Skip-when-zero is deliberate and fenced (zero_source_port_omits_the_field): an input that never learned the port omits the field entirely rather than reporting a fakeSource-Port: 0. The disclosure question was surfaced at the wave’s planning and answered — always emit when known, deliberately no config switch (decision-inventory entry 5 below):Source-IPis already unconditionally disclosed in the same report, so the port adds no new disclosure class. - RFC 9991 — done. Adopted by the DMARCbis waves (#44/#45): the
forensic path is already 9991-shaped —
Identity-Alignment, headers-only content minimization per §7.1, and the §5 external-destination gate (module doc,dmarc_forensic.rs:1-30). The row records the fact; nothing is open.
Cluster 8 — IMAP (bases: RFC 3501, 2342)
Owning surfaces: protocol semantics in imap_session over the adopted
imap-types 2.0.0-alpha.7 AST (the repo enables its starttls,
ext_namespace, and — since wave-set #49 lane A — ext_condstore_qresync
features, workspace Cargo.toml:124), driven by imap_server over the
adopted imap-next 0.3.4 flow layer. The crate’s own RFC block and
deliberate-deferral list live in imap_session/src/lib.rs — IMAP4rev2
(RFC 9051) is deliberately not advertised there, with the rev2 mandatory
baseline (ESEARCH, LIST-EXTENDED) and, since the CONDSTORE landing, the
QRESYNC half of RFC 7162 listed as deferred. Every update row below
therefore starts with an imap-types support check, per the planning note.
Recorded gap — closed in wave-set #48 lane B:
imap_server/src/lib.rsnow carries the “RFCs implemented” block its two sibling drivers already had (pop_server/src/lib.rs:7,smtp_server/src/lib.rs:7). Rather than duplicating the session crate’s RFC list (imap_session/src/lib.rs:10, which exists and is accurate), the driver’s block points at it and credits the driver layer’s own obligations: imap-next wire framing, implicit TLS/STARTTLS overserver_common, SASL execution, storage effects.
The RFC 5738 and 6858 deferrals are now themselves a recorded decision (wave-set #51 lane C): the EAI program is deferred with criteria — parked until a concrete demand signal (an operator or user needing non-ASCII addresses, or interop with an EAI sender); no implementation now. The ready-made
ext_utf8types stay ready, not used. Decision-inventory entry 7 is the governing record.
| Update | What it is | imap-types 2.0.0-alpha.7 support | Audited status | Verdict |
|---|---|---|---|---|
| RFC 4466 | collected extension ABNF | modeled implicitly (e.g. Capability::Other) | grammar infrastructure; no standalone behavior | decline (nothing to do) |
| RFC 4469 | CATENATE | absent (zero hits) | fork-blocked; pairs with declined BURL | decline (final) (wave-set #48 lane B) |
| RFC 4551 | CONDSTORE (obsoleted by 7162) | present behind ext_condstore_qresync (now enabled) | implemented at its RFC 7162 target — CONDSTORE in full, mod-sequences on every store backend; the QRESYNC half stays queued | adopted: CONDSTORE (wave-set #49 lane A; QRESYNC queued) |
| RFC 5032 | SEARCH WITHIN (OLDER/YOUNGER) | absent (no such search keys) | fork-blocked, marginal value | decline (final) (wave-set #48 lane B) |
| RFC 5182 | SEARCHRES (saved search results) | absent (no ESEARCH at all — prerequisite RFC 4731 missing) | fork-blocked; rev2-baseline adjacent | decline (falls with the answered strategy — see below) |
| RFC 5738 | UTF8= (obsoleted by 6855) | present behind ext_utf8 (Utf8Kind::{Accept,Only} — the 6855 shape) | EAI | defer (EAI) |
| RFC 6186 | SRV service discovery | n/a — no protocol surface | operator side already documented; client side superseded by the signed DHT records | decline (answered as superseded, both halves — wave-set #48) |
| RFC 6858 | EAI message downgrading | absent | EAI | defer (EAI) |
| RFC 7817 | TLS server identity check | n/a | covered by the landed cluster-3 adoption | adopted (cluster 3, wave-set #48 lane A) |
| RFC 8314 | TLS before credentials | n/a | implemented and credited (imap_session/src/lib.rs:20-21) | done |
| RFC 8437 | UNAUTHENTICATE | absent (zero hits) | fork-blocked, niche | decline (final) (wave-set #48 lane B) |
| RFC 8474 | OBJECTID (MAILBOXID/EMAILID/THREADID) | absent (zero hits) | fork-blocked; modern-sync bundle | decline (final) (wave-set #48 lane B) |
| RFC 8996 | deprecates TLS 1.0/1.1 | n/a | covered by the landed cluster-3 adoption (shared acceptors) | adopted (cluster 3, wave-set #48 lane A) |
Method for the support column: grep the vendored imap-types source for the
extension’s identifiers (Older/Younger, Catenate, UNAUTHENTICATE,
ObjectId/MAILBOXID, ESEARCH, rev2/9051) — each “absent” above is a
zero-hit result, 2026-08-05 — and read the Capability enum
(response.rs:1058) plus the extensions/ module list and feature table
(vendored Cargo.toml:55-66).
- RFC 4466 (and 2342 ← 4466). Pure ABNF infrastructure — it defines the
extension grammar other RFCs reuse and changes no protocol behavior by
itself; its 2342 update is the same story on the NAMESPACE grammar.
imap-typesmodels extensibility structurally (unknown capabilities viaCapability::Other,response.rs:1121). Recommendation: decline — nothing to do; 4466 is “adopted” only ever through the extensions built on it. - RFC 4469 (CATENATE) — declined, final (wave-set #48 lane B). No types
in
imap-types— the same fork-blocked bucket as URLAUTH (cluster 2’s BURL row); and CATENATE’s purpose (compose from existing message parts without re-upload) is the BURL use case this stack already declined in favor of the account API compose endpoint. With the strategic question answered as piecemeal, the session #10 decision not to forkimap-typesis final; the decline is recorded in-crate inimap_session’s new “Declined (final)” scope-doc section alongside 5032/8437/8474. - RFC 4551 (CONDSTORE) — the queued wave landed its CONDSTORE half:
adopted in wave-set #49 lane A, at the RFC 7162 target the answered
strategy chose (piecemeal — decision-inventory entry 1, wave-set #48
lane B; 7162 obsoletes the inventory’s 4551). What landed: the
imap-typesext_condstore_qresyncfeature flip, the fullimap_session/imap_serverCONDSTORE surface (auth-gated capability, ENABLE,SELECT/EXAMINE (CONDSTORE),HIGHESTMODSEQ/NOMODSEQon select, STATUS, SEARCH MODSEQ, the MODSEQ fetch item + CHANGEDSINCE, STORE UNCHANGEDSINCE withMODIFIED), and real mod-sequence state — per-mailbox highest-mod-sequence plus per-message mod-sequences on all sixmail_storebackends (sqlite migration 0013, postgres 0011), production mailboxes always tracked soNOMODSEQnever appears in production. Coverage assertions moved together per the #48 rule: standards.md’s new RFC 7162 row (and the 9051 row’s note), the conformance appendix, andimap_session/src/lib.rs’s RFC block. Two residuals stay open: QRESYNC is still queued as its own follow-up wave (behind an upstream maturity probe of the imap-types QRESYNC grammar; its parameters are refused BAD today), and a confirmed upstream imap-codec defect — 2.0.0-alpha.9 serializes the FETCH data itemMODSEQ 4where 7162’sfetch-mod-resprequiresMODSEQ (4); the typed emission is correct, and an upstream fix or pin bump is queued before client-conformance testing (recorded in the conformance appendix). - RFC 5032 / 8437 / 8474 — declined, final (wave-set #48 lane B). All
fork-blocked on
imap-types(zero hits each): 5032 (SEARCH OLDER/YOUNGER) is marginal, 8437 (UNAUTHENTICATE, connection reuse for proxies) is niche, 8474 (OBJECTID) is the JMAP-era resync feature set. With the strategy answered as piecemeal, the session #10 fork decline is final for all three — recorded inimap_session’s “Declined (final)” section with 4469. RFC 5182 falls with the same answer without joining the final list: it needs ESEARCH (RFC 4731), absent entirely and part of the rev2 mandatory baselineimap_sessiondefers, so under piecemeal it stays out — but it is rev2-baseline machinery rather than a standalone extension, so it would return only inside a future 9051 program (a new decision, were one ever opened), never by reopening this one. - RFC 5738 / 6858. Both EAI: 5738 (obsoleted by RFC 6855) is UTF-8
mailbox/header support, 6858 is the downgrade path for legacy clients.
imap-typesalready carries the 6855-shaped types behindext_utf8(Utf8Kind::{Accept,Only},extensions/utf8.rs:17-20) — useful when the EAI program runs, irrelevant before. Recommendation: defer (EAI), decided with the whole family (clusters 4, 5, 6, 10). - RFC 6186 — the IMAP half of the shared decision is answered: declined
as superseded (wave-set #48 lane B; the POP3 half landed in lane C of
this same wave-set). The record mirrors cluster 9’s: the operator half
stands as adopted — the
DNS setup SRV section
publishes
_imaps/_imapguidance with the RFC 8314 implicit-TLS variants preferred, and third-party mail clients remain served by those published records. But SithBit’s own tooling will not consult SRV for IMAP: thenode_certsigned DHT service records (surfaced assithbit discover) are signed and wallet-anchored, which plain SRV can never be, so SithBit-native clients trust only them. With both halves recorded, decision-inventory entry 2 below is answered. - RFC 7817 / 8996 — adopted via cluster 3 (wave-set #48 lane A). The
acceptors all three servers ride are shared (
server_common/src/tls.rs), so the landed cluster-3 evidence and fences cover the IMAP surface wholesale: the standards.md transport-hardening table’s 7817/8996/8997 rows explicitly speak for every acceptor and connector, which is why the IMAP per-protocol table carries no duplicate rows — neither do the SMTP or POP3 tables. 7817’s identity-check duties on the 2595/3501 side bind third-party clients, not these servers (the stack’s only email TLS client is outbound SMTP). Cite the cluster-3 record; never re-audit.
Cluster 9 — POP3 (bases: RFC 1939, 2449)
Owning surfaces: the hand-rolled pop3_proto typestate machine (the one
protocol core not riding an adopted grammar crate), driven by pop_server.
Its RFC block (pop3_proto/src/lib.rs:8-16) credits 1939, 2449, 2595, 5034,
3206, and — notably for the EAI family — RFC 6856 (POP3 UTF-8 support,
UTF8/LANG), which is not in this cluster’s update graph (6856 is not an
official 1939 updater) but means the POP3 surface is already EAI-positioned
ahead of every other protocol in the stack.
| Update | What it is | Audited status | Verdict |
|---|---|---|---|
| RFC 1957 | 1939 implementation notes | already implemented, previously uncredited and unfenced | adopted (wave-set #48 lane C) |
| RFC 2449 | POP3 extension mechanism (CAPA) | implemented and credited | done |
| RFC 6186 | SRV service discovery | operator side already documented; client side superseded by the signed DHT records | decline (POP3 half answered, wave-set #48 lane C) |
| RFC 8314 | TLS before credentials | implemented and credited (implicit TLS primary; cluster-3 evidence) | done |
| RFC 5034 | POP3 SASL AUTH (updates 2449) | implemented and credited | done |
- RFC 1957 — adopted in wave-set #48 lane C, as a citation/fence pass
rather than an implementation: the behavior was found already present but
uncredited. Of its two short implementation notes on 1939 — clients poll
too aggressively (a client-side scold with no server duty), and the
actionable half, that real clients depend on the optional UIDL command so
servers should provide it —
pop3_protoalready did the latter:Command::Uidl(command.rs:95-96, both list and per-message forms), theUIDLCAPA tag (capability.rs:23-24), and the maildrop’s per-message UID scan (uidl_all,maildrop.rs:74). What landed: the 1957 credit line inpop3_proto’s RFC block (lib.rs), the standards.md POP3 table row, and the fence testuidl_for_one_message_follows_rfc_vector(session/tests.rs) asserting RFC 1939’s own UIDL example on the per-message success path (transaction.rs::uidl_one) — which the adopting wave’s scout found had no test in either POP crate. No behavior changes. - RFC 2449 / 5034 / 8314 — done. All three credited in the crate’s RFC
block (
lib.rs:8-16) and implemented: CAPA with limits and response codes, the SASLAUTHexchange (mechanisms inserver_common::auth), and the TLS-before-credentials posture whose acceptor-level evidence is cluster 3’s (sharedserver_commonacceptors; implicit TLS on 995 primary,STLSsecondary). - RFC 6186 — the POP3 half of the shared decision is answered: declined
as superseded (wave-set #48 lane C). The operator half stands as
adopted — the
DNS setup SRV section
publishes
_pop3s/_pop3guidance with 8314 preference, and third-party mail clients remain served by those published records. But SithBit’s own tooling will not consult SRV for POP3: thenode_certsigned DHT service records (surfaced assithbit discover) are signed and wallet-anchored, which plain SRV can never be, so SithBit-native clients trust only them. The decision-inventory entry below spans both protocols and was marked answered when cluster 8’s docs phase recorded the IMAP half — lane B of this same wave-set.
Cluster 10 — Message format / MIME (bases: RFC 5322, 2045, 2047)
Owning surfaces: parsing and generation are fully delegated to the adopted
mail-parser 0.11.5 and mail-builder 0.4.4, re-exported through
mail_message (its scope doc, mail_message/src/lib.rs:8-10, records the
division). Coverage assertions: the four MIME rows in
standards.md. As planned, the wave shape is verify the
libraries.
The RFC 6532 deferral is now itself a recorded decision (wave-set #51 lane C): the EAI program is deferred with criteria — parked until a concrete demand signal (an operator or user needing non-ASCII addresses, or interop with an EAI sender); no implementation now. Decision-inventory entry 7 is the governing record.
| Update | What it is | Audited status | Verdict |
|---|---|---|---|
| RFC 6854 | group syntax allowed in From:/Sender: | parse side present; generation side conformant by never emitting groups; credit landed | adopted (wave-set #48 lane A; DMARC-edge fence pinned in wave-set #49 lane B) |
| RFC 2231 | MIME parameter continuations + charset (via 2184; updates 2045/2047/2183) | decode done; encode side diverges in mail-builder with no repo emission path | done (with residual recorded) |
| RFC 6532 | internationalized headers (via 5335 → 6532) | parse-side support claimed by mail-parser; adoption is the EAI program | defer (EAI) |
- RFC 6854. Its parser-side duty (accept group syntax where 5322 only
allowed mailbox lists) is met by the dependency:
mail-parsermodels groups first-class (Group, vendoredlib.rs:183;HeaderValue::Group,lib.rs:309-310). Its generator-side duty is a restriction — group syntax inFrom:is reserved for limited cases (e.g. MDN-suppressing notifications) — and the repo conforms by construction: no call site usesmail-builder’s group support (Address::new_group, vendoredheaders/address.rs:48— repo-wide grep fornew_group: zero hits), so every generatedFrom:(DSNs, DMARC reports, submissions) is a singleton mailbox. Adopted in wave-set #48 lane A: the credit rides the standards.md 5322 row as recommended. The residual closed in wave-set #49 lane B — a fence pinned the behavioral edge the audit recorded as current behavior: an empty-groupFrom:(undisclosed-recipients:;) yields no RFC5322.From domain, so DMARC evaluation collapses to the default output and the message reaches the Inbox even against a publishedp=reject. The hardening question that fence left open was then answered in wave-set #50 lane B, from RFC 9989’s own guidance (DMARCbis — RFC 9989 obsoletes 7489/9091; 9990 is aggregate reporting, 9991 failure reporting): §5.3.1 terminates DMARC without a verdict on zero or multiple extracted From domains, its MAY for the multi-domain case deliberately not taken, and §4.4 places such non-compliant From fields outside the spec’s scope — so the edge is now an explicit disposition, not an incidental bypass. The fence was renamedgroup_from_terminates_dmarc_without_verdictand gained a multi-differing-From sibling; the conformance appendix records the disposition. - RFC 2231 — done, with one refinement to the claims snapshot. The
decode half is genuinely done:
mail-parserimplements the full parameter-continuation machinery (theContinuationaccumulator and reassembly inparsers/fields/content_type.rs:25-45andcontent_type.rs:160-205), covering split, charset-tagged, and language-tagged parameters. The encode half diverges:mail-builderwrites non-ASCII parameter values as RFC 2047 encoded-words inside the parameter (rfc2047_encodeatheaders/content_type.rs:69) — the widespread de-facto compatibility convention, not 2231*=continuations. That divergence has no repo emission path today: generated messages (DSNs, ARF, aggregate reports) carry only ASCII parameters, and submission relays user bytes untouched. Method: grep2231/continuationin both vendored crates; read the builder’s parameter writer. Recommendation: keep done; record the encode-side residual so an EAI or attachment-features wave knowsmail-builderneeds upstream work (or post-processing) before emitting non-ASCII filenames. - RFC 6532.
mail-parserclaims 6532 conformance for parsing (vendoredREADME.md:214— UTF-8 header tolerance is native to its design), but adopting internationalized headers end-to-end is the EAI program: SMTPUTF8 is off (driver.rs:168), so no 6532 message can enter the system, and the generation, storage, and auth surfaces (clusters 4, 5, 6) all gate on the same decision. Recommendation: defer (EAI) — the cluster-4 rule binds here too: the EAI family (6530–6533, 8616, 6855/6858, and SMTPUTF8 itself) is one program, decided once.
Cross-cluster overlaps and wave-shaping notes
This page exists so no update is half-adopted from one cluster’s vantage point. The overlaps to plan around:
- 8553 + 8616 appear in both SPF (cluster 5) and DKIM (cluster 6) —
now closed: both clusters audited to the same verdicts on the same
evidence (8553: the underscored names are already the registry forms,
inside
mail-authon the DKIM side; 8616:mail-authhas no idna and SMTPUTF8 is off). No reconciliation left to do. - 7817 + 8314 + 8996/8997 cut across SMTP-TLS (cluster 3), IMAP
(cluster 8), and POP3 (cluster 9): the cluster-3 evidence (rustls choke
points, webpki identity checks) covers all three servers because the
acceptors are shared in
server_common, and the cluster-8/9 rows now cite it rather than re-audit — any citing wave should keep that shape. - The EAI family is one program, decided once — and the decision is
recorded: deferred with criteria (wave-set #51 lane C;
decision-inventory entry 7). Its rows span five clusters: 6533
(DSN, cluster 4), 8616 (SPF cluster 5 and DKIM cluster 6),
5738/6855 + 6858 (IMAP, cluster 8), 6532 (MIME, cluster 10),
plus SMTPUTF8 itself (the structural gate at
driver.rs:168). Two ready-made pieces to reuse if it ever runs:imap-typesalready ships the 6855-shapedext_utf8types, andpop3_protoalready implements RFC 6856 (POP3 UTF-8) — the POP3 surface is EAI-positioned before the rest of the stack. - 4466 spans both IMAP bases (3501 and 2342) — audited once in cluster 8 (decline, grammar infrastructure). 6186 appears in both IMAP and POP3 and is one decision, not two: its operator half is already adopted (the docs SRV section), and its client half — the shared decision-inventory entry — is answered in wave-set #48 (declined as superseded, both halves recorded).
- Lane scheduling — cluster pairs that can never run concurrently
(write-footprint overlaps, from #47 planning plus this page’s audits):
- Email TLS (3) × SMTP core (1) on
smtp_session/src/lib.rs+mail_spooler— the known pair from planning. - SPF (5) × DKIM (6) × ARF (7): all three converge on
smtp_server/src/policy.rs(the SPF/DKIM/DMARC policies and the forensic input live in one file) and on the sharedmail-authdependency surface; cluster 7 additionally ownsmail_spooler/src/pipeline/dmarc_forensic.rs, and its 6692 row would also touchsmtp_server/src/driver.rs— which SMTP core (1) and enhanced codes (2) also edit. - SMTP core (1) × enhanced codes (2) × DSN/MDN (4): pairwise
overlaps on
smtp_session(reply.rs,session/ready.rs) andmail_spooler(pipeline/dsn.rs,relay.rs); email TLS (3) also meets them insidemail_spooler. - IMAP (8) and POP3 (9) are disjoint from each other and from the
SMTP-side clusters in code (
imap_session/imap_servervspop3_proto/pop_server) — the cleanest concurrent-lane candidates — except through the shared docs sync sites below andserver_common(owned by cluster 3’s evidence; neither 8 nor 9 should edit it). - Every cluster touches the three coverage-assertion sync sites
(standards.md, the
conformance appendix, the owning
crate’s
lib.rsRFC block) pluschange-history.md— treat those as hot files: concurrent cluster lanes must leave them to the main loop or serialize the docs edits.
- Email TLS (3) × SMTP core (1) on
User decision inventory
The adopt/decline questions each future cluster wave must surface at its planning — stated here as decisions with options and stakes, deliberately not answered. Nothing below is decided by this page; an entry is marked answered only once an adopting wave has landed the decision, and then it records which option was taken.
- IMAP strategy: stay on RFC 3501 (IMAP4rev1) or move toward RFC 9051
(IMAP4rev2)? — ANSWERED: option (a), piecemeal (wave-set #48 lane B).
The entry was narrowed before it was answered: option (b)’s
fork-or-heavily-contribute path was already declined in session #10, so
the live choice was (a) vs (c). The question as recorded: 3501 is
obsoleted by 9051;
imap_sessionimplements IMAP4rev1 plus individually-advertised extensions and deliberately does not advertise rev2 (imap_session/src/lib.rs:23-26). The vendored dependency constrains both paths:imap-types2.0.0-alpha.7 has no IMAP4rev2 support at all (zero hits forrev2/9051; theCapabilityenum’s only base isImap4Rev1,response.rs:1059), no ESEARCH (the rev2-mandatory RFC 4731), and no URLAUTH (the already recorded fork-blocked bucket) — while it does hold ready types for CONDSTORE/QRESYNC (ext_condstore_qresync) and UTF8= (ext_utf8). Options were: (a) piecemeal 3501 updates only whereimap-typesalready has types (CONDSTORE/QRESYNC is the one real candidate); (b) target 9051, which means forking or heavily contributing toimap-typesand implementing the rev2 mandatory baseline (ESEARCH, LIST-EXTENDED — exactly the listimap_sessiondefers today); (c) stay put — rev1 plus the current extension set is what real clients interoperate with. Taken: (a) — a dedicated RFC 7162 implementation wave (theimap-typesfeature flip,imap_sessionsemantics,imap_server/backend MODSEQ state) has joined the queue, and the fork-blocked declines became final with the answer (cluster 8’s rows above;imap_session’s “Declined (final)” section). The recording itself implements nothing. Status since: that wave’s CONDSTORE half landed in wave-set #49 lane A (cluster 8’s RFC 4551 row above); QRESYNC remains queued as its own follow-up wave. - POP3/IMAP client-side discovery: RFC 6186 SRV, the SithBit DHT, or
both? — ANSWERED: option (b), declined as superseded (wave-set #48 —
the POP3 half in lane C, the IMAP half in lane B, one decision recorded
in both clusters). The overlap as recorded: 6186 defines SRV lookup
(
_pop3s/_imaps/_submissions) for standard mail clients; SithBit already ships its own discovery —node_certsigned DHT service records surfaced assithbit discover— covering the same “which host and port serves this account” question. The operator half of 6186 is already adopted (the docs SRV section tells deployments to publish the records), so the decision was about SithBit’s own tooling: (a) adopt — teachsithbit discover(or the webclient onboarding flows) to consult SRV as well; (b) decline as superseded; (c) both, with a defined precedence. Taken: (b) — the DHT records are signed and wallet-anchored, which plain SRV can never be, so SithBit-native clients trust only them; the operator-side SRV documentation stands, and the accepted stake is that third-party mail clients stay dependent on operators publishing SRV correctly. - DKIM verify posture for
rsa-sha1(RFC 8301)? — ANSWERED: option (a), the repo-side post-filter (cluster 6, wave-set #50 lane B). The question as recorded:mail-authstill verifiesrsa-sha1signatures, so an inbound legacy signature can producedkim=passcontrary to 8301’s verifier MUST NOT. Options were: (a) add a repo-side post-filter downgradingrsa-sha1-verified results to failure; (b) leave as-is and record the dependency’s behavior (DKIM never rejects standalone here, so the practical blast radius is DMARC alignment input, not message refusal); (c) raise it upstream withmail-authfirst. Stakes: strictness vs interop with unmaintained legacy signers. Taken: (a) —downgrade_rsa_sha1rewrites a verifiedrsa-sha1pass into a failure immediately after everyverify_dkimcall, before the outputs feedAuthentication-Resultsor DMARC alignment, keeping the signature evidence so reporting still names the signing domain. The accepted stake is the strict side: an unmaintained legacy signer’s mail loses its DKIM pass here, which is what the RFC’s MUST NOT demands. Fenced both ways, and one assert deliberately pins thatmail-authstill verifiesrsa-sha1— the retire signal for the filter should a future dependency version close the gap upstream (option (c) remains open to pursue independently; the filter costs nothing meanwhile). Status since: landed in the same wave-set — cluster 6’s RFC 8301 row above records the adoption. - Ed25519 DKIM signing (RFC 8463)? — ANSWERED: option (a), opt-in
dual-signing, default off (cluster 6, wave-set #50 lane B). The
question as recorded: the dependency can sign and generate Ed25519
keys; the repo’s
[spooler.dkim]was RSA-only. Options were: (a) add an Ed25519 (dual-signing) option — modern, small keys, but requires publishing a second DNS key record per domain and accepting that RSA-only verifiers ignore it; (b) decline until ecosystem verification share justifies the operational surface. Stakes: config and key-management surface vs standards momentum. Taken: (a) — each[spooler.dkim]entry accepts the optionaled25519_selector+ed25519_key_filepair (the same file-or-secret-manager key source askey_file; a PKCS#8 PEM fromopenssl genpkey -algorithm ed25519), validated both-or-neither at load. Configured, the spool emits a second ed25519-sha256DKIM-Signatureover the same headers alongside the rsa-sha256 one, so RSA-only verifiers simply keep honoring the RSA signature; absent, signing is rsa-only unchanged — the operational surface is only bought where an operator publishes the second DNS record (v=DKIM1; k=ed25519; p=<raw-32-byte-key-base64>, not DER SPKI). Status since: landed in the same wave-set — cluster 6’s RFC 8463 row above records the adoption. - ARF
Source-Port(RFC 6692)? — ANSWERED: implement, always emit (cluster 7, wave-set #49 lane B). The question as recorded: the recommended small implementation (thread the peer port through the policy seam) sends new information — the client’s TCP source port — in outbound forensic reports; confirm that disclosure is wanted before building, the alternative being to decline a field whose entire purpose is NAT-era attribution. Taken: implement, emitted whenever the port is known, with deliberately no config switch —Source-IPis already unconditionally disclosed in the same report, soSource-Portadds no new disclosure class; an unknown (zero) port omits the field entirely rather than reportingSource-Port: 0. - Pin
.use_rustls_tls()on the two reqwest fetchers? — ANSWERED: option (a) (wave-set #48 lane A). The question as recorded: the MTA-STS fetcher and TLS-RPT submitter rode rustls only via reqwest’s feature defaults plus the lockfile. Options were: (a) pin in code — one line each, makes the 8996/8997 floor an asserted property; (b) fence with a dependency-graph test instead; (c) accept the inherited guarantee. Taken: (a) — both sites (HttpsPolicyFetcher::production_builderandTlsRptReportWorker::new) now call.tls_backend_rustls(), reqwest 0.13.4’s current name foruse_rustls_tls, closing the exposure to a silent backend change on a future reqwest upgrade. - The EAI program (RFC 6530–6533 internationalized email): adopt,
decline, or defer? — ANSWERED: option (c), defer with criteria
(wave-set #51 lane C — decision-recording only, nothing implemented).
The question as recorded: five clusters carry defer (EAI) rows —
6533 (DSN, cluster 4), 8616 (SPF cluster 5 and DKIM cluster 6),
5738/6855 + 6858 (IMAP, cluster 8), 6532 (MIME, cluster 10) — all
gated on the same structural switch (SMTPUTF8 deliberately disabled,
driver.rs:168), and the overlap map’s rule is that the family is one program, decided once, never row by row. Options were: (a) adopt — open the EAI program as its own wave program (SMTPUTF8 on, then the 6532 header, 6533 DSN, 8616 auth, and IMAP/POP UTF-8 surfaces, with 8616 an upstreammail-authquestion first); (b) decline outright — close all five rows as declined and stay ASCII-only permanently; (c) defer with criteria — park the program, unopened, behind a named demand signal. Stakes: a program-sized adoption spanning five clusters plus an upstream dependency gap, against no demonstrated demand today — but an outright decline would discard the ready-made pieces already in place (imap-types’ 6855-shapedext_utf8types,pop3_proto’s RFC 6856 support) and foreclose a future interop need. Taken: (c) — deferred until a concrete demand signal: an operator or user needing non-ASCII addresses, or interop with an EAI sender. No EAI implementation now; the five cluster rows keep their defer (EAI) tags with this entry as their governing record, and reopening the question requires the demand signal, not a new audit.