Merge pull request 'Designs 47, 24 and 39 and the glossary follow ADR 0548, 0549, 0550, 0551 and ADR 0547's answers' (#480) from amend/0548-0551 into main

This commit was merged in pull request #480.
This commit is contained in:
2026-10-26 12:34:59 +00:00
4 changed files with 288 additions and 74 deletions
+24 -7
View File
@@ -235,12 +235,18 @@ every other domain has something to run on. **Recorded by** the controller and t
## Placement — what runs on which node ## Placement — what runs on which node
**Purpose.** To decide, send and apply what each node runs, and to say why. **Purpose.** To decide, send and apply what each node runs, and to say why.
**Recorded by** the controller's `inventory` database. **Upstream of** Provisioning, Connectivity, Data **Recorded by** the controller's `inventory` database; from ADR 0549, by the catalogue's placement files, which
and Health and repair. **Decided by** ADR 0100, 0126, 0176, 0181, 0207, 0221, 0252, 0261, 0411, 0539. the indexer reads onto the bus. **Upstream of** Provisioning, Connectivity, Data
and Health and repair. **Decided by** ADR 0100, 0126, 0176, 0181, 0207, 0221, 0252, 0261, 0411, 0539, 0549.
**Uses:** node, machine, module, seat, manifest (Module), config value (Config). **Uses:** node, machine, module, seat, manifest (Module), config value (Config).
- **assignment** — a module put on a node. Its config values on that node (module-assignment config, - **assignment** — a module put on a node. Its config values on that node (module-assignment config,
Config) are `mesh-config`'s, never part of what the controller records (ADR 0348 §9). Config) are `mesh-config`'s, never part of what the controller records (ADR 0348 §9).
- **placement file** — the catalogue's file for one node: the modules placed on it and, for each, its pins, its
host ports and its bindings to the providers it requires. It changes only by a pull request on the catalogue,
and the indexer reads it at each trunk merge into its state `placement`, one key per node, which every reader
of placement watches (ADR 0549 §1 to §3). Until ADR 0547's third milestone the controller's assignments are
kept equal to it.
- **pending assignment** — an assignment of a module whose build is still running, kept, and made by the - **pending assignment** — an assignment of a module whose build is still running, kept, and made by the
controller when that build registers the module, or ended with why when it does not controller when that build registers the module, or ended with why when it does not
(ADR 0261). (ADR 0261).
@@ -365,7 +371,7 @@ and vault (Identity and access).
**Purpose.** To issue, hold, rotate and check the credentials and grants by which modules, nodes, agents **Purpose.** To issue, hold, rotate and check the credentials and grants by which modules, nodes, agents
and the operator act. **Recorded by** the controller's `identity` and `licences` databases and the vault. and the operator act. **Recorded by** the controller's `identity` and `licences` databases and the vault.
**Upstream of** Provisioning, Delivery, and Operator and conversation. **Upstream of** Provisioning, Delivery, and Operator and conversation.
**Decided by** ADR 0085, 0113, 0183, 0225, 0234, 0386, 0387, 0388, 0411, 0413, 0414. **Decided by** ADR 0085, 0113, 0183, 0225, 0234, 0386, 0387, 0388, 0411, 0413, 0414, 0550.
**Uses:** module, node, seat, tool (Module), operator, consumer and provision (Provisioning), agent and ask (Operator and conversation). **Uses:** module, node, seat, tool (Module), operator, consumer and provision (Provisioning), agent and ask (Operator and conversation).
- **credential** — anything that proves an identity: a password, a key, a token. A **pair credential** - **credential** — anything that proves an identity: a password, a key, a token. A **pair credential**
@@ -377,7 +383,8 @@ and the operator act. **Recorded by** the controller's `identity` and `licences`
and never made by the mesh and never made by the mesh
(ADR 0283). (ADR 0283).
- **vault** — the module that owns every secret (`mesh-vault`, - **vault** — the module that owns every secret (`mesh-vault`,
[24 — The secrets vault](../03-DESIGN/01-to-be/24-the-secrets-vault.md)). [24 — The secrets vault](../03-DESIGN/01-to-be/24-the-secrets-vault.md)): the mesh's signing key, with which
it signs on request, licence grants and tokens, bus account passwords and module secrets (ADR 0550).
- **identity** — a person, an agent or a module as the mesh knows it: a name, a kind, a role, and whether it - **identity** — a person, an agent or a module as the mesh knows it: a name, a kind, a role, and whether it
is switched on; a person or an agent also has a login name, the machines it is present on and, for a person, is switched on; a person or an agent also has a login name, the machines it is present on and, for a person,
the login kept on a machine where it differs. Every identity and role is held by the identity seat, in the the login kept on a machine where it differs. Every identity and role is held by the identity seat, in the
@@ -424,7 +431,7 @@ and the operator act. **Recorded by** the controller's `identity` and `licences`
back when it fails. The domain is continuous integration and delivery, named **delivery**, and its parts live in back when it fails. The domain is continuous integration and delivery, named **delivery**, and its parts live in
the repository `mesh-delivery` (ADR 0429 §2). **Recorded by** the `mesh-delivery` module (deliveries) and the the repository `mesh-delivery` (ADR 0429 §2). **Recorded by** the `mesh-delivery` module (deliveries) and the
controller (the planner, the rollout) until release 6 of ADR 0429; from each release on, by the parts it builds. **Downstream of** Module, Core, Health and repair and Data. controller (the planner, the rollout) until release 6 of ADR 0429; from each release on, by the parts it builds. **Downstream of** Module, Core, Health and repair and Data.
**Decided by** ADR 0162, 0218, 0236, 0237, 0238, 0239, 0250, 0267, 0270, 0276, 0323, 0401–0408, 0428, 0429, 0444–0447, 0524–0530, 0539. **Decided by** ADR 0162, 0218, 0236, 0237, 0238, 0239, 0250, 0267, 0270, 0276, 0323, 0401–0408, 0428, 0429, 0444–0447, 0524–0530, 0539, 0548, 0551.
**Uses:** module, node, declaration and send (Placement), health (Health and repair), person. **Uses:** module, node, declaration and send (Placement), health (Health and repair), person.
- **merge check** — what a pull request carries before it may merge, judging the merge of its head into a - **merge check** — what a pull request carries before it may merge, judging the merge of its head into a
@@ -442,9 +449,19 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel
- **kept verdict** — a package's passing verdict at one test level, kept by the checker under the digest of - **kept verdict** — a package's passing verdict at one test level, kept by the checker under the digest of
everything its tests read, written once and read-only; a check takes it instead of running an unchanged everything its tests read, written once and read-only; a check takes it instead of running an unchanged
package (ADR 0444). package (ADR 0444).
- **carried verdict** — a delivery's verdict moved to a newer trunk commit, or a newer sibling commit, by its
package digests: the checker merges the head onto the new commit and runs only the packages whose digest the
move changed, keeping the composition while no composed fingerprint changed; the verdict names the commits it
was carried from (ADR 0548 §5, §6). A head git refuses onto the new commit is not carried: its next check is
whole (ADR 0548 §7).
- **trunk commit** — the commit of the trunk a merge check's verdict was judged against: the trunk's head when - **trunk commit** — the commit of the trunk a merge check's verdict was judged against: the trunk's head when
the build module cloned it. The verdict holds for that commit only, and goes out of date when the trunk moves the build module cloned it. The verdict holds for that commit only, goes out of date when the trunk moves, and
(ADR 0323). is then carried to the new commit (ADR 0323, ADR 0548).
- **merge turn** — an approved merge's key on a repository in the gate's `turns` bucket: the deliveries waiting
to merge there in the order of their Approve, and the check each waits for. It holds new checks off that
repository until the merge is done (ADR 0548 §3). Written only while the check gates merges (the gate's
setting `check-gates-merge`); while it does not, no turn is written and an approved merge goes in at once
(ADR 0551 §1).
- **build seat** — a language's node seat, held on a node by that language's build module: `node-build-go`, - **build seat** — a language's node seat, held on a node by that language's build module: `node-build-go`,
`node-build-node` and `node-build-image` (ADR 0525 §2). Its accepted kinds are the **build streams**, and its `node-build-node` and `node-build-image` (ADR 0525 §2). Its accepted kinds are the **build streams**, and its
verbs `current`, `pause` and `resume` serve that node's pulls. It replaces the seat `node-build-agent`, retired verbs `current`, `pause` and `resume` serve that node's pulls. It replaces the seat `node-build-agent`, retired
+62 -8
View File
@@ -1,9 +1,10 @@
--- ---
layer: to-be layer: to-be
status: implemented status: in-progress
code: [mesh-catalog, mesh-controller, mesh-host, mesh-media-catalog] code: [mesh-catalog, mesh-controller, mesh-host, mesh-media-catalog, mesh-vault]
updated: 2026-10-12 updated: 2026-10-26
decisions: decisions:
- "ADR 0550"
- "ADR 0305" - "ADR 0305"
- "ADR 0158" - "ADR 0158"
- "ADR 0094" - "ADR 0094"
@@ -31,9 +32,10 @@ wrong.
- **A provisioned credential** is the login one module uses against another — a database password, - **A provisioned credential** is the login one module uses against another — a database password,
a broker account. The mesh mints it per consumer↔provider pair and seals it to the machines that a broker account. The mesh mints it per consumer↔provider pair and seals it to the machines that
must hold it (ADR 0048), must hold it (ADR 0048),
and its provider makes it true. **This is not the vault's**, and the vault does not change it. It and its provider makes it true. This design first left it out of the vault, since it already has an owner
already has an owner and a rotation and a rotation ([13](13-credentials-and-their-rotation.md)). **It is the vault's now** (ADR 0550 §5, from
([13](13-credentials-and-their-rotation.md)); disturbing it would buy nothing. ADR 0113): the vault keeps the value and hands it sealed; its provider still makes it true, and its
rotation is the same machinery.
- **A module's own secret** is a value a single module needs for itself — the password of a store - **A module's own secret** is a value a single module needs for itself — the password of a store
it runs privately, an internal signing token. Today the mesh generates this as a value nothing it runs privately, an internal signing token. Today the mesh generates this as a value nothing
owns, and so it cannot be rotated. **This is the vault's.** owns, and so it cannot be rotated. **This is the vault's.**
@@ -45,6 +47,56 @@ The vault, then, is the provider a module turns to for a secret that is **not**
some other provision. It is the answer to *"this module needs a password, and there is no provider some other provision. It is the answer to *"this module needs a password, and there is no provider
whose job it is to give it one."* whose job it is to give it one."*
## Every secret lives in the vault
*Decided 2026-10-26 (ADR 0550), on the operator's answers; built in the milestones of ADR 0547.*
**The seat `mesh-vault` holds every secret the mesh keeps.** That is every shared secret, the enrolment tokens
among them; the mesh's signing key; every licence's grants and tokens; every bus account's password or, where
the vault has no value, its hash; and every module's own secrets and credentials. A holder gets a value only
sealed to its own key, on request and reply, or asks the vault to act with it, as for a signature. No secret is
kept in a bucket, a store database or a module's own rows. The private keys a node or the operator makes for
itself stay where they are made (ADR 0550 §1).
- **The signing key.** The vault makes a new signing key for the mesh, with the mesh's authority beside it; the
controller's key is never copied out of its database. The vault signs enrolments, node certificates and the
authority's own on request, through its verb `sign`, for the callers its manifest names, and says `signed`
naming the caller, the kind and the digest, never the key. The public halves are in a state of the vault that
every node reads. The key and the authority leave the vault only as the one copy sealed to the operator key,
opened only in the break-glass recovery below, so losing the vault does not lose the key every signature
depends on. Each node trusts the vault's key beside the controller's, one node first, and the controller's no
more once it loses its lease (ADR 0550 §2).
- **Licence grants and tokens.** The refresh tokens, the API key and the access tokens of every licence are vault
secrets; the licence manager keeps which licence goes to which holder, and nothing secret
([39](39-the-anthropic-licence-manager.md), ADR 0550 §3).
- **Bus account passwords.** A bus account's value is the vault's: until ADR 0547's third milestone the controller
hands the vault the value of each account ADR 0374 §1 covers and keeps the others' values as today (ADR 0374
§4), whose hashes the vault adopts; from then the vault mints every one. The agent of the node holding `mesh-broker` hands the vault,
sealed to it, the bcrypt hash of every user of the list the bus loaded; the vault adopts the hash of each user
it holds no value for (the controller's own, the node and device accounts, the module and process accounts its
values do not cover), writes it under `bus-accounts.<user>` and says `account-hashed` with `adopted: true`. It
never touches a key that holds the hash of its own value, and writes an adopted key again when the loaded list
carries another hash for that user. Its tool `secret_own` lists the adopted users and each adoption, and
`account_adopt` adopts now (ADR 0550 §4).
- **Module secrets** stay as the sections below describe them: a module's own secrets, the credentials between a
consumer and its provider, and the values an operator or a backend delivers. A node composing its own modules
asks the vault for them sealed to its key, and no composition carries one in the clear (ADR 0550 §5).
- **Three exceptions until ADR 0547's third milestone, each ending there:** the controller's own signing key in
its identity database; the bus account values the controller mints, handed to the vault where the accounts are
covered and kept by the controller for the others; and the enrolment tokens and new node accounts the
controller makes and keeps in its store. So **no machine is enrolled before the third milestone** (ADR 0550 §1,
§6).
*How it is checked:* before the third milestone's lease write, the controller's licence and identity databases and
the licence manager hold no secret the vault does not hold, and no exception is left that the vault has not
replaced, read with the vault's `secret_holders` and the store's reader. A unit test that `sign` refuses a caller
its manifest does not name and that no answer or event carries the key; `secret_holders` showing the
operator-sealed copy of the key and no other holder; and live, a node certificate the vault signed that another
node verifies. After the delivery of the hash hand-over, `mesh-grants.grants_user_list` shows no user without a
hash and `secret_own` lists the adopted users; unit tests in the vault (adopt; never touch its own value or a
covered account; rewrite on a new loaded hash) and in the node agent (every loaded user handed, sealed). The
hand-act log shows no enrolment before the third milestone.
## A secret as a provision ## A secret as a provision
A module that needs a secret for its own use requires a `secret` provision, exactly as it requires A module that needs a secret for its own use requires a `secret` provision, exactly as it requires
@@ -77,8 +129,10 @@ the foundation: installed at genesis, the way the store and broker are raised fi
adopted as modules (ADR 0078). A adopted as modules (ADR 0078). A
mesh has root secrets, so a mesh has a vault; it is not something a mesh opts into mesh has root secrets, so a mesh has a vault; it is not something a mesh opts into
(ADR 0085, amended). It is provisioned the (ADR 0085, amended). It is provisioned the
ordinary way, and it does **not** mint the mesh's delivery credentials — the controller does that, ordinary way. It does not yet mint the mesh's bus accounts: until the third milestone of ADR 0547 the
because the controller must mint in order to deliver any provision, the vault's own included. controller mints them, hands the vault each covered account's value (ADR 0374 §1) and keeps the others as
today, and from then the vault mints every one
(*Every secret lives in the vault*, above).
There is **one vault per mesh**, on the control-node, reached from any node the way identity is. There is **one vault per mesh**, on the control-node, reached from any node the way identity is.
Node scoping (ADR 0084, Node scoping (ADR 0084,
@@ -1,9 +1,10 @@
--- ---
layer: to-be layer: to-be
status: implemented status: in-progress
code: [mesh-catalog modules/claude-licence-manager] code: [mesh-catalog modules/claude-licence-manager, mesh-vault]
updated: 2026-10-04 updated: 2026-10-26
decisions: decisions:
- "ADR 0550"
- "ADR 0209" - "ADR 0209"
- "ADR 0206" - "ADR 0206"
- "ADR 0183" - "ADR 0183"
@@ -18,13 +19,35 @@ decisions:
# 39 — The Anthropic licence manager # 39 — The Anthropic licence manager
**One module knows every Anthropic licence the mesh has, keeps each alive, decides which consumer gets **One module knows every Anthropic licence the mesh has, keeps each alive, and decides which consumer gets
which, and hands every node's agent its token over the bus.** which; the vault keeps every grant and token and hands every node's agent its token over the bus**
(ADR 0550 §3, amending the first shape, in which the manager kept the grants and handed the tokens itself).
ADR 0183 ADR 0183
decides it; this is the shape. It is the successor of the predecessor's manager module, built from what decides it; this is the shape. It is the successor of the predecessor's manager module, built from what
that module learned the hard way, and the counterpart of [36 — The operator's agent on a machine](36-the-operators-agent-on-a-machine.md), that module learned the hard way, and the counterpart of [36 — The operator's agent on a machine](36-the-operators-agent-on-a-machine.md),
which is the consumer on every node. which is the consumer on every node.
## Every grant in the vault
*Decided 2026-10-26 (ADR 0550 §3), on the operator's answer that every secret lives in the vault; built in
ADR 0547's second milestone (issue 1126). Until it is delivered, the sections below hold as first written.*
- **The vault keeps every licence's secrets**: the refresh tokens, the API key and the access tokens are vault
secrets ([24](24-the-secrets-vault.md)). The manager keeps its bindings, its licence records without a secret
(account, kind, health, usage, audit), and nothing at rest that is secret.
- **The manager stays the one rotation source.** It alone calls the vendor's token endpoint: to refresh or adopt,
it asks the vault for the grant sealed to itself and hands what it gets back to the vault. A grant offered at
login, sealed to the manager's key (its `public-key` verb is kept), is handed on to the vault the same way.
- **A holder's token comes from the vault.** The agent module on a node registers its public half with the vault,
not the seat, and asks the vault for its token sealed to it. The vault serves only the licence the manager's
binding names for that holder, and says `secret-changed`, never a value. The seat's `current` verb answers which
licence a consumer holds and its health, never the token.
- **It waits for accounts of their own.** The vault hands a value only to a module running under a bus account of
its own (issue 569), so the move waits until the manager and each agent module run under one.
*How it is checked:* a unit test that the vault refuses a token to a holder no binding names or to one without an
account of its own, and a scan after the move that the manager's tables hold no grant.
## 1. What it is ## 1. What it is
A module, `claude-licence-manager`, holding the mesh-scoped seat **`anthropic-licence-manager`**. One A module, `claude-licence-manager`, holding the mesh-scoped seat **`anthropic-licence-manager`**. One
@@ -43,7 +66,8 @@ Its store holds four things:
**The grants are encrypted with a key the vault made for the manager** — its one `secret` requirement. **The grants are encrypted with a key the vault made for the manager** — its one `secret` requirement.
The vault keeps that key; the manager keeps the grants. That is ADR 0050's carve-out, one module, one The vault keeps that key; the manager keeps the grants. That is ADR 0050's carve-out, one module, one
node, the long-lived grants only. node, the long-lived grants only. ADR 0550 §3 ends the carve-out: the grants move into the vault, and the
`licences` table keeps no grant (*Every grant in the vault*, above).
## 2. The licences it manages today ## 2. The licences it manages today
@@ -77,7 +101,9 @@ Carried from the predecessor, where each rule was earned by an incident:
## 4. Handing a token to a node ## 4. Handing a token to a node
*Amended 2026-10-04 by ADR 0206*, replacing the manager's visits: **what each consumer *Amended 2026-10-04 by ADR 0206*, replacing the manager's visits: **what each consumer
should hold is the manager's state, and the token is fetched when it changes.** should hold is the manager's state, and the token is fetched when it changes.** *Amended 2026-10-26 by
ADR 0550 §3:* the token is fetched from the vault, not the seat; the `bindings` state and its generation stay
the manager's, and the vault serves the licence a binding names.
- **The manager keeps a `bindings` state**, one key per consumer: the licence, its kind, and a - **The manager keeps a `bindings` state**, one key per consumer: the licence, its kind, and a
**generation** that increases with every rotation and every switch. Nothing in it is secret. **generation** that increases with every rotation and every switch. Nothing in it is secret.
@@ -162,7 +188,8 @@ gone; a rotation or a switch is a new generation in the `bindings` state.
identity, expiry, failures, who is bound), `bindings`, `bind`, `switch`, `release`, `refresh` (now, one identity, expiry, failures, who is bound), `bindings`, `bind`, `switch`, `release`, `refresh` (now, one
or all), `usage` (current and history), `adopt` (a file on the manager's node, or a key sealed to its or all), `usage` (current and history), `adopt` (a file on the manager's node, or a key sealed to its
`public-key` — ADR 0209), `public-key`, and `current` (a consumer's token, sealed to the key the `public-key` — ADR 0209), `public-key`, and `current` (a consumer's token, sealed to the key the
consumer sends — ADR 0206). The manager asks a node for a candidate grant by the agent module's own tool. consumer sends — ADR 0206; from ADR 0550 §3, which licence a consumer holds and its health, never the
token, which the vault hands). The manager asks a node for a candidate grant by the agent module's own tool.
## 8. Settings ## 8. Settings
@@ -179,6 +206,8 @@ one definition serves and one mesh may differ.
| a grant offered with a mismatching identity is refused and one notification emitted | ADR 0183, attribution | | a grant offered with a mismatching identity is refused and one notification emitted | ADR 0183, attribution |
| a failing licence notifies once, and once a day after, not once per tick | §3 | | a failing licence notifies once, and once a day after, not once per tick | §3 |
| the mesh MCP server lists the seat's verbs and `switch` changes a workstation's token end to end | ADR 0132, the exit of the build | | the mesh MCP server lists the seat's verbs and `switch` changes a workstation's token end to end | ADR 0132, the exit of the build |
| the vault refuses a token to a holder no binding names, or to one without a bus account of its own | ADR 0550 §3 |
| after the move, the manager's tables hold no grant | ADR 0550 §3 |
## What this does not settle ## What this does not settle
@@ -4,6 +4,10 @@ status: in-progress
code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-delivery, mesh-host, mesh-sdk, mesh-vault, hq 00-META/checks] code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-delivery, mesh-host, mesh-sdk, mesh-vault, hq 00-META/checks]
updated: 2026-10-26 updated: 2026-10-26
decisions: decisions:
- "ADR 0551"
- "ADR 0550"
- "ADR 0549"
- "ADR 0548"
- "ADR 0547" - "ADR 0547"
- "ADR 0539" - "ADR 0539"
- "ADR 0536" - "ADR 0536"
@@ -121,7 +125,10 @@ source revision is derived from the keys: every **want** equals its module's **f
- **The forge bridge** turns the forge's events into stream messages and is the only part that calls the - **The forge bridge** turns the forge's events into stream messages and is the only part that calls the
forge. forge.
- **The indexer** computes each module's fingerprint at the merge preview and writes the candidates of each - **The indexer** computes each module's fingerprint at the merge preview and writes the candidates of each
group and the modules of the trunk. group and the modules of the trunk. At each trunk merge of the catalogue it also reads the catalogue's
**placement files**, one per node, into its state `placement`: one key `placement.<node>` with that node's
modules, their pins, host ports and bindings, and the source revision. It adds the nodes to `modules.<module>`
and says `placement-changed` only for a node whose key differs (ADR 0549 §1, §2).
- **The builder** claims a build by creating its key, once per fingerprint, and orders it as an ask on the stream of the artifact's - **The builder** claims a build by creating its key, once per fingerprint, and orders it as an ask on the stream of the artifact's
language; it makes no artifact's bytes since R4e and chooses no node, because the build modules pull the asks (ADR 0498 §1, ADR 0525 §1, §4). From R4g it language; it makes no artifact's bytes since R4e and chooses no node, because the build modules pull the asks (ADR 0498 §1, ADR 0525 §1, §4). From R4g it
delivers its own module, the build modules and the controller from its keys, and nothing falls back to build-agent, which is removed delivers its own module, the build modules and the controller from its keys, and nothing falls back to build-agent, which is removed
@@ -134,8 +141,13 @@ source revision is derived from the keys: every **want** equals its module's **f
- **The checker** runs the merge check on built artifacts: a change's tests, through the build module of each - **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 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); it runs dark in R4c-5 (ADR 0484). taking the kept verdict of the rest; it writes the change's one status (ADR 0444, ADR 0445, ADR 0447); it runs dark in R4c-5 (ADR 0484).
It judges a delivery once per set of heads, and carries a verdict to a newer trunk commit by its package
digests instead of judging it again (ADR 0548 §1, §5; *A move of the trunk carries every verdict*, below).
- **The gate** merges a group's pull requests once check, review and the operator's Approve agree on the same - **The gate** merges a group's pull requests once check, review and the operator's Approve agree on the same
heads, and then moves the mesh's source revision in one write. heads, and then moves the mesh's source revision in one write. While the check gates merges, it holds an
approved merge for another delivery's running check of the repositories the merge goes into, and keeps the
merge's **merge turn** there (ADR 0548 §2, §3, as ADR 0551 §1 bounds them; *Nothing merges into a repository
under check*, below).
- **The teller** carries conditions and asks to the operator's phone and is the only writer of an ask's answer. - **The teller** carries conditions and asks to the operator's phone and is the only writer of an ask's answer.
- **The assigner** writes which fingerprint each node should run, by six rules: the build is done, the - **The assigner** writes which fingerprint each node should run, by six rules: the build is done, the
fingerprint is not held, the node is the module's **canary** or the canary runs it healthy, at most `step` fingerprint is not held, the node is the module's **canary** or the canary runs it healthy, at most `step`
@@ -145,7 +157,10 @@ source revision is derived from the keys: every **want** equals its module's **f
the artifact's digest, the source revision and whether the module holds data; the assigner also writes the the artifact's digest, the source revision and whether the module holds data; the assigner also writes the
node's own want `want.<node>.node`, and never deletes a want (ADR 0408 §4). A move a person must allow is judged node's own want `want.<node>.node`, and never deletes a want (ADR 0408 §4). A move a person must allow is judged
by the node agent, which waits; the assigner raises the ask and on a yes writes the want again naming it by the node agent, which waits; the assigner raises the ask and on a yes writes the want again naming it
(ADR 0547 §3). (ADR 0547 §3). It reads which modules run on which node from the indexer's `placement`, on its watch
(ADR 0549 §3); until ADR 0547's third milestone it also reads the controller's assignments, writes no want for
a module on a node that the two do not both name, and raises a condition naming the pair while they differ
(ADR 0549 §5).
It also runs the **composition check**: whether the machines a change touches still compose with it, read 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 and from the machines, settings and grants it reads, with from the keys the indexer and the builder hold and from the machines, settings and grants it reads, with
mesh-sdk's composition, the one every node agent composes with (ADR 0446, ADR 0547 §2). Its module was made in mesh-sdk's composition, the one every node agent composes with (ADR 0446, ADR 0547 §2). Its module was made in
@@ -187,18 +202,22 @@ there is three milestones, one issuer of each key at every moment (ADR 0547 §11
part publishes memberships (by the one grant the operator allowed in the controller's composer and its part publishes memberships (by the one grant the operator allowed in the controller's composer and its
mesh-sdk copy, publishing the assignment subjects and nothing more) and composes and compares the user list, mesh-sdk copy, publishing the assignment subjects and nothing more) and composes and compares the user list,
assertions and grants in shadow with its tools; the vault hashes the bus accounts it is handed into its key assertions and grants in shadow with its tools; the vault hashes the bus accounts it is handed into its key
`bus-accounts.<user>` and adopts once the hashes of accounts it holds no value for, from the list the bus `bus-accounts.<user>`. The agent of the node holding `mesh-broker` hands the vault, sealed to it, the hash of
loaded. The every user of the list the bus loaded, and the vault adopts the hash of each user it holds no value for, and
again when the loaded list carries a new hash for that user (ADR 0550 §4). The
operator's `take-over` makes the grants part's list the one loaded; it is allowed only when the users of both operator's `take-over` makes the grants part's list the one loaded; it is allowed only when the users of both
lists are equal but for users placement no longer names, so it waits until the enrolment users and the persons lists are equal but for users placement no longer names, so it waits until the enrolment users and the persons
have records on the bus, and the second milestone waits for it (ADR 0547 §8, §11). have records on the bus, and the second milestone waits for it (ADR 0547 §8, §11).
2. **Nodes compose** (issue 1126): each node agent composes its own modules; no node applies a composition made 2. **Nodes compose** (issue 1126): each node agent composes its own modules; no node applies a composition made
elsewhere but the bus's user list, which the bus node keeps able to follow until the third milestone so `hand-back` has a list to return to. elsewhere but the bus's user list, which the bus node keeps able to follow until the third milestone so `hand-back` has a list to return to.
3. **Nothing is left with the controller** (issues 1126, 774): the vault mints bus accounts, the grants part 3. **Nothing is left with the controller** (issues 1126, 774): the vault mints bus accounts, the grants part
writes grants, the try is the checker's own verb, placement and the signing key are where the operator's writes grants, the try is the checker's own verb, placement is read from the catalogue alone (ADR 0549 §5,
answers put them, and the controller's lease is handed to a holder that is no controller once every other job §6), the vault signs with the mesh's signing key (ADR 0550 §2), and the controller's lease is handed to a holder that is no controller once every other job
it keeps has a home by its own decision (research 072). it keeps has a home by its own decision (research 072).
No machine is enrolled before the third milestone: until the vault mints enrolment tokens and node accounts,
those are the controller's alone (ADR 0550 §6).
Until each milestone is delivered, release 6's text below holds for what that milestone replaces (ADR 0547 §11). Until each milestone is delivered, release 6's text below holds for what that milestone replaces (ADR 0547 §11).
It lands in six releases, each leaving the mesh working, each one milestone below (ADR 0429 §7); releases 4 and 5 end in one milestone, R4g, It lands in six releases, each leaving the mesh working, each one milestone below (ADR 0429 §7); releases 4 and 5 end in one milestone, R4g,
@@ -215,10 +234,10 @@ The target (ADR 0547):
``` ```
forge ──forge messages──► forge bridge ──► the bus ◄── done keys ── builder, build modules (build seats) forge ──forge messages──► forge bridge ──► the bus ◄── done keys ── builder, build modules (build seats)
│ ▲ │ ▲
gate: the merge, the source revision ◄┤ ├── indexer: each module's fingerprint and manifest gate: the merge, the source revision ◄┤ ├── indexer: fingerprints, manifests, placement
grants part: memberships, assertions,◄┤ ├── assigner: each node's wants, by six rules grants part: memberships, assertions,◄┤ ├── assigner: each node's wants, by six rules
the user list, grants │ ├── watchman: presence, pulses, stuck keys the user list, grants │ ├── watchman: presence, pulses, stuck keys
vault: secrets, bus accounts ◄┤ └── status view: delivered, moving, settled, stuck vault: secrets, signing, accounts ◄┤ └── status view: delivered, moving, settled, stuck
▼ ▼
node agent in the node-engine on every node node agent in the node-engine on every node
(reads its wants; composes its own modules; backs up first; applies; writes its haves; (reads its wants; composes its own modules; backs up first; applies; writes its haves;
@@ -231,11 +250,16 @@ The target (ADR 0547):
plan, never sends to a machine and writes no composition (ADR 0539 §17). plan, never sends to a machine and writes no composition (ADR 0539 §17).
- **The controller** is no part of build and delivery (ADR 0547 §1). The jobs it still keeps outside them - **The controller** is no part of build and delivery (ADR 0547 §1). The jobs it still keeps outside them
(nodes and adoption, identities, secrets and given values, licences, config moves, conditions and facts, ADR (nodes and adoption, identities, secrets and given values, licences, config moves, conditions and facts, ADR
0429 §9) each move by a decision of their own under research 072 before it loses its lease; where placement and 0429 §9) each move by a decision of their own under research 072 before it loses its lease. Two are decided, by
the mesh's signing key live is the operator's choice, asked apart (issue 1126). the operator's answers of 2026-10-26: placement lives in the catalogue (ADR 0549), and the mesh's signing key in
- **The vault** keeps every secret and, from ADR 0547's third milestone, mints each bus account a membership the vault (ADR 0550 §2).
names, seals it to its node and writes its bcrypt hash for the grants part alone; until then it hashes the - **The vault** keeps every secret the mesh keeps (ADR 0550 §1): the mesh's signing key, licence grants and
accounts it is handed (ADR 0547 §9). tokens, bus account passwords and module secrets; a holder gets a value only sealed to its own key, or asks the
vault to act with it. It makes the mesh's signing key and signs enrolments and node certificates on request, by
its verb `sign` (ADR 0550 §2). From ADR 0547's third milestone it mints each bus account a membership names,
seals it to its node and writes its bcrypt hash for the grants part alone; until then it hashes the accounts it
is handed, and adopts from the bus node's agent the hashes of the accounts it holds no value for (ADR 0547 §9,
ADR 0550 §4).
- **The build modules** build and check with toolchains installed on their node, each as an account of its own, and pull - **The build modules** build and check with toolchains installed on their node, each as an account of its own, and pull
their asks from the bus's streams, deliveries first (ADR 0405, ADR 0525). their asks from the bus's streams, deliveries first (ADR 0405, ADR 0525).
- **The forge module** (`gitea`) publishes every forge event on the bus through the forge's system webhook - **The forge module** (`gitea`) publishes every forge event on the bus through the forge's system webhook
@@ -302,9 +326,9 @@ ended, as ADR 0505 §3 has it for a delivery in motion (issue 1946).
**One key per pull request.** Beside the delivery, the gate keeps one key per open pull request on the **One key per pull request.** Beside the delivery, the gate keeps one key per open pull request on the
bus: its head, the trunk commit its current check is asked against, and its verdict, written by bus: its head, the trunk commit its current check is asked against, and its verdict, written by
compare-and-set (ADR 0406 §4). It writes a new head when the forge says one, and a new trunk commit only when it compare-and-set (ADR 0406 §4). It writes a new head when the forge says one, and a new trunk commit when the
asks the pull request's check again (ADR 0395 §1). A running check watches that key and stops when the head or pull request's verdict is carried to it or a whole check is asked against it (ADR 0548 §5, §7). A running check
the trunk commit in it moves. watches that key and stops only when the head in it moves; a trunk move never ends it (ADR 0548 §1).
## The state table ## The state table
@@ -319,17 +343,21 @@ state has a **bound**: how long it may be held before `stalled` lists it, for a
| proposed | a head was announced and is being checked | 1 hour from when its check is asked; none while its verdict is out of date and no check is asked | | proposed | a head was announced and is being checked | 1 hour from when its check is asked; none while its verdict is out of date and no check is asked |
| ready | it passed; its Approve is asked (a group member's once the group is ready), and it waits for it and the merge | none | | ready | it passed; its Approve is asked (a group member's once the group is ready), and it waits for it and the merge | none |
| rejected | it failed its check | none | | rejected | it failed its check | none |
| held | it waits for a person or a fresh check: an approved merge unchecked at the trunk's head, a conflict, a member the forge refused | 1 day | | held | it waits for a person, a carry or a check: an approved merge whose verdict is being carried to the trunk's head, a conflict, a member the forge refused, and, while the check gates merges, an approved merge waiting on its merge turn for another delivery's running check (ADR 0548 §2, §8, ADR 0551 §1) | 1 day; a merge turn 30 minutes |
| merged | merged on its trunk; its source revision moved | final | | merged | merged on its trunk; its source revision moved | final |
| closed | closed without a merge | final | | closed | closed without a merge | final |
**A verdict holds for one trunk commit** (ADR 0323). The check judges the head merged into the trunk's head **A verdict holds for one trunk commit, and is carried when the trunk moves** (ADR 0323, ADR 0548 §5). The
when the build module clones it, and the verdict names both. When another merge moves the trunk, a `ready` check judges the head merged into the trunk's head when the build module clones it, and the verdict names both,
delivery goes back to `proposed` on the event `trunk moved`, and the gate asks the check of every active, and the commit of each sibling it read at its trunk (ADR 0548 §6). When another merge moves the trunk, or a
cleanly merging open pull request into that trunk at once (ADR 0395, *A move of the trunk asks every check sibling's trunk, a `ready` delivery goes back to `proposed` on the event `trunk moved`, its `mesh/check` is
again* below). An Approve already asked stays; the merge waits for the fresh check, and the Approve is not asked pending and says it is being carried, and the checker carries the verdict to the new commit once any check
again for a trunk move (ADR 0421 §1, §3). The row from `proposed` to `ready` or `rejected` takes only a verdict running on it has ended: it merges the head onto the new trunk head, computes every package's digest, and runs
that names the trunk's head. only the packages whose digest the move changed; the composition is kept while no fingerprint of a module it
composed changed. A carried pass names the commits it was carried from (`carried-from`). An Approve already
asked stays; the merge waits for the carried verdict, and the Approve is not asked again for a trunk move
(ADR 0421 §1, §3, as ADR 0548 §8 changes them). The row from `proposed` to `ready` or `rejected` takes only a
verdict that names the trunk's head (*A move of the trunk carries every verdict*, below).
**Nothing of a merged delivery is kept moving in the gate.** The delivery states of the plans (delivering, the **Nothing of a merged delivery is kept moving in the gate.** The delivery states of the plans (delivering, the
backup hold, superseded, covered, stopped, retired and failed) and the machine steps went at release 6: a backup hold, superseded, covered, stopped, retired and failed) and the machine steps went at release 6: a
@@ -370,14 +398,14 @@ commit on the SDK's trunk or the head of an SDK pull request the forge holds, op
## Checks ## Checks
### One check per pull request, kept by the bus ### One check per set of heads, kept by the bus
*ADR 0323, ADR 0350, ADR 0395, ADR 0406.* *ADR 0323, ADR 0350, ADR 0395, ADR 0406, ADR 0548 §1.*
- **Asks on streams, taken in order.** A build or a check step is an ask, a message on one of the work-queue streams of - **Asks on streams, taken in order.** A build or a check step is an ask, a message on one of the work-queue streams of
the artifact's language, which the build modules of that language claim as the accepted kinds of their node seat: `delivery` for the the artifact's language, which the build modules of that language claim as the accepted kinds of their node seat: `delivery` for the
build of a trunk fingerprint, `check` for the build of a candidate's fingerprint, a new head's check and the checker's steps (a try is a build of a trunk fingerprint, `check` for the build of a candidate's fingerprint, a new head's check and the checker's steps (a try is a
check ask), and `recheck` for the checker's re-judges after a move of the trunk (ADR 0525 §1, §2, ADR 0536 §4). A build module pulls check ask), and `recheck` for the checker's carries after a move of a trunk or a sibling (ADR 0525 §1, §2, ADR 0536 §4, ADR 0548 §5). A build module pulls
`delivery`, then `check`, then `recheck`, while it has a free slot of its node's build capacity, and no part chooses the node (ADR 0525 §4). `delivery`, then `check`, then `recheck`, while it has a free slot of its node's build capacity, and no part chooses the node (ADR 0525 §4).
Each check stream has one subject per pull request and keeps only the newest request: a newer request replaces one still waiting, by the Each check stream has one subject per pull request and keeps only the newest request: a newer request replaces one still waiting, by the
stream's rule; a request left behind for a head and trunk commit already judged or running is acknowledged and dropped when taken, by stream's rule; a request left behind for a head and trunk commit already judged or running is acknowledged and dropped when taken, by
@@ -387,26 +415,50 @@ commit on the SDK's trunk or the head of an SDK pull request the forge holds, op
- **Nothing holds a check while a delivery builds.** The order of the streams is the only priority deliveries have: the controller's - **Nothing holds a check while a delivery builds.** The order of the streams is the only priority deliveries have: the controller's
key saying that a delivery builds, and the let-through of a check that waited 30 minutes, are gone, so during a large delivery an key saying that a delivery builds, and the let-through of a check that waited 30 minutes, are gone, so during a large delivery an
Approve ask may come later (ADR 0525 §7, which supersedes ADR 0483). Approve ask may come later (ADR 0525 §7, which supersedes ADR 0483).
- **A running check stops itself.** It watches its pull request's key and stops when the head or the trunk - **A check runs to its end.** A delivery, a lone pull request or a delivery group, is judged by one check per
commit in it moves, without asking the forge (issue 726). An ended check delivers no verdict, so none of its set of heads: the checker claims its verdict key once, and the check runs to its verdict (ADR 0548 §1). Only a
builds is reused. new head ends a running check: a push, or a member joining or leaving its group. The check watches its pull
request's key and stops when the head in it moves, without asking the forge (issue 726); an ended check
delivers no verdict, so none of its builds is reused. A trunk move never ends a check: its verdict goes out of
date when it ends, and is carried. A check that failed because a part of the mesh was not heard is still asked
again when the nodes change, which judges heads no check judged.
- **A failed build node loses nothing.** An ask a build module took and never acknowledged goes to another node by the - **A failed build node loses nothing.** An ask a build module took and never acknowledged goes to another node by the
stream's own acknowledgement wait, with no timer of a part; a step's end is written on the build module's step key named stream's own acknowledgement wait, with no timer of a part; a step's end is written on the build module's step key named
by the ask's id (ADR 0525 §6). by the ask's id (ADR 0525 §6).
- **A change is built once** (ADR 0350). A build is keyed by its module's fingerprint, so the merge commit's - **A change is built once** (ADR 0350). A build is keyed by its module's fingerprint, so the merge commit's
fingerprints find the builds the check already made, and the merge builds nothing again (ADR 0453 clause 5). fingerprints find the builds the check already made, and the merge builds nothing again (ADR 0453 clause 5).
### A move of the trunk asks every check again ### A move of the trunk carries every verdict
*ADR 0395.* *ADR 0548 §5 to §8, which change ADR 0395 §1 to §3 and ADR 0323 §3, §4; ADR 0551 §1 keeps them whether or not
the check gates merges.*
- A trunk move asks the check of every active open pull request into that trunk that merges cleanly, against the - **A carry, not a check.** A trunk move puts every verdict judged on the old commit out of date and carries it,
new head; a conflict is told once on the pull request, not checked. once any check running on it has ended: one ask on the build seats' `recheck` stream that merges the head onto
the new trunk head and computes every package's digest. A package whose digest has a kept verdict does not run;
a move that changes nothing a package's tests read runs nothing; the composition check is kept while no
fingerprint of a module it composed changed, and runs again otherwise (ADR 0548 §5). A carried pass is
rewritten under its key by compare-and-set with the new trunk heads and names the commits it was carried from;
a failure fails it, naming the package and the move. This bends the operator's "only a conflict asks a new
check" once, on purpose: a package whose inputs the move changed runs, so the trunk never gets a combination no
test ran.
- **A sibling's move is carried too.** A verdict names the commit of each sibling it read at its trunk, beside
the repositories it merged (ADR 0484 §4); a move of one is carried as a trunk move is, and only the packages
whose tests read siblings can change digest and run (ADR 0548 §6).
- **Only a head git refused gets a whole check.** A carry whose merge conflicts, or a merge the forge refuses for
a conflict, fails the verdict naming the files in conflict, and its Approve's ask is withdrawn; its next check
is a whole check of its head, at its next push or at the first later trunk move onto which it merges cleanly
(ADR 0548 §7). That is the one check a trunk move asks; a verdict that can be carried is never checked again
for a trunk move.
- **The line says the carry.** A carried verdict's line names the head on the new trunk commit first, as the gate
and the merge tool read a line, then per level the trunk commit it was carried from and the packages run and
kept (ADR 0548 §8). While a verdict is carried, `mesh/check` on the heads is pending and says so (ADR 0548 §6).
- **A group carries one verdict.** For a group, a move carries the group's one verdict on every member's head;
the group's own merges, made in one pass on its Approve in its order, carry nothing (ADR 0418 §4, ADR 0323 §6).
- A pull request with no push for 7 days and no Approve asked or given is left out; its statuses say out of date - A pull request with no push for 7 days and no Approve asked or given is left out; its statuses say out of date
and that a push or a recheck asks its check (ADR 0421 §10). and that a push or a recheck asks its check (ADR 0421 §10).
- For a group, a move asks each member's own check, and the composed check runs again through those checks; the - Its cost is at most one carry per open verdict per trunk move, each running only the packages whose digest the
group's own merges, made in one pass on its Approve, ask its members nothing again (ADR 0418 §4). move changed; issue 944 measures it.
- Its cost is at most one check per active, cleanly merging pull request per trunk move; issue 944 measures it.
### A delivery group's checks ### A delivery group's checks
@@ -429,6 +481,43 @@ commit on the SDK's trunk or the head of an SDK pull request the forge holds, op
merged again on its fresh check while the group waits in the gate, `held`, and its source revision does not move merged again on its fresh check while the group waits in the gate, `held`, and its source revision does not move
(ADR 0539 §17). (ADR 0539 §17).
### Nothing merges into a repository under check
*ADR 0548 §2 to §4, §9, §10, as ADR 0551 bounds them.*
**Only while the check gates merges.** The hold, the merge turns and their stalled line hold only while the
setting `check-gates-merge` of mesh-delivery-gate, set together with the forge module's, is true. While it is
false (the operator's setting since 2026-10-25: the check runs, but gates no merge), the gate writes no turn and
holds no approved merge for another delivery's running check: the merge is handed to the forge bridge at once,
the running check ends on the commit it read, and its verdict is carried (ADR 0551 §1, §2). The checker does not
read the setting: it reads `turns`, finds none, and claims its checks at once.
- **The hold.** The gate hands no approved merge to the forge bridge while a verdict of the checker's verdicts
bucket in the state `running` names, among its trunk heads, a repository the merge goes into; the verdict of
the merging delivery's own heads excepted. The gate already watches that bucket, so the verdict leaving
`running` (a pass, a failure, its key deleted) gives the waiting merge its turn at once, with no timer and no
new event. Siblings a check reads beside are not held: the catalogue is read beside nearly every check. A merge
made at the forge by hand is not held; the check it lands under ends on the commit it read and is then carried
(ADR 0548 §2).
- **The merge turn.** Before it reads the checker's verdicts for an approved merge, the gate writes one key per
repository the merge goes into in its bucket `turns` (`turns.<owner>.<name>`): the deliveries that wait there in
the order of their Approve, the verdict key each waits for, and since when; for a delivery group, on every
member's repository from its first member handed until its last merged, so the group merges whole. The gate is
the key's one writer; the checker reads the bucket, reads it absent as empty, claims no check of a repository a
turn names, and claims on the key's delete, so an approved merge goes before a check not yet started. The key
goes when the last delivery in it merged or left (a Decline, a push, a refusal). A check claimed in the moment
between the gate's read and the merge is judged on the commit it read and carried once after, never restarted
(ADR 0548 §3).
- **The bound and the tools.** A turn waiting longer than 30 minutes is a stalled line naming the check it waits
for, when that check started and the step the checker says it is at, raised as the condition
`delivery.<id>.stalled` (ADR 0421 §7). A tool of the gate reads every turn with the check it waits for; another,
on the operator's word, hands a waiting merge at once, the check it waited for then carried (ADR 0548 §4).
- **What the operator sees.** While the check gates merges, an approved merge into a repository under a running
check merges when that check ends, at most one check's length later; `deliveries` and `show` say it is approved
and waits for the check of the named delivery on the named repository, running since a given time. While it
does not, an approved merge goes in at once and no merge waits for a check. Either way no check is thrown away
for another merge, and the Approve is asked once per set of heads (ADR 0548 §9, ADR 0551 §2).
### The check from release 4 ### The check from release 4
*ADR 0444, ADR 0445, ADR 0446, ADR 0447; research 058.* *ADR 0444, ADR 0445, ADR 0446, ADR 0447; research 058.*
@@ -470,8 +559,7 @@ From its delivery, a check is this:
and the check stops at their first failure, before the rest and before the composition. A kept verdict is and the check stops at their first failure, before the rest and before the composition. A kept verdict is
written once, by the checker's credential alone, from the result it read, and is addressed by its digest; written once, by the checker's credential alone, from the result it read, and is addressed by its digest;
each check builds with a cache of its own, so one pull request cannot poison another's verdict (ADR 0444, each check builds with a cache of its own, so one pull request cannot poison another's verdict (ADR 0444,
issue 482). With every check asked again on a trunk move (ADR 0395), such a re-ask runs only what the move issue 482). A trunk move asks no check but a carry, which runs only what the move changed (ADR 0548 §5).
changed.
- **The composition check is the assigner's.** Whether the machines still compose with a change is checked by - **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 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; the machines, their roles, assignments and settings, and the indexer holds and the builds the builder holds; the machines, their roles, assignments and settings, and
@@ -496,8 +584,8 @@ From its delivery, a check is this:
`mesh/repo-check` passed at its head against its trunk's head), mesh-delivery asks the operator's Approve of its `mesh/repo-check` passed at its head against its trunk's head), mesh-delivery asks the operator's Approve of its
merge into main at once, on a channel that proves who answered (ADR 0274; Telegram today). The ask names the merge into main at once, on a channel that proves who answered (ADR 0274; Telegram today). The ask names the
pull request, its issues, the reviewer's verdict, the modules it moves and the trunk commit the checks judged. A pull request, its issues, the reviewer's verdict, the modules it moves and the trunk commit the checks judged. A
verdict that names a trunk commit the trunk had already left raises no ask: mesh-delivery asks that head's check verdict that names a trunk commit the trunk had already left raises no ask: the checker carries it to the
against the trunk's head, and its passing verdict raises the ask (ADR 0421 §1). trunk's head, and the carried verdict raises the ask (ADR 0421 §1, as ADR 0548 §8 changes it).
- **A group is asked once.** One ask names every member and its head, once every member is `ready` and the - **A group is asked once.** One ask names every member and its head, once every member is `ready` and the
composed check passed at those heads; one Approve covers them all (ADR 0421 §2). From the delivery of issues 1781 to composed check passed at those heads; one Approve covers them all (ADR 0421 §2). From the delivery of issues 1781 to
1783 the ask is the milestone's, made once when every one of its issues is ready, and a pull request linked to no 1783 the ask is the milestone's, made once when every one of its issues is ready, and a pull request linked to no
@@ -510,9 +598,12 @@ From its delivery, a check is this:
description is read (ADR 0493 §5, §6). The ask carries it; with none, or one naming another commit, the ask says so in its first line and description is read (ADR 0493 §5, §6). The ask carries it; with none, or one naming another commit, the ask says so in its first line and
the operator decides (ADR 0421 §5). the operator decides (ADR 0421 §5).
- **The merge.** mesh-delivery merges through the forge's merge tool at the heads the Approve names, only while - **The merge.** mesh-delivery merges through the forge's merge tool at the heads the Approve names, only while
they are still the heads and both checks passed against the trunk's head. When the trunk moved, the merge tool they are still the heads, their check passed against the trunk's head, and, while the check gates merges, no
asks the fresh check, and the event of its passing verdict asks the merge again; no timer asks it, and no person check of other heads runs on a repository the merge goes into (*Nothing merges into a repository under check*,
rechecks (ADR 0421 §3, §12). above). When the trunk moved, the merge waits for the carried verdict, and the event of its line asks the merge
again; no timer asks it, no person rechecks, and the Approve is not asked again (ADR 0421 §3, §12, as ADR 0548
§8 changes them). The merge tool still refuses a verdict naming a trunk commit other than the trunk's head and
asks nothing (ADR 0534 §4); the carry makes the verdict current.
- **A push or a Decline ends the Approve.** A new head ends its ask or its Approve, for a group every member's, and - **A push or a Decline ends the Approve.** A new head ends its ask or its Approve, for a group every member's, and
is said once on the pull request; the new head is asked again once its checks pass. A Decline merges nothing and is said once on the pull request; the new head is asked again once its checks pass. A Decline merges nothing and
is said once (ADR 0421 §6). is said once (ADR 0421 §6).
@@ -686,15 +777,18 @@ and `delivered` events.
*ADR 0408, ADR 0429 §17, ADR 0539 §4, §12, §13.* *ADR 0408, ADR 0429 §17, ADR 0539 §4, §12, §13.*
From release 6, module, source revision, build, want and have are one chain, each link answerable from the next From release 6, module, source revision, build, want and have are one chain, each link answerable from the next
(ADR 0429 §17). The assignments bucket keeps placement alone, and the rollouts bucket is kept read-only with its (ADR 0429 §17). Placement is the catalogue's, read onto the bus by the indexer (ADR 0549 §1, §2); the controller's
history: no rollout is written after release 5's last plan (ADR 0539 §12). assignments bucket is kept equal to it until ADR 0547's third milestone and is a source of nothing from then
(ADR 0549 §5, §6). The rollouts bucket is kept read-only with its history: no rollout is written after release
5's last plan (ADR 0539 §12).
| Link | Names | Written by | Bucket | | Link | Names | Written by | Bucket |
|---|---|---|---| |---|---|---|---|
| build | its module, repository and commit, its reuse key, what it published: an artifact by digest or a package release by name and version | the controller | `mesh-controller_builds` | | build | its module, repository and commit, its reuse key, what it published: an artifact by digest or a package release by name and version | the controller | `mesh-controller_builds` |
| want | the fingerprint a node should run of a module, and the digest of the one composition it allows; the node's own want names its node composition | the assigner | `mesh-delivery-assigner_wants` | | want | the fingerprint a node should run of a module, and the digest of the one composition it allows; the node's own want names its node composition | the assigner | `mesh-delivery-assigner_wants` |
| have | what the node runs of a module: the fingerprint, the composition's digest, the phase and the health | the node agent | `node-engine_have` | | have | what the node runs of a module: the fingerprint, the composition's digest, the phase and the health | the node agent | `node-engine_have` |
| assignment | the module and node, pinned or not, ended or not: placement alone, written by `assign` and `unassign` | the controller | `mesh-controller_assignments` | | placement | each node's modules with their pins, host ports and bindings, from the catalogue's placement file of that node at each trunk merge of the catalogue | the indexer | the indexer's state `placement` |
| assignment | until ADR 0547's third milestone: the module and node, pinned or not, ended or not, written by `assign` and `unassign` after a merged placement change, so that it equals the catalogue (ADR 0549 §5) | the controller | `mesh-controller_assignments` |
| rollout | read-only from release 6: each plan of releases 1 to 5, its tiers, the builds it carried and the assignments it changed | nobody from release 6 | `mesh-controller_rollouts` | | rollout | read-only from release 6: each plan of releases 1 to 5, its tiers, the builds it carried and the assignments it changed | nobody from release 6 | `mesh-controller_rollouts` |
Beside the chain, on the bus too: deliveries and groups (the gate's `deliveries` and `groups`, ADR 0239 §37), one Beside the chain, on the bus too: deliveries and groups (the gate's `deliveries` and `groups`, ADR 0239 §37), one
@@ -709,8 +803,10 @@ at its first start of release 6 (ADR 0539 §13).
reads the buckets it names to decide; a part resumes from its keys after a restart. No table of the reads the buckets it names to decide; a part resumes from its keys after a restart. No table of the
controller's store holds builds, rollouts, batches or assignments, so no record mirror, controller's store holds builds, rollouts, batches or assignments, so no record mirror,
audit or healer exists for them; the nodes, settings, declared-config and predefined-keys mirrors stay as audit or healer exists for them; the nodes, settings, declared-config and predefined-keys mirrors stay as
ADR 0289 and ADR 0356 have them. A module reads a bucket by naming it in `reads`; mesh-config reads the ADR 0289 and ADR 0356 have them. A module reads a bucket by naming it in `reads`. The assigner, the grants part,
assignments bucket. mesh-config and the node agents read placement from the indexer's state, on its watch; from ADR 0547's second
milestone no part but the controller reads the assignments bucket, and the assigner until the third
(ADR 0549 §3).
- **No key of the chain is removed.** Each bucket keeps up to 64 earlier revisions of each key as its history. A - **No key of the chain is removed.** Each bucket keeps up to 64 earlier revisions of each key as its history. A
value is never cut to a summary and stays under the bus's largest message. The bus's storage is declared as data value is never cut to a summary and stays under the bus's largest message. The bus's storage is declared as data
protected by a backup, so it is backed up nightly and before a delivery moves the bus. protected by a backup, so it is backed up nightly and before a delivery moves the bus.
@@ -851,7 +947,9 @@ What the build proves before this design is implemented (research 055's directio
newer fingerprint once its rules hold, a fingerprint nobody wants any more is never applied, and nothing is newer fingerprint once its rules hold, a fingerprint nobody wants any more is never applied, and nothing is
released by a person or held in the gate. released by a person or held in the gate.
12. No table in the controller's store holds builds, deliveries or assignments: builds are the builder's keys, 12. No table in the controller's store holds builds, deliveries or assignments: builds are the builder's keys,
wants the assigner's, haves the node agents', and placement, for now, the controller's assignments bucket (where it lives is the operator's choice, issue 1126). wants the assigner's, haves the node agents', and placement the catalogue's placement files, read onto the bus
by the indexer, with the controller's assignments bucket kept equal to them until ADR 0547's third milestone
(ADR 0549).
Tests 1 to 12 are stated as they hold from release 6. Tests 1, 3, 7, 8, 9, 10 and 11 were first proved by Tests 1 to 12 are stated as they hold from release 6. Tests 1, 3, 7, 8, 9, 10 and 11 were first proved by
milestones 1 to 5 in the shape of their time, the controller's plans and what it sent (the milestones table keeps milestones 1 to 5 in the shape of their time, the controller's plans and what it sent (the milestones table keeps
@@ -917,6 +1015,17 @@ development, the check's share about a minute):
line naming what was proved and each part's time; no repository a module is built from holds a line naming what was proved and each part's time; no repository a module is built from holds a
`merge-check.sh`. `merge-check.sh`.
From ADR 0548 and ADR 0551 (issue 568):
25. **One check per delivery.** A delivery group of two repositories is under check, and a lone pull request into
one of them is approved during the run. While the check gates merges, it waits, `mesh-delivery.show` says
what it waits for, and it merges when the group's verdict is written; while it does not, it merges at once and
the group's running check ends on the commit it read. Either way the group's verdict is then carried to the
new trunk commit with no test run for an unchanged digest, and the group merges on its Approve with no second
check. Read from `mesh-delivery.show`, the checker's verdict (`carried-from`, the levels' run and kept counts)
and the forge's statuses; issue 568 is resolved only once this has passed on the mesh (ADR 0548 §10, ADR 0551
§2).
## What retires ## What retires
- The "release branches" and the controller's judge of them (ADR 0358, superseded by ADR 0401). - The "release branches" and the controller's judge of them (ADR 0358, superseded by ADR 0401).
@@ -927,6 +1036,11 @@ development, the check's share about a minute):
- The ready mark: the label `mesh/ready`, the `ready at` comment, `mark-ready`, the forge module's - The ready mark: the label `mesh/ready`, the `ready at` comment, `mark-ready`, the forge module's
`ready-authors` setting, and mesh-delivery's subscriptions to labeled, unlabeled and commented events `ready-authors` setting, and mesh-delivery's subscriptions to labeled, unlabeled and commented events
(ADR 0421 §4, §11); a recheck by hand as a step of the flow (ADR 0421 §12). (ADR 0421 §4, §11); a recheck by hand as a step of the flow (ADR 0421 §12).
- A check ended or asked again for a trunk move, and the re-ask of every open pull request's check at each move
(ADR 0395 §1, §3, as ADR 0548 §1 and §5 change them): a running check ends only at a new head, and a trunk
move carries a verdict by its package digests.
- Placement written only by the controller's `assign` and `unassign` (ADR 0539 §12, as ADR 0549 §1 changes it):
from ADR 0547's third milestone its tables and verbs are a source of nothing (ADR 0549 §6).
- A group's order: `after:` lines, the ranked rules and the order of the repositories' names (ADR 0419, which - A group's order: `after:` lines, the ranked rules and the order of the repositories' names (ADR 0419, which
supersedes ADR 0249). supersedes ADR 0249).
- Delivery member by member, a stop of a member after a failed one, and the own path's separate batch for a - Delivery member by member, a stop of a member after a failed one, and the own path's separate batch for a