mas_modes.mailer.Mailer is the only outbound path (own SQLite + lock), shared by the ticket service and both EmailMode roles. Over the cap mail is held and reported (send-cap-reached, held); held mail is purged after email-held-duration-max (7d) and not stored beyond emails-held-storage-max (100MB). The ticket service's legacy outbox is imported once so the live count carries over (checked on a copy of the live DB: 4 sent). Entrypoint passes the cap and both limits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5787@bnt-lap001 Assistant-Session: 5db26b82-138b-40cc-9856-4d5eb0f752fd
57 lines
3 KiB
Markdown
57 lines
3 KiB
Markdown
# Reuse surface
|
|
|
|
This repository is the email building block for a multimodal communication
|
|
framework that is yet to be designed (INTENT.md, *Mode reference
|
|
implementation*). This page says what such a framework can depend on, and
|
|
how stable each part is.
|
|
|
|
## Depend on these
|
|
|
|
| Part | Where | Stability |
|
|
|---|---|---|
|
|
| MAS address spec | `mas-v0.1-spec/` (v0.1.1), `mas-v0.2-spec/` (draft) | v0.1.1 stable. v0.2 draft until a second implementation passes its corpus (MAS-WP-0009) |
|
|
| Mode contract | `mas-modes-v0.1-spec/` | v0.1 draft. Changes are versioned; messages carry `mas_modes_version` |
|
|
| Gateway event | `mas-modes-v0.1-spec/schema/mas-event-v0.1.schema.json` | v0.1. Events carry `mas_event_version` |
|
|
| Conformance corpora | the bundles' `conformance/` | Normative for their version. Consume them unchanged |
|
|
| `mas_core` | parse (no I/O), discover (exact host), resolve (pure), generate / `for_destination` | Python reference library |
|
|
| `mas_gateway` | MTA `pipe` and provider `webhook` → event | Reference adapter. The event is the interface, not the code |
|
|
| Postfix profile | `integrations/postfix/` | Tested against Postfix 3.7 (`tests/test_postfix_profile.py`) |
|
|
|
|
## Integrating as an outside master
|
|
|
|
Configure the resource type as `slave` (`mas_modes.email_mode.RoleConfig`),
|
|
point `master_url` at your system, set `master_peer` to your peer id, and
|
|
exchange a key with the email operator. Every request in both directions is
|
|
signed (CONTRACT.md section 7; `mas_modes.signing`, standard library only).
|
|
You then:
|
|
|
|
- receive `case.intake` and `case.message`, each carrying a gateway event;
|
|
- answer `case.assign` with your own case id; email adopts it as
|
|
`TYPE=ID@domain`;
|
|
- send replies with `mail.send` (`in_reply_to` a recorded message);
|
|
principle 10 can refuse them, and over the deployment's one send cap
|
|
they are held (`held: true`) instead of sent;
|
|
- decide per case on `autonomous_send` and `transfers`: `block`, or a
|
|
mode webhook with that mode's `peer`. The peer must be one the email
|
|
operator has a key for;
|
|
- own every timeout; end a handoff with `handoff.cancel`.
|
|
|
|
## Integrating a mode
|
|
|
|
Implement the mode endpoint in CONTRACT.md: accept `handoff.request`,
|
|
`handoff.update` and `handoff.cancel` only when signed by email, and post
|
|
`handoff.status`, signed with your peer id, to exactly the `status_url` of
|
|
that handoff (it carries a per-handoff token), with an increasing `seq`.
|
|
Never send `timed-out`.
|
|
`mas_modes/stubs/callback.py` is a complete example.
|
|
|
|
## Examples only, not products
|
|
|
|
- `examples/ticket_service/`: the reference ticket service, used as the
|
|
store for email-mastered cases.
|
|
- `mas_modes/stubs/`: the callback stub and the stub outside master.
|
|
They never contact a person or a service.
|
|
- `mas_modes/email_mode.py`: the reference email side. It authenticates
|
|
every peer (section 7), but it is single-process with SQLite, has no key
|
|
rotation, and serves plain HTTP. Put it behind TLS before exposing it
|
|
beyond loopback. The contract is the interface.
|