# 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, SCP-5 and the recommendation part of SCP-7. Errata here are changes that clarify or tighten without changing what canonical addresses mean. SCP-6 is a new feature and targets v0.2. 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). **Counter-evidence (T04):** the IONOS forwarding form refused `=` and forced lower case. Google Groups accepted `=` but lower-cased the member address (SCP-6, SCP-7). SRS and list bounce addresses never collided with `=` or `+`. Mail *clients* preserved MAS syntax; provider *configuration forms* did not. **Proposal:** keep the normative text. Add an informative note recording the tested paths, including the IONOS refusal, 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. --- ## SCP-6: statute-declared alternate resource separator (`--` for `=`) **Sections:** §6 Resource semantics, §11 Statute document, §12. **Evidence:** the IONOS forwarding form refuses `=` in a destination address. The operator compensated with `ticket--GS-…`, and it was delivered, but under v0.1 it is only an opaque target. The service correctly could not attach it to the ticket. **Proposal:** a statute MAY declare an alternate separator for resource targets, for example: ```json "resource_syntax": { "alternate_separator": "--" } ``` When it is declared, a target `TYPE--ID`, where `TYPE` is a declared resource type, is equivalent to `TYPE=ID` in that namespace. The policy resolver reports `target_syntax: "resource-alternate"` and the canonical equivalence key `TYPE=ID`. Without the declaration, `--` has no meaning (§6.1 still applies). Generators SHOULD offer the alternate form when the statute declares one and the destination is known to reject `=`. **Open points:** the first `--` after a declared type is the split point, so IDs may still contain `--`. The separator must be a dot-atom-safe string and may not contain `.`. A namespace whose existing opaque names start with `TYPE--` must not declare it. **Impact:** additive, optional schema field, policy change, new fixtures. A candidate for v0.2 rather than errata. --- ## SCP-7: resource identifiers must survive lower-casing **Sections:** §6.2 Resource identifiers, §8 Address equivalence, §13. **Evidence:** the IONOS forwarding form forces destination addresses to lower case: `GS-85QJ8WC09P` became `gs-85qj8wc09p`. Google Groups did the same after a member accepted the invitation: the invitation was delivered mixed-case, but list mail went to the lower-cased address and was quarantined as an unknown resource. With the spec default (exact comparison) and a statute declaring `case: exact`, the identifier no longer matches. Many systems treat local-parts as case-insensitive in practice, despite RFC 5321. **Priority:** highest of this set. Two of two forwarding/list providers lower-cased the recipient. **Proposal:** - §6.2: "Generators SHOULD use resource identifiers whose meaning does not depend on letter case (for example lower-case only, or a case-insensitive alphabet such as Crockford base32), because forwarders and web forms may change the case of local-parts." - Statute: allow `equivalence.resource_id_case: "insensitive"` independently of the local-part `case` setting. Receivers then fold the identifier for lookup but must not fold anything else. - Together with SCP-2, the resource type is already lower-case. **Impact:** recommendation plus an optional statute field. The reference service could switch to lower-case IDs today. Crockford base32 decoding is case-insensitive by design. --- ## 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.