mail-address-semantics/docs/spec-change-proposals.md
tegwick d7264e7ec5 MAS-WP-0003-T05: provider results in review, spec change proposals, gate recommendation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 252470@bnt-lap001
Assistant-Session: ad628c8f-4be2-4979-94c9-76c7ed6f8241
2026-10-18 13:34:21 +02:00

145 lines
5.9 KiB
Markdown

# MAS v0.1 spec change proposals (from MAS-WP-0002/0003)
Status: **draft for review**. These are proposals against
`mas-v0.1-spec/`. The spec bundle stays unchanged until they are accepted,
because `mas_conformance/` and `mas_core/schema/` are vendored copies and
the tests check them for drift. Evidence references point to
`docs/experiment-review.md`.
Proposed target: a v0.1.1 errata release for SCP-1 to SCP-3 and SCP-5,
which clarify or tighten without changing what canonical addresses mean.
SCP-4 is informative only.
---
## SCP-1: quoted local-parts that are valid dot-strings are equivalent
**Sections:** §4 Canonical ASCII local-part, §8 Address equivalence.
**Evidence:** Postfix delivered `"ticket=PR42"@…` as `ticket=PR42` in all
five probe configurations (RFC 5321 treats unnecessary quoting as
equivalent). A receiver behind an MTA cannot tell which form the sender
used.
**Proposed text (§4, after the second paragraph):**
> A quoted local-part whose content, after removing the quotes and with no
> quoted-pairs, is a valid canonical MAS local-part is equivalent to that
> unquoted form. Receivers MUST treat the two identically. Generators MUST
> emit the unquoted form.
**Impact:** clarification only. No parser change, since quoted input still
does not parse. A new conformance fixture should record the equivalence.
---
## SCP-2: resource-type names are lower-case
**Sections:** §6.1 Resource types, grammar `resource-type`, §8.
**Evidence:** the ABNF accepts `Ticket=PR42`, but the statute schema only
registers lower-case type names. The address parses but can never match a
declared type, even under `ascii-insensitive`.
**Options:**
- **(a) recommended:** restrict `resource-type` in the grammar to lower-case
ALPHA, DIGIT and `-`. `Ticket=PR42` then parses as an opaque target, which
is the safe outcome under §6.1 ("no semantics solely because of `=`").
- (b) keep the grammar and state in §8 that the statute's equivalence policy
also applies to the type name.
(a) keeps the type a protocol token rather than user data, and it matches
the schema. (b) makes type matching depend on the statute, which is
exactly the hidden inference §8 tries to avoid.
**Impact:** (a) is a grammar tightening. None of the 31 shared conformance
fixtures uses an upper-case type, so a new fixture (`Ticket=PR42` →
opaque) records the change. No repo test uses one either.
Live traffic in MAS-WP-0003 used only lower-case types.
---
## SCP-3: type-intake semantics for `TYPE!MODE`
**Section:** §7 Interaction semantics.
**Evidence:** in `ticket!callback`, the target `ticket` is an opaque
target with no defined link to the resource type `ticket`. The canonical
§7 example implies one. In the experiment, the statute had to register
`ticket` as a function (registry key) and the service had to know what
that means. Live, `ticket!callback@mas.coulomb.social` worked from Gmail
and M365 only because of that registry entry.
**Proposed text (§7, new paragraph):**
> An opaque target that equals a resource type declared in the statute,
> and that the statute also registers as a function, is that type's
> *intake*: mail to it requests creation or selection of a resource of
> that type. Without such a registration the target has no intake
> semantics, even if it equals a declared resource type.
Also add a statute-schema field such as `"intake_for": "ticket"` on
registry entries, so the link is declared rather than implied by equal
names.
**Impact:** additive; the schema gains an optional field. The policy
resolver reports `intake_for` when it is present.
---
## SCP-4 (informative): deliverability evidence for `!` and `=`
**Section:** §12 Deliverability and rewriting.
**Evidence:** Gmail (web and app) and Microsoft 365 (Outlook mobile and
desktop) accepted and delivered all four test forms byte-identical. That
includes `!`, a doubled `=` and a `+` facet, both inbound and in a reply to
an `=` From address. Postfix 3.7 never applied the legacy `!`/`%` rewrites
to MAS addresses carrying an `@domain`. Pending: SRS and VERP (MAS-WP-0003
T04).
**Proposal:** keep the normative text. Add an informative note recording
the tested paths, and an implementation note that a default Postfix relay
configuration rejects every local-part containing `!` (see SCP-5 and the
review's operational findings). The "cooperating environments" wording for
`!` stays until T04 has covered forwarding.
---
## SCP-5: intake auto-replies are a reflection vector
**Section:** §14 Security (items 4 and 5).
**Evidence:** an intake address that answers every request (as
`ticket!callback@` does with "your request is now ticket …") sends mail to
whatever `From:` the request carried. A forged `From:` makes the service
send mail to a third party, which is backscatter in all but name. §14.5
only says "avoid backscatter" and is usually read as covering MTA bounces.
The live deployment had to add an application-level cap (T06) and discard
MTA bounces to keep the relay bounded.
**Proposed text (§14, new item):**
> 10. A receiver that automatically replies to mail sent to an intake or
> interaction address SHOULD reply only when the sender is
> authenticated (for example DMARC alignment pass), and MUST bound
> the volume of such replies (rate limits or caps). Replies MUST NOT
> be sent to automated mail (`Auto-Submitted`, `Precedence`).
**Impact:** normative for receivers. The reference ticket service already
skips automated mail and has a send cap. A DMARC check would need the
gateway to pass `Authentication-Results` in the event, which is a small
event-schema addition.
---
## Lower-priority gaps (no proposal yet)
Recorded in the review, not urgent:
- interaction-mode names allowed by the value grammar but not by the schema
(`call.back`, `a=b`);
- registry keys containing `=` or leading/trailing dots, which need semantic
lint;
- discovery: whether the content type is checked, and the exact redirect
same-origin rule;
- statute-declared facets.