Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0738fa1405 | ||
|
|
a0a4edabc9 | ||
|
|
ebc7665b2a | ||
|
|
f96f964a2d | ||
|
|
4a2c15f725 | ||
|
|
ae9768c2c1 | ||
|
|
440279fec4 | ||
|
|
3439d19d06 | ||
|
|
89c4295f6d | ||
|
|
3e061bbd99 | ||
|
|
f09cc22d99 | ||
|
|
6ffd3709d8 | ||
|
|
990a77c760 | ||
|
|
cc605e3b13 | ||
|
|
023ad01160 |
@@ -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). The page it serves is 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 §7) 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 (ADR 0459 §4). 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 §6).
|
||||
- **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
|
||||
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
layer: to-be
|
||||
status: in-progress
|
||||
code: [mesh-controller, mesh-catalog modules/mesh-delivery, mesh-delivery, mesh-host, mesh-sdk]
|
||||
updated: 2026-10-19
|
||||
updated: 2026-10-20
|
||||
decisions:
|
||||
- "ADR 0453"
|
||||
- "ADR 0452"
|
||||
- "ADR 0450"
|
||||
- "ADR 0449"
|
||||
- "ADR 0447"
|
||||
- "ADR 0446"
|
||||
- "ADR 0445"
|
||||
@@ -85,8 +89,8 @@ source revision is derived from the keys: every **want** equals its module's **f
|
||||
forge.
|
||||
- **The indexer** computes each module's fingerprint at the merge preview and writes the candidates of each
|
||||
group and the modules of the trunk.
|
||||
- **The builder** claims a build by creating its key, once per fingerprint, and builds it; build-agent becomes
|
||||
this part.
|
||||
- **The builder** claims a build by creating its key, once per fingerprint, and builds it; the builder is made in R4c from
|
||||
build-agent's code, and build-agent builds the builder's own module beside it until R4g, then leaves (ADR 0453 clause 5).
|
||||
- **The checker** runs the merge check on built artifacts: a change's tests, through the build module of each
|
||||
module's language and by that language's convention, running only the packages whose inputs changed and
|
||||
taking the kept verdict of the rest; it writes the change's one status (ADR 0444, ADR 0445, ADR 0447).
|
||||
@@ -97,8 +101,9 @@ source revision is derived from the keys: every **want** equals its module's **f
|
||||
fingerprint is not held, the node is the module's **canary** or the canary runs it healthy, at most `step`
|
||||
other nodes are ahead when `step` is above zero, every provider runs healthy, and the module's credential for that fingerprint exists.
|
||||
It also runs the **composition check**: whether the machines a change touches still compose with it, read
|
||||
from the keys the indexer and the builder hold, with the composition it sends with (ADR 0446). Its module
|
||||
is made in release 4 for that check alone; its wants come in release 5.
|
||||
from the keys the indexer and the builder hold and from what the controller keeps of machines, settings and
|
||||
grants, with the composition it sends with (ADR 0446). Its module
|
||||
is made in R4c for that check alone; its wants come in release 5.
|
||||
- **The node agent**, the node-engine's own process, applies its wants one module at a time, backs up a data
|
||||
module first, and writes its haves.
|
||||
- **The watchman** turns the bus's connections into presence and mirrors every key whose next move a machine
|
||||
@@ -323,16 +328,16 @@ commit on the SDK's trunk or the head of an SDK pull request the forge holds, op
|
||||
|
||||
*ADR 0444, ADR 0445, ADR 0446, ADR 0447; research 058.*
|
||||
|
||||
Until release 4 is delivered, the subsections above are the rule, with their two statuses. From its delivery, a
|
||||
check is this:
|
||||
Until the status switch of release 4 (R4f) is delivered, the subsections above are the rule, with their two statuses.
|
||||
From its delivery, a check is this:
|
||||
|
||||
- **One status per change.** A pull request carries one required status, `mesh/check`, written by the checker
|
||||
on its head; it passes only when the head merged onto its trunk's head passed its tests and the composition
|
||||
check. For a member of a delivery group it is the group's one verdict, the same on every member's head: every
|
||||
member's tests, read beside the others' heads, and one composition of all members' changes. It replaces
|
||||
`mesh/merge-gate` and `mesh/repo-check`; the forge requires it, the checker writes it and the gate reads it from
|
||||
the same delivery (ADR 0447). `mesh/delivery-group` stays the delivery's view, not a required check. Wherever
|
||||
the sections above say both checks passed, they read this one status.
|
||||
`mesh/merge-gate` and `mesh/repo-check`; the forge requires it and the gate reads it from R4f, the delivery in which
|
||||
the checker's line is the only one (ADR 0447 §5); the checker writes it unrequired from R4c (ADR 0453 clause 4). `mesh/delivery-group` stays the delivery's view, not a required check. Wherever
|
||||
this design says both checks passed, they read this one status.
|
||||
- **What the status says.** Its line says the verdict, the tests run and kept at each level, the machines
|
||||
composed, and how long each part took: waiting in the queue, cloning, the unit level, the integration level's
|
||||
setup and its running, and the composition. A failure names the test or the machine first. The line links to
|
||||
@@ -343,8 +348,9 @@ check is this:
|
||||
are apart by construction; in Node and TypeScript, the type-check and the package's `test` script, and its
|
||||
`test:integration` script when it has one. A repository with no tests has none, and says so. Each level is
|
||||
judged by its own bounds: the unit level by its running time (five seconds), the integration level by its
|
||||
setup (thirty seconds) and its tests' running time (sixty seconds), measured and judged apart. A
|
||||
repository's `merge-check.sh` goes; hq, which builds no module, keeps its script until issue 1296 settles how
|
||||
setup (thirty seconds) and its tests' running time (sixty seconds), measured and judged apart; the integration level's bounds fail a repository from its
|
||||
first check that meets them (ADR 0453 clause 9). A
|
||||
repository's `merge-check.sh` goes in R4g (ADR 0453 clause 8); hq, which builds no module, keeps its script until issue 1296 settles how
|
||||
it is checked (ADR 0445).
|
||||
- **Only what changed runs.** The build module names, from the toolchain, everything each package's tests read,
|
||||
and the checker keeps a package's passing verdict at each level under the digest of those inputs. A check
|
||||
@@ -357,13 +363,18 @@ check is this:
|
||||
changed.
|
||||
- **The composition check is the assigner's.** Whether the machines still compose with a change is checked by
|
||||
the part that owns what each machine should run. The assigner reads the modules, fingerprints and manifests
|
||||
the indexer holds and the builds the builder holds, clones no repository but at most the change's own, and
|
||||
the indexer holds and the builds the builder holds; the machines, their roles, assignments and settings, and
|
||||
the grants and credentials it reads from the controller's facts snapshot and from the controller's buckets it
|
||||
names in its manifest's `reads` (ADR 0237 §1, ADR 0408 §3). It clones no repository but at most the change's
|
||||
own, and
|
||||
composes only the machines that run or could run a module the change moves or adds, or whose grants or
|
||||
providers it alters; for a group, once over every member's change, read from the indexer's candidates of the
|
||||
group, and while the indexer holds none the group's check waits and says why. It composes with the function the
|
||||
controller sends with, moved into mesh-sdk, so the two agree for one mesh-sdk version. No judge is built from
|
||||
a change: a change to the composition is proved by its own tests, and a field only a newer composition reads
|
||||
goes out as optional first. What it fails on, and its warning past twelve rebuilt modules, are today's merge
|
||||
controller sends with, moved into mesh-sdk, so the two agree for one mesh-sdk version; its verdict names the
|
||||
mesh-sdk version it composed with, and while the assigner and the controller run different versions the
|
||||
controller's self-check raises a condition until they agree. No judge is built from a change: a change to the
|
||||
composition is proved by its own tests, a field only a newer composition reads goes out as optional first, and
|
||||
the running composition refuses a manifest that uses a field it does not read, naming the field. What it fails on, and its warning past twelve rebuilt modules, are today's merge
|
||||
gate's (ADR 0446, ADR 0237 §2).
|
||||
|
||||
## The Approve and the merge
|
||||
@@ -506,9 +517,10 @@ delivery time.
|
||||
- **Builds and tests run directly**, as the build seat's own account on its node, in no container. The
|
||||
build module of each module's language runs its tests by that language's convention; no repository's
|
||||
script or toolchain line decides it, hq's alone excepted until issue 1296 (ADR 0445).
|
||||
- **A judge has an account of its own.** A judge built from a sibling's merge (ADR 0382 §3) is built and run as a
|
||||
second account of the Go build module, whose home, configuration and cache the build seat's account cannot write,
|
||||
so a check's script cannot change it.
|
||||
- **A judge has an account of its own, until release 4 is delivered (R4f).** Until then, a judge built from a sibling's
|
||||
merge (ADR 0382 §3) is built and run as a second account of the Go build module, whose home, configuration and
|
||||
cache the build seat's account cannot write, so a check's script cannot change it. From R4f no judge is
|
||||
built from a change and the account is not made (ADR 0446 §5).
|
||||
- **Every dependency comes by the version its lock file names**, checked against its checksum: the mesh's own
|
||||
code from the mesh's forge, its own packages from its package registry, any other from its public source.
|
||||
- **A builder fetches from the forge over SSH with a key of its own**, as the build seat's account, under a forge
|
||||
@@ -652,9 +664,11 @@ development, the check's share about a minute):
|
||||
each part's time as the status's line says it.
|
||||
22. A change that adds a failing test is answered failed with only that test's package run; a check asked again
|
||||
after one failed package runs that package alone; a check whose inputs equal an earlier one's runs nothing
|
||||
and takes every kept verdict.
|
||||
and takes every kept verdict. Measured on the status's line: the tests run and kept at each level, and the
|
||||
failed test it names.
|
||||
23. A library or catalogue change's composition check composes only the machines it touches, and clones no
|
||||
repository but at most the change's own.
|
||||
repository but at most the change's own. Measured in the check's report: the machines composed, against the
|
||||
machines that run or could run a module the change moves or adds, and the repositories cloned.
|
||||
24. A pull request carries one required status, and a delivery group one verdict on every member's head, its
|
||||
line naming what was proved and each part's time; no repository a module is built from holds a
|
||||
`merge-check.sh`.
|
||||
@@ -675,6 +689,11 @@ development, the check's share about a minute):
|
||||
group's merges (ADR 0418 §1, §5, §6).
|
||||
- The controller's tables of builds, build requests, rollouts and their tiers, batches and merges, and
|
||||
assignments; the record mirrors, probe D17's audit and healer H6 for those kinds (ADR 0408).
|
||||
- At release 4's deliveries (R4f for the merge gate, the judge and the two statuses; R4g for the scripts): `merge-check.sh` and its `# mesh-check-toolchain` line in every repository a module is
|
||||
built from, hq's alone kept until issue 1296 (ADR 0445 §6); the controller's merge gate, composing every
|
||||
machine from clones and throwaway stores (ADR 0446 §1, §6); the judge built from a change and the Go build
|
||||
module's second account for it (ADR 0446 §5); and the two statuses `mesh/merge-gate` and `mesh/repo-check`
|
||||
(ADR 0447 §1).
|
||||
|
||||
## Milestones
|
||||
|
||||
@@ -695,7 +714,7 @@ release reports the controller's code lines against research 063's baseline (acc
|
||||
| 3 fix | A group approved together merges in one pass and goes out in one delivery plan, also when its members' tests read each other's repositories | 1 | mesh-catalog (mesh-delivery, gitea) | 1082, 1049, 1047, 1083, 1079 (1084 closed as its duplicate) |
|
||||
| 5 | One read of a module on a node names the commit, build and rollout that put it there | 10, 12 | mesh-controller, mesh-catalog (mesh-config, nats) | 981 |
|
||||
| 5b | Decided: building and delivering leave the controller for parts that watch and write keys in the repository `mesh-delivery`, landing in six releases (ADR 0429); the forge module makes that repository from its config, protected before any team reaches it (ADR 0428) | — (ADR 0429 names them: 13 to 20) | hq, mesh-catalog (gitea) | 1117, 1124, 1128 |
|
||||
| 6 | Folded into release 4 by ADR 0429 §10: installed toolchains, builders fetching over SSH with their own key, and an SDK change shipping with its users are built in the builder's new home, so the builder is changed once | (2, 4: proved by release 4) | — | 979, 971 (moved to release 4) |
|
||||
| 6 | Folded into release 4 by ADR 0429 §10 (the fetch over SSH in R4c, the cut-over in R4e): installed toolchains, builders fetching over SSH with their own key, and an SDK change shipping with its users are built in the builder's new home, so the builder is changed once | (2: proved by R4e; 4: in part by R4e, wholly by R4g) | — | 979, 971 (moved to release 4) |
|
||||
| R1a | The node-engine, the controller and the parts can read one layout of the have, presence, pulse and stuck keys: mesh-sdk ships it before its users | — (13, 14 need it) | mesh-sdk | 1131 (key layouts) |
|
||||
| R1b | Every node writes what it runs of each module, on its own keys and nobody else's, and the bus says to one part when a connection opens and closes | 13 in part | the node-engine (`mesh-host`), mesh-controller | 1132 (have keys), 1142 (the node-engine's check, its tests half), 1136 (the have bucket and its grants), 1145 (a module and a build per resource), 1146 (a new repository's first module registered at its merge's Approve), 1147 (the bus's connect events for the watchman), 1160 (a plan passes a machine silent at a middle tier), 1162 (the have bucket takes a node's facts) |
|
||||
| R1c | The operator sees every module on every node, with its build, phase and health, in `mesh-delivery-cli` (aliased `nox-delivery`) and its web view | 13 | mesh-delivery (view) | 1134 (the view), 1137 (the alias, in the view's manifest) |
|
||||
@@ -706,18 +725,28 @@ release reports the controller's code lines against research 063's baseline (acc
|
||||
| R3a | The gate, the bridge, the indexer and the teller can read one layout of the source revision, candidates, modules, merges, asks, answers, owed acts, forge messages and conditions, and one function computes the source fingerprint: mesh-sdk ships them before their users (ADR 0437) | — (15 needs it) | mesh-sdk | 1200 (source revision, candidates, modules, forge messages), 1201 (merges, asks, owed acts, answers), 1202 (a condition on its one subject), 1203 (the source fingerprint, proven against three fingerprints the live builder recorded); ahead of it in mesh-controller, so those could be read: 1204 and 1208 (`builds` says each build's source fingerprint) |
|
||||
| R3b | The controller finds the delivery seat's holder by its claim and records each build's fingerprint inputs; the router takes conditions on their one subject; the operator sees no change (ADR 0437) | — | mesh-controller, mesh-catalog (messenger) | 1210 (the controller's own path and the merge gate's rule by the seat's claim), 1211 (a merge's announcement heard from the seat's holder), 1212 (the pull requests' keys read from the holder's bucket), 1213 (a merge's warrant read under the asker the announcement names: the teller, or mesh-delivery until R3d), 1214 (the builder computes the source fingerprint with mesh-sdk's function), 1215 (a build record carries its fingerprint's inputs), 1216 (a module may say a condition only under its own name, proven on the controller's grant); in the messenger: 1217 (the router takes a condition on its one subject), 1218 (the same over the bus); one delivery group. Its prepare step found that the controller hears no `transition` or `group` event, and that the router cannot refuse a condition under another module's name, the grant does: both go into R3c's insight on ADR 0437 with 1209 |
|
||||
| R3c | The forge bridge, the indexer and the teller run beside today's mesh-delivery and write their keys; the view shows modules against the controller's source fingerprints; nothing is merged by them yet (ADR 0437) | 15 in part | mesh-delivery (forge bridge, indexer, teller, view), mesh-catalog (the forge module) | 1235 (the forge bridge writes pull messages on FORGE), 1236 (its merged message, with the trees of the merge commit), 1237 (its messages for the pull requests open at its start and each reconnect), 1238 (the indexer writes the candidate groups), 1239 (the indexer writes the modules' fingerprints at a trunk merge, and 1209: none for an image that compiles a Go program from a context), 1240 (the teller runs and carries nothing yet), 1241 (the view shows the candidate groups and each module's fingerprint against the controller's); in the forge module: 1234 (a merge commit's trees in one call, and the head branch in the open pull requests); one delivery group, mesh-catalog first. Its prepare step found three orders: the forge had no tool for a commit's trees, so the forge module joins the milestone as a member of its group; and mesh-sdk shipped two layouts before it, the controller's build record (1223) and a build's directory and a pull request's module directories (1233). It also found that the bridge's FORGE is a stream the others hear by `consumes`, not a bucket they `read`; that the broker test of the three credentials goes into R3d with the gate's (1243); and that the parts hand-write their bus connection until mesh-sdk gives one (1242): facts for ADR 0437's next insight, with R3d's |
|
||||
| R3d | A group reaches the mesh as one source revision written by the gate; the merge's Approve is asked by the teller and answered on the phone until issue 953; the view shows the open asks; today's module mesh-delivery is carried over into the gate and ends (ADR 0437) | 15 | mesh-delivery (gate, forge bridge, teller), mesh-catalog (mesh-delivery removed, mesh-issues) | opened when it is prepared |
|
||||
| R4 | The controller asks no build: a build is keyed by its fingerprint, so a merge builds nothing its check built; with milestone 6, toolchains are installed, builders fetch over SSH, and an SDK change ships with its users; a check runs only what changed, its tests by the language's build module, its composition by the assigner, and says in one status what it proved and how long each part took (ADR 0444 to ADR 0447) | 16, 2, 4, 21 to 24 | mesh-delivery (builder, checker, assigner's composition check), mesh-controller (build dispatch and merge gate deleted; build-agent leaves), mesh-catalog (build modules, ssh-client, gitea), mesh-sdk (the composition), the node-engine (`mesh-host`) and mesh-tools (scripts deleted), hq | 979, 971; the check: 1287, 1288, 1289 (kept verdicts, the change's own tests first), 1290, 1291, 1292 (the build modules run the tests), 1293, 1294, 1295 (`merge-check.sh` goes), 1296 (how hq is checked: the operator's), 1297, 1298 (the assigner's composition check), 1299 (the controller's merge gate deleted), 1300, 1301, 1302 (one status), 1303 (the word merge gate struck); the rest opened when it is prepared |
|
||||
| R3d | The gate's keys can carry what the forge needs and the controller answers a what-if as data, so the gate has what it reads before it runs; a failed delivery plan asks the operator Retry on the phone, and a seat whose holder is assigned nowhere passes to its only claimant; the operator sees only the Retry notice (ADR 0450, ADR 0449) | — | mesh-sdk, mesh-controller | in mesh-sdk: 1321 (a merge key carries the Approve's heads), 1322 (an owed act carries a status's target, a commit without a pull request, two comments), 1323 (a name a key cannot hold is escaped); in mesh-controller: 1324 (what-if as data), 1325 (the build seat reads the gate's pull keys), 1326 (the gate's buckets writable by its runner only), 1243 (the three parts' credentials); and, delivered first as feature no-terminal (ADR 0449): 1317 (the seat passes to its only claimant), 1314 (a failed delivery plan raises a condition), 1315 (Retry offered and performed), 1316 (a refused answer is told). Its prepare step found four things the gate reads that ship before it, which cut the former R3d in two (ADR 0450), and two steps on the path that needed the operator's terminal (ADR 0449) |
|
||||
| R3e | A group reaches the mesh as one source revision written by the gate; the merge's Approve is asked by the teller and answered on the phone until issue 953; the view shows the open asks; today's module mesh-delivery is carried over into the gate when it first holds the seat and ends; no step needs the operator's terminal (ADR 0437, ADR 0450) | 15 | mesh-delivery (gate's parts: forge bridge, teller, indexer, view), mesh-catalog (the gate, mesh-delivery removed, mesh-issues), mesh-tools (the tool runner's waits) | opened when it is prepared, from R3d's survey; the controller's deletions it makes possible go to release 4 (1318) |
|
||||
| R4a | The shared layouts of release 4 are on mesh-sdk's main before their users pin them: the catalogue, the validator and the composition over a plain input, the fingerprint's new form, and the key layouts of the builder, the checker, the kept verdicts, the manifests and the candidates; the node-engine reports the user namespaces capability (ADR 0453 clauses 1, 2, 3) | — (2 needs it) | mesh-sdk, the node-engine (`mesh-host`) | in mesh-sdk: 1353 to 1364, 1298 (the composition over a plain input); in the node-engine: 1308 (the user namespaces capability) |
|
||||
| R4b | mesh-controller and the node-engine use the catalogue, the validator and the composition from mesh-sdk and delete their copies; the controller composes every node both ways on the live facts and the two agree before this is delivered; it writes the grants and credential bindings the assigner reads; its unit level meets its bound (ADR 0453 clauses 1, 3) | — | mesh-controller, the node-engine (`mesh-host`) | 1375 (to be split when it is prepared), 1337 (the unit level's bound) |
|
||||
| R4c | The new parts run dark beside today's: the indexer writes the manifests by digest and the fingerprints in the new form beside today's (its own, first delivery), then the build modules (the Go build module, the Node and TypeScript build module: toolchain, sandbox, fetch, digest, test, build), the builder, the checker writing `mesh/check` as a status the forge does not require, and the assigner's composition check writing into the checker's report; the build seat's accounts are decided by a record before the fetch step merges (ADR 0453 clauses 4, 6, 7, 8, 11, 12, 16) | 22, 23 (measured on the dark run, proved in R4f) | mesh-delivery (indexer, builder, checker, assigner's composition check), mesh-catalog (build modules, ssh-client, gitea), mesh-controller (the build agent's whole-check tests, the script's steps as tests), mesh-sdk | 971 (its record first), 1297 (the assigner's composition check), 1309 (the fetch and run steps), 1287, 1288, 1289, 1290, 1291, 1292 (the checker; the build modules run the tests), 1251; the steps of 1293 and 1294 that are no test become tests in R4c to R4e; the rest opened when it is prepared |
|
||||
| R4d | Four modules stop being built from a Dockerfile: route-proxy, nats, n8n and mail's autoconfiguration module (automx, replaced by a Go program), each rework its own release step, nats in a delivery of its own; free between R4a and R4e and never in the same delivery as another release (ADR 0452, ADR 0453 clauses 13, 14, 16) | — | mesh-catalog, mesh-controller (route-proxy), the node-engine (`mesh-host`: n8n's supplementary group) | the four image reworks, opened when it is prepared |
|
||||
| R4e | The controller asks no build: a build is keyed by its fingerprint, the new form becomes the only one as one group, and a merge builds nothing its check built; builders fetch over SSH, so an SDK change ships with its users; the vendored copies leave mesh-controller and mesh-sdk; delivered only once the builder's artifact digests equal build-agent's (ADR 0453 clauses 2, 4, 5, 6) | 16, 2, 4 in part | mesh-controller (builds are no longer asked), mesh-delivery (builder), mesh-sdk | 979 (the installed toolchains; closed with the toolchain images in R4g), 1304, 1305, the controller asking no build (opened when it is prepared) |
|
||||
| R4f | A pull request carries one required status that says what it proved and how long each part took; the controller's merge gate and its replays are deleted with the two old statuses; the controller's deletions R3e makes possible go; each level's times are measured, and a bound fails a repository from the first check that meets it (ADR 0447, ADR 0450 §8, ADR 0453 clauses 4, 9, 10) | 21, 22, 23, 24 (the status; the scripts' absence is proved in R4g) | mesh-delivery (checker, assigner), mesh-controller (merge gate, replays, `delivery-plan`, `forget-checks`, the asker `mesh-delivery` deleted), mesh-catalog (gitea) | 1299 (the merge gate deleted; closes issue 709, the replays' socket), 1300, 1301, 1302 (one status), 1318 |
|
||||
| R4g | The clean-up: the scripts of the repositories a module is built from, build-agent with its socket and Dockerfile code, the toolchain images and the word merge gate go; the builder's own module is delivered from the builder's keys (ADR 0453 clauses 5, 8, 10) | 4 (no container image builds remain), 24 (no `merge-check.sh` in a repository a module is built from) | mesh-controller (build-agent removed), mesh-catalog, mesh-delivery, mesh-tools (scripts deleted), hq | 1295 (`merge-check.sh` goes; the tests of 1293 and 1294 are R4c to R4e's), 979 (closed with the toolchain images), 1303 (the word merge gate struck); 1296 (how hq is checked) is the operator's and undated by this release |
|
||||
| R5 | The assigner writes what each node should run by its six rules, compared with what the controller sends, and the view shows every difference; the operator answers the asks that need no proof of who answered in the view (ADR 0437 §10) | 17 | mesh-delivery (assigner), mesh-controller (grants keys) | opened when it is prepared |
|
||||
| R6 | Each node applies from its wants, a new version reaches the module's canary first and the rest once it is healthy there, and the plans are deleted from the code | 18, 19 | the node-engine (`mesh-host`: the node agent), mesh-controller (plans deleted), mesh-delivery (the gate's delivery states go) | opened when it is prepared |
|
||||
|
||||
The issues are linked `depends-on` in this order; 976 depends on 975, and 979 also on 971. R3's prepare step on 2026-10-19 found ADR 0429 §20 contradicting itself and four release orders; ADR 0437 (accepted, the operator's Approve) cuts release 3 into R3a to R3d, each one release, and moves answering asks in the view to R5. R2c's prepare step on 2026-10-19 found one more order: the alive message is the only source of when the controller last heard a machine, which `nodes`, `node` and `status` read, so the controller takes that from presence (1183, R2c) and is delivered before the node-engine stops sending (1158, R2d); 1158 depends on 1183. In release 1-2, 1132 and 1136 depend on 1131, 1134 and 1135 on 1136, 1134 also on 1132 and 1128, and 1137 on 1134. Release 1-2 was confirmed as one milestone; its prepare step on 2026-10-18 found the release orders hidden in it, and the operator chose at 18:52 to cut it by them, so it is the milestones R1a to R2d above, each one release (the operator, 2026-10-19: a milestone is one release): an SDK change still ships before its users until release 4 (ADR 0429 §10); a new key on the wire goes only to a node that says it reads it; a new repository's first module registers at its merge's Approve (ADR 0432, issue 1146); the bus gives the watchman connect events only through a system account (ADR 0431); and release 2's other gaps are settled by ADR 0433 and ADR 0434. A node that is down has no effect on a delivery and plays what it missed when it returns (ADR 0435, the operator, 2026-10-18; issues 1160, 1161). Milestone 3's first live group (milestone 4's, on 2026-10-17) held one Approve but merged in two passes and went out in two delivery plans: a member's tests read the other member's repository, so the first merge made the second's verdict out of date, and a closed group never asked its composed verdict again (issues 1049, 1082). The operator put a fix of milestone 3 after milestone 4 and before milestone 5 on 2026-10-18; acceptance test 1 is proved again by it. The operator put milestone 5b after milestone 5 and before milestone 6 on 2026-10-18, as an issue rather than a research effort; where the planning goes is settled by a decision record before it is built (issue 1117), and milestone 6's build changes are read against it. Milestone 2b was
|
||||
The issues are linked `depends-on` in this order; 976 depends on 975, and 979 also on 971. R3's prepare step on 2026-10-19 found ADR 0429 §20 contradicting itself and four release orders; ADR 0437 (accepted, the operator's Approve) cuts release 3 into R3a to R3d, each one release, and moves answering asks in the view to R5. R2c's prepare step on 2026-10-19 found one more order: the alive message is the only source of when the controller last heard a machine, which `nodes`, `node` and `status` read, so the controller takes that from presence (1183, R2c) and is delivered before the node-engine stops sending (1158, R2d); 1158 depends on 1183. In release 1-2, 1132 and 1136 depend on 1131, 1134 and 1135 on 1136, 1134 also on 1132 and 1128, and 1137 on 1134. Release 1-2 was confirmed as one milestone; its prepare step on 2026-10-18 found the release orders hidden in it, and the operator chose at 18:52 to cut it by them, so it is the milestones R1a to R2d above, each one release (the operator, 2026-10-19: a milestone is one release): an SDK change still ships before its users until R4e (ADR 0429 §10, ADR 0453 clause 2); a new key on the wire goes only to a node that says it reads it; a new repository's first module registers at its merge's Approve (ADR 0432, issue 1146); the bus gives the watchman connect events only through a system account (ADR 0431); and release 2's other gaps are settled by ADR 0433 and ADR 0434. A node that is down has no effect on a delivery and plays what it missed when it returns (ADR 0435, the operator, 2026-10-18; issues 1160, 1161). Milestone 3's first live group (milestone 4's, on 2026-10-17) held one Approve but merged in two passes and went out in two delivery plans: a member's tests read the other member's repository, so the first merge made the second's verdict out of date, and a closed group never asked its composed verdict again (issues 1049, 1082). The operator put a fix of milestone 3 after milestone 4 and before milestone 5 on 2026-10-18; acceptance test 1 is proved again by it. The operator put milestone 5b after milestone 5 and before milestone 6 on 2026-10-18, as an issue rather than a research effort; where the planning goes is settled by a decision record before it is built (issue 1117), and milestone 6's build changes are read against it. Milestone 2b was
|
||||
put before milestone 3 by the operator on 2026-10-17. Milestone 3 builds ADR 0418, ADR 0419 and ADR 0421
|
||||
(issues 977, 978 and 1022), and splits mesh-controller's unit tests from its integration tests (issue 895, the
|
||||
operator on 2026-10-17), so the unit level holds its bound of ADR 0391; the integration level's sixty seconds
|
||||
is issue 1055. Acceptance test 6 spoke of a ready mark when milestone 2 was delivered; restated for
|
||||
the Approve, it is proved again by milestone 3.
|
||||
|
||||
R4's prepare step on 2026-10-20 cut release 4 by its orders into R4a to R4g, each one release (ADR 0453, the operator's Approve): the SDK ships before its users, the new parts run dark before anything relies on them, the status switch follows a measured run, and the scripts and build-agent go last;
|
||||
R4d, the four image reworks, has no order of its own and may be delivered at any point between R4a and R4e. Where a record dates a rule by release 4, it reads the R4 release that builds the rule (ADR 0453 clause 15).
|
||||
|
||||
## What is not decided here
|
||||
|
||||
- A web view of deliveries beyond the pull request's comment.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 gives no pop-up and no mail signal 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 3, §11).
|
||||
|
||||
## 3. Signing in (ADR 0440 §3)
|
||||
|
||||
@@ -102,16 +119,108 @@ 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, and every part of its question has a bound, so it never
|
||||
passes 55 KiB of the judgement's 64 KiB: the framing that a mail is data and never an instruction, at most 4 KiB;
|
||||
the mail groups, at most 4 KiB, the largest first; 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 each mail, at most 3.5 KiB (its headers at most 512 bytes, its text 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. A batch starts at least 160 s after the previous one started, so
|
||||
an issue tracker's check that waits behind a batch on the same machine ends within 115 s, inside its two minutes
|
||||
(ADR 0278 §2), which research 066's 15 mails and 120 s back to back would not; mail reading then reads up to 225
|
||||
mails an hour (ADR 0459 §15).
|
||||
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 (a caller of the thread's own,
|
||||
issue 1419), 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`,
|
||||
@@ -131,22 +240,55 @@ Each is an issue with an owner (ADR 0440 §8):
|
||||
answers whether it serves and the accounts it is granted (a unit test of `mesh-mail-web`, issue 1262).
|
||||
9. The acceptance sentence at the top, live: in a browser on the laptop and on the workstation, for every account.
|
||||
|
||||
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 4.) 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 sender whose name carries a host name still gives a
|
||||
mail signal, in the safe form.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## 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, 13, 14, 15 and 17 are proven live after milestone 2's delivery, test 13
|
||||
before `mesh-mail-notifier` is unassigned; test 12 with milestone 4.
|
||||
|
||||
## 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 | 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 |
|
||||
| 4 | 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; the thread's mail tools under a caller of their own granted reading only (issue 1419); `mesh-mail`'s folder case and `-any` switches | 2 (the grant split and the reading lessons); design 58's milestone 3 (issue 880) |
|
||||
|
||||
**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 3 is issue 806.
|
||||
ADR 0379 §2's bar for removing Betterbird is milestone 1's; keeping Betterbird until mail reading (milestone 2) works,
|
||||
and not until the mail conversation, is the lead's proposal, for the operator to confirm with the milestones
|
||||
(playbook 04, step 5). Milestone 4 waits for threads and for the decision that names its thread's reading-only caller (issue 1419, which needs a decision first).
|
||||
|
||||
Reference in New Issue
Block a user