MAS-WP-0005-T01: SCP-6 decided (statute opt-in, split rule, destination transforms)

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
This commit is contained in:
tegwick 2026-10-18 17:57:21 +02:00
parent 95cae6d26a
commit 8351b8a1f0
2 changed files with 71 additions and 14 deletions

View file

@ -152,27 +152,75 @@ 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:
**Decisions (founder, 2026-10-18):**
- `=` stays canonical. `--` is only a replacement for endpoints that refuse
`=`.
- It is enabled by **statute opt-in** (option A), not as a spec-wide default.
- The spec stays normative for the mechanism and explains how specific
integrations are done through the statute when needed. Concrete
integrations are not part of the normative text.
**Proposal, receiving side (normative):** a statute MAY declare an
alternate separator for resource targets:
```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 `=`.
- When it is declared, a target `TYPE--ID`, where `TYPE` is a resource type
declared in the same statute, is equivalent to `TYPE=ID`. The policy
resolver reports `target_syntax: "resource-alternate"` and the canonical
equivalence key `TYPE=ID`. Receivers store, correlate and reply using the
canonical form only.
- **Split rule:** together with SCP-2, resource-type names are lower-case
letters and digits with single hyphens and never contain `--`. The first
`--` therefore always ends the type: `ticket--RE--2026` is type `ticket`,
ID `RE--2026`. IDs may contain `--`, just as they may contain `=`.
- Only a declared type triggers the split. Without the declaration, or
with an undeclared type, `--` has no meaning (§6.1 still applies).
- The separator must be dot-atom-safe and must not contain `.` or `=`. A
namespace whose existing opaque names start with `TYPE--` must not
declare it.
**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.
**Proposal, sending side (normative mechanism, informative integrations):**
generators produce addresses for a *destination*, such as a forwarding
form, a mailing list or a reply header. The spec defines a **destination
transform**, the set of changes a generator may apply so that an address
fits a destination's constraints. For v0.1/v0.2 there are two:
**Impact:** additive, optional schema field, policy change, new fixtures.
A candidate for v0.2 rather than errata.
| Transform | Effect | Allowed only if the namespace's statute |
|---|---|---|
| `separator` | `TYPE=ID` → `TYPE<alt>ID` | declares `alternate_separator` |
| `lowercase` | fold the whole local-part to lower case | declares case-insensitive identifiers (SCP-7) and lower-case types (SCP-2) |
A generator MUST emit the canonical form when the destination allows it.
It MAY apply the transforms the destination needs, and only those the
namespace's statute permits. If the result would not be accepted by the
namespace, the generator MUST report that the address cannot be expressed
for that destination, instead of emitting a form the receiver would
misread. Outbound service mail (From/Reply-To) stays canonical unless a
destination transform is known to be needed.
An informative section, "Integrating with constrained endpoints", explains
the procedure:
1. observe what the endpoint refuses or rewrites;
2. declare the matching acceptance in the statute;
3. describe the endpoint's constraints as a destination profile in the
generator's configuration.
It uses IONOS forwarding as the worked example: `=` is refused and case is
folded, so the profile is `separator` + `lowercase`, and the result is
`ticket--gs-85qj8wc09p+comments@`. Concrete profiles (e.g. `ionos-forward`)
live in implementation configuration or a catalog, not in the spec.
**Open:** whether transforms beyond separator and case are needed, for
example for `!`. No endpoint has refused `!` so far, but none was tested
with it. Leave the transform list closed in v0.2 and extend it only on
evidence.
**Impact:** additive: an optional schema field, a policy change, a
generator `destination` parameter, and new fixtures. Targets v0.2. The
composer (MAS-WP-0006) is the first consumer of destination profiles.
---

View file

@ -39,6 +39,15 @@ SCP-6 split rules), and record which proposals are accepted.
canonical and `--` is accepted as a replacement only for endpoints that
refuse `=`. A transform profile per recipient/destination may be needed
when something we send out must match that destination's requirements.
- 2026-10-18: SCP-6 decided. The statute opts in (option A) to
`alternate_separator`. The split is at the first `--` after a declared
type, and type names may not contain `--`. The sending side gets a
normative "destination transform" mechanism (`separator`, `lowercase`)
plus an informative integration section with IONOS as the example.
Concrete destination profiles live in implementation config, not the
spec. Still open: transforms beyond separator and case, to be added
only on evidence. Remaining T01 items: confirm SCP-1, SCP-3, SCP-5 and
SCP-7 as written.
## v0.1.1 errata