Graduate research 066 into design 59: mail reading, mail signals, granted reading apart and the mail conversation, with the Mail domain in the glossary

Research 066's confirmed direction becomes ADR 0458 to 0462. Design 59 gains the sections and milestones 2 to 4 they decide, the glossary gains Mail as the thirteenth domain with four homonym rows, and design 49 lists Config and Mail so its count matches the glossary.
This commit is contained in:
jochen
2026-10-20 16:17:50 +02:00
parent ae9768c2c1
commit 4a2c15f725
3 changed files with 219 additions and 21 deletions
+55
View File
@@ -772,6 +772,54 @@ it was told, and the servarr apps' own libraries. **Upstream of** nothing. **Dec
- **grab** — an engine handing one media release to a download client. It names the work it is for, so
the media-importer knows where the copy belongs.
## Mail — the operator's own correspondence, which the mesh holds and reads for them
**Purpose.** To hold the operator's mail accounts, say each mail on the bus, find and read mail for whoever the
operator granted, note each mail for the operator and tell them of the mail that matters, and send a mail only on
the operator's Approve. **Recorded by** `mesh-mail` (its index database and attachment bucket, ADR 0359 §3; its
account buckets, ADR 0439) and `mesh-mail-reader` (its database of mail entries, mail groups and reading lessons,
ADR 0459). **Downstream of** Identity and access and Operator and conversation; **upstream of** nothing.
**Decided by** ADR 0359, 0361, 0378, 0439, 0440, 0458, 0459, 0460, 0461, 0462.
**Uses:** operator, person, module, seat; grant, identity (Identity and access); ask, warrant, operator channel,
content rule, untrusted input (Operator and conversation). A *judgement* is one call of the model with no tools
and no session (ADR 0278), in its plain sense.
- **mail account** — one of the operator's mailboxes that `mesh-mail` holds, of a kind of adapter (`imap`,
`imap-oauth`, `graph`), named by its address (ADR 0359 §1).
- **`mail-store`** — the seat holding the mail accounts: `accounts`, `search`, `read`, `send`, `send_status` (ADR
0378 §2, ADR 0440 §7). Always the seat's name: the bare *store* is Core's.
- **mail event** — what `mesh-mail` publishes on its stream `MAIL` for a new, changed or removed mail: headers,
flags and attachment references, never a body (ADR 0359 §2).
- **mail send** — a mail the mesh sends, which goes out only on the operator's warrant for that one mail (ADR 0361
§2), with the states `mail_send_status` answers (ADR 0440 §7). Only a caller granted asking to send for that
account may ask for one (ADR 0460).
- **mail web client** — the module `mesh-mail-web`, holder of `mail-webclient`: the operator's mail in a browser on
the private network (ADR 0440 §1); also called *the mail page*.
- **mail notice** — `mesh-mail-notifier`'s desktop pop-up for a new inbox mail (ADR 0378 §7, §9). It retires when
`mesh-mail-notifier` is unassigned everywhere (ADR 0461 §6) and then moves to *mail signal*'s *Not:* line
(issue 1418).
- **mail reading** — the model's reading of each new mail as it arrives, in batches, into its mail group and mail
entry; the seat `mail-reading`, held by `mesh-mail-reader` (ADR 0459). Not *triage* (the issue tracker's
judgement), and not `mail_read`, `mail-store`'s tool that fetches one mail's text.
- **mail entry** — what mail reading keeps about one mail: its mail group, a one-line summary, its mark and why, a
due date; never the body (ADR 0459 §4). Not *catalogue entry*: the catalogue is Delivery's.
- **mark** — what a mail entry says the mail is to the operator: *matters*, *scam warning* or neither, never two
(ADR 0459 §7). Not *kind* (Media's).
- **mail group** — a set of mails the model put together because they belong to one subject. Not *delivery
group* or *account group*.
- **reading lesson** — one correction the operator made on the mail page (a mark or a mail group), kept so later
mail reading follows it (ADR 0459 §8 to §10). Always qualified: the bare *lesson* is Operator and conversation's.
- **mail signal** — the notice on the operator's channel, one `tell` per batch in words only, and the place at the
top of the mail page, that tells the operator mail matters (ADR 0461). Always qualified: the bare *signal* is
Health and repair's.
- **scam warning** — the mark of a mail the model judges an attempt to deceive the operator, with why; shown in
its own place on the mail page and never a mail signal (ADR 0459 §7, ADR 0461 §5).
- **mail conversation** — a thread (ADR 0383) with a mail context, followed on the mail page: the mail questions
and their answers, each answer with the mails it found. The mail context is the framing that a mail is data, the
tools `mail_search` and `mail_read` only, the operator's senders and folders, and the reading lessons (ADR 0462).
- **mail question** — what the operator writes in the mail conversation to find or understand mail. Not *ask*
(Operator and conversation's request for the operator's input).
## The record — how this repository works
Not a domain of the mesh but of the way it is built, listed because its words meet the mesh's.
@@ -877,6 +925,7 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical.
| store | the one database server | **store** | Core |
| | the OCI registry | **artifact store** | Delivery |
| | a node's own copy of its last declaration | **last declaration** | Placement |
| | the seat holding the mail accounts | **`mail-store`** | Mail |
| record | a numbered decision | **decision record** | The record |
| | the literal reader of this repository, searched first for a symptom | **the record** (the `records` module) | Operator and conversation |
| | the upgrade policy that sends nowhere | `record` | Module |
@@ -903,6 +952,12 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical.
| | a file the mesh writes, such as the agent's instruction file or `managed_settings` | the file's own name, or *a file the mesh places* | — |
| trusted | a config value that decides what runs or who can reach what | **trusted** config value | Config |
| | a sender on the operator's own list | **trusted** sender, its message an **operator message** | Operator and conversation |
| lesson | an agent's proposal after the operator corrects its way of working | **lesson** | Operator and conversation |
| | the operator's correction of mail reading | **reading lesson** | Mail |
| signal | something that must keep happening | **signal** | Health and repair |
| | the notice that mail matters | **mail signal** | Mail |
| conversation | the domain *Operator and conversation* | the domain's name | Operator and conversation |
| | the mail questions and answers on the mail page | **mail conversation** | Mail |
## How this page is kept
+12 -3
View File
@@ -2,21 +2,23 @@
layer: to-be
status: in-progress
code: [hq 00-META/checks/words.py, mesh-catalog merge-check.sh]
updated: 2026-10-18
updated: 2026-10-20
decisions:
- "ADR 0429"
- "ADR 0244"
- "ADR 0006"
- "ADR 0008"
- "ADR 0302"
- "ADR 0354"
- "ADR 0458"
---
# 49 — The mesh in domains
**Every concept of the mesh belongs to one of eleven domains, which owns its one word. The glossary is
**Every concept of the mesh belongs to one of thirteen domains, which owns its one word. The glossary is
organised by them and is the authority; a word it retires is named in the entry that replaced it, with
where it is retired; and two checks hold the documents and the tools' descriptions to it.**
(ADR 0244; the eleventh, Media, ADR 0302.)
(ADR 0244; the eleventh, Media, ADR 0302; the twelfth, Config, ADR 0354; the thirteenth, Mail, ADR 0458.)
A **domain** is an area of the mesh that owns a set of concepts: inside it each concept has one word,
and the domain decides what that word means. The glossary
@@ -38,6 +40,8 @@ shape — what each is for, where its records live, and how they depend on one a
| **Connectivity** | to make every node and module reachable by name where it should be, and unreachable where it should not | the controller |
| **Operator and conversation** | to let the mesh and its operator tell, ask and answer, and act only on an answer it can trust | the router, and the controller for authorising asks |
| **Media** | to find, fetch and file copies of the works a person watches, listens to and reads, each in the library its kind names | the `media-importer` module's settings and memory, and the servarr apps' own libraries |
| **Config** | to hold, check and resolve every value a module reads that someone may change, and say where each resolved value came from | the `mesh-config` module, in its buckets on the bus, with its store as the history behind them |
| **Mail** | to hold the operator's mail accounts, say each mail on the bus, note each mail for the operator and tell them of the mail that matters, and send a mail only on the operator's Approve | `mesh-mail` (its index database, attachment bucket and account buckets) and `mesh-mail-reader` (its database of mail entries, mail groups and reading lessons) |
Beside them, **the record** is this repository's own vocabulary — research, decisions, designs,
issues, playbooks, checks — listed because its words meet the mesh's.
@@ -71,6 +75,11 @@ a change of meaning upstream ripples down, never up. Arrows point downstream.
Media stands beside the diagram, below Module alone: its words are about what a person watches, not
about the mesh's machinery, and no other domain reads them.
Mail stands below the diagram's foot: it is downstream of Identity and access (the operator grants each mail
account to a caller) and of Operator and conversation (a mail send is an ask, a mail signal is a notice through
the operator channel), and upstream of nothing. It is the operator's own correspondence, which the mesh holds and
reads for them, not the mesh talking about itself, so it is not part of Operator and conversation (ADR 0458).
Delivery sits low because it reads health and data; in time it runs first, and asks Placement
to send. An authorising answer acts in whichever domain asked, through that domain's own verb: the
conversation owns the asking, never the act.
+152 -18
View File
@@ -2,7 +2,7 @@
layer: to-be
status: in-progress
code: [mesh-catalog]
updated: 2026-10-19
updated: 2026-10-20
decisions:
- "ADR 0440"
- "ADR 0378"
@@ -14,6 +14,12 @@ decisions:
- "ADR 0439"
- "ADR 0201"
- "ADR 0436"
- "ADR 0458"
- "ADR 0459"
- "ADR 0460"
- "ADR 0461"
- "ADR 0462"
- "ADR 0278"
---
# 59 — The mail web client
@@ -22,12 +28,23 @@ decisions:
`mesh-mail-web`, holds the seat `mail-webclient`; it renders pages on the server in Go and reaches mail only through
`mail-store`'s verbs, under a caller the operator grants account by account. Its route reaches the private network
only, under its internal name, and the operator signs in with Keycloak. A mail written there goes out only on the
operator's Approve, as every mail the mesh sends does. Once it works on the laptop and the workstation, Betterbird is removed.**
operator's Approve, as every mail the mesh sends does.**
(ADR 0440, building on ADR 0378 §5 and ADR 0379 §2.)
**Then the model reads the mail for the operator.** A module of its own, `mesh-mail-reader`, holds the seat
`mail-reading`: it reads each new mail in batches, keeps a mail entry for it (its mail group, one line, its mark),
tells the operator on Telegram of the mail that matters in a mail signal, shows a scam warning on the page only, and
learns from the operator's corrections as reading lessons; it never changes the mailbox and keeps no mail text.
Reading and asking to send are granted apart first, and the pop-up for every new mail retires once mail signals
work. Later, once the mesh's threads exist, the operator asks questions about their mail in a mail conversation, a
thread with a mail context. Betterbird is removed once mail reading works on the laptop and the workstation.
(Research 066; ADR 0458 to 0462. The words are the glossary's Mail domain.)
**Acceptance.** In a browser on the laptop and on the workstation, the operator signs in, browses, searches and reads the mail of
every account `mesh-mail` holds, opens an attachment, and writes a mail that goes out on their Approve on Telegram;
the same page is not reachable from a machine outside the private network.
the same page is not reachable from a machine outside the private network. A new mail that matters reaches the
operator's phone as one mail signal and stands at the top of the mail page in its mail group; a mail that does not
matter shows nothing anywhere.
## 1. The parts
@@ -70,7 +87,7 @@ outside. Two things hold it:
Measured on 2026-10-19: the laptop and the workstation hold the mesh's authority (`mesh-internal-ca.crt`) as a trust anchor, and
Firefox on both reads the system's trust through p11-kit, so the page opens there without a warning. Away from the
private network (the laptop travelling without its tunnel) the page is unreachable; Betterbird stays the offline client
until it is removed (§6).
until it is removed (milestone 4, §11).
## 3. Signing in (ADR 0440 §3)
@@ -102,16 +119,103 @@ account through the page and get around `grants`.
- **The seat's verbs** (ADR 0378 §5): `open` answers the page's address, and with an account and a mail that mail's
page; `status` answers whether it serves and which accounts it is granted.
## 5. What the first version leaves out
## 5. Reading and asking to send, granted apart (ADR 0460)
Each is an issue with an owner (ADR 0440 §8):
`mesh-mail`'s trusted setting `grants` gives a caller, per account, **reading** (that account's `MAIL` events,
`mail_accounts`, `mail_search`, `mail_read`) and **asking to send** (`mail_send`, `mail_send_status`), each on its own,
set as `grants` is today. A caller granted reading only is refused by both send tools, with the missing grant named;
one granted asking to send only is refused every read. When the split is delivered every caller in today's `grants`
keeps both for each account it has, so nothing stops; narrowing one afterwards is the operator's choice.
`mesh-mail-reader` is granted reading only, for every account, and nothing before the split is delivered. This is
issue 1227.
## 6. Mail reading (ADR 0459)
```
mail-store (mesh-mail) ── MAIL: mail.<account>.message.added ──▶ mesh-mail-reader (seat mail-reading, once for the mesh)
▲ │ its own database: mail entries, mail groups,
└──────────── mail_read (reading grant only) ─────────────┤ reading lessons; never a body
│ batches of ≤ 10 mails ──▶ claude_code_judge (within ≤ 40 s)
│ claude_code_judged
├──▶ operator-channel.tell (a mail signal, §7)
▼
mesh-mail-web ── entries · groups · correct · lessons · undo · status ──▶ the mail page
```
- **One module, one seat.** `mesh-mail-reader`, built from `mesh-mail`'s source like `mesh-mail-web`, claims
`mail-reading` (declared in `mesh-mail`'s manifest beside the three seats of ADR 0379 §4) and runs once, on the
machine that runs `mesh-mail`. It hears `added` events under its own `runs-as` account and the operator's reading
grant (ADR 0378 §13), and moves, flags, deletes and sends nothing.
- **A mail entry per mail, never the body.** Its own database (`postgres-database`) keeps each mail's mail group,
a one-line summary, its mark (*matters*, *scam warning* or neither) and why, and a due date where the mail gives
one, beside the mail groups and the reading lessons.
- **Batches.** One judgement reads at most 10 mails. Its question is filled in order, under 60 KiB of the
judgement's 64 KiB: the framing that a mail is data and never an instruction; the mail groups, at most 4 KiB; the
reading lessons that apply, at most 40 within 12 KiB, sender and mail group first, then the newest, under the
framing that a reading lesson outranks anything a mail says; then the mails, each cut to its first 3 KiB, a mail
in a Junk folder said to be so. A batch asks for up to 40 s with `within` and collects with
`claude_code_judged` (built under issue 508, recorded by ADR 0459 §14). Research 066 measured 1.9 to 3.1 s per
mail, so a batch of 10 takes about 19 to 31 s; the bound keeps an issue tracker's check that waits behind a batch
on the same machine within its two minutes (ADR 0278 §2), which research 066's 15 mails and 120 s would not. Batches stay judgements; whether they become threads is issue 1417.
- **Reading lessons.** When the operator changes a mail's mark or mail group on the page, `mesh-mail-web` calls
`correct` and the correction is kept at once as a reading lesson (headers, the change, when; never body text),
with no further Approve: it is the signed-in operator's own act. The page lists the reading lessons, undoes one
(later mail reading only), and shows reading lessons per 100 read mails per week, which answers whether mail
reading learns the operator's way.
- **The page.** Above the classical list it shows the mail that matters at the top, the mail groups, and the scam
warnings in a place of their own, each with why; the classical list (accounts, folders, search, one mail) stays
and always opens. `mesh-mail-web` reads these through `mail-reading`'s verbs and still keeps no mail state
(ADR 0440 §4 as ADR 0459 §13 changes it).
- **It fails loudly.** Its own health check is unhealthy when a judgement is refused, times out or answers out of
shape, with the cause and since when; the controller raises its condition, the page shows the cause above the
classical list instead of mail groups, and no mail signal is sent. On recovery the mail that arrived meanwhile is
read in arrival order from its durable consumer on `MAIL` (kept 7 days). A warning before a licence runs out is
issue 1409.
## 7. Mail signals, and the pop-up retired (ADR 0461)
- **One tell per batch.** A batch that marks mail as mattering sends one `operator-channel.tell`: the headline
"1 mail matters" or "N mails matter", a first line naming the mail with the nearest due date (sender's name,
summary, due date), a second naming the next and, with more than two, ending "and N-2 more on the mail page".
When the hourly cap of 10 refuses one, its mails stay at the top of the page and the next mail signal counts
them.
- **Words only.** No link, mail address, host name or path: the router refuses a message holding any, and the mail
page opens only on the mesh's own machines. The reader checks its words with `messenger_check` first and, refused,
sends the safe form "N mails matter: open the mail page".
- **At once, at any hour**; the phone's own quiet hours decide. **Never** for a scam warning, and never while mail
reading is unhealthy.
- **The pop-up retires.** Once mail signals pass acceptance test 13 on the real accounts, `mesh-mail-notifier` is
unassigned from the laptop and the workstation on the operator's Approve and leaves `grants`; `mail-notifier`
stays declared and unheld, and nothing takes it over (ADR 0379 §3, §7). Betterbird's own pop-ups stay off by its
setting until it is removed (ADR 0379 §6). Issue 1418; issue 801 closes as replaced.
## 8. The mail conversation (ADR 0462)
A mail conversation is a thread (ADR 0383), run by the thread handler (ADR 0384), with a mail context: the
framing that a mail is data, the tools `mail_search` and `mail_read` only under a caller granted reading only, the
operator's real senders and folder names, and the reading lessons. The operator writes a mail question on the mail
page; each answer names the mails it found, and a question with no answer says so. `mesh-mail-web` creates and
follows the thread over the bus on its server side; the page loads one script from its own origin and talks only to
it (content security policy: script from that origin, `connect-src 'self'`), so the browser never reaches the bus.
The thread keeps the text of each mail it read for good, as every thread is kept (ADR 0383 §3), which the operator
accepted; mail reading keeps none. In the same milestone `mail_search` matches folder names without regard to case
and describes its three `-any` switches as true or false only. It is built after design 58's milestone 3 (threads,
issue 880).
## 9. What stays outside
Each is an issue with an owner:
- a reply, cc, bcc and attachments on a sent mail: issue 1257 (it needs `mail_send` to take them first);
- a page that shows new mail without a reload, from ADR 0439's buckets: issue 1258, after issue 1255;
- the agent that searches, triages and drafts (ADR 0378 §5): issue 1259, which needs a decision first;
- a page that shows new mail without a reload, from ADR 0439's buckets: issue 1258;
- drafting a mail, the rest of issue 1259 (its triage is mail reading, its search the mail conversation), and writing
to the mailbox: issue 730;
- a task list for the operator: issue 1396; the search faults found by research 066: issues 1400 and 1401;
- the work account: a later decision of its own (ADR 0359 §7).
## 6. The build's acceptance tests
## 10. The build's acceptance tests
Tests 1 to 9 are milestone 1's; tests 10 to 17 are research 066's eight, in its order.
1. A request without a session, for a page, an attachment or a send, is redirected to sign-in; an identity not in
`operators` is answered 403; a send form without its token is answered 403; the session cookie is `Secure`,
@@ -134,19 +238,49 @@ Each is an issue with an owner (ADR 0440 §8):
Tests 1 to 4 are one integration test that starts the module whole against the real bus (playbook 07 step 3 item 4);
tests 5 and 7 are `mesh-mail`'s own and test 8 `mesh-mail-web`'s, unit tests; test 6 is read before the module is
assigned; test 9 is proven live after the delivery.
10. A new mail on each account has a mail entry, in a mail group, within 5 minutes of its mail event; a test searches
`mesh-mail-reader`'s database for a known body line and finds none.
11. The reader's caller is refused by `mail_send` for every account, and no mail is moved, flagged or deleted by it.
12. (Milestone 3.) On the mail page, a mail question by a person, by a time range and by "what needs a reply" finds
its target mails, research 066's three failed kinds included; a question with no answer says so; the conversation
is a thread readable through the thread seat; and the browser makes no request but to the mail page's own origin.
13. A batch with one mail that matters sends exactly one `tell` naming it, with no URL, mail address or host name in
its words, and the mail is at the top of the page; a subject carrying a host name still gives a mail signal.
14. Research 066's 20 steering mails, read again, mark no injected words as mattering, and every phishing decoy that
is marked is a scam warning, which sends no `tell`.
15. A reading lesson given on a real mail changes how the next mail of that sender is noted; undone, it no longer
does; the page lists it.
16. With the judgement refused (the reader's licence binding removed in the integration test), the condition is
raised with its cause, the page shows it over the classical list, no `tell` is sent, and after recovery the mail
that arrived meanwhile is read in arrival order.
17. With `mesh-mail-notifier` unassigned, a new mail that does not matter shows nothing on the laptop or the
workstation, and one that matters gives one mail signal.
## 7. Milestones
Tests 11, 13 (with a stand-in router), 16 and the grant split's refusals are one integration test that starts
`mesh-mail` and `mesh-mail-reader` whole against the real bus and store; the batch's budget, the seat's verbs and the
mail signal's words are unit tests; tests 10, 14, 15 and 17 are proven live after milestone 2's delivery; test 12
with milestone 3.
## 11. Milestones
| # | Outcome, in one sentence | Proves | Repositories and their parts | Depends on |
|---|---|---|---|---|
| 1 | In a browser on the laptop and the workstation, the operator signs in and browses, searches and reads every account's mail with its attachments, and writes a mail that goes out on their Approve | tests 1 to 9 | mesh-catalog: `mesh-mail`'s account bucket (issue 1255, ADR 0439 §2); the module `mesh-mail-web` (manifest, sign-in, the pages, the send, the seat's verbs, the integration test) | — |
| 2 | Betterbird is gone from the laptop and the workstation, its profile and mail kept in the home | ADR 0379 §2 | mesh-catalog: Betterbird unassigned on the operator's Approve, then the `betterbird` module removed from the catalogue (issue 806) | 1 |
| 2 | Each new mail is read into a mail group on the mail page; the mail that matters reaches the operator's phone as one mail signal, a scam warning shows on the page only, the operator's corrections become reading lessons, and the pop-up for every new mail is gone | tests 10, 11, 13 to 17 | mesh-catalog: `mesh-mail`'s grants split (issue 1227) and the seat `mail-reading` declared; the module `mesh-mail-reader` (batches, mail entries, reading lessons, mail signals, health, the integration test); `mesh-mail-web`'s mail groups, mail signals, scam warnings and reading lessons; `mesh-mail-notifier` unassigned (issue 1418) | 1 |
| 3 | On the mail page the operator asks questions about their mail and gets the mails that answer them, in a mail conversation kept as a thread | test 12 | mesh-catalog: `mesh-mail-web`'s mail conversation as a client of the thread seat; `mesh-mail`'s folder case and `-any` switches | 1; design 58's milestone 3 (issue 880) |
| 4 | Betterbird is gone from the laptop and the workstation, its profile and mail kept in the home | ADR 0379 §2 | mesh-catalog: Betterbird unassigned on the operator's Approve, then the `betterbird` module removed from the catalogue (issue 806) | 2 |
**Confirmed by the operator on 2026-10-19.** Milestone 1's issues, one repository part each, in their order:
1255 (`mesh-mail`'s account bucket), 1261 (`mail_send_status` answers only its caller), 1262 (the module), 1263
(sign-in), 1264 (accounts, folders and mails), 1265 (search), 1266 (a mail and its attachments), 1267 (writing a
mail), 1268 (the integration test). Milestone 2 is issue 806.
**Milestone 1, confirmed by the operator on 2026-10-19, is delivered;** its live proof on the laptop and the
workstation (a search, an attachment, one send on the Approve) is still the operator's. Its issues, one repository
part each, in their order: 1255 (`mesh-mail`'s account bucket), 1261 (`mail_send_status` answers only its caller),
1262 (the module), 1263 (sign-in), 1264 (accounts, folders and mails), 1265 (search), 1266 (a mail and its
attachments), 1267 (writing a mail), 1268 (the integration test). After its delivery four values were set, each on
the operator's Approve: `mesh-mail-web`'s `reach` on its machine (`internal`), its assignment there, its
`operators`, and its caller in `mesh-mail`'s `grants` for every account.
After milestone 1's delivery and before its live proof, four values are set, each on the operator's Approve:
`mesh-mail-web`'s `reach` on its machine (`internal`), then its assignment there, its `operators`, and its caller in
`mesh-mail`'s `grants` for every account.
Milestones 2 to 4 are written by research 066's graduation and wait for the operator's confirmation and their issues
(playbook 04, steps 5 and 6). Milestone 2 is one release of `mesh-catalog`: the grant split, the new seat, the new
module and the page change ship together, and `mesh-mail-reader` is granted reading only after that delivery, on the
operator's Approve; `mesh-mail-notifier` is unassigned only after test 13 passes live. Milestone 4 is issue 806;
Betterbird stays until mail reading (milestone 2) works, not until the mail conversation.