2026-10-08 00:14:14 +02:00
# MAS — Mail Address Semantics
2026-10-19 10:10:23 +02:00
## Status
**Phase 1 (reference experiment) passed** its decision gate on 2026-10-18
(MAS-WP-0002, `docs/experiment-review.md` ). All ten success criteria were
met, including the live run through Gmail, Microsoft 365 and Postfix.
**Phase 2** is described in *Phase 2 intent* below. The phase-1 sections
are kept as the record of what was tested; where phase 2 changes them, it
says so.
## Intent (phase 1)
2026-10-08 00:14:14 +02:00
Build the smallest practical implementation of **Mail Address Semantics (MAS) v0.1** that can prove whether the specification is useful in real email workflows.
The project should demonstrate that ordinary email addresses can carry limited, human-readable and machine-parseable semantics for:
- opaque organizational targets,
- resource addressing,
- facets,
- optional interaction preferences,
without modifying SMTP and without turning addresses into credentials, commands, contracts, or payment instructions.
The implementation must preserve the core architectural boundary of MAS:
> **Parsing is local and deterministic. Discovery is networked. Policy is pure. Delivery remains external.**
The first implementation should be deliberately narrow. Its purpose is not to build a full MAS ecosystem, but to test the convention against real messages, real routing, resource lifecycle, malformed input, and namespace metadata.
---
## Core hypothesis
MAS is valuable if the following can be made both simple and reliable:
```text
ticket!callback@great -service.example
```
can express:
> initiate a ticket interaction with callback as the preferred continuation mode
and result in a stable resource address:
```text
ticket=GS-41872@great -service.example
```
that can subsequently be used to correlate email with that ticket without embedding application identifiers in subject lines.
If this lifecycle works cleanly through ordinary email infrastructure, MAS has demonstrated its core value.
---
## Design principles
### 1. The parser does not use the network
Parsing operates only on the address syntax.
It must:
- validate canonical MAS syntax,
- produce an explicit parse tree,
- identify which MAS profile the syntax requires,
- never perform statute discovery,
- never infer person, actor, or function kind from `.` , `-` , or `_` .
Example:
```text
ticket!callback
```
parses structurally as an interaction-bearing target and records:
```text
required_profile = P2
```
Whether the addressed namespace supports P2 is decided later.
---
### 2. Discovery returns facts or typed failure
MAS discovery is responsible only for retrieving and validating the exact-host statute.
Given:
```text
anna.mueller@acme .coulomb.social
```
discovery targets:
```text
https://acme.coulomb.social/.well-known/mas
```
It must not walk parent domains implicitly.
Discovery should return either:
```text
ValidatedStatute
```
or a typed failure such as:
```text
NotFound
HttpFailure
CrossHostRedirect
SchemaInvalid
NamespaceMismatch
InheritanceCycle
UnsupportedVersion
```
Failure to discover MAS metadata does not invalidate the email address.
---
### 3. Policy is pure
Policy evaluation takes:
```text
parse tree
+
validated statute
+
optional local registry
```
and produces semantic interpretation.
Policy performs no network access.
This allows the same policy implementation to be exercised entirely through the conformance corpus.
---
### 4. No semantic inference from naming punctuation
The following remain naming hints only:
```text
.
-
_
```
Therefore:
```text
bernd.worsch@
research-companion@
invoice_ingest@
```
may visually suggest person, actor, and function, but machine classification requires statute or registry metadata.
No statute means:
```text
kind = opaque
```
not:
```text
kind = person-like
```
---
### 5. Resource semantics are the primary proof
The initial implementation should strongly support:
```text
type=id@
```
Resource addresses must remain usable as correlation identifiers while remaining independent of authorization.
Example:
```text
ticket=GS-41872@
```
identifies the ticket communication endpoint.
It does not grant permission to inspect or mutate ticket GS-41872.
---
### 6. Resource addressability outlives mutability
Closed resources remain addressable.
A closed ticket may:
- archive later email,
- reject mutation,
- return lifecycle information,
- create a linked follow-up ticket.
It must not become mutable merely because mail can still reach its address.
---
### 7. Facets degrade safely
A facet:
```text
ticket=GS-41872+comments@
```
may be stripped by existing email infrastructure.
If so, the remaining address:
```text
ticket=GS-41872@
```
still identifies the base resource.
Facet preservation is desirable but never assumed.
---
### 8. Interaction remains a preference
The P2 syntax:
```text
ticket!callback@
```
requests that the addressed endpoint continue through `callback` .
It does not imply:
- who initiates the callback,
- that callback is available,
- that callback has been accepted,
- an SLA,
- a command.
The application decides whether and how to satisfy the request.
2026-10-19 10:35:56 +02:00
*(Phase 2: `!MODE` is a requested **handoff** from email to another mode.
The mode contract defines what can happen to it, including refusal. It
stays a request, never a command. See Mode reference implementation.)*
2026-10-08 00:14:14 +02:00
---
### 9. Economic syntax remains closed
The characters:
```text
$
^
```
remain reserved only.
No implementation work on price, reward, conditions, offers, contracts, or settlement belongs in this phase.
---
2026-10-19 10:10:23 +02:00
### 10. Auto-reply endpoints are gated and capped
*(Added in phase 2, from the live run.)*
An address that answers automatically, such as `ticket!callback@` , turns
any forged `From:` into outbound mail to a third party. Any endpoint that
replies automatically therefore:
- replies only when the sender is authenticated (DMARC pass, read from
trusted `Authentication-Results` );
- never replies to automated mail or to the null sender;
- caps how much it can send in total.
This is application policy, not MAS syntax. But a MAS deployment that
leaves it out reflects mail at third parties, and the reference
implementation must show how to avoid that.
---
2026-10-08 00:14:14 +02:00
## Initial architecture
The first repository should contain only the pieces needed for the experiment.
```text
mas/
├── mas_core/
│ ├── parser
│ ├── model
│ ├── discovery
│ ├── policy
│ └── lint
├── cli/
│ └── mas
├── conformance/
│ ├── addresses
│ ├── statutes
│ └── properties
├── examples/
│ ├── statute/
│ └── ticket_service/
├── gateway/
│ └── smtp_or_webhook_to_http/
└── docs/
```
The existing MAS v0.1 specification bundle is the normative basis.
---
## Initial components
### `mas-core`
Python reference implementation.
Responsibilities:
- parse canonical MAS syntax,
- expose structured parse objects,
- identify required profile,
- validate statutes,
- discover exact-host statutes,
- apply equivalence rules,
- evaluate semantics from parse tree plus statute,
- lint statutes.
The first implementation should be clear and auditable rather than clever.
---
### `mas-cli`
Primary human interface.
Initial commands:
```text
mas parse ADDRESS
mas explain ADDRESS
mas discover HOST
mas lint-statute FILE
mas test
```
`mas explain` should clearly distinguish:
```text
syntactic facts
discovered namespace facts
policy-derived semantics
unknowns
```
A discovery failure must remain visible.
---
### `mas-conformance`
The conformance corpus should become a first-class package rather than an incidental test directory.
It should contain:
- positive syntax cases,
- negative syntax cases,
- parser expectations,
- generator expectations,
- statute validation cases,
- discovery policy cases,
- property and boundary cases.
Every future language implementation should consume this corpus unchanged.
---
### Static statute
The first service does not need a statute server framework.
A static file served at:
```text
/.well-known/mas
```
is sufficient.
The point is to test discovery semantics, not middleware.
---
### Generic mail gateway
The first mail integration should translate inbound mail into a simple HTTP request.
It may receive mail via:
- a local SMTP listener, or
- a provider-style inbound webhook.
Its responsibility should be minimal:
```text
email recipient
→ MAS parse
→ statute/policy resolution
→ normalized HTTP event
```
It should not contain ticket-specific business logic.
---
### Reference ticket service
A deliberately small example application proving the canonical lifecycle.
Required behavior:
#### Initial interaction
Mail to:
```text
ticket!callback@great -service.example
```
creates a ticket.
The service generates:
```text
ticket=GS-41872@great -service.example
```
#### Subsequent correlation
Mail sent to:
```text
ticket=GS-41872@great -service.example
```
is associated with that ticket without depending on the subject line.
#### Closed lifecycle
After the ticket is closed, its address remains routable.
Later mail must not silently reopen or mutate the resource unless application policy explicitly allows it.
---
2026-10-19 10:10:23 +02:00
## Explicit non-goals (phase 1)
*Phase 2 removes the address composer and the MTA integration profile
from this list (see Phase 2 intent). The rest still applies.*
2026-10-08 00:14:14 +02:00
The initial implementation does not include:
- TypeScript reference library,
- Go implementation,
- Postfix policy daemon,
- central MAS registry,
- mail client plugin,
- browser extension,
- address composer,
- payment semantics,
- electronic signatures,
- generalized service marketplace,
- production identity federation,
- automatic DNS-parent inheritance.
These should be considered only after the reference experiment succeeds.
---
## Success criteria
The first experiment succeeds if:
1. the parser conforms to the shared fixture corpus;
2. parser behavior requires no network access;
3. discovery produces validated statute or typed failure;
4. policy evaluation is deterministic and offline;
5. `mas explain` never invents semantics on discovery failure;
6. the ticket lifecycle works end to end;
7. ticket identifiers no longer need to be encoded in subject lines;
8. closed resources remain addressable without becoming mutable;
9. facet loss degrades safely;
10. the experiment exposes no need to change SMTP itself.
---
2026-10-19 10:10:23 +02:00
## Phase 2 intent
Phase 1 showed that the convention works through ordinary infrastructure
once the MTA is configured correctly, and that resource addressing is the
strongest part of MAS. Phase 2 turns the experiment into a usable
reference. It still stays narrow.
### Role of this repository
This repository is the **spec workbench** as well as the reference
implementation. It maintains the normative bundles (`mas-v0.1-spec/` as
v0.1.1 errata, and the `mas-v0.2-spec/` draft) and records every change as
a proposal in `docs/spec-change-proposals.md` . Every spec change needs:
- evidence from a test or a live run;
- conformance fixtures in the bundle;
- an implementation in `mas_core` .
Implementation and spec move together. A version is declared final only
after a second implementation or deployment has passed its corpus
unchanged.
### Goals
1. **Adoptable integration.** A documented, tested MTA profile, so that
P2 addresses survive. Default Postfix drops them. Postfix is done; Exim
only on demand.
2. **Forwarder-safe generation.** Provider forms refuse `=` and fold case.
The generator and `mas compose` emit the canonical form and, where the
statute allows it, a forwarder-safe form. When that form would be
misread, they refuse to emit it.
3. **v0.2 to final.** Settle stand-ins, destination transforms and
`resource_id_case` . Finalize once an independent implementation
validates the corpus.
4. **Safe reference behavior.** The reference service demonstrates
principle 10.
2026-10-19 10:35:56 +02:00
5. **Email as a building block.** A mode reference implementation makes
MAS email a capable, reusable component of a larger multimodal
communication framework. That framework is yet to be designed and is not
built here. See below.
2026-10-19 10:10:23 +02:00
2026-10-19 10:35:56 +02:00
### Decided: interaction modes are handoffs (P2)
2026-10-19 10:10:23 +02:00
2026-10-19 10:35:56 +02:00
*Decided by the founder on 2026-10-19. This replaces the open question
from the first phase-2 draft.*
2026-10-19 10:10:23 +02:00
2026-10-19 10:35:56 +02:00
Phase 1 proved resource addressing strongly, and interaction only partly:
`!callback` states the intent, but the service still has to ask for a
number and a time. The decision gives `!MODE` defined semantics, but at
the **mode-contract** layer, not in address syntax:
- `!MODE` requests a handoff of the conversation from email to `MODE` .
The address grammar and statute fields stay as they are. `intake_for`
still links an intake target such as `ticket` to its resource type.
- What a handoff does is defined in the mode contract (below): negotiate,
run, time out, complete, fail or be refused. These are statuses reported
back to email, not side effects of parsing.
- The P2 work is narrowed accordingly. No new address mechanism is added
for modes (beyond the existing `---` stand-in) unless the contract needs
it.
## Mode reference implementation
### Purpose
Make MAS email a **capable building block** for a multimodal
communication framework, which is yet to be designed. The framework will
combine email with other modes (callback, chat, video, SMS, web forms, and
so on). This repository supplies the email part, plus enough of an
interface landscape around it that the framework can be designed against
something that runs.
### Boundary
- **Email is the only real communication channel.** The repository sends
and receives real mail. It does not place calls, run chats, send SMS or
integrate with telephony or messaging providers.
- **Other modes exist only as test stubs.** A stub speaks the mode contract
and simulates how a mode develops. It never contacts a person or an
outside service.
- **Callback first.** One fully worked stub, callback. The contract is
generic, so other modes plug in the same way. A second, trivial stub may
exist only to prove that.
- The framework itself, orchestration beyond what email-as-master needs,
and connectors to real CMS, ticketing or support products are out of
scope.
### Two roles for email
Email takes one of two roles, **configured per resource type** and fixed
for the life of a case. One deployment can do both, for example `ticket`
mastered by email and `case` slaved to an external CMS.
**Email as master.** Email is the reference for the communication. It owns
the case and its durable thread. When a handoff is requested
(`ticket!callback@` ), email negotiates the missing details by email,
hands off to the mode, and records every mode status in the thread. When
the other mode times out, fails or ends, email **picks the conversation
back up**. Email owns the timeouts in this role.
**Email as slave.** Email is one element in a control flow owned
elsewhere: a CMS, a ticketing or support system, or the future framework.
The email side provides case-based communication for that master:
- **The master issues the case identifier; email adopts it.** The case is
exposed as a resource address (for example `case=EXT-123@` ) under the
statute. Email maps the identifier but never invents it. Intake mail
without a case is reported to the master, which answers with the
identifier to use.
- Inbound mail becomes events for the master.
- **The master configures whether email may send on its own,** per case:
for example acknowledgements, or negotiation questions. Otherwise email
sends only when the master instructs it.
- Mode transfers are **controlled from outside** . The master may block
them, or prime them with a mode webhook that email calls when a
`!MODE` request arrives.
- **Timeouts belong to the master.** Email reports, but does not
escalate on its own.
- Principle 10 holds in both roles. A send the master requests can still
be refused (unauthenticated sender, automated mail, cap reached). The
refusal is reported back to the master.
### Callback stub
The callback stub simulates the relevant ways a callback can develop. Its
scenarios are **scripted and deterministic** : chosen by a fixture or a
test header, and reproducible in pytest and as contract fixtures.
- **Negotiation over email.** The number or time is missing, so the service
asks by email. The customer replies, and the request becomes
schedulable. This is the gap phase 1 found.
- **Outcome lifecycle.** Scheduled; attempted with no answer; retried;
completed; failed; expired. Every status reaches the email thread
(master) or the outside master (slave).
- **Refusal paths.** The mode is unavailable or not enabled, the request
is declined, or it is out of hours. Email falls back and says why.
## Current scope and reuse surface
What the larger framework can build on. Each item is versioned and tested
on its own.
| Reuse surface | What it is | Status |
|---|---|---|
| MAS address spec | `mas-v0.1-spec/` (v0.1.1), `mas-v0.2-spec/` (draft): grammar, statute schema, conformance corpora | exists |
| `mas_core` | parse (no I/O), discover (exact host), resolve (pure), generate / `for_destination` | exists |
| Gateway event | `mas-gateway` pipe/webhook → normalized JSON event with parse, semantics and trusted sender authentication | exists; to be versioned with a schema |
| Postfix profile | `integrations/postfix/` : receiving setup that keeps MAS syntax intact | exists |
| **Mode contract** | Language-neutral, versioned, separate from the address spec. It defines handoff requests, mode statuses, timeouts, roles (master/slave), outside-master commands (send, block, prime webhook, assign case id) and refusals. Comes with JSON schemas and conformance fixtures | new |
| **Email mode reference** | Email side of the contract in both roles, built from the gateway and the reference ticket service | new |
| **Stub mode server** | Scriptable stub that speaks the contract, callback first | new |
| **Stub outside master** | Minimal fake CMS/ticketing master that drives email in slave mode end to end | new |
The reference ticket service and the stubs are **examples and test
fixtures, not products**. The contract and schemas, `mas_core` and the
address spec are the parts meant to be reused unchanged.
## Not in phase 2
2026-10-19 10:10:23 +02:00
Other language implementations (except one used to validate v0.2), a
policy daemon, a central registry, mail-client plugins, signed statutes,
implicit parent inheritance, and economic semantics. A web composer is out
2026-10-19 10:35:56 +02:00
until something asks for one. Real non-email modes, telephony or messaging
integrations, connectors to real CMS or ticketing products, and the
multimodal framework itself are out too.
2026-10-19 10:10:23 +02:00
2026-10-19 10:35:56 +02:00
## Phase 2 is done when
2026-10-19 10:10:23 +02:00
1. a fresh Postfix install, using only `integrations/postfix/` , delivers
the full corpus unchanged and refuses relaying;
2. `mas compose` produces correct forms for every destination observed so
far, and refuses the rest;
3. v0.2 is declared final, or is withdrawn with recorded reasons;
2026-10-19 10:35:56 +02:00
4. the handoff reading of P2 is recorded in the v0.2 spec text, and the
address spec points to the mode contract;
5. the live test environment is retired, with its evidence archived;
6. mode contract v0.1 is published with JSON schemas and fixtures;
7. the email mode reference passes them in both roles: as master against
the callback stub, and as slave under the stub outside master;
8. every callback scenario (negotiation, outcome lifecycle, refusals) runs
deterministically in the test suite.
2026-10-19 10:10:23 +02:00
---
2026-10-08 00:14:14 +02:00
## Longer-term direction
If the experiment validates the concept, MAS may later grow into:
- additional language libraries,
- infrastructure gateways,
- mail client affordances,
- signed semantic metadata,
- richer interaction discovery,
- economic profiles,
- service-market coordination.
Those extensions should remain subordinate to the core principle:
> **MAS should add useful semantics to email without making ordinary email depend on MAS.**