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
589 lines
20 KiB
Markdown
589 lines
20 KiB
Markdown
# Mail Address Semantics (MAS) v0.2 (draft)
|
|
|
|
## 1. Status and normative language
|
|
|
|
This document is a **draft** of MAS v0.2. It includes v0.1.1 and adds
|
|
statute-enabled stand-ins for `=` and `!`, destination transforms for
|
|
generators, and a statute-declared resource-identifier case rule (see
|
|
`CHANGELOG.md`). The canonical grammar is unchanged from v0.1.1.
|
|
|
|
A statute opts into v0.2 features by declaring `"mas_version": "0.2"`. A
|
|
v0.1 statute stays valid and is interpreted under v0.1.1 rules.
|
|
|
|
The key words **MUST**, **MUST NOT**, **REQUIRED**, **SHOULD**, **SHOULD NOT**,
|
|
**RECOMMENDED**, **MAY**, and **OPTIONAL** are to be interpreted as described
|
|
in BCP 14 when, and only when, they appear in uppercase.
|
|
|
|
MAS is an overlay on ordinary email addressing. It does not replace SMTP,
|
|
establish identity, grant authority, define delivery topology, or create
|
|
contractual commitments.
|
|
|
|
## 2. Scope
|
|
|
|
MAS v0.1 standardizes:
|
|
|
|
1. non-structural naming hints for people, actors, and functions;
|
|
2. structured resource targets using `=`;
|
|
3. facets using `+`;
|
|
4. an optional interaction profile using `!`;
|
|
5. exact-host statute discovery;
|
|
6. conservative equivalence behavior;
|
|
7. parser and generator conformance.
|
|
|
|
`$` and `^` are reserved. They have no MAS v0.1 meaning.
|
|
|
|
## 3. Profiles
|
|
|
|
### 3.1 Profile P1 — Naming + Resource
|
|
|
|
P1 is the base v0.1 profile.
|
|
|
|
- `.` MAY be used as a person-style naming separator.
|
|
- `-` MAY be used as an actor-style naming separator.
|
|
- `_` MAY be used as a function-style naming separator.
|
|
- `=` structurally binds a resource type to a resource identifier.
|
|
- `+` structurally adds one facet.
|
|
|
|
`.`, `-`, and `_` never classify an address by themselves.
|
|
|
|
### 3.2 Profile P2 — Interaction
|
|
|
|
P2 extends P1 with `!`.
|
|
|
|
`TARGET!MODE` requests that the addressed endpoint continue the interaction
|
|
using `MODE` as the preferred interaction mode.
|
|
|
|
The address does not state which party initiates a non-email leg and does not
|
|
constitute acceptance. Acceptance is external to the address.
|
|
|
|
### 3.3 Profile P3 — Economic
|
|
|
|
P3 is not defined in v0.1.
|
|
|
|
`$` and `^` are reserved so that later profiles may define consideration and
|
|
conditions without creating v0.1 parsing ambiguity.
|
|
|
|
## 4. Canonical ASCII local-part
|
|
|
|
The normative v0.1 machine grammar is the ABNF in
|
|
`grammar/mas-v0.2.abnf`.
|
|
|
|
Canonical MAS v0.1 local-parts are unquoted ASCII dot-atom-like strings.
|
|
Quoted local-parts and SMTPUTF8 local-parts are outside the canonical v0.1
|
|
machine grammar.
|
|
|
|
A MAS-aware implementation MAY transport such non-canonical email addresses
|
|
as ordinary email, but MUST NOT claim that they are canonical MAS v0.1
|
|
addresses.
|
|
|
|
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 (RFC 5321 treats unnecessary quoting as equivalent, and MTAs
|
|
remove such quotes in transit). Receivers MUST treat the two identically.
|
|
Generators MUST emit the unquoted form. Parsers that check canonical syntax
|
|
still reject the quoted form.
|
|
|
|
### 4.1 Target
|
|
|
|
A target is non-empty.
|
|
|
|
A target without `=` is opaque. Its semantic kind MUST NOT be inferred from
|
|
`.`, `-`, or `_`.
|
|
|
|
If a target contains `=`, the target is a resource target:
|
|
|
|
- text before the first `=` is `resource-type`;
|
|
- text after the first `=` is `resource-id`;
|
|
- neither may be empty;
|
|
- subsequent `=` characters are resource-id data.
|
|
|
|
Examples:
|
|
|
|
ticket=PR42
|
|
invoice=RE=2026-4711
|
|
|
|
The second example has resource type `invoice` and resource id
|
|
`RE=2026-4711`.
|
|
|
|
### 4.2 Facet
|
|
|
|
A facet is introduced by `+`.
|
|
|
|
`+` MAY occur at most once and its value MUST be non-empty.
|
|
|
|
ticket=PR42+comments
|
|
|
|
The base target remains meaningful if a mail system strips the facet. MAS
|
|
therefore treats facet loss as graceful degradation:
|
|
|
|
ticket=PR42+comments -> ticket=PR42
|
|
|
|
This is a semantic design property, not a preservation guarantee.
|
|
|
|
### 4.3 Interaction
|
|
|
|
An interaction preference is introduced by `!`.
|
|
|
|
`!` MAY occur at most once and its value MUST be non-empty.
|
|
|
|
P2 examples:
|
|
|
|
ticket!callback
|
|
ticket=PR42!web
|
|
|
|
Canonical operator order is:
|
|
|
|
TARGET [+FACET] [!INTERACTION]
|
|
|
|
Non-canonical order is invalid MAS syntax. A conforming parser MUST reject it
|
|
and MUST NOT silently reorder it.
|
|
|
|
### 4.4 Composition rule
|
|
|
|
A parser implementing P2 MUST be able to parse the canonical combined form:
|
|
|
|
TARGET+FACET!INTERACTION
|
|
|
|
A v0.1 generator MUST NOT emit both `+` and `!` in the same generated
|
|
local-part. Implementations requiring both semantics SHOULD move one of them
|
|
to external metadata.
|
|
|
|
This deliberately makes receivers slightly more tolerant than generators
|
|
while retaining one canonical parse.
|
|
|
|
### 4.5 Reserved characters
|
|
|
|
Within canonical MAS v0.1 structured values:
|
|
|
|
+ ! $ ^
|
|
|
|
are reserved.
|
|
|
|
MAS v0.1 defines no escaping mechanism.
|
|
|
|
A percent-looking sequence such as `%2B` is ordinary data in v0.1 and MUST NOT
|
|
be percent-decoded by the MAS parser.
|
|
|
|
## 5. Naming semantics
|
|
|
|
The following are style conventions only:
|
|
|
|
bernd.worsch@example.org person-like
|
|
research-companion@example.org actor-like
|
|
invoice_ingest@example.org function-like
|
|
|
|
They are not classifier rules.
|
|
|
|
Examples such as these remain opaque without statute metadata:
|
|
|
|
anne-marie.schmidt@example.org
|
|
support@example.org
|
|
happy-helper.v2@example.org
|
|
|
|
A domain registry or statute metadata determines semantic kind.
|
|
|
|
## 6. Resource semantics
|
|
|
|
A resource address identifies a communication endpoint associated with a
|
|
resource.
|
|
|
|
ticket=PR42@example.org
|
|
|
|
It does not grant access to, mutation of, or knowledge about the resource.
|
|
|
|
Resource addressability and resource mutability are independent.
|
|
|
|
A closed resource MAY remain addressable. A receiver MAY archive the mail,
|
|
reject mutation, return lifecycle information, or create a linked follow-up
|
|
resource.
|
|
|
|
### 6.1 Resource types
|
|
|
|
A resource type is lower-case: one or more words of `a-z` and `0-9`, joined
|
|
by single `-` or `_` characters (grammar rule `resource-type`). A
|
|
local-part whose part before the first `=` is not a valid resource type,
|
|
such as `Ticket=PR42`, is not a canonical MAS address.
|
|
|
|
Resource types are protocol tokens, not user data. Forwarders and list
|
|
servers commonly lower-case local-parts, so mixed-case types would not
|
|
survive transit.
|
|
|
|
A statute SHOULD enumerate resource types it recognizes.
|
|
|
|
Unknown resource types MUST NOT acquire application semantics solely because
|
|
they use `=` syntax.
|
|
|
|
### 6.2 Resource identifiers
|
|
|
|
Resource identifiers are correlation identifiers, not credentials.
|
|
|
|
Predictable identifiers are enumerable. Deployments SHOULD prefer
|
|
non-guessable external identifiers when addresses are widely forwarded or
|
|
exposed and enumeration is undesirable.
|
|
|
|
High entropy does not transform an identifier into an authorization token.
|
|
|
|
Forwarders, mailing lists and web forms commonly change the case of
|
|
local-parts. 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, and receivers SHOULD
|
|
then match them case-insensitively.
|
|
|
|
### 6.3 Stand-ins (v0.2)
|
|
|
|
Some endpoints, for example provider forwarding forms, refuse `=` or `!` in
|
|
an address. v0.2 defines two fixed **stand-ins** built from dashes only:
|
|
|
|
| Stand-in | Stands for | Statute switch |
|
|
|---|---|---|
|
|
| `--` | `=` (resource separator) | `alternate_syntax.resource: true` |
|
|
| `---` | `!` (interaction) | `alternate_syntax.interaction: true` |
|
|
|
|
The stand-ins are defined by this specification and are not configurable.
|
|
`+` has no stand-in; it is functional by default, and facet loss degrades
|
|
safely (§12).
|
|
|
|
A stand-in has meaning only in a namespace whose statute enables it.
|
|
Without the switch, `--` and `---` are ordinary characters (§6.1). A
|
|
stand-in form is not canonical: the parser treats it as an opaque target,
|
|
and only a statute-aware implementation interprets it.
|
|
|
|
**Matching order.** A statute-aware implementation interprets a local-part
|
|
in this order:
|
|
|
|
1. **Interaction.** If the interaction stand-in is enabled and the
|
|
local-part ends in `---MODE`, where `MODE` is an interaction mode the
|
|
statute enables, the suffix after the last such `---` is the
|
|
interaction, equivalent to `!MODE`.
|
|
2. **Resource.** If the resource stand-in is enabled and the remaining
|
|
target has the form `TYPE--ID`, where `TYPE` is a resource type the
|
|
statute declares, it is equivalent to `TYPE=ID`. The split is at the
|
|
first `--`.
|
|
|
|
| Received | Equivalent canonical form |
|
|
|---|---|
|
|
| `ticket---callback` | `ticket!callback` |
|
|
| `ticket--gs1---callback` | `ticket=gs1!callback` |
|
|
| `ticket--a---b` (`b` not an enabled mode) | `ticket=a---b` |
|
|
| `ticket--gs1+comments` | `ticket=gs1+comments` |
|
|
|
|
**Constraints.**
|
|
|
|
- Resource-type names never contain `--` (grammar, §6.1).
|
|
- Interaction mode names MUST NOT start with `-`.
|
|
- A namespace that enables the interaction stand-in MUST NOT issue resource
|
|
identifiers containing `---`.
|
|
- A namespace with existing opaque names matching a stand-in pattern MUST
|
|
NOT enable that stand-in.
|
|
|
|
Receivers MUST store, correlate and reply using the canonical form. The
|
|
equivalence key (§8) is always computed from the canonical form.
|
|
|
|
## 7. Interaction semantics
|
|
|
|
The recommended P2 initiation pattern is:
|
|
|
|
ticket!callback@great-service.example
|
|
|
|
followed by creation or disclosure of a resource:
|
|
|
|
ticket=GS-41872@great-service.example
|
|
|
|
The first address expresses interaction intent. The second names the resource
|
|
created or selected by the service.
|
|
|
|
`!callback` is a preference/request, not a command, guarantee, SLA, or proof
|
|
of acceptance.
|
|
|
|
The bare target in `ticket!callback` is an opaque target. It has no link
|
|
to the resource type `ticket` merely because the names are equal. A
|
|
statute declares the link on the address registry entry:
|
|
|
|
"addresses": { "ticket": { "kind": "function", "intake_for": "ticket" } }
|
|
|
|
An address whose base target is registered with `intake_for: T` is the
|
|
*intake* for resource type `T`: mail to it requests creation or selection
|
|
of a resource of type `T`. The entry MUST have `kind` `function`, and `T`
|
|
MUST be a resource type the statute declares or inherits. Without such a
|
|
registration a target has no intake semantics, even if it equals a declared
|
|
resource type.
|
|
|
|
## 8. Address equivalence
|
|
|
|
MAS does not impose case folding, dot folding, alias folding, or Unicode
|
|
normalization in the absence of a successfully discovered statute.
|
|
|
|
If no statute is available, comparison is exact over the presented canonical
|
|
ASCII local-part.
|
|
|
|
A statute MAY declare:
|
|
|
|
- `exact` local-part comparison;
|
|
- `ascii-insensitive` local-part comparison;
|
|
- dot folding for explicitly named address kinds or registry entries.
|
|
|
|
Dot folding MUST NOT be assumed by default.
|
|
|
|
A v0.2 statute MAY declare `equivalence.resource_id_case`:
|
|
|
|
- `exact` (default): resource identifiers compare exactly, subject to
|
|
`local_part_case`;
|
|
- `insensitive`: resource identifiers compare ASCII case-insensitively,
|
|
even when `local_part_case` is `exact`. Nothing else is folded.
|
|
|
|
Generators for such a namespace SHOULD emit identifiers in lower case
|
|
(§6.2).
|
|
|
|
A-label/U-label domain processing follows the underlying IDNA-aware HTTPS and
|
|
DNS stack; MAS does not invent a second IDN mapping algorithm.
|
|
|
|
## 9. Unicode
|
|
|
|
SMTPUTF8 allows non-ASCII local-parts, but MAS v0.1 does not define a
|
|
canonical Unicode local-part grammar.
|
|
|
|
A statute may declare `unicode_local_part: true` for experimental/private
|
|
extensions. Such addresses MUST NOT be advertised as canonical MAS v0.1
|
|
machine syntax.
|
|
|
|
A future MAS version may define NFC normalization and Unicode comparison
|
|
rules. v0.1 deliberately avoids doing so.
|
|
|
|
## 10. Statute discovery
|
|
|
|
The intended discovery URI is:
|
|
|
|
https://HOST/.well-known/mas
|
|
|
|
where `HOST` is the exact domain appearing after `@`.
|
|
|
|
For:
|
|
|
|
anna.mueller@acme.coulomb.social
|
|
|
|
the lookup host is:
|
|
|
|
acme.coulomb.social
|
|
|
|
A client MUST NOT walk to parent domains implicitly.
|
|
|
|
### 10.1 Registration caveat
|
|
|
|
RFC 8615 requires applications minting a new well-known URI suffix to
|
|
register it for general Internet use.
|
|
|
|
Therefore `/.well-known/mas` is a candidate MAS discovery location in this
|
|
draft. General public deployment SHOULD wait for the required registration.
|
|
Controlled deployments MAY use it by agreement.
|
|
|
|
### 10.2 Retrieval
|
|
|
|
A statute-aware client:
|
|
|
|
1. constructs the HTTPS URI for the exact host;
|
|
2. performs an HTTPS GET;
|
|
3. requires a successful 2xx response;
|
|
4. requires a document conforming to the v0.1 statute schema;
|
|
5. verifies that `namespace` equals the queried host after normal domain-name
|
|
canonicalization;
|
|
6. otherwise treats discovery as failed.
|
|
|
|
Discovery failure does not make the email address invalid. It means MAS
|
|
semantics are unconfirmed.
|
|
|
|
### 10.3 Redirects
|
|
|
|
Clients SHOULD NOT follow cross-origin redirects for statute discovery.
|
|
|
|
Same-origin redirects MAY be followed.
|
|
|
|
A cross-origin policy transfer requires an explicit future delegation
|
|
mechanism and is not defined in v0.1.
|
|
|
|
### 10.4 Inheritance
|
|
|
|
No parent-domain inheritance is implicit.
|
|
|
|
A child statute MAY contain an `inherits` URI. v0.1 inheritance is
|
|
**defaults-only**:
|
|
|
|
- the parent document is fetched and validated independently;
|
|
- the child remains authoritative for its exact namespace;
|
|
- child values override inherited defaults;
|
|
- address registry entries are never inherited;
|
|
- resource types and interaction modes MAY be inherited;
|
|
- an inheritance cycle is invalid.
|
|
|
|
Implementations MAY choose not to implement inheritance. If they do not,
|
|
they MUST ignore `inherits` rather than walking DNS parents.
|
|
|
|
## 11. Statute document
|
|
|
|
The normative schema is:
|
|
|
|
schema/mas-statute-v0.2.schema.json
|
|
|
|
The document describes:
|
|
|
|
- namespace and version;
|
|
- enabled profiles;
|
|
- accepted resource types;
|
|
- accepted interaction modes;
|
|
- equivalence policy;
|
|
- optional explicit address classification;
|
|
- optional inheritance;
|
|
- optional stand-in switches (`alternate_syntax`, v0.2);
|
|
- optional resource-identifier case rule (`equivalence.resource_id_case`, v0.2).
|
|
|
|
The statute is metadata, not an authorization database.
|
|
|
|
## 12. Deliverability and rewriting
|
|
|
|
RFC-validity is weaker than ecosystem compatibility.
|
|
|
|
Mailing lists, SRS, VERP, gateways, web forms, validators, and security
|
|
products may reject or rewrite otherwise legal local-parts.
|
|
|
|
Deployments MUST NOT assume preservation of MAS syntax through arbitrary
|
|
rewriting.
|
|
|
|
`+` is intentionally degradation-friendly: loss of a facet leaves the base
|
|
target.
|
|
|
|
`!` is intended primarily for cooperating environments where all relevant
|
|
systems are known to preserve it. Where an endpoint refuses it, a namespace
|
|
can enable the `---` stand-in (§6.3).
|
|
|
|
### 12.1 Destination transforms (v0.2)
|
|
|
|
A generator produces an address for a *destination*: a mail header, a
|
|
forwarding form, a list membership, a printed page. A **destination
|
|
transform** changes an address so that it fits a destination's constraints.
|
|
The set is closed:
|
|
|
|
| Transform | Effect | Allowed only if |
|
|
|---|---|---|
|
|
| `resource-alternate` | `TYPE=ID` → `TYPE--ID` | the statute enables `alternate_syntax.resource` |
|
|
| `interaction-alternate` | `!MODE` → `---MODE` | the statute enables `alternate_syntax.interaction` and `MODE` |
|
|
| `lowercase` | fold the local-part to lower case | the statute declares `resource_id_case: insensitive` |
|
|
| `drop-facet` | remove `+FACET` | always; only on explicit request |
|
|
| `drop-interaction` | remove `!MODE` | always; only on explicit request, with a warning |
|
|
|
|
A generator:
|
|
|
|
- MUST emit the canonical form when the destination allows it;
|
|
- MAY apply the transforms a destination needs, and only those the
|
|
namespace's statute permits;
|
|
- MUST refuse, rather than emit a form the receiver would misread, when the
|
|
destination needs a transform the statute does not permit;
|
|
- MUST check the length limit (§13) after all transforms and refuse rather
|
|
than truncate.
|
|
|
|
Outbound service mail (From, Reply-To) stays canonical unless a destination
|
|
transform is known to be needed.
|
|
|
|
### 12.2 Integrating with constrained endpoints (informative)
|
|
|
|
To integrate with an endpoint that rejects or rewrites MAS syntax:
|
|
|
|
1. Observe what the endpoint refuses or rewrites.
|
|
2. Enable the matching acceptance in the statute (stand-ins, identifier
|
|
case).
|
|
3. Describe the endpoint as a **destination profile** in the generator's
|
|
configuration: the list of transforms it needs.
|
|
|
|
Concrete profiles are implementation configuration, not part of this
|
|
specification.
|
|
|
|
*Example.* An IONOS mail-forward form (observed 2026-10) refuses `=` and
|
|
forces lower case. With a statute that enables `alternate_syntax.resource`
|
|
and declares `resource_id_case: insensitive`, the profile
|
|
`resource-alternate` + `lowercase` turns `ticket=GS-85QJ8WC09P+comments`
|
|
into `ticket--gs-85qj8wc09p+comments`, which the receiving namespace
|
|
correlates to the original resource. Google Groups accepts `=` but stores
|
|
members in lower case, so it needs only `lowercase`.
|
|
|
|
## 13. Length
|
|
|
|
An SMTP local-part is limited to 64 octets.
|
|
|
|
Generators MUST enforce the underlying transport limit after encoding and
|
|
after destination transforms. `--` adds one octet and `---` adds two.
|
|
|
|
Because the budget is small, v0.1 permits at most one facet and one
|
|
interaction, and generators MUST NOT emit both simultaneously.
|
|
|
|
## 14. Security
|
|
|
|
1. MAS identifiers are not credentials.
|
|
2. Resource knowledge grants no authority.
|
|
3. Interaction selectors are not commands.
|
|
4. Dynamic addresses MUST define handling for bounces, unknown resources,
|
|
expired resources, verification traffic, and abuse.
|
|
5. Receivers MUST avoid backscatter behavior.
|
|
6. Syntax-derived classifications MUST NOT substitute for statute metadata.
|
|
7. `$` and `^` MUST NOT be rendered as payment/contract semantics in v0.1.
|
|
8. Authentication remains external to MAS.
|
|
9. A statute endpoint is security-relevant configuration and SHOULD be
|
|
protected with the same care as other origin-wide metadata.
|
|
10. A receiver that automatically replies to mail sent to an intake or
|
|
interaction address turns any forged sender into outbound mail to a
|
|
third party. Such a receiver SHOULD reply only when the sender is
|
|
authenticated (for example DMARC alignment pass), MUST bound the volume
|
|
of such replies (rate limits or caps), and MUST NOT reply to automated
|
|
mail (`Auto-Submitted` other than `no`, or `Precedence` `bulk`, `list`
|
|
or `junk`).
|
|
|
|
## 15. Conformance classes
|
|
|
|
### 15.1 P1 parser
|
|
|
|
A P1 parser:
|
|
|
|
- validates canonical ASCII syntax;
|
|
- parses resource binding and facet;
|
|
- rejects `!`, `$`, and `^` as MAS operators;
|
|
- does not classify opaque target kind by punctuation.
|
|
|
|
### 15.2 P2 parser
|
|
|
|
A P2 parser additionally parses `!`.
|
|
|
|
### 15.3 Generator
|
|
|
|
A generator:
|
|
|
|
- emits only canonical operator order;
|
|
- emits no empty component;
|
|
- emits no reserved operator within a value;
|
|
- emits at most one `+`;
|
|
- emits at most one `!`;
|
|
- MUST NOT emit both `+` and `!` in v0.1;
|
|
- enforces the SMTP local-part octet limit.
|
|
|
|
### 15.4 Statute-aware implementation
|
|
|
|
A statute-aware implementation additionally validates the discovery document
|
|
against the normative schema and applies only explicitly declared equivalence
|
|
and classification rules.
|
|
|
|
## 16. Reserved future work
|
|
|
|
Future specifications may define:
|
|
|
|
- Unicode canonical grammar;
|
|
- escaping;
|
|
- signed statutes and signed semantic assertions;
|
|
- interaction negotiation;
|
|
- service discovery;
|
|
- economic request/offer/acceptance/settlement;
|
|
- condition tokens;
|
|
- IANA registrations.
|
|
|
|
## 17. One-sentence definition
|
|
|
|
**Mail Address Semantics is a voluntary convention for naming people, actors
|
|
and functions, and for addressing resources, facets, and optional interaction
|
|
preferences through ordinary email addresses while keeping classification,
|
|
authority, authentication, equivalence, and delivery implementation explicit
|
|
and external to the address syntax.**
|