Issue 597 (genesis stops at its control-plane step: the installer takes the controller's merge-window settings file for a secret nobody writes). Related: hq ADR 0276 (the merge window's settings reach the controller in MESH_MERGE_WINDOW_FILE, a file its manifest writes from its settings).
What: secretsByVariableIn (step 11) treated every MESH_..._FILE in the controller's environment as a secret, and refused the merge-window file because no own-secret writes it. A ..._FILE naming a file resource the module itself declares is now the module's own, so it is skipped. A ..._FILE naming neither an own-secret nor a file of the module is still refused, and the refusal now says both.
Tests (fail on main)
TestAFileTheControllersManifestWritesIsNotASecret: a process-form fixture with the merge-window file and its variable passes step 9's secret reading. The store and bus secrets are still wanted, and the merge window is not.
TestTheControllersOwnManifestPassesStepNine: the controller's own module.json, read from MESH_CHECK_BESIDE in a merge check (else a checkout beside, else a loud skip). On main it fails with the step-11 refusal.
merge-check.sh passes (no nats-server here, so the bus tests are skipped and said).
Lab, 2026-10-13 on g14: with this change and the change for issue 596, a genesis from bare passed steps 11 and 12. The controller's secrets were accepted and the temporary control plane was retired. It then stopped at step 13 on issue 121; see the issue 596 pull request.
Fixes issue 597.
Issue 597 (genesis stops at its control-plane step: the installer takes the controller's merge-window settings file for a secret nobody writes). Related: hq ADR 0276 (the merge window's settings reach the controller in MESH_MERGE_WINDOW_FILE, a file its manifest writes from its settings).
**What**: `secretsByVariableIn` (step 11) treated every `MESH_..._FILE` in the controller's environment as a secret, and refused the merge-window file because no own-secret writes it. A `..._FILE` naming a file resource the module itself declares is now the module's own, so it is skipped. A `..._FILE` naming neither an own-secret nor a file of the module is still refused, and the refusal now says both.
**Tests (fail on main)**
- `TestAFileTheControllersManifestWritesIsNotASecret`: a process-form fixture with the merge-window file and its variable passes step 9's secret reading. The store and bus secrets are still wanted, and the merge window is not.
- `TestTheControllersOwnManifestPassesStepNine`: the controller's own module.json, read from MESH_CHECK_BESIDE in a merge check (else a checkout beside, else a loud skip). On main it fails with the step-11 refusal.
- `TestAFileNothingOfTheControllerWritesIsStillRefused`.
- merge-check.sh passes (no nats-server here, so the bus tests are skipped and said).
**Lab, 2026-10-13 on g14**: with this change and the change for issue 596, a genesis from bare passed steps 11 and 12. The controller's secrets were accepted and the temporary control plane was retired. It then stopped at step 13 on issue 121; see the issue 596 pull request.
Fixes issue 597.
The controller reads its merge window's settings from a file its manifest declares from its
settings (MESH_MERGE_WINDOW_FILE, ADR 0276). Step 11 took every MESH_..._FILE for a secret and
refused this one as a file nobody writes, so no genesis got past step 11. A _FILE naming a file
resource of the module is now the module's own; one naming neither an own-secret nor a file of the
module is still refused.
Deliverynovox/mesh-host@b7f70bc4c01d — delivered since 2026-10-13T00:40:36Z
Delivery plan — builds nothing: the change touches no module of the mesh's graph
Transitions
2026-10-13 00:29 (new) → proposed (announced): novox/mesh-host#100's head announced
2026-10-13 00:31 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-13 00:31 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-13 00:40 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-13 00:40 published → delivered (done): nothing for a walk to move
The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-host@b7f70bc4c01d` — **delivered** since 2026-10-13T00:40:36Z
**Delivery plan** — builds nothing: the change touches no module of the mesh's graph
**Transitions**
- 2026-10-13 00:29 (new) → proposed (announced): novox/mesh-host#100's head announced
- 2026-10-13 00:31 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-13 00:31 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-13 00:40 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-13 00:40 published → delivered (done): nothing for a walk to move
The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
Independent review (read-only worktree at the head; mesh-catalog main 827b89d and mesh-controller main 4473bc7 beside it through MESH_CHECK_BESIDE).
Acceptance (issue 597): genesis no longer refuses the controller's MESH_MERGE_WINDOW_FILE at step 11. The controller's real module.json declares merge-window as a file resource at ${dir:mesh-state}/merge-window.json and its container env names the same path, so the new declared set matches it. The lab log of the run (run2) shows step 11 passed and the run stopped at step 13 on the build-agent assignment, which matches what the PR body claims; nothing is overclaimed.
Tests fail without the fix: with control.go reverted to main and the new tests kept, TestAFileTheControllersManifestWritesIsNotASecret and TestTheControllersOwnManifestPassesStepNine fail with the step-11 refusal; TestAFileNothingOfTheControllerWritesIsStillRefused passes on both (it guards the refusal, as intended). merge-check.sh passes at the head (bus tests skipped and said: no nats-server). mesh/merge-gate and mesh/repo-check are green at this head. The two PRs (#100, #101) merged together also build and pass internal/bootstrap and cmd/.
No hand workaround: the fix is in the installer's reading of the manifest.
Risk read (could the skip hide a real secret?): the skip applies only when no own-secret writes the path AND a file resource of the module declares that exact path (after following a mount). A declared file is written by the node-engine from the manifest, so genesis has nothing to carry into it. The remaining gap: a declared file whose content holds a secret in a form other than VAR=${secret:x} (e.g. JSON with ${secret:x} inside) would now be skipped silently, where before it was refused. The controller's manifest has no ${secret: at all today, so nothing is hidden now. Non-blocking suggestion: skip only when the declared file's content holds no ${secret: reference, so that case stays loud.
Nit (non-blocking): the test helper and test names say "step nine" (theStepNineSecretsOf, TestTheControllersOwnManifestPassesStepNine), while the issue, the error and Steps put control-plane at step 11 of 24.
Verdict: approve at b7f70bc4c01de826075faa55494931e1a8e0c530
Independent review (read-only worktree at the head; mesh-catalog main 827b89d and mesh-controller main 4473bc7 beside it through MESH_CHECK_BESIDE).
Acceptance (issue 597): genesis no longer refuses the controller's MESH_MERGE_WINDOW_FILE at step 11. The controller's real module.json declares `merge-window` as a file resource at `${dir:mesh-state}/merge-window.json` and its container env names the same path, so the new `declared` set matches it. The lab log of the run (run2) shows step 11 passed and the run stopped at step 13 on the build-agent assignment, which matches what the PR body claims; nothing is overclaimed.
Tests fail without the fix: with control.go reverted to main and the new tests kept, `TestAFileTheControllersManifestWritesIsNotASecret` and `TestTheControllersOwnManifestPassesStepNine` fail with the step-11 refusal; `TestAFileNothingOfTheControllerWritesIsStillRefused` passes on both (it guards the refusal, as intended). merge-check.sh passes at the head (bus tests skipped and said: no nats-server). mesh/merge-gate and mesh/repo-check are green at this head. The two PRs (#100, #101) merged together also build and pass internal/bootstrap and cmd/.
No hand workaround: the fix is in the installer's reading of the manifest.
Risk read (could the skip hide a real secret?): the skip applies only when no own-secret writes the path AND a file resource of the module declares that exact path (after following a mount). A declared file is written by the node-engine from the manifest, so genesis has nothing to carry into it. The remaining gap: a declared file whose content holds a secret in a form other than `VAR=${secret:x}` (e.g. JSON with `${secret:x}` inside) would now be skipped silently, where before it was refused. The controller's manifest has no `${secret:` at all today, so nothing is hidden now. Non-blocking suggestion: skip only when the declared file's content holds no `${secret:` reference, so that case stays loud.
Nit (non-blocking): the test helper and test names say "step nine" (`theStepNineSecretsOf`, `TestTheControllersOwnManifestPassesStepNine`), while the issue, the error and Steps put control-plane at step 11 of 24.
Independent review, replacing the builder's own. I read the diff in a fresh clone at the head, with mesh-controller main cloned beside it so that TestTheControllersOwnManifestPassesStepNine was judged and not skipped. I read ADR 0276 through knowledge-base.get; its merge window is what MESH_MERGE_WINDOW_FILE carries, and mesh-controller's module.json declares that file as a file resource (id merge-window, path ${dir:mesh-state}/merge-window.json) and names it in the container's environment.
No blocking findings.
What I checked:
The new tests fail on main. With only the test file taken from the head and the code at main 8431ac9, TestAFileTheControllersManifestWritesIsNotASecret and TestTheControllersOwnManifestPassesStepNine fail. TestAFileNothingOfTheControllerWritesIsStillRefused passes on main as well as at the head, which is right: it is the guard that the old refusal stays.
A ..._FILE that neither an own-secret nor a file of the module writes is still refused, and the error names the variable. The guard test proves it.
A real secret cannot be skipped by declaring its path as a file. The own-secret lookup runs first and the declared-file exception applies only when !named. I proved it with a throwaway test (not pushed): a file resource at ${dir:mesh-state}/inventory, the inventory own-secret's path, still yields MESH_STORE_INVENTORY = inventory, with no error.
merge-check.sh passes at the head (gofmt, vet, the whole suite). This toolchain holds no nats-server, so the bus tests were skipped, and the script says so.
Non-blocking:
The tests and their helper say "step 9", but the PR title and issue 597 say step 11. One of the two is wrong. The next reader should not have to work out that they mean the same check.
A manifest that declares a file resource and an own-secret at the same path is still accepted, because the secret wins. The two writes would then overwrite each other on the node. That is a manifest validation question, not something genesis has to judge. If the validator does not already refuse it, it is worth an issue.
Gitea statuses at this head: mesh/merge-gate success, "head b7f70bc4c0 merged into trunk 8431ac9656 - pass: the change touches no module of the mesh's graph". mesh/repo-check success, "head b7f70bc4c0 merged into trunk 8431ac9656 - pass: its merge-check.sh passed". mesh/delivery success, "ready: it delivers once merged". The trunk is still 8431ac9, so the verdicts are current.
Verdict: approve at b7f70bc4c01de826075faa55494931e1a8e0c530
Independent review, replacing the builder's own. I read the diff in a fresh clone at the head, with mesh-controller main cloned beside it so that TestTheControllersOwnManifestPassesStepNine was judged and not skipped. I read ADR 0276 through knowledge-base.get; its merge window is what MESH_MERGE_WINDOW_FILE carries, and mesh-controller's module.json declares that file as a `file` resource (id merge-window, path ${dir:mesh-state}/merge-window.json) and names it in the container's environment.
No blocking findings.
What I checked:
1. The new tests fail on main. With only the test file taken from the head and the code at main 8431ac9, TestAFileTheControllersManifestWritesIsNotASecret and TestTheControllersOwnManifestPassesStepNine fail. TestAFileNothingOfTheControllerWritesIsStillRefused passes on main as well as at the head, which is right: it is the guard that the old refusal stays.
2. A `..._FILE` that neither an own-secret nor a file of the module writes is still refused, and the error names the variable. The guard test proves it.
3. A real secret cannot be skipped by declaring its path as a file. The own-secret lookup runs first and the declared-file exception applies only when `!named`. I proved it with a throwaway test (not pushed): a `file` resource at ${dir:mesh-state}/inventory, the inventory own-secret's path, still yields MESH_STORE_INVENTORY = inventory, with no error.
4. merge-check.sh passes at the head (gofmt, vet, the whole suite). This toolchain holds no nats-server, so the bus tests were skipped, and the script says so.
Non-blocking:
1. The tests and their helper say "step 9", but the PR title and issue 597 say step 11. One of the two is wrong. The next reader should not have to work out that they mean the same check.
2. A manifest that declares a file resource and an own-secret at the same path is still accepted, because the secret wins. The two writes would then overwrite each other on the node. That is a manifest validation question, not something genesis has to judge. If the validator does not already refuse it, it is worth an issue.
Gitea statuses at this head: mesh/merge-gate success, "head b7f70bc4c01d merged into trunk 8431ac96562e - pass: the change touches no module of the mesh's graph". mesh/repo-check success, "head b7f70bc4c01d merged into trunk 8431ac96562e - pass: its merge-check.sh passed". mesh/delivery success, "ready: it delivers once merged". The trunk is still 8431ac9, so the verdicts are current.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Issue 597 (genesis stops at its control-plane step: the installer takes the controller's merge-window settings file for a secret nobody writes). Related: hq ADR 0276 (the merge window's settings reach the controller in MESH_MERGE_WINDOW_FILE, a file its manifest writes from its settings).
What:
secretsByVariableIn(step 11) treated everyMESH_..._FILEin the controller's environment as a secret, and refused the merge-window file because no own-secret writes it. A..._FILEnaming a file resource the module itself declares is now the module's own, so it is skipped. A..._FILEnaming neither an own-secret nor a file of the module is still refused, and the refusal now says both.Tests (fail on main)
TestAFileTheControllersManifestWritesIsNotASecret: a process-form fixture with the merge-window file and its variable passes step 9's secret reading. The store and bus secrets are still wanted, and the merge window is not.TestTheControllersOwnManifestPassesStepNine: the controller's own module.json, read from MESH_CHECK_BESIDE in a merge check (else a checkout beside, else a loud skip). On main it fails with the step-11 refusal.TestAFileNothingOfTheControllerWritesIsStillRefused.Lab, 2026-10-13 on g14: with this change and the change for issue 596, a genesis from bare passed steps 11 and 12. The controller's secrets were accepted and the temporary control plane was retired. It then stopped at step 13 on issue 121; see the issue 596 pull request.
Fixes issue 597.
Delivery
novox/mesh-host@b7f70bc4c01d— delivered since 2026-10-13T00:40:36ZDelivery plan — builds nothing: the change touches no module of the mesh's graph
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Verdict: approve at
b7f70bc4c0Independent review (read-only worktree at the head; mesh-catalog main 827b89d and mesh-controller main 4473bc7 beside it through MESH_CHECK_BESIDE).
Acceptance (issue 597): genesis no longer refuses the controller's MESH_MERGE_WINDOW_FILE at step 11. The controller's real module.json declares
merge-windowas a file resource at${dir:mesh-state}/merge-window.jsonand its container env names the same path, so the newdeclaredset matches it. The lab log of the run (run2) shows step 11 passed and the run stopped at step 13 on the build-agent assignment, which matches what the PR body claims; nothing is overclaimed.Tests fail without the fix: with control.go reverted to main and the new tests kept,
TestAFileTheControllersManifestWritesIsNotASecretandTestTheControllersOwnManifestPassesStepNinefail with the step-11 refusal;TestAFileNothingOfTheControllerWritesIsStillRefusedpasses on both (it guards the refusal, as intended). merge-check.sh passes at the head (bus tests skipped and said: no nats-server). mesh/merge-gate and mesh/repo-check are green at this head. The two PRs (#100, #101) merged together also build and pass internal/bootstrap and cmd/.No hand workaround: the fix is in the installer's reading of the manifest.
Risk read (could the skip hide a real secret?): the skip applies only when no own-secret writes the path AND a file resource of the module declares that exact path (after following a mount). A declared file is written by the node-engine from the manifest, so genesis has nothing to carry into it. The remaining gap: a declared file whose content holds a secret in a form other than
VAR=${secret:x}(e.g. JSON with${secret:x}inside) would now be skipped silently, where before it was refused. The controller's manifest has no${secret:at all today, so nothing is hidden now. Non-blocking suggestion: skip only when the declared file's content holds no${secret:reference, so that case stays loud.Nit (non-blocking): the test helper and test names say "step nine" (
theStepNineSecretsOf,TestTheControllersOwnManifestPassesStepNine), while the issue, the error and Steps put control-plane at step 11 of 24.Verdict: approve at
b7f70bc4c0Independent review, replacing the builder's own. I read the diff in a fresh clone at the head, with mesh-controller main cloned beside it so that TestTheControllersOwnManifestPassesStepNine was judged and not skipped. I read ADR 0276 through knowledge-base.get; its merge window is what MESH_MERGE_WINDOW_FILE carries, and mesh-controller's module.json declares that file as a
fileresource (id merge-window, path ${dir:mesh-state}/merge-window.json) and names it in the container's environment.No blocking findings.
What I checked:
8431ac9, TestAFileTheControllersManifestWritesIsNotASecret and TestTheControllersOwnManifestPassesStepNine fail. TestAFileNothingOfTheControllerWritesIsStillRefused passes on main as well as at the head, which is right: it is the guard that the old refusal stays...._FILEthat neither an own-secret nor a file of the module writes is still refused, and the error names the variable. The guard test proves it.!named. I proved it with a throwaway test (not pushed): afileresource at ${dir:mesh-state}/inventory, the inventory own-secret's path, still yields MESH_STORE_INVENTORY = inventory, with no error.Non-blocking:
Gitea statuses at this head: mesh/merge-gate success, "head
b7f70bc4c0merged into trunk8431ac9656- pass: the change touches no module of the mesh's graph". mesh/repo-check success, "headb7f70bc4c0merged into trunk8431ac9656- pass: its merge-check.sh passed". mesh/delivery success, "ready: it delivers once merged". The trunk is still8431ac9, so the verdicts are current.