From 0e0f0298c6f5f6313e983e012d12351a411ac021 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 21 Sep 2026 23:33:47 +0200 Subject: [PATCH 1/5] ADR 0099: a step that runs once names what it reads; issues 077 and 078 resolved; designs 08 and 20 amended --- ...step-that-runs-once-names-what-it-reads.md | 92 +++++++++++++++++++ 02-DECISIONS/README.md | 1 + 03-DESIGN/01-to-be/08-connectivity.md | 7 +- 03-DESIGN/01-to-be/20-writing-a-module.md | 9 ++ .../00-report.md | 6 +- .../01-diagnosis.md | 16 ++++ .../00-report.md | 5 +- .../01-diagnosis.md | 17 ++++ 8 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md create mode 100644 04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/01-diagnosis.md create mode 100644 04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md diff --git a/02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md b/02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md new file mode 100644 index 0000000..3e73e62 --- /dev/null +++ b/02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md @@ -0,0 +1,92 @@ +--- +topic: what runs on it +status: accepted +date: 2026-09-21 +deciders: jochen +reconstructed: false +extends: 0052-a-step-that-runs-once-before-a-container.md +--- + +# 99. A step that runs once names what it reads, and runs again when it changed + +## Context + +[ADR 0098](0098-a-fact-a-provider-makes-at-first-start-is-fetched-from-it.md) has a consumer +fetch a fact its provider made at first start through a run-once step: the route proxy fetches +the certificate authority's root before it starts. A run-once step runs once per declaration +([ADR 0052](0052-a-step-that-runs-once-before-a-container.md)): its marker is the digest of its +own declaration, and a re-apply that finds the marker does nothing. + +The provider can move. When the authority is assigned to another node it makes a new root there, +and the mesh rewrites the consumer's binding file with the new address — but the step's own +declaration has not changed, so the step does not run again, the proxy keeps the old root, and it +refuses every certificate the new authority issues +([issue 077](../04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/00-report.md)). A +restart trigger was the natural remedy and was refused on a run-once step, on the ground that a +step does not stay running to be restarted. + +Two things the host already does point at the answer. What a container reads is part of what it +is: a container's digest includes the digest of every resource it names under `restart-on`, so a +rewritten file it reads is a changed container +([issue 045](../04-ISSUES/045-a-container-keeps-the-values-it-started-with/00-report.md)). +And a run-once step's marker *is* its digest. Nothing new is needed for the step to run again when +what it reads changed; only the refusal stands in the way. + +## Decision + +**A run-once step may name what it reads under `restart-on`. For a step the word means *run +again*: when a named resource changed in this apply, the step's digest has moved, its marker no +longer matches, and it runs again — gating what follows, as it did the first time.** Nothing +about the marker changes; the refusal of the pair is lifted, in the control plane and on the host. + +**The container that consumes what a step made names the step.** A step that ran counts as a +change, so a service that names it under `restart-on` is recreated after it, holding what the step +fetched. Without this the step fetches a new root and the service keeps serving with the old one. + +The route proxy's gate names the binding file it reads; the proxy's server names the gate and the +binding. When the authority moves, the binding is rewritten, the gate fetches the new root, and the +server is recreated with it — in one apply. + +## Considered Options + +1. **A provider epoch in the binding — the mesh raises a number when a provider is re-issued or + moved, and the consumer's file carries it.** Rejected: the binding already changes when the + provider moves (its address does), and a re-issue does not change what the authority serves — + its state persists. An epoch would be a second signal for a change the file already shows. +2. **The step runs before every start of the service, with no marker.** Rejected: every reconcile + would run it, and a step that runs on every apply reads as a change on every apply, so the + service naming it would be recreated every few minutes. +3. **The proxy fetches the root itself, at start.** Rejected as the general answer: it fixes the + proxy and leaves the next consumer of a fact made at first start to fix itself. The step is the + general shape ([ADR 0098](0098-a-fact-a-provider-makes-at-first-start-is-fetched-from-it.md)). +4. **Lift the refusal and read `restart-on` as *again* on a step.** Adopted: it is what the + digest already does, and it needs no new word. + +## Consequences + +A fact fetched at first start follows its provider when the provider moves. What is not covered: +a provider whose state is wiped behind the mesh's back, on the same node, makes a new fact that +nothing the mesh knows reflects. That is not a change the mesh can see, and it is not claimed. + +The one contradiction the refusal named is real and is now a documented reading: on a running +container `restart-on` means recreate, on a step it means run again. Both are "this must reflect +what it reads". + +## How it is checked + +- mesh-host: a unit test declares a run-once step naming a file, records its marker against the + file's old content, applies with the new content and asserts the step ran; applies again with + nothing changed and asserts it did not. A second test declares a container naming a run-once + step and asserts the container is recreated after the step ran, with the step as the stated + reason. +- mesh-controller: the manifest parser accepts a run-once step with `restart-on`; the + catalogue-wide manifest test parses the route proxy's manifest, whose gate and server name what + they read. +- The route-forwarding bed still passes with the host that accepts the pair. No bed moves the + authority: the mechanism is proven by the unit tests, the declaration by the manifest test. + +## References + +- [issue 077](../04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/00-report.md) +- [ADR 0052](0052-a-step-that-runs-once-before-a-container.md), [ADR 0053](0053-a-step-that-runs-on-a-schedule.md), [ADR 0098](0098-a-fact-a-provider-makes-at-first-start-is-fetched-from-it.md) +- [`03-DESIGN/01-to-be/08-connectivity.md`](../03-DESIGN/01-to-be/08-connectivity.md), [`03-DESIGN/01-to-be/20-writing-a-module.md`](../03-DESIGN/01-to-be/20-writing-a-module.md) diff --git a/02-DECISIONS/README.md b/02-DECISIONS/README.md index 63d6133..e0ac7a4 100644 --- a/02-DECISIONS/README.md +++ b/02-DECISIONS/README.md @@ -146,6 +146,7 @@ python3 00-META/checks/index.py fail if stale - **0085** — [A secret is a provision, and the vault is the module that provides it](0085-a-secret-is-a-provision.md) - **0087** — [A seeded file is created once, and what grows in it is not the mesh's](0087-a-seeded-file-is-created-once.md) - **0091** — [A mount is declared, and there are three things it can be](0091-a-mount-is-declared-three-ways.md) +- **0099** — [A step that runs once names what it reads, and runs again when it changed](0099-a-step-that-runs-once-names-what-it-reads.md) ### How it is built diff --git a/03-DESIGN/01-to-be/08-connectivity.md b/03-DESIGN/01-to-be/08-connectivity.md index 8aa3640..7598b7d 100644 --- a/03-DESIGN/01-to-be/08-connectivity.md +++ b/03-DESIGN/01-to-be/08-connectivity.md @@ -9,6 +9,7 @@ code: - mesh-host internal/apply (the service that reflects a rule set) updated: 2026-09-21 decisions: + - 02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md - 02-DECISIONS/0098-a-fact-a-provider-makes-at-first-start-is-fetched-from-it.md - 02-DECISIONS/0005-the-node-host.md - 02-DECISIONS/0004-a-node-and-how-it-joins.md @@ -564,9 +565,9 @@ The mesh mints the authority's password and nothing else of its: a root certific are things only the authority can make, and a served fact written in a manifest cannot carry what does not exist until the authority has run. So the authority serves its root at a path beside its ACME directory, and the proxy that requires it fetches that root over the mesh network in a -run-once step before it starts. The step is run once per declaration: a root that changes -after first start is fetched again only when the declaration changes -([issue 077](../../04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/00-report.md)). +run-once step before it starts. The step names the binding it reads and the proxy names the +step, so when the authority moves the root is fetched again and the proxy is recreated with it +([ADR 0099](../../02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md)). *How it is checked:* the route-forwarding bed installs the authority, the proxy and a consumer from the catalogue and asserts the routed name is served. diff --git a/03-DESIGN/01-to-be/20-writing-a-module.md b/03-DESIGN/01-to-be/20-writing-a-module.md index f103d43..32fb4d4 100644 --- a/03-DESIGN/01-to-be/20-writing-a-module.md +++ b/03-DESIGN/01-to-be/20-writing-a-module.md @@ -7,6 +7,7 @@ code: - mesh-sdk src updated: 2026-09-21 decisions: + - 02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md - 02-DECISIONS/0053-a-step-that-runs-on-a-schedule.md - 02-DECISIONS/0074-the-wire-is-specified-not-the-types.md - 02-DECISIONS/0040-what-a-module-is.md @@ -198,3 +199,11 @@ one shape this does not protect, and should not be written. *How it is checked:* the lab's coupled-pair spike declares exactly this pair, pushes a refused file, and asserts the file on disk is the new one, the service serves the old one, and the machine reports the push failed. + +A `run-once` step may itself name what it reads under `restart-on`; for a step the word means +*run again* — a step that fetches a fact from a provider names the binding it reads, and runs +again when the provider moved. The service that consumes what the step made names the step, so it +is recreated with the new fact +([ADR 0099](../../02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md)). *How it is +checked:* the host's unit tests run a step again when its named file changed and not otherwise, +and recreate a container naming a step after the step ran. diff --git a/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/00-report.md b/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/00-report.md index 727ad05..dbcd8cf 100644 --- a/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/00-report.md +++ b/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/00-report.md @@ -1,7 +1,9 @@ --- -status: open +status: resolved opened: 2026-09-21 -located-in: [mesh-host internal/apply (run-once marker), mesh-catalog modules/route-proxy] +located-in: [mesh-host internal/declaration, mesh-controller internal/catalogue, mesh-catalog modules/route-proxy] +fixed-by: ADR 0099; mesh-host and mesh-controller multiple-fixes (a run-once step may name what it reads and runs again when it changed); mesh-catalog multiple-fixes (the proxy's gate names the binding, the server names the gate) +amended-design: 03-DESIGN/01-to-be/08-connectivity.md, 03-DESIGN/01-to-be/20-writing-a-module.md --- # 077 — A fact fetched at first start is fetched once per declaration diff --git a/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/01-diagnosis.md b/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/01-diagnosis.md new file mode 100644 index 0000000..096f38d --- /dev/null +++ b/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/01-diagnosis.md @@ -0,0 +1,16 @@ +# Diagnosis — 2026-09-21 + +1. The host's marker for a run-once step is the digest of its declaration, and that digest + already includes the digest of every resource the container names under `restart-on` — what a + container reads is part of what it is (issue 045). So a run-once step that named the binding + file it reads would run again the moment the mesh rewrote that file. Only the refusal of the + pair run-once + `restart-on`, in the manifest parser and on the host, stood in the way. +2. When the authority moves, the binding's address changes and the file is rewritten; a re-issue + changes nothing the authority serves, since its state persists. The file is the signal. +3. The service also had to follow: a step that ran counts as a change, so a service naming the + step under `restart-on` is recreated with what the step fetched. + +**Located in:** the two refusals and the proxy's manifest. Decided in +[ADR 0099](../../02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md); proven by unit +tests on the host (the step runs again when its file changed, and not when it did not; the +container naming the step is recreated after it ran) and the catalogue-wide manifest test. diff --git a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md index 6377996..840a1d1 100644 --- a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md +++ b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md @@ -1,7 +1,8 @@ --- -status: open +status: resolved opened: 2026-09-21 -located-in: [mesh-controller internal/inventory (secrets), mesh-controller cmd (secret accept)] +located-in: [mesh-controller internal/inventory (secrets)] +fixed-by: mesh-controller multiple-fixes (a delivery is refused for a name the module does not declare as an own secret, a requirement it has not got, or a local it does not keep; the refusal names what it does declare); found one stale delivery in the whole-mesh bed on the spot --- # 078 — A delivered secret is accepted under any name diff --git a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md new file mode 100644 index 0000000..b049a0e --- /dev/null +++ b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md @@ -0,0 +1,17 @@ +# Diagnosis — 2026-09-21 + +1. Acceptance sealed the value and wrote the row without reading the module's manifest, which the + mesh holds. Both delivery paths did: a module's own secret, and a pair credential for a + requirement kept in the vault. +2. Refused now, in the inventory, so every caller gets it: an own secret must be one the manifest + declares; a pair credential must name a requirement the module has, and where the module keeps + several secrets for it (ADR 0094) a local it keeps — and no local where it keeps one. Each + refusal names what the module does declare. +3. The refusal found a stale delivery at once: the whole-mesh bed delivered `smtp-pass` to a module + that declares `smtp-password`. Corrected in the bed. + +**Located in:** the inventory's two accept paths. Not a decision: the manifest was already the +authority on what a module holds. Proven by unit tests against the store: a delivery under an +undeclared name is refused naming the declared ones; under a declared name it is kept; to an +unknown module it is refused with the remedy; a pair delivery for a requirement the module has not +got, or with no local where several are kept, or under a local it does not keep, is refused. From 8d159cee84cc10473eb8b1f797e92adb419d6c25 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 21 Sep 2026 23:43:31 +0200 Subject: [PATCH 2/5] Issue 074 resolved: the declared list is empty of WEARING; what the last three cost --- .../00-report.md | 7 +++---- .../01-diagnosis.md | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/00-report.md b/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/00-report.md index 04fe590..773cd6d 100644 --- a/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/00-report.md +++ b/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/00-report.md @@ -1,9 +1,8 @@ --- -status: located -opened: 2026-09-21 +status: resolved +opened: 2026-09-20 located-in: [mesh-lab test/integration] -fixed-by: -amended-design: +fixed-by: mesh-lab, over three multiple-fixes rounds — nine beds read the catalogue or were retired as duplicate coverage; the three mechanism fixtures wear names that are no catalogue module's; the declared list in test/beds-read-the-catalogue.test.ts is empty of WEARING --- # A mesh test wears a catalogue module's name diff --git a/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/01-diagnosis.md b/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/01-diagnosis.md index f2313f7..d3753f8 100644 --- a/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/01-diagnosis.md +++ b/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/01-diagnosis.md @@ -33,3 +33,17 @@ route-forwarding, which needs the certificate authority beside the proxy, and th *Later the same day.* Route-forwarding converted, with the authority beside the proxy (ADR 0098). One bed remains declared: the large mesh test, with its three fixtures. + +*2026-09-21, late.* The last three `WEARING` declarations are gone. The large mesh test's fixtures +are `a-store` (a provider with no resources), `self-builder` and `adopted-analytics`; the +runtime-restart bed's fixture is `a-runtime`. The credential-mechanism bed could not be renamed: +its runtime image is the catalogue's, and a runtime names its queues by the module compiled into +it, so the mesh's account for a module of another name is refused at the broker. It was retired — +the grant end-to-end bed proves the same login against the catalogue's redis, with the mesh writing +the contributions the retired bed wrote by hand — and its one assertion nothing else made (the +provider needs no seal key) moved there. Running the large test's renamed tests found two things +its long idleness had hidden: the consumer fixture's login exceeded a backend's twenty characters +(ADR 0049; it has a slug now), and the builder-as-module test declared the builder's image as an +upstream artifact by bare image ID, which a registry copy cannot fetch since ADR 0096 — retired, +since genesis installs the catalogue's builder and proves the same. The large test as a whole has +not been run end to end; its renamed tests and the tests around them have. From faa7196ad66a5b5465e7aa10041db82f93e6074d Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 21 Sep 2026 23:44:22 +0200 Subject: [PATCH 3/5] Issue 074: opened date restored --- .../074-a-mesh-test-wears-a-catalogue-modules-name/00-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/00-report.md b/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/00-report.md index 773cd6d..04e1542 100644 --- a/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/00-report.md +++ b/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/00-report.md @@ -1,6 +1,6 @@ --- status: resolved -opened: 2026-09-20 +opened: 2026-09-21 located-in: [mesh-lab test/integration] fixed-by: mesh-lab, over three multiple-fixes rounds — nine beds read the catalogue or were retired as duplicate coverage; the three mechanism fixtures wear names that are no catalogue module's; the declared list in test/beds-read-the-catalogue.test.ts is empty of WEARING --- From ead8913a7496c378551edf9582048ed32bd0bcb3 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 21 Sep 2026 23:46:51 +0200 Subject: [PATCH 4/5] Issue 078: module issue's orphan account, refused before it is made --- .../00-report.md | 2 +- .../01-diagnosis.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md index 840a1d1..b5d1340 100644 --- a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md +++ b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md @@ -2,7 +2,7 @@ status: resolved opened: 2026-09-21 located-in: [mesh-controller internal/inventory (secrets)] -fixed-by: mesh-controller multiple-fixes (a delivery is refused for a name the module does not declare as an own secret, a requirement it has not got, or a local it does not keep; the refusal names what it does declare); found one stale delivery in the whole-mesh bed on the spot +fixed-by: mesh-controller multiple-fixes (a delivery is refused for a name the module does not declare as an own secret, a requirement it has not got, or a local it does not keep; the refusal names what it does declare); module issue refuses a module with no broker secret before making the account; found one stale delivery in the whole-mesh bed and one orphan account the mesh itself made --- # 078 — A delivered secret is accepted under any name diff --git a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md index b049a0e..b54e41a 100644 --- a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md +++ b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md @@ -15,3 +15,10 @@ authority on what a module holds. Proven by unit tests against the store: a deli undeclared name is refused naming the declared ones; under a declared name it is kept; to an unknown module it is refused with the remedy; a pair delivery for a requirement the module has not got, or with no local where several are kept, or under a local it does not keep, is refused. + +*Later the same day.* The refusal caught the mesh itself: `module issue` made a broker account +for any module and delivered it as the own secret named `broker`, whether or not the module +declared one — a bed issuing the certificate authority, which speaks on no bus, left an account +on the broker that nothing would ever read. `module issue` now refuses a module with no `broker` +own secret before the account is made. An own secret the mesh mints (the authority's password) +never needed an issue: it is minted when the node is resolved. From 3ea5e47c21d95f22c556b3703bba73c1496dd0a6 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 21 Sep 2026 23:58:15 +0200 Subject: [PATCH 5/5] Review: 077 says what closed it and what did not; 078 names module issue; 074's retired fixture; ADR 0099's scope --- .../0099-a-step-that-runs-once-names-what-it-reads.md | 4 +++- .../01-diagnosis.md | 2 +- .../01-diagnosis.md | 9 +++++++++ .../00-report.md | 2 +- .../01-diagnosis.md | 3 ++- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md b/02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md index 3e73e62..b18c94a 100644 --- a/02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md +++ b/02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md @@ -70,7 +70,9 @@ nothing the mesh knows reflects. That is not a change the mesh can see, and it i The one contradiction the refusal named is real and is now a documented reading: on a running container `restart-on` means recreate, on a step it means run again. Both are "this must reflect -what it reads". +what it reads". This record is about a run-once *container*, the step ADR 0052 defined. A +run-once process is a different shape whose marker does not carry what it reads; it is not +covered here. ## How it is checked diff --git a/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/01-diagnosis.md b/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/01-diagnosis.md index d3753f8..03ab2ab 100644 --- a/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/01-diagnosis.md +++ b/04-ISSUES/074-a-mesh-test-wears-a-catalogue-modules-name/01-diagnosis.md @@ -35,7 +35,7 @@ route-forwarding, which needs the certificate authority beside the proxy, and th (ADR 0098). One bed remains declared: the large mesh test, with its three fixtures. *2026-09-21, late.* The last three `WEARING` declarations are gone. The large mesh test's fixtures -are `a-store` (a provider with no resources), `self-builder` and `adopted-analytics`; the +are `a-store` (a provider with no resources) and `adopted-analytics`, its builder fixture retired below; the runtime-restart bed's fixture is `a-runtime`. The credential-mechanism bed could not be renamed: its runtime image is the catalogue's, and a runtime names its queues by the module compiled into it, so the mesh's account for a module of another name is refused at the broker. It was retired — diff --git a/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/01-diagnosis.md b/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/01-diagnosis.md index 096f38d..2beec1c 100644 --- a/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/01-diagnosis.md +++ b/04-ISSUES/077-a-fact-fetched-at-first-start-is-fetched-once/01-diagnosis.md @@ -14,3 +14,12 @@ [ADR 0099](../../02-DECISIONS/0099-a-step-that-runs-once-names-what-it-reads.md); proven by unit tests on the host (the step runs again when its file changed, and not when it did not; the container naming the step is recreated after it ran) and the catalogue-wide manifest test. + +**What closed it, and what did not.** The report named two ways the fact changes: the provider +moved, or its state wiped. The move is closed: it rewrites the consumer's binding, the step names +that binding, and the host's unit test runs the step again on exactly that rewrite — the bed that +would re-key a live authority was not written, because a move *is* a rewritten file and the unit +test covers the file. A state wiped behind the mesh's back on the same node is not closed and is +not claimed (ADR 0099, consequences): nothing the mesh knows changes, so nothing it declares can +follow it. On the mesh's own path it does not arise — the authority's state directory survives +unassign and reassign, and a re-issue does not touch it. diff --git a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md index b5d1340..02e870c 100644 --- a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md +++ b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/00-report.md @@ -1,7 +1,7 @@ --- status: resolved opened: 2026-09-21 -located-in: [mesh-controller internal/inventory (secrets)] +located-in: [mesh-controller internal/inventory (secrets), mesh-controller cmd (module issue)] fixed-by: mesh-controller multiple-fixes (a delivery is refused for a name the module does not declare as an own secret, a requirement it has not got, or a local it does not keep; the refusal names what it does declare); module issue refuses a module with no broker secret before making the account; found one stale delivery in the whole-mesh bed and one orphan account the mesh itself made --- diff --git a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md index b54e41a..af52a2a 100644 --- a/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md +++ b/04-ISSUES/078-a-delivered-secret-is-accepted-under-any-name/01-diagnosis.md @@ -20,5 +20,6 @@ got, or with no local where several are kept, or under a local it does not keep, for any module and delivered it as the own secret named `broker`, whether or not the module declared one — a bed issuing the certificate authority, which speaks on no bus, left an account on the broker that nothing would ever read. `module issue` now refuses a module with no `broker` -own secret before the account is made. An own secret the mesh mints (the authority's password) +own secret before the account is made; a unit test holds it to that. A pair delivery for a +requirement the module keeps no secret for is refused too, on review. An own secret the mesh mints (the authority's password) never needed an issue: it is minted when the node is resolved.