Feature feat/mail-hardening (playbook 07), one delivery group with novox/mesh-catalog#feat/mail-hardening.
Issue 727 (ADR 0376 §1, §2): a restricted stream is heard only from a module's own runs-as account, never the tool runner's.
Issue 728 (ADR 0376 §3-§6): a restricted stream's dead letters age out with the stream and never show their body; a message already past its age is kept as a record without its body; reading the aging dead letters never waits for letters that are gone.
Issue 785 (ADR 0377): under a module's own record, a move that recreates no container and moves no data rolls out; anything outside §3's list (archive, package, user, network, ...) still waits; the walk says per machine which way each recorded module went.
Issue 789: an own secret's manifest may declare a desk prompt (one line, at most PromptMax characters, {member} only for a family); the controller sends what to the desk.
Issue 711: a starting controller never marks a call abandoned over its recorded finish (compare-and-set on the call's record, at most 10 tries).
Reviewed locally before the push: round 1 (changes requested), round 2 approved at 2347a4c7. merge-check.sh green; all 64 cmd/mesh-controller store tests and the internal/inventory store tests passed against a throwaway postgres. Follow-ups opened: 808, 819, 822.
Feature feat/mail-hardening (playbook 07), one delivery group with novox/mesh-catalog#feat/mail-hardening.
- Issue 727 (ADR 0376 §1, §2): a restricted stream is heard only from a module's own runs-as account, never the tool runner's.
- Issue 728 (ADR 0376 §3-§6): a restricted stream's dead letters age out with the stream and never show their body; a message already past its age is kept as a record without its body; reading the aging dead letters never waits for letters that are gone.
- Issue 785 (ADR 0377): under a module's own record, a move that recreates no container and moves no data rolls out; anything outside §3's list (archive, package, user, network, ...) still waits; the walk says per machine which way each recorded module went.
- Issue 789: an own secret's manifest may declare a desk prompt (one line, at most PromptMax characters, {member} only for a family); the controller sends `what` to the desk.
- Issue 711: a starting controller never marks a call abandoned over its recorded finish (compare-and-set on the call's record, at most 10 tries).
Reviewed locally before the push: round 1 (changes requested), round 2 approved at 2347a4c7. merge-check.sh green; all 64 cmd/mesh-controller store tests and the internal/inventory store tests passed against a throwaway postgres. Follow-ups opened: 808, 819, 822.
A family like mesh-mail's mail-credential-* names only the module and the secret's key at the desk, so the operator cannot tell which account is asked. An own secret (or a family) may now declare a one-line prompt in its manifest, with {member} filled by a family member's suffix; the module check refuses one that is not one line, over 120 characters, or holds another placeholder. desk_secret.go reads it from the controller's own catalogue and sends it to the desk as what, never from the call or the module's runtime; omitted when none is declared, so an old desk or module behaves as today.
The tool runner's bus account carried the heard grants, consumer and bind word of every module it runs, and every agent session on that machine reaches the bus as that account, so any session could pull a granted module's consumer on MAIL. Per ADR 0376 §1 the controller now composes a restricted stream's consumer, grants and bind word only for a module that declares runs-as; registration refuses a consumes of a restricted stream without runs-as (§2), and a grant that composes nothing is said in doctor (D-heard) and in the controller's log on every raise and send.
DEAD_LETTERS kept a message given up on MAIL forever and showed it whole to any caller of dead-letters, outside the grant and past MAIL's week. Per ADR 0376 §3-§6: the kept copy carries a per-message time to live of what is left of its stream's age (a copy already past it is kept without its body), DEAD_LETTERS and EVENTS allow per-message TTL, the list and show give no body or own headers for it, delivering it again needs a minute left and the copy keeps the time left, and its max-deliveries condition clears saying how many aged out undelivered and from which stream.
A record kept without its body still carried its subject, which names whose mail it was, with no age. The lead decided such a message is not kept at all: the notice is taken, the message counted, and the log and an aged-out condition say how many messages of the stream aged out undelivered. Unrestricted streams are unchanged.
Under a module's own record (its manifest's, or its irreplaceable data's), every
move waited for a person's push, even one that only changed a tools bundle: the
database server stayed behind on ace on 2026-10-15 although its walk said it
recreated none of its containers. ADR 0377 lets such a move roll out.
A move is judged per machine against the build that machine was last sent: it
goes when no container, mounted file, data path, data declaration, provider or
(for a module with data) long-running process changes. A person's record, the
bus and any move that cannot be judged still wait. The walk keeps per machine
which way each recorded module went and why, says it in its note and log, and
status names a machine behind with `push <node>` only for a move that waits.
A starting controller's sweep read each call it saw running and wrote it back
abandoned unconditionally, so a finish written in between, with its kept answer,
was lost. The mark is now a compare-and-set on the call's record: a finish already
recorded, or racing the mark, stands.
Reverts 45b6c347, which kept nothing of such a message and raised an aged-out
condition: that departed from an accepted decision on a lead's word alone. The
concern behind it (the record keeps the subject, with no age) is its own issue.
ADR 0377 §3's allowlist names only tools bundles, files no container mounts
and holds no data, and manifest fields that recreate nothing. Holds only
checked containers, files, directories and processes/services; any other
resource type (archive, package, user, network, ...) fell through unheld.
Add a default case that holds and names the resource type and id.
route-proxy provides route: its consumers are sent again after it
route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before route-proxy, build-agent is judged on its first machine
2026-10-15 14:24 (new) → proposed (announced): novox/mesh-controller#344's head announced
2026-10-15 14:28 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-15 14:28 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-15 14:36 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-15 14:36 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path — not a failed walk that carried a later commit for it, after which it waits for a walk of its own commit
2026-10-15 14:39 delivering → delivered (done): its walk is done, carrying its own commit: every machine of its deploy plan passed, or was left as its policy says
The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-controller@2347a4c73bd0` — **delivered** since 2026-10-15T14:39:32Z
**Delivery plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller, route-proxy
- tier 1: build-agent
- ace: receives route-proxy, build-agent
- g14: receives build-agent
- novox: receives mesh-controller, route-proxy, build-agent
- shanks: receives build-agent
- route-proxy provides route: its consumers are sent again after it
- route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before route-proxy, build-agent is judged on its first machine
**Group** `feat/mail-hardening`, in order: novox/mesh-controller@2347a4c73bd0 → novox/mesh-catalog@eb97a3d9a2d7
- novox/mesh-controller@2347a4c73bd0 before novox/mesh-catalog@eb97a3d9a2d7: declared
**Machines**
- mesh-controller on every machine running it: sent
- route-proxy on every machine running it: sent
- build-agent on every machine running it: sent
**Transitions**
- 2026-10-15 14:24 (new) → proposed (announced): novox/mesh-controller#344's head announced
- 2026-10-15 14:28 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-15 14:28 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-15 14:36 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-15 14:36 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path — not a failed walk that carried a later commit for it, after which it waits for a walk of its own commit
- 2026-10-15 14:39 delivering → delivered (done): its walk is done, carrying its own commit: every machine of its deploy plan passed, or was left as its policy says
The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
route-proxy provides route: its consumers are sent again after it
route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before route-proxy, build-agent is judged on its first machine
read by no module's build: cmd/mesh-controller/deadletters_aging_test.go, cmd/mesh-controller/desk_secret_test.go, cmd/mesh-controller/heard_withheld_test.go, cmd/mesh-controller/recorded_moves_test.go, internal/broker/modstreams_test.go, internal/broker/msgttl_live_test.go, internal/catalogue/holds_test.go, internal/catalogue/own_secret_prompt_test.go, internal/catalogue/streams_test.go, internal/inventory/sent_builds_test.go, internal/inventory/streams_test.go, internal/link/calls_kept_test.go, internal/link/deadletters_restricted_test.go, testdata/store-tests
Run by the build seat on ace as build-1792074289744702568 (builds --log build-1792074289744702568).
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 60 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-15T11:29:40Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-15T11:29:40Z
modules the change moves:
- mesh-controller (changed)
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 2 tier(s): build-agent, mesh-controller, route-proxy
notes:
- cmd/mesh-controller/deadletters_aging_test.go, cmd/mesh-controller/desk_secret_test.go, cmd/mesh-controller/heard_withheld_test.go, cmd/mesh-controller/recorded_moves_test.go, internal/broker/modstreams_test.go, internal/broker/msgttl_live_test.go, internal/catalogue/holds_test.go, internal/catalogue/own_secret_prompt_test.go, internal/catalogue/streams_test.go, internal/inventory/sent_builds_test.go, internal/inventory/streams_test.go, internal/link/calls_kept_test.go, internal/link/deadletters_restricted_test.go and testdata/store-tests read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.117s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.019s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.023s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.017s
ok github.com/novox/mesh-controller/examples/route-proxy 1.124s
ok github.com/novox/mesh-controller/internal/artifacts 1.056s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 7.615s
ok github.com/novox/mesh-controller/internal/catalogue 13.238s
ok github.com/novox/mesh-controller/internal/conditions 3.309s
ok github.com/novox/mesh-controller/internal/envfile 1.038s
ok github.com/novox/mesh-controller/internal/facts 1.048s
ok github.com/novox/mesh-controller/internal/identity 7.679s
ok github.com/novox/mesh-controller/internal/lease 10.229s
ok github.com/novox/mesh-controller/internal/licences 6.241s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.037s
ok github.com/novox/mesh-controller/internal/lint 3.396s
ok github.com/novox/mesh-controller/internal/outward 1.110s
ok github.com/novox/mesh-controller/internal/overlay 1.051s
ok github.com/novox/mesh-controller/internal/secrets 1.600s
ok github.com/novox/mesh-controller/internal/store 4.286s
ok github.com/novox/mesh-controller/internal/testbus 1.300s
ok github.com/novox/mesh-controller/internal/token 1.046s
ok github.com/novox/mesh-controller/cmd/mesh-controller 31s (shard 1 of 8: 118 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 38s (shard 2 of 8: 118 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 31s (shard 3 of 8: 118 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 36s (shard 4 of 8: 118 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 29s (shard 5 of 8: 118 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 28s (shard 6 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 42s (shard 7 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 39s (shard 8 of 8: 117 tests)
ok github.com/novox/mesh-controller/internal/inventory 15s (shard 1 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 14s (shard 2 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 14s (shard 3 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 14s (shard 4 of 4: 68 tests)
ok github.com/novox/mesh-controller/internal/builder 39s (shard 1 of 4: 52 tests)
ok github.com/novox/mesh-controller/internal/builder 13s (shard 2 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/builder 35s (shard 3 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/builder 17s (shard 4 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/link 14s (shard 1 of 4: 47 tests)
ok github.com/novox/mesh-controller/internal/link 20s (shard 2 of 4: 46 tests)
ok github.com/novox/mesh-controller/internal/link 18s (shard 3 of 4: 46 tests)
ok github.com/novox/mesh-controller/internal/link 13s (shard 4 of 4: 46 tests)
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.27s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.32s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.27s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.26s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.23s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.22s)
./cmd/mesh-controller --- PASS: TestAPlanFollowedFromTheStoreAnswersWhenItMoves (2.21s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.35s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.13s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.78s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.32s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.24s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (1.33s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (1.31s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.73s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.64s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.41s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.39s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.47s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.51s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.34s)
./cmd/mesh-controller --- PASS: TestTheSendMakesNoValueForAnOutsideSecretNobodyGave (0.70s)
./cmd/mesh-controller --- PASS: TestAQuestionComposesWithoutAnOutsideSecretNobodyGave (0.72s)
./cmd/mesh-controller --- PASS: TestReplay201 (0.18s)
./cmd/mesh-controller --- PASS: TestARollbackWhoseSendWasRefusedIsCompletedByTheNextSend (0.17s)
./cmd/mesh-controller --- PASS: TestAGateJudgesTheOtherMovesBesideAKeptCore (0.19s)
./cmd/mesh-controller --- PASS: TestReplay401 (0.29s)
./cmd/mesh-controller --- PASS: TestReplay201ThePlansSend (0.39s)
./cmd/mesh-controller --- PASS: TestPlanAndNodeListAnOptionalRequirementLeftUnbound (0.89s)
./cmd/mesh-controller --- PASS: TestReplay340 (0.33s)
./cmd/mesh-controller --- PASS: TestOnlyATrustedFilesNamedKeyIsRefusedThroughAVerb (0.39s)
./cmd/mesh-controller --- PASS: TestReplay349 (0.25s)
./cmd/mesh-controller --- PASS: TestReplay348AFaultFromBeforeTheSendFailsNoGate (0.21s)
./cmd/mesh-controller --- PASS: TestReplay239AModuleNameIsNotTakenOverByAnotherRepository (0.22s)
./cmd/mesh-controller --- PASS: TestAWalkThatMovedNothingSaysWhichModulesMatchedWhatRuns (0.21s)
./cmd/mesh-controller --- PASS: TestAWalkWhoseEveryBuildCameOutTheSameIsDone (0.18s)
./cmd/mesh-controller --- PASS: TestReplay614ANewSDKPlansTheToolchainAndThenItsBundles (0.07s)
./cmd/mesh-controller --- PASS: TestOneAcceptForAProviderIsPlacedForEveryConsumer (1.29s)
./cmd/mesh-controller --- PASS: TestReplay164 (0.40s)
./cmd/mesh-controller --- PASS: TestAnApprovedLayerOpensTheWalkThatSendsIt (0.20s)
./cmd/mesh-controller --- PASS: TestASettingsWalkSendsOneMachineAtATimeEachJudged (0.25s)
./cmd/mesh-controller --- PASS: TestAFailedSettingsWalkStopsAndHoldsNothingBack (0.22s)
./cmd/mesh-controller --- PASS: TestASettingsWalkSendsTheLayerAloneEveryBuildKept (0.19s)
./cmd/mesh-controller --- PASS: TestASettingsWalkStopsBeforeADataMoveAndPassesOverAMachineAway (0.70s)
./cmd/mesh-controller --- PASS: TestACrossingSendSupersedesASettingsGate (0.37s)
./cmd/mesh-controller --- PASS: TestASettingsWalkFailsOnARefusalThatCannotClear (0.32s)
./cmd/mesh-controller --- PASS: TestAProviderElsewhereServesItsOwnComposedName (0.35s)
./cmd/mesh-controller --- PASS: TestAReusedCheckBuildIsRegisteredByItsDigestAndGatedAsABuiltOne (0.42s)
./cmd/mesh-controller --- PASS: TestAReleaseSendsTheRestAtOnceAfterTheFirstPasses (0.25s)
./cmd/mesh-controller --- PASS: TestARestMachineThatFailsIsPutBackAloneAndTheOthersAreJudgedOn (0.21s)
./cmd/mesh-controller --- PASS: TestAWalkTakesOverTheReadingsOfAGateJudgingTheSameBuildThere (0.19s)
./cmd/mesh-controller --- PASS: TestAFirstSendMadeAndNotKeptIsNotSentAgain (0.32s)
./cmd/mesh-controller --- PASS: TestAReleaseSendKeptAndMadeIsNotMadeAgain (0.19s)
./cmd/mesh-controller --- PASS: TestAFirstMachineThatFailsStillStopsTheWalk (0.21s)
./cmd/mesh-controller --- PASS: TestTheControlNodeIsSentLastInAStep (0.22s)
./cmd/mesh-controller --- PASS: TestARestMachineSilentPastItsBoundIsLeftAndSaid (0.21s)
./cmd/mesh-controller --- PASS: TestANoMoveTierWaitsForNoNewReport (0.40s)
./cmd/mesh-controller --- PASS: TestOneProviderDownAndThreeConsumersFailingAreOneCondition (0.32s)
./cmd/mesh-controller --- PASS: TestAConsumerFailingBesideAHealthyProviderIsItsOwn (0.24s)
./cmd/mesh-controller --- PASS: TestARecordedModulesBundleOnlyMoveRollsOutInItsWalk (0.45s)
./cmd/mesh-controller --- PASS: TestARecordedModulesMoveThatRecreatesAContainerWaits (0.89s)
./cmd/mesh-controller --- PASS: TestARecordedModulesMoveThatTouchesDataOrAProviderWaits (0.90s)
./cmd/mesh-controller --- PASS: TestAPersonsRecordAndTheBusHoldEveryMove (0.58s)
./cmd/mesh-controller --- PASS: TestARecordedMoveThatCannotBeJudgedWaits (0.52s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.10s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.10s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.10s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.08s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.06s)
./internal/inventory --- PASS: TestAPlanIdHoldingAQuoteIsReadAsAPlainId (0.11s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.09s)
./internal/inventory --- PASS: TestAWalksRestIsReadFromEachMachinesOwnSend (0.09s)
./internal/inventory --- PASS: TestAStoredBuildWithASilentMergeableFileIsStillReadAndComposed (0.08s)
./internal/inventory --- PASS: TestACredentialIssuedOutsideIsNeverMade (0.09s)
./internal/inventory --- PASS: TestOneAcceptForAProviderIsSealedToEveryConsumer (0.09s)
./internal/inventory --- PASS: TestASharedOwnSecretIssuedOutsideIsNeverMade (0.12s)
./internal/inventory --- PASS: TestAReportOfABusyContainerIsKeptAndReadBack (0.36s)
./internal/inventory --- PASS: TestWhatRunsIsTheRegisteredBuildNotANewerOnePutBack (0.10s)
**Merge check** at `2347a4c7`
Judged: head `2347a4c73bd0` merged into trunk `20e58907b0f8`; read beside it: mesh-catalog `0914a33fba5a`, mesh-controller-main `20e58907b0f8`, mesh-host `198fd34ec497`, mesh-tools `6b3e15042fee`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller, route-proxy
- tier 1: build-agent
- ace: receives route-proxy, build-agent
- g14: receives build-agent
- novox: receives mesh-controller, route-proxy, build-agent
- shanks: receives build-agent
- route-proxy provides route: its consumers are sent again after it
- route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before route-proxy, build-agent is judged on its first machine
- read by no module's build: cmd/mesh-controller/deadletters_aging_test.go, cmd/mesh-controller/desk_secret_test.go, cmd/mesh-controller/heard_withheld_test.go, cmd/mesh-controller/recorded_moves_test.go, internal/broker/modstreams_test.go, internal/broker/msgttl_live_test.go, internal/catalogue/holds_test.go, internal/catalogue/own_secret_prompt_test.go, internal/catalogue/streams_test.go, internal/inventory/sent_builds_test.go, internal/inventory/streams_test.go, internal/link/calls_kept_test.go, internal/link/deadletters_restricted_test.go, testdata/store-tests
Run by the build seat on ace as `build-1792074289744702568` (`builds --log build-1792074289744702568`).
```
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 60 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-15T11:29:40Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-15T11:29:40Z
modules the change moves:
- mesh-controller (changed)
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 2 tier(s): build-agent, mesh-controller, route-proxy
notes:
- cmd/mesh-controller/deadletters_aging_test.go, cmd/mesh-controller/desk_secret_test.go, cmd/mesh-controller/heard_withheld_test.go, cmd/mesh-controller/recorded_moves_test.go, internal/broker/modstreams_test.go, internal/broker/msgttl_live_test.go, internal/catalogue/holds_test.go, internal/catalogue/own_secret_prompt_test.go, internal/catalogue/streams_test.go, internal/inventory/sent_builds_test.go, internal/inventory/streams_test.go, internal/link/calls_kept_test.go, internal/link/deadletters_restricted_test.go and testdata/store-tests read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.117s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.019s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.023s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.017s
ok github.com/novox/mesh-controller/examples/route-proxy 1.124s
ok github.com/novox/mesh-controller/internal/artifacts 1.056s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 7.615s
ok github.com/novox/mesh-controller/internal/catalogue 13.238s
ok github.com/novox/mesh-controller/internal/conditions 3.309s
ok github.com/novox/mesh-controller/internal/envfile 1.038s
ok github.com/novox/mesh-controller/internal/facts 1.048s
ok github.com/novox/mesh-controller/internal/identity 7.679s
ok github.com/novox/mesh-controller/internal/lease 10.229s
ok github.com/novox/mesh-controller/internal/licences 6.241s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.037s
ok github.com/novox/mesh-controller/internal/lint 3.396s
ok github.com/novox/mesh-controller/internal/outward 1.110s
ok github.com/novox/mesh-controller/internal/overlay 1.051s
ok github.com/novox/mesh-controller/internal/secrets 1.600s
ok github.com/novox/mesh-controller/internal/store 4.286s
ok github.com/novox/mesh-controller/internal/testbus 1.300s
ok github.com/novox/mesh-controller/internal/token 1.046s
ok github.com/novox/mesh-controller/cmd/mesh-controller 31s (shard 1 of 8: 118 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 38s (shard 2 of 8: 118 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 31s (shard 3 of 8: 118 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 36s (shard 4 of 8: 118 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 29s (shard 5 of 8: 118 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 28s (shard 6 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 42s (shard 7 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 39s (shard 8 of 8: 117 tests)
ok github.com/novox/mesh-controller/internal/inventory 15s (shard 1 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 14s (shard 2 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 14s (shard 3 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 14s (shard 4 of 4: 68 tests)
ok github.com/novox/mesh-controller/internal/builder 39s (shard 1 of 4: 52 tests)
ok github.com/novox/mesh-controller/internal/builder 13s (shard 2 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/builder 35s (shard 3 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/builder 17s (shard 4 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/link 14s (shard 1 of 4: 47 tests)
ok github.com/novox/mesh-controller/internal/link 20s (shard 2 of 4: 46 tests)
ok github.com/novox/mesh-controller/internal/link 18s (shard 3 of 4: 46 tests)
ok github.com/novox/mesh-controller/internal/link 13s (shard 4 of 4: 46 tests)
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.27s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.32s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.27s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.26s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.23s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.22s)
./cmd/mesh-controller --- PASS: TestAPlanFollowedFromTheStoreAnswersWhenItMoves (2.21s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.35s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.13s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.78s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.32s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.24s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (1.33s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (1.31s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.73s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.64s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.41s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.39s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.47s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.51s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.34s)
./cmd/mesh-controller --- PASS: TestTheSendMakesNoValueForAnOutsideSecretNobodyGave (0.70s)
./cmd/mesh-controller --- PASS: TestAQuestionComposesWithoutAnOutsideSecretNobodyGave (0.72s)
./cmd/mesh-controller --- PASS: TestReplay201 (0.18s)
./cmd/mesh-controller --- PASS: TestARollbackWhoseSendWasRefusedIsCompletedByTheNextSend (0.17s)
./cmd/mesh-controller --- PASS: TestAGateJudgesTheOtherMovesBesideAKeptCore (0.19s)
./cmd/mesh-controller --- PASS: TestReplay401 (0.29s)
./cmd/mesh-controller --- PASS: TestReplay201ThePlansSend (0.39s)
./cmd/mesh-controller --- PASS: TestPlanAndNodeListAnOptionalRequirementLeftUnbound (0.89s)
./cmd/mesh-controller --- PASS: TestReplay340 (0.33s)
./cmd/mesh-controller --- PASS: TestOnlyATrustedFilesNamedKeyIsRefusedThroughAVerb (0.39s)
./cmd/mesh-controller --- PASS: TestReplay349 (0.25s)
./cmd/mesh-controller --- PASS: TestReplay348AFaultFromBeforeTheSendFailsNoGate (0.21s)
./cmd/mesh-controller --- PASS: TestReplay239AModuleNameIsNotTakenOverByAnotherRepository (0.22s)
./cmd/mesh-controller --- PASS: TestAWalkThatMovedNothingSaysWhichModulesMatchedWhatRuns (0.21s)
./cmd/mesh-controller --- PASS: TestAWalkWhoseEveryBuildCameOutTheSameIsDone (0.18s)
./cmd/mesh-controller --- PASS: TestReplay614ANewSDKPlansTheToolchainAndThenItsBundles (0.07s)
./cmd/mesh-controller --- PASS: TestOneAcceptForAProviderIsPlacedForEveryConsumer (1.29s)
./cmd/mesh-controller --- PASS: TestReplay164 (0.40s)
./cmd/mesh-controller --- PASS: TestAnApprovedLayerOpensTheWalkThatSendsIt (0.20s)
./cmd/mesh-controller --- PASS: TestASettingsWalkSendsOneMachineAtATimeEachJudged (0.25s)
./cmd/mesh-controller --- PASS: TestAFailedSettingsWalkStopsAndHoldsNothingBack (0.22s)
./cmd/mesh-controller --- PASS: TestASettingsWalkSendsTheLayerAloneEveryBuildKept (0.19s)
./cmd/mesh-controller --- PASS: TestASettingsWalkStopsBeforeADataMoveAndPassesOverAMachineAway (0.70s)
./cmd/mesh-controller --- PASS: TestACrossingSendSupersedesASettingsGate (0.37s)
./cmd/mesh-controller --- PASS: TestASettingsWalkFailsOnARefusalThatCannotClear (0.32s)
./cmd/mesh-controller --- PASS: TestAProviderElsewhereServesItsOwnComposedName (0.35s)
./cmd/mesh-controller --- PASS: TestAReusedCheckBuildIsRegisteredByItsDigestAndGatedAsABuiltOne (0.42s)
./cmd/mesh-controller --- PASS: TestAReleaseSendsTheRestAtOnceAfterTheFirstPasses (0.25s)
./cmd/mesh-controller --- PASS: TestARestMachineThatFailsIsPutBackAloneAndTheOthersAreJudgedOn (0.21s)
./cmd/mesh-controller --- PASS: TestAWalkTakesOverTheReadingsOfAGateJudgingTheSameBuildThere (0.19s)
./cmd/mesh-controller --- PASS: TestAFirstSendMadeAndNotKeptIsNotSentAgain (0.32s)
./cmd/mesh-controller --- PASS: TestAReleaseSendKeptAndMadeIsNotMadeAgain (0.19s)
./cmd/mesh-controller --- PASS: TestAFirstMachineThatFailsStillStopsTheWalk (0.21s)
./cmd/mesh-controller --- PASS: TestTheControlNodeIsSentLastInAStep (0.22s)
./cmd/mesh-controller --- PASS: TestARestMachineSilentPastItsBoundIsLeftAndSaid (0.21s)
./cmd/mesh-controller --- PASS: TestANoMoveTierWaitsForNoNewReport (0.40s)
./cmd/mesh-controller --- PASS: TestOneProviderDownAndThreeConsumersFailingAreOneCondition (0.32s)
./cmd/mesh-controller --- PASS: TestAConsumerFailingBesideAHealthyProviderIsItsOwn (0.24s)
./cmd/mesh-controller --- PASS: TestARecordedModulesBundleOnlyMoveRollsOutInItsWalk (0.45s)
./cmd/mesh-controller --- PASS: TestARecordedModulesMoveThatRecreatesAContainerWaits (0.89s)
./cmd/mesh-controller --- PASS: TestARecordedModulesMoveThatTouchesDataOrAProviderWaits (0.90s)
./cmd/mesh-controller --- PASS: TestAPersonsRecordAndTheBusHoldEveryMove (0.58s)
./cmd/mesh-controller --- PASS: TestARecordedMoveThatCannotBeJudgedWaits (0.52s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.10s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.10s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.10s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.08s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.06s)
./internal/inventory --- PASS: TestAPlanIdHoldingAQuoteIsReadAsAPlainId (0.11s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.09s)
./internal/inventory --- PASS: TestAWalksRestIsReadFromEachMachinesOwnSend (0.09s)
./internal/inventory --- PASS: TestAStoredBuildWithASilentMergeableFileIsStillReadAndComposed (0.08s)
./internal/inventory --- PASS: TestACredentialIssuedOutsideIsNeverMade (0.09s)
./internal/inventory --- PASS: TestOneAcceptForAProviderIsSealedToEveryConsumer (0.09s)
./internal/inventory --- PASS: TestASharedOwnSecretIssuedOutsideIsNeverMade (0.12s)
./internal/inventory --- PASS: TestAReportOfABusyContainerIsKeptAndReadBack (0.36s)
./internal/inventory --- PASS: TestWhatRunsIsTheRegisteredBuildNotANewerOnePutBack (0.10s)
```
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.
Feature feat/mail-hardening (playbook 07), one delivery group with novox/mesh-catalog#feat/mail-hardening.
whatto the desk.Reviewed locally before the push: round 1 (changes requested), round 2 approved at
2347a4c7. merge-check.sh green; all 64 cmd/mesh-controller store tests and the internal/inventory store tests passed against a throwaway postgres. Follow-ups opened: 808, 819, 822.A family like mesh-mail's mail-credential-* names only the module and the secret's key at the desk, so the operator cannot tell which account is asked. An own secret (or a family) may now declare a one-line prompt in its manifest, with {member} filled by a family member's suffix; the module check refuses one that is not one line, over 120 characters, or holds another placeholder. desk_secret.go reads it from the controller's own catalogue and sends it to the desk as what, never from the call or the module's runtime; omitted when none is declared, so an old desk or module behaves as today.Delivery
novox/mesh-controller@2347a4c73bd0— delivered since 2026-10-15T14:39:32ZDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Group
feat/mail-hardening, in order: novox/mesh-controller@2347a4c73b → novox/mesh-catalog@eb97a3d9a2Machines
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
2347a4c7Judged: head
2347a4c73bd0merged into trunk20e58907b0f8; read beside it: mesh-catalog0914a33fba5a, mesh-controller-main20e58907b0f8, mesh-host198fd34ec497, mesh-tools6b3e15042feemesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Run by the build seat on ace as
build-1792074289744702568(builds --log build-1792074289744702568).