diff --git a/03-DESIGN/01-to-be/57-building-config-and-provisioning.md b/03-DESIGN/01-to-be/57-building-config-and-provisioning.md index a708f91a..4f5a440c 100644 --- a/03-DESIGN/01-to-be/57-building-config-and-provisioning.md +++ b/03-DESIGN/01-to-be/57-building-config-and-provisioning.md @@ -33,7 +33,8 @@ Each of mesh-controller, `mesh-host`, mesh-sdk, mesh-catalog and hq has the bran main. When the last package is merged, the whole is rehearsed in the lab: the walk, the moves of data in their order, and every proof that is run live. Then each repository's branch reaches main in one pull request, and the five, sharing their branch's name, are one delivery group (ADR 0239 §2), judged as one -future state and delivered by one walk (ADR 0276). The release holds every package but T6, R1 and R2: +future state. The five are merged within one merge window, so they are one batch and one walk (ADR 0276 +§1, §2), in the group's order: mesh-sdk, `mesh-host`, mesh-controller, mesh-catalog, hq (ADR 0239 §12). The release holds every package but T6, R1 and R2: the media catalogue and the applications live in repositories of their own and move after it, and only then can the old forms be refused (R1) and the record say what runs (R2). @@ -43,10 +44,12 @@ the vault, nothing rotated (V3), then the providers one by one (B2, B3). Each is first, and each is checked by reading back through the module that owns the data before anything points at it. -**What a release costs.** A proof that is run live (dunst on g14, a secret reaching its file, a database -consumer connecting) is first seen in the lab rehearsal, and a fault found then holds the release, not -one package. A failed member of the group stops the walk, which walks the others again without it -(ADR 0299). +**What a release costs.** A proof that is run live (dunst on a workstation, a secret reaching its file, a +database consumer connecting) is first seen in the lab rehearsal, and a fault found then holds the +release, not one package. A walk that fails fails every commit it carries (ADR 0276 §3), so a fault on +the release's first node holds all five; the merges walked again without one exist only after a person's +stop, and leave out every merge that shares its modules (ADR 0299 §1, §2), which in this release is most +of them. **Nothing breaks on the way.** ADR 0349 clause 17: each file is filled the old way or the new way, never both, by the form of its manifest, and the old forms stay accepted until the last module has moved. @@ -64,9 +67,10 @@ Counted 2026-10-14 at mesh-controller `1601cb1`, the node-engine (`mesh-host`) ` | settings | tables `settings`, `settings_history`; the `settings` verb (`modules.go` 407–760); proposals and asks (`proposals.go`, 975 lines); trusted files; `takes-settings` merging; about 4 100 lines and 2 500 of tests | the `mesh-config` module and its buckets; the verb `config` | | placement kept as settings | `places`, `accesses` and the kept networks are read from settings layers | facts of an assignment, the controller's own | | secrets | the controller mints, seals and accepts every secret (`internal/secrets`, `inventory/secrets.go` 1 125 lines; tables `secret`, `module_secret`, `secret_ask`, `operator_key`); the vault (`mesh-vault`, TypeScript) is read-only and never asked | the vault, in Go, holding and minting; handing out on request and reply | -| bindings | grant files and binding files composed by the controller (`declaration.go` 750–818); `${bound:}` 116 uses | each provider answers its consumers; the vault mints the pair's credential | +| bindings | grant files and binding files composed by the controller (`declaration.go` 750–818); `${bound:}` 117 uses | each provider answers its consumers; the vault mints the pair's credential | | contributions | `${contribution:}` (4 collectors), `${shell:}` (3), `${environment:}` (1); 22 contributors | collections, filled by the provisioner client | -| file text | 225 file resources in 88 modules, all inline (about 193 KB); 12 modules keep a second copy in 34 files with a test that the two agree | template files under `files/`, packed by the module's build | +| file text | 225 file resources in 88 modules, all inline (about 193 KB); 12 modules keep a second copy in 34 files with a test that the two agree (ADR 0349's context counted +eleven; the twelfth is lemurs) | template files under `files/`, packed by the module's build | | packing a directory | the builder's `archive` artifact packs a tree and publishes it by digest; the node-engine fetches and unpacks it | the same mechanism carries a module's templates | | the node-engine's file writing | `applyFile`, `applyBlock`, `applyInto`, create-once, drift written back, `Keep` backups, restart-on and reload-on, container reads | the same code, reached also through a narrow local write verb | | the node-engine's local verbs | one socket (`cli.sock`), peer-checked by uid, forwarding to the controller; no local write | a second, narrow socket for the provisioner client | @@ -102,8 +106,10 @@ L1 P6 L2 L1 S1 P6 R1 T5, T6, K6, K7, P7, V4, B3, L2, S1 R2 R1 ``` -The issue tracker holds the same links as `depends-on`, so the packages ready to start are those whose -linked packages are all merged into the release's branches. The first wave touches different repositories and different files: +The issue tracker carries these as `depends-on` links (thirteen issues also link what they wait for +through another package), so the packages ready to start are those whose linked packages are all merged +into the release's branches. An issue's "Waits for: … delivered" means merged into the release's +branches: nothing is delivered before the release. The first wave touches different repositories and different files: **T1, F1, F3, P1 and F4**. K1 waits for T1 because both change `internal/catalogue/manifest.go`; P3 waits for F3 because both change `internal/broker`; F2 joins as soon as a slot is free. @@ -164,9 +170,12 @@ repository. Two days.* **Proof:** as T2, per repository. **K1 (issue 660) — A module declares its config.** *mesh-controller. Two days.* The manifest takes `config` (type, description, validation, trusted, `predefined`, `default` or `required`), `takes-config` and `${config:}`, with `settings`, `takes-settings` and `${setting:}` read as aliases; registration -refuses what ADR 0348's check list names (a value without type or description, a default failing its -validation, an untrusted object, an untrusted value falling back to a trusted key, a placeholder naming -an undeclared value, a mesh word in `takes-config`). **Proof:** the registration refusal tests, one per +refuses everything ADR 0348's "How it is checked" lists for registration: a value without type or +description; a value with neither a default nor `required`; a default failing its validation; an +object or list not trusted; a predefined key not on the list or of another type (with K2); an untrusted +value falling back to a trusted key; a value neither in a template nor read at runtime; a placeholder +naming an undeclared value; a `reload-on` or `restart-on` naming an undeclared file; a moved module's +mergeable file not naming its keys; a mesh word or `puid`/`pgid` in `takes-config`. **Proof:** the registration refusal tests, one per rule; every manifest in the catalogue still registers. **K2 (issue 661) — The list of predefined keys.** *mesh-controller and mesh-catalog. A day.* `predefined.json` at the @@ -191,17 +200,18 @@ refused. **K5 (issue 664) — The values move, and `settings` forwards.** *mesh-controller and mesh-catalog. Two days.* Each existing layer moves into mesh-config (a node layer to `module..`; a whole-mesh layer to mesh config, a manifest default or each node, as ADR 0348's consequences say; claude-code's managed -settings to `agent-managed-settings`), recorded with why; the controller reads `mesh-config_resolved` -where it read its layers, and `settings` answers by forwarding to `config`. **Proof:** composition of +settings to `agent-managed-settings`), recorded with why; for a module not yet handed to the provisioner +the controller reads `mesh-config_resolved` where it read its layers (ADR 0349 clause 17's old way, +an exception to ADR 0348 §9 that R1 removes), and `settings` answers by forwarding to `config`. **Proof:** composition of every node before and after is byte-identical; `settings` and `config` list the same values. **K6 (issue 665) — The catalogue says config.** *mesh-catalog. A day.* The 15 modules using `${setting:}`, the 9 declaring settings and the 4 with `takes-settings` move to the new names and the full declaration. **Proof:** the catalogue's check finds no old name in a moved module. -**K7 (issue 666) — The operator's acceptance on dunst.** *live. An hour.* With every level cleared g14's dunstrc says -10; a mesh font size, then g14's node font size, then dunst's own value on g14 each appear in g14's -dunstrc within the call's answer, and the history shows each change with who and why. Needs P6. +**K7 (issue 666) — The operator's acceptance on dunst.** *live. An hour.* With every level cleared the first +workstation's dunstrc says 10; a mesh font size, then that node's font size, then dunst's own value on +that node each appear in its dunstrc within the call's answer, and the history shows each change with who and why. Needs P6. ## 3 — The provisioner (ADR 0349 clauses 3–5, 11, 13) @@ -236,11 +246,12 @@ comes back. Its first owners are placement (from the declaration) and config (fr Two days.* For a module marked moved, the declaration carries placement, the templates' digest and the filled-files list, and the controller runs no other filling pass for it; the first-node gate counts the module healthy only after its node's `prov.applied` for the new build (`gateFacts`). dunst moves first. -**Proof:** composition and gate tests; dunst on g14 filled by the client, live. +**Proof:** composition and gate tests; dunst on the first workstation filled by the client, live. **P7 (issue 673) — The node-engine stops writing placed files from the declaration.** *`mesh-host`. A day.* For a moved module the engine writes its filled files only through P2, and removes as an orphan only what the verb -placed. **Proof:** the apply tests; no file written twice in a day's journal on g14. +placed. **Proof:** the apply tests; no placed file written twice in a day's journal on the +first workstation. ## 4 — Secrets (ADR 0349 clauses 6–11, 16; issue 647) @@ -255,7 +266,7 @@ answering the vault alone) and `rotate` become the vault's; the controller's ver `secret-ask` and issuing provider tests in ADR 0349. **V3 (issue 676) — The secrets move to the vault.** *mesh-controller and mesh-catalog. Two days.* Every row of -`secret`, `module_secret`, `secret_ask` and the operator key's export is copied into the vault as it is, +`secret`, `module_secret`, `secret_ask` and the operator key's public half are copied into the vault as it is, nothing rotated, and read back through the vault before anything points at it. **Proof:** for every secret, the vault's sealed answer opens to the same value the controller's does. @@ -266,7 +277,8 @@ nothing; the core's credentials travel sealed by the vault to their node and the **V5 (issue 677) — The vault mints pair credentials.** *mesh-catalog. Two days.* One value per provider assignment and provision, remade for all holders when the vault sees a consumer's need recorded or deleted (ADR 0158 -§4–§6). **Proof:** the provider test in ADR 0349, with a stand-in provider. +§4–§6). A need recorded for a bind the vault already holds from V3 adopts that value and remakes +nothing, so the move itself rotates no credential. **Proof:** the provider test in ADR 0349, with a stand-in provider. ## 5 — Bindings (ADR 0349 clause 12) @@ -277,7 +289,7 @@ tests with a stand-in bus. **B2 (issue 679) — PostgreSQL answers its consumers.** *mesh-catalog and mesh-controller. Three days.* The first provider moves; its grant files and binding files are retired. **Proof:** every database consumer on -every node connects after the move with the credential it had (no rotation), live. +every node connects after the move with the credential it had, adopted by the vault as V5 says, live. **B3 (issue 680) — The other providers.** *mesh-catalog. A week, one pull request per provider.* **Proof:** as B2, per provider; afterwards the controller composes no grant file. @@ -307,11 +319,13 @@ ADR 0349; claude-code reads its managed settings through it. every catalogue has moved: the catalogue's check refuses inline text, `settings`, `${setting:}` and the old contribution forms; the controller's filling passes but placement, its settings, secret and binding code and tables (a new migration) go; the node-engine keeps opening sealed values for the core's files -only. **Proof:** the controller's test that its code opens no secret outside genesis; the absence of the +only; the controller stops reading `mesh-config_resolved`. **Proof:** the controller's test that its +code opens no secret outside genesis and reads no config value; the absence of the removed code. -**R2 (issue 683) — The record says what runs.** *hq. A day.* The as-is designs are written, designs 27 and 32 are -amended, ADR 0348's and 0349's built status is said, and this document's status becomes `implemented`. +**R2 (issue 683) — The record says what runs.** *hq. Two days.* The as-is designs are written, designs 27 and 32 are +amended, the 67 documents that still say "setting" in running prose are reworded so the glossary can +retire the word (F4 left it off the *Not:* line for them), design 49 lists the Config domain, ADR 0348's and 0349's built status is said, and this document's status becomes `implemented`. ## What is deliberately not here