diff --git a/docs/experiment-review.md b/docs/experiment-review.md index 36f0a0e..b9e7d7a 100644 --- a/docs/experiment-review.md +++ b/docs/experiment-review.md @@ -149,8 +149,30 @@ four sender setups: - **Outbound port 25 was blocked** at the hosting provider (and on a second host). Replies need an authenticated submission relay. -**Still untested (T04):** overlap with SRS (`SRS0=...`) and VERP when -forwarding, and facet stripping by forwarders and lists. +**Forwarding (T04, IONOS mail forward, 2026-10-18):** this is the first +real failure in the run. +- **The IONOS forwarding form refuses `=`** in the destination address. + `+` is accepted. A resource address cannot be configured as a forward + target at all. +- **The form also forces lower case.** It only accepts lower-case + destinations and "corrects" input. The operator entered + `ticket--GS-85QJ8WC09P+comments@` (with `--` standing in for `=`), and + `ticket--gs-85qj8wc09p+comments@` arrived. Under the spec's default + exact comparison, a lower-cased identifier no longer matches its + resource, even if the `=` had been allowed. +- **SRS does not collide with `=`.** IONOS rewrote the *envelope sender* + to `SRS0=ppc5=II=gmail.com=bernd.worsch@srs2.kundenserver.de`. SRS never + touches the recipient, so `=` in recipients is safe from it. +- The facet `+comments` survived forwarding. +- The header `To:` showed the forwarding address (`mas-fwd@coulomb.social`), + so MAS receivers must classify the **envelope recipient**, as + `mas-gateway` does. +- Result: the gateway classified the mail as an opaque target with a facet. + The ticket service correctly declined it (404, not handled), because + nothing in the statute gives `ticket--…` resource meaning. See SCP-6 + (declared alternate separator) and SCP-7 (identifier case). + +**Still untested (T04):** a mailing list (VERP). ### Resource addressing: did it improve correlation? Yes. The service replies *from* `ticket=GS-…@great-service.example`, so an @@ -205,8 +227,8 @@ This is a recommendation; the decision is the founder's. | Candidate | Demonstrated need? | Recommendation | |---|---|---| | Postfix/Exim integration | **Yes.** Default Postfix drops every P2 address, and the correct relay config is non-obvious | Build first: a documented, tested Postfix profile (later Exim) based on `deploy/railiance/entrypoint.sh` | -| Spec v0.1.1 errata | **Yes**, SCP-1 to SCP-5 | Do alongside the integration | -| Address composer | Weak. Providers accepted hand-typed addresses; the 64-octet budget and facet/interaction exclusivity are the only traps | Defer; `mas generate` in the CLI covers it | +| Spec v0.1.1 errata | **Yes**, SCP-1 to SCP-7 (SCP-6 is an additive feature and could go to v0.2) | Do alongside the integration | +| Address composer | Partly. Mail clients accepted hand-typed addresses, but the IONOS forwarding form refused `=` and lower-cased input | Defer the tool; first settle SCP-6/SCP-7, then `mas generate` emits the forwarder-safe form | | Mail-client inspector | Not shown; nothing was rewritten that a user would need to see | Defer | | TypeScript / Go implementations | Not shown; no consumer outside Python yet | Defer until a second consumer exists | | Signed statutes | Not shown; pinned local statutes covered the operator case (see Discovery) | Defer | diff --git a/docs/spec-change-proposals.md b/docs/spec-change-proposals.md index 5c483d2..e109805 100644 --- a/docs/spec-change-proposals.md +++ b/docs/spec-change-proposals.md @@ -6,8 +6,9 @@ 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. +Proposed target: a v0.1.1 errata release for SCP-1 to SCP-3, SCP-5 and the +recommendation part of SCP-7, with SCP-6 targeted at v0.2. Errata here are changes that clarify or +tighten without changing what canonical addresses mean. SCP-4 is informative only. --- @@ -98,8 +99,12 @@ 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 (SCP-6, SCP-7). Mail *clients* preserved MAS syntax; +provider *configuration forms* did not. + **Proposal:** keep the normative text. Add an informative note recording -the tested paths, and an implementation note that a default Postfix relay +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. @@ -133,6 +138,65 @@ 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`. 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. + +**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: diff --git a/workplans/MAS-WP-0003-provider-live-test.md b/workplans/MAS-WP-0003-provider-live-test.md index f6186e5..a57689e 100644 --- a/workplans/MAS-WP-0003-provider-live-test.md +++ b/workplans/MAS-WP-0003-provider-live-test.md @@ -167,7 +167,7 @@ address and what envelope recipient arrives. ```task id: MAS-WP-0003-T04 -status: todo +status: progress priority: medium state_hub_task_id: "97c88b4f-14c3-5f6c-8f31-6b9fc3afd236" ``` @@ -176,6 +176,20 @@ Send via one forwarding service (SRS) and one mailing list (VERP). Check whether `=` collides with SRS0/VERP encoding, and whether facets survive or are stripped. +- 2026-10-18, IONOS mail forward (`mas-fwd@coulomb.social`): the IONOS form + refuses `=` in the destination and forces lower case. The operator used + `ticket--GS-85QJ8WC09P+comments@`, and `ticket--gs-85qj8wc09p+comments@` + arrived at 11:47:06Z from mout.kundenserver.de. The envelope sender was + SRS-rewritten (`SRS0=ppc5=II=gmail.com=bernd.worsch@srs2.kundenserver.de`). + SRS only touches the sender, so there is no collision with `=` in + recipients. The facet survived, and the header To kept the forward + address. The gateway saw an opaque target with a facet, and the app + correctly declined it (404). This led to SCP-6 (statute-declared `--` + separator; the operator endorses the mapping) and SCP-7 (case-robust + identifiers). + Gmail forwarding: skipped (optional; would only add a second forwarder + that accepts `=`). Still open: one mailing list (VERP). + ## Cap total outbound mail ```task