Say every forge event on the bus through a signed system webhook (hq issue 729) #304

Merged
mesh-admin merged 1 commits from feat/729-the-forge-says-every-event-on-the-bus into main 2026-10-14 20:28:01 +00:00
Contributor

novox/hq issue 729. The gitea module keeps one system webhook (all event families) with a secret it keeps, receives on 172.17.0.1:3047 (the default bridge's gateway, reachable only from containers on the machine), verifies each delivery's HMAC, dedupes on X-Gitea-Delivery, answers at once, and publishes forge.. on the bus; the announcer announces a head or merge at once. Polls run at 30 s until the first verified delivery, 5 min while deliveries come, and back to 30 s (said MISSED) on a missed head/merge or 10 min without one. ALLOWED_HOST_LIST is exactly 172.17.0.1. Reviewed before push (approved at 1d8a244). Follow-ups: merge-on-ready on events, mesh-delivery's recheck of an out-of-date verdict, the module's own stream (ADR 0363) once issue 725 ships.

novox/hq issue 729. The gitea module keeps one system webhook (all event families) with a secret it keeps, receives on 172.17.0.1:3047 (the default bridge's gateway, reachable only from containers on the machine), verifies each delivery's HMAC, dedupes on X-Gitea-Delivery, answers at once, and publishes forge.<kind>.<action> on the bus; the announcer announces a head or merge at once. Polls run at 30 s until the first verified delivery, 5 min while deliveries come, and back to 30 s (said MISSED) on a missed head/merge or 10 min without one. ALLOWED_HOST_LIST is exactly 172.17.0.1. Reviewed before push (approved at 1d8a244). Follow-ups: merge-on-ready on events, mesh-delivery's recheck of an out-of-date verdict, the module's own stream (ADR 0363) once issue 725 ships.
mesh-admin added 1 commit 2026-10-14 20:23:21 +00:00
Say every forge event on the bus through a signed system webhook, and announce a head or merge at once (novox/hq issue 729)
mesh/merge-gate out of date: judged against trunk 2edef5a00ae0, the trunk is now 0e7d9e74d22a; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk 2edef5a00ae0, the trunk is now 0e7d9e74d22a; judged again on a recheck or when it is merged
mesh/delivery covered after its stop: a later walk that contains it was delivered: plan-1792011830935225963 (novox/mesh-catalog at 0361c44a into main, do…
1d8a244ba4
The gitea module keeps one system webhook for every event family, made or
corrected at start with the admin account (POST /admin/hooks, forge 1.27.3)
and a secret it mints and keeps. Its receiver, at the docker bridge's
gateway, refuses an unsigned request before reading it, a body over 5 MB,
and a signature that does not verify; it answers a verified delivery at once,
drops one already heard by its delivery id, and publishes each as
forge.<kind>.<action> on the module's events (its own stream, ADR 0363,
follows issue 725). A pull request opened, pushed to or merged is announced
at once. The polls look every five minutes only while deliveries arrive, and
every 30 s again, saying so loudly, when one finds what no event said or ten
minutes pass without a delivery. The announced records keep both paths from
announcing twice.
mesh-admin added the mesh/ready label 2026-10-14 20:23:38 +00:00
Author
Contributor

Reviewed before push and approved (independent review, issue 729).

ready at 1d8a244ba4

Reviewed before push and approved (independent review, issue 729). ready at 1d8a244ba42bcea8def1751b75fb6de5c8bc28a1
Author
Contributor

Delivery novox/mesh-catalog@1d8a244ba42b — stopped since 2026-10-14T20:32:19Z

Covered: covered after its stop: a later walk that contains it was delivered: plan-1792011830935225963 (novox/mesh-catalog at 0361c44a into main, done, contains its merge 0e7d9e74)

Delivery plan — builds gitea → novox; no bus step

  • tier 0: gitea
  • novox: receives gitea
  • gitea provides npm-package-registry, git: its consumers are sent again after it
  • gitea keeps data (ADR 0233): what it holds is backed up before it moves

Transitions

  • 2026-10-14 20:23 (new) → proposed (announced): novox/mesh-catalog#304's head announced
  • 2026-10-14 20:27 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
  • 2026-10-14 20:27 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
  • 2026-10-14 20:32 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
  • 2026-10-14 20:32 published → stopped (stop): its walk plan-1792009301770286799 was stopped by mesh-delivery for mesh-delivery: novox/mesh-catalog@d94764f001 was stopped: its group fix/a-module-moves-only-when-its-program-changes stopped: novox/mesh-controller@b34055f580 failed; its merge contains the stopped merge 2edef5a00a, so it cannot be walked without delivering it, and was left out with it (novox/hq ADR 0299)

The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.

<!-- mesh-delivery:view --> **Delivery** `novox/mesh-catalog@1d8a244ba42b` — **stopped** since 2026-10-14T20:32:19Z **Covered**: covered after its stop: a later walk that contains it was delivered: plan-1792011830935225963 (novox/mesh-catalog at 0361c44a into main, done, contains its merge 0e7d9e74) **Delivery plan** — builds gitea → novox; no bus step - tier 0: gitea - novox: receives gitea - gitea provides npm-package-registry, git: its consumers are sent again after it - gitea keeps data (ADR 0233): what it holds is backed up before it moves **Transitions** - 2026-10-14 20:23 (new) → proposed (announced): novox/mesh-catalog#304's head announced - 2026-10-14 20:27 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit - 2026-10-14 20:27 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail - 2026-10-14 20:32 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move - 2026-10-14 20:32 published → stopped (stop): its walk plan-1792009301770286799 was stopped by mesh-delivery for mesh-delivery: novox/mesh-catalog@d94764f00168 was stopped: its group fix/a-module-moves-only-when-its-program-changes stopped: novox/mesh-controller@b34055f580d4 failed; its merge contains the stopped merge 2edef5a00ae0, so it cannot be walked without delivering it, and was left out with it (novox/hq ADR 0299) The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
Author
Contributor

Merge check at 1d8a244b
Judged: head 1d8a244ba42b merged into trunk 2edef5a00ae0; read beside it: mesh-controller 86057f455194, mesh-controller-main 5d22d7df86c7, mesh-host 1a2677882380, mesh-tools 5d70eb3e35a9

  • mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: gitea)
  • mesh/repo-check: PASS — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)

Delivery plan — builds gitea → novox; no bus step

  • tier 0: gitea
  • novox: receives gitea
  • gitea provides npm-package-registry, git: its consumers are sent again after it
  • gitea keeps data (ADR 0233): what it holds is backed up before it moves

Run by the build seat on shanks as build-1792009501691055362 (builds --log build-1792009501691055362).

--- the gate: gitea
gitea: ok, keeps data (valuable), ready: server by http /api/healthz on web expecting 200 every 30s
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 0
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-14T20:20:33Z 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-14T20:20:33Z

modules the change moves:
  - gitea (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 1 module(s) in 1 tier(s): gitea
--- its merge-check.sh (go toolchain)
ok  	git.novox.be/novox/mesh-catalog/checks/words	0.003s
words: 12 retired words and 70 daemons' lines, none in the 47260 strings of 722 files
ok  	git.novox.be/novox/mesh-catalog/checks/agenthome	0.013s
agent-home: no archive and no file written into under the agent's home
ok  	git.novox.be/novox/mesh-catalog/checks/secrets	0.012s
secrets: no setting can replace a vault secret in a mergeable file (1 known, nested)
ok  	git.novox.be/novox/mesh-catalog/checks/paths	0.006s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 62, as kept
ok  	git.novox.be/novox/mesh-catalog/checks/deps	0.210s
testing modules/gitea
ok  	gitea/cmd/forge	1.504s
ok  	gitea/cmd/npm-registry	1.809s
?   	gitea/internal/forgehttp	[no test files]
--- its merge-check-typescript.sh (typescript toolchain)
type-checking modules/gitea (TypeScript)
testing modules/gitea (TypeScript)
✔ a pull request opened after the margin is looked at, by its own update time (10.350661ms)
✔ every open pull request is read with what its base requires and what its head has (gitea_open_pulls) (51.015975ms)
✔ a pull request or issue number that is not one is refused before the forge is asked (1.408678ms)
✔ a merged pull request whose branch was deleted is announced with its branch, not its pull ref (10.342371ms)
✔ a pull request's ready mark is read: the label and the head the newest listed ready comment names (15.974682ms)
✔ a ready comment by an account not listed is ignored, and said (0.437266ms)
✔ a ready comment older than the latest push, or than the label, never counts (43.654042ms)
[gitea] f cannot be read (gone); only mesh-admin may mark a pull request ready
[gitea] f names no account that may mark a pull request ready; only mesh-admin may
✔ a long thread hides nothing: every page of the timeline is read (14.089358ms)
✔ the accounts that may mark are the setting's, and only the mesh's own when it cannot be read (0.706129ms)
✔ the newest status of each context is kept, with what it said, when and by whom (15.904931ms)
✔ a commit merges only when every required status is a success; a warning blocks (0.606088ms)
✔ no rule requires nothing; a rule that cannot be read says nothing, never yes (0.219073ms)
✔ a commit is contained in another when the compare finds nothing on it the other lacks (0.698919ms)
✔ a note line is appended once, as the forge's user, in its own repository (11.131671ms)
✔ a note that cannot be written is said, never read as written (0.602498ms)
✔ one view per pull request, found by its marker; only the mesh's statuses (0.79026ms)
✔ a build machine taking the check is said on the head: building on which machine, since the local time (12.824052ms)
✔ the verdict heard while a 'building' write is in flight lands last and stays (7.768909ms)
[gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check now pending; not written
✔ the verdict written while a start's read of the forge is in flight stays the newest status (0.931301ms)
✔ the verdict heard while a 'building' write still waits its turn: the 'building' is never written (0.421355ms)
✔ a start heard after the verdict writes nothing (0.580307ms)
✔ a start from before the check now pending (a run before a recheck, the stream's history) writes nothing (0.543617ms)
✔ an old run's verdict redelivered after a recheck's pending is not written over it (0.77963ms)
[gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check the forge holds pending; not written
[gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check now pending; not written
✔ an old run's verdict in flight when the recheck comes lands before the recheck's pending (1.740582ms)
✔ a rechecked head says where its new run is: building on which machine (0.894661ms)
✔ the recheck's own verdict is written, even asked a little before the pending by another machine's clock (0.684329ms)
✔ after a restart, an old run's verdict is weighed against the check the forge's history holds open (0.496466ms)
✔ a recheck the forge does not take fails its caller, and the head is as it was (0.453556ms)
✔ the status tool writes the merge check's pending through the writer, and the mesh's other statuses as they were (5.617201ms)
✔ when a check was asked is read from its id; the opening of the check now pending from the gate's history (0.271344ms)
✔ a head this process did not announce (it restarted) is said only while the forge holds its gate pending (0.374725ms)
✔ a repository as the mesh clones it is told from another (0.300644ms)
✔ gitea_api refuses the forge's administration, a branch's protection and the merge check's status, and sends nothing (5.412318ms)
✔ gitea_api refuses a file written to the default branch or one a rule guards, and writes one on a branch of its own (49.709008ms)
✔ a protection rule covers a branch as the forge decides it: classes, alternatives, a plain name in any case (issue 539) (19.307164ms)
✔ gitea_api still writes what an author writes (8.458488ms)
✔ gitea_branch_protection_set only strengthens (15.8861ms)
✔ gitea_merge_pull_request merges only a head whose required statuses all succeeded, and only that head (50.242936ms)
✔ gitea_merge_pull_request refuses a verdict judged against an earlier trunk, and asks the check once (150.556983ms)
✔ gitea_merge_pull_request merges only the head it is named, and refuses one that is not the head (15.684688ms)
✔ gitea_merge_pull_request is loud when the forge merged a head other than the one it was handed (12.759181ms)
✔ gitea_merge_pull_request says the merge happened when reading back what landed fails (24.922586ms)
✔ gitea_merge_pull_request reads back a fast-forward, and says it cannot read back a squash or a rebase (56.181221ms)
✔ gitea_delete_repo deletes only the tools' own user's repository, unguarded, untouched for 30 days, named in full (18.747767ms)
✔ gitea_api sends the path it judged, and refuses moving a pull request's base (4.048971ms)
✔ gitea_merge_pull_request merges only into a branch whose protection requires the checks (6.682995ms)
✔ a rule named for a branch is not made weaker than the glob rule that guards it now (13.43011ms)
✔ a repository owner or name is never another path (0.212853ms)
✔ the judges, without a forge (0.339605ms)
✔ gitea_api never acts as another user: sudo, in any case, and any query key it does not send are refused (1.411068ms)
✔ gitea_api never approves a pull request nor requests changes: those are the operator's (1.195405ms)
✔ no tool's caller text becomes another path or another user: `..` and `?sudo=` are refused before the forge (3.702327ms)
✔ every page of a pull request's files is read, though the forge caps a page at fifty (31.825172ms)
✔ a pass asks only the repositories that moved since the last look, every one before the first (0.520447ms)
✔ the directories above a merge's files that hold a module at the commit are said, the root never (13.922106ms)
✔ a lookup the forge refuses is thrown, not read as no module (5.260496ms)
✔ a renamed file is said under its old name too, as gone (novox/hq ADR 0267) (6.38032ms)
✔ a new head beyond the newest 20 open pull requests is announced, exactly once (49.485155ms)
✔ a pass pages until it reaches back past its floor, and no further (23.329535ms)
✔ the statuses asked for replace the rule's, and an empty list requires none (8.70432ms)
✔ a new rule refuses direct pushes unless asked; an administrator's override only when said (0.364005ms)
✔ each open pull request's new head is announced once, and nothing closed or merged (10.27433ms)
✔ a verdict is the head commit's status; an error is the forge's error, never a success (0.887661ms)
✔ each layer is its own status: the gate with the modules it judged, the repository's own check beside it (0.581298ms)
✔ no verdict sets warning on a required check; only a person's decision fails (0.881021ms)
✔ a commit status is set on the commit, under the merge check's context (37.14496ms)
✔ a change plan is the gate's result: said on the status and, when it builds something, as a comment (0.511146ms)
✔ a head announced is pending in the build queue, since the local time it was announced (0.228693ms)
✔ the vault's token is used, a setting of it is ignored and said once, without its value (2.492832ms)
✔ a consumer that asks nothing, or write, publishes: the package team (1.774133ms)
✔ a consumer that asks to read joins the readers, who write no package (0.506226ms)
✔ a reader is made, put on the readers team, and taken off the package team (0.652298ms)
✔ a publisher is made and put on the package team, as before (0.253873ms)
✔ first start: mints with the admin account, keeps the token at 0600, asks for the tools' scopes only (29.553413ms)
✔ second start: reuses the kept token, mints nothing (16.108804ms)
✔ the forge rejects the kept token (its data was restored): minted afresh, once, and the call goes through (19.822191ms)
✔ a token kept with write:admin by an earlier build is minted again without it at the next start, and the forge drops the old one (25.850927ms)
✔ a kept token lacking a scope the tools need: the forge refuses the call for the scope, the token is re-minted with the whole list, and the call goes through (18.669016ms)
✔ the kept file is gone but the forge still holds a token by that name: replaced, not refused (19.917302ms)
✔ concurrent first calls share one mint (12.271936ms)
✔ the admin account is refused: said plainly, nothing kept, and the next call fails the same way rather than crashing (11.14901ms)
✔ one process shares one source per kept file — the watcher and the tools never renew against each other (1.199585ms)
✔ a second process finds the token the first renewed, and reuses it instead of minting over it (21.150907ms)
✔ a configured token wins, and is reported rather than minted over when the forge rejects it (2.582903ms)
✔ nothing to mint with and no token: the client says what is missing (0.218633ms)
[gitea] no tools — no Gitea token, and nothing to mint one with — set MESH_GITEA_TOKEN, or MESH_GITEA_ADMIN_USER, MESH_GITEA_ADMIN_PASSWORD_FILE, MESH_GITEA_STATE_DIR
[gitea] no token kept — minting one
[gitea] the forge already holds a token named "mesh-tools" — replacing it
[gitea] minted a token for "mesh-admin" (write:repository, write:issue, read:user), kept at /tmp/gitea-eGKUrf/state/token
✔ the tools register once there is a way to a token, and the first call mints it (9.990156ms)
[gitea] no token kept — minting one
[gitea] the forge already holds a token named "mesh-tools" — replacing it
[gitea] minted a token for "mesh-admin" (write:repository, write:issue, read:user), kept at /tmp/gitea-z19WcO/state/token
✔ a pull request can be closed, read and cleaned up through the tools (25.409571ms)
[gitea] novox/mesh-host's main moved from a2c2c35bbbbb to d28ca95ccccc: 25 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323)
[gitea] novox/mesh-host's main moved from d28ca95ccccc to ffffffffffff: 0 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323)
[gitea] novox/mesh-host: whether a trunk moved could not be weighed, so it is weighed again on the next pass — the forge is away
[gitea] novox/mesh-host's main moved from a2c2c35bbbbb to d28ca95ccccc: 0 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323)
[gitea] novox/mesh-controller's feat/57-config-and-provisioning moved from eeeeeeeeeeee to d28ca95ccccc: 1 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323)
✔ both statuses say the head and the trunk commit the verdict judged, first, whatever the summary's length (2.288189ms)
✔ a trunk's move puts an open head's merge check out of date, naming both commits, unless a check is on its way (1.532879ms)
✔ a push to a trunk puts every open pull request into it out of date — twenty-five of them — and none into another (6.219829ms)
✔ a trunk that cannot be read is weighed again on the next pass, never recorded half (0.498007ms)
✔ the trunk's move takes its turn after a verdict in flight, and weighs what the forge holds then (0.589757ms)
✔ a verdict judged against a trunk newer than the pass's first read is not put out of date (0.356344ms)
✔ a verdict that landed out of date keeps its account on the pull request (0.344774ms)
✔ a release branch's move puts every open pull request into it out of date, as a trunk's does (ADR 0358 §5) (0.575997ms)
✔ a signed event is published on the bus and acted on once (60.249012ms)
✔ an unsigned event, or one whose signature does not verify, is refused and published nowhere (34.348294ms)
✔ an event and the poll seeing the same head announce it once (0.483136ms)
✔ each forge event is named in the module's stream and trimmed (0.73834ms)
✔ the system webhook is made when none points at the receiver, and corrected when one does (0.605018ms)
✔ the polls look every 30 s until events are heard, every five minutes while they are, and 30 s again on a miss (17.717364ms)
ℹ tests 101
ℹ suites 0
ℹ pass 101
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 648.044204
**Merge check** at `1d8a244b` Judged: head `1d8a244ba42b` merged into trunk `2edef5a00ae0`; read beside it: mesh-controller `86057f455194`, mesh-controller-main `5d22d7df86c7`, mesh-host `1a2677882380`, mesh-tools `5d70eb3e35a9` - `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: gitea) - `mesh/repo-check`: **PASS** — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript) **Delivery plan** — builds gitea → novox; no bus step - tier 0: gitea - novox: receives gitea - gitea provides npm-package-registry, git: its consumers are sent again after it - gitea keeps data (ADR 0233): what it holds is backed up before it moves Run by the build seat on shanks as `build-1792009501691055362` (`builds --log build-1792009501691055362`). ``` --- the gate: gitea gitea: ok, keeps data (valuable), ready: server by http /api/healthz on web expecting 200 every 30s long-running resources without health: 0 files asking for a setting without saying whether it is trusted: 0 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-14T20:20:33Z 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-14T20:20:33Z modules the change moves: - gitea (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 1 module(s) in 1 tier(s): gitea --- its merge-check.sh (go toolchain) ok git.novox.be/novox/mesh-catalog/checks/words 0.003s words: 12 retired words and 70 daemons' lines, none in the 47260 strings of 722 files ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.013s agent-home: no archive and no file written into under the agent's home ok git.novox.be/novox/mesh-catalog/checks/secrets 0.012s secrets: no setting can replace a vault secret in a mergeable file (1 known, nested) ok git.novox.be/novox/mesh-catalog/checks/paths 0.006s paths: no module names another's state on its machine (3 known, listed to go) long-running resources without health: 62, as kept ok git.novox.be/novox/mesh-catalog/checks/deps 0.210s testing modules/gitea ok gitea/cmd/forge 1.504s ok gitea/cmd/npm-registry 1.809s ? gitea/internal/forgehttp [no test files] --- its merge-check-typescript.sh (typescript toolchain) type-checking modules/gitea (TypeScript) testing modules/gitea (TypeScript) ✔ a pull request opened after the margin is looked at, by its own update time (10.350661ms) ✔ every open pull request is read with what its base requires and what its head has (gitea_open_pulls) (51.015975ms) ✔ a pull request or issue number that is not one is refused before the forge is asked (1.408678ms) ✔ a merged pull request whose branch was deleted is announced with its branch, not its pull ref (10.342371ms) ✔ a pull request's ready mark is read: the label and the head the newest listed ready comment names (15.974682ms) ✔ a ready comment by an account not listed is ignored, and said (0.437266ms) ✔ a ready comment older than the latest push, or than the label, never counts (43.654042ms) [gitea] f cannot be read (gone); only mesh-admin may mark a pull request ready [gitea] f names no account that may mark a pull request ready; only mesh-admin may ✔ a long thread hides nothing: every page of the timeline is read (14.089358ms) ✔ the accounts that may mark are the setting's, and only the mesh's own when it cannot be read (0.706129ms) ✔ the newest status of each context is kept, with what it said, when and by whom (15.904931ms) ✔ a commit merges only when every required status is a success; a warning blocks (0.606088ms) ✔ no rule requires nothing; a rule that cannot be read says nothing, never yes (0.219073ms) ✔ a commit is contained in another when the compare finds nothing on it the other lacks (0.698919ms) ✔ a note line is appended once, as the forge's user, in its own repository (11.131671ms) ✔ a note that cannot be written is said, never read as written (0.602498ms) ✔ one view per pull request, found by its marker; only the mesh's statuses (0.79026ms) ✔ a build machine taking the check is said on the head: building on which machine, since the local time (12.824052ms) ✔ the verdict heard while a 'building' write is in flight lands last and stays (7.768909ms) [gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check now pending; not written ✔ the verdict written while a start's read of the forge is in flight stays the newest status (0.931301ms) ✔ the verdict heard while a 'building' write still waits its turn: the 'building' is never written (0.421355ms) ✔ a start heard after the verdict writes nothing (0.580307ms) ✔ a start from before the check now pending (a run before a recheck, the stream's history) writes nothing (0.543617ms) ✔ an old run's verdict redelivered after a recheck's pending is not written over it (0.77963ms) [gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check the forge holds pending; not written [gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check now pending; not written ✔ an old run's verdict in flight when the recheck comes lands before the recheck's pending (1.740582ms) ✔ a rechecked head says where its new run is: building on which machine (0.894661ms) ✔ the recheck's own verdict is written, even asked a little before the pending by another machine's clock (0.684329ms) ✔ after a restart, an old run's verdict is weighed against the check the forge's history holds open (0.496466ms) ✔ a recheck the forge does not take fails its caller, and the head is as it was (0.453556ms) ✔ the status tool writes the merge check's pending through the writer, and the mesh's other statuses as they were (5.617201ms) ✔ when a check was asked is read from its id; the opening of the check now pending from the gate's history (0.271344ms) ✔ a head this process did not announce (it restarted) is said only while the forge holds its gate pending (0.374725ms) ✔ a repository as the mesh clones it is told from another (0.300644ms) ✔ gitea_api refuses the forge's administration, a branch's protection and the merge check's status, and sends nothing (5.412318ms) ✔ gitea_api refuses a file written to the default branch or one a rule guards, and writes one on a branch of its own (49.709008ms) ✔ a protection rule covers a branch as the forge decides it: classes, alternatives, a plain name in any case (issue 539) (19.307164ms) ✔ gitea_api still writes what an author writes (8.458488ms) ✔ gitea_branch_protection_set only strengthens (15.8861ms) ✔ gitea_merge_pull_request merges only a head whose required statuses all succeeded, and only that head (50.242936ms) ✔ gitea_merge_pull_request refuses a verdict judged against an earlier trunk, and asks the check once (150.556983ms) ✔ gitea_merge_pull_request merges only the head it is named, and refuses one that is not the head (15.684688ms) ✔ gitea_merge_pull_request is loud when the forge merged a head other than the one it was handed (12.759181ms) ✔ gitea_merge_pull_request says the merge happened when reading back what landed fails (24.922586ms) ✔ gitea_merge_pull_request reads back a fast-forward, and says it cannot read back a squash or a rebase (56.181221ms) ✔ gitea_delete_repo deletes only the tools' own user's repository, unguarded, untouched for 30 days, named in full (18.747767ms) ✔ gitea_api sends the path it judged, and refuses moving a pull request's base (4.048971ms) ✔ gitea_merge_pull_request merges only into a branch whose protection requires the checks (6.682995ms) ✔ a rule named for a branch is not made weaker than the glob rule that guards it now (13.43011ms) ✔ a repository owner or name is never another path (0.212853ms) ✔ the judges, without a forge (0.339605ms) ✔ gitea_api never acts as another user: sudo, in any case, and any query key it does not send are refused (1.411068ms) ✔ gitea_api never approves a pull request nor requests changes: those are the operator's (1.195405ms) ✔ no tool's caller text becomes another path or another user: `..` and `?sudo=` are refused before the forge (3.702327ms) ✔ every page of a pull request's files is read, though the forge caps a page at fifty (31.825172ms) ✔ a pass asks only the repositories that moved since the last look, every one before the first (0.520447ms) ✔ the directories above a merge's files that hold a module at the commit are said, the root never (13.922106ms) ✔ a lookup the forge refuses is thrown, not read as no module (5.260496ms) ✔ a renamed file is said under its old name too, as gone (novox/hq ADR 0267) (6.38032ms) ✔ a new head beyond the newest 20 open pull requests is announced, exactly once (49.485155ms) ✔ a pass pages until it reaches back past its floor, and no further (23.329535ms) ✔ the statuses asked for replace the rule's, and an empty list requires none (8.70432ms) ✔ a new rule refuses direct pushes unless asked; an administrator's override only when said (0.364005ms) ✔ each open pull request's new head is announced once, and nothing closed or merged (10.27433ms) ✔ a verdict is the head commit's status; an error is the forge's error, never a success (0.887661ms) ✔ each layer is its own status: the gate with the modules it judged, the repository's own check beside it (0.581298ms) ✔ no verdict sets warning on a required check; only a person's decision fails (0.881021ms) ✔ a commit status is set on the commit, under the merge check's context (37.14496ms) ✔ a change plan is the gate's result: said on the status and, when it builds something, as a comment (0.511146ms) ✔ a head announced is pending in the build queue, since the local time it was announced (0.228693ms) ✔ the vault's token is used, a setting of it is ignored and said once, without its value (2.492832ms) ✔ a consumer that asks nothing, or write, publishes: the package team (1.774133ms) ✔ a consumer that asks to read joins the readers, who write no package (0.506226ms) ✔ a reader is made, put on the readers team, and taken off the package team (0.652298ms) ✔ a publisher is made and put on the package team, as before (0.253873ms) ✔ first start: mints with the admin account, keeps the token at 0600, asks for the tools' scopes only (29.553413ms) ✔ second start: reuses the kept token, mints nothing (16.108804ms) ✔ the forge rejects the kept token (its data was restored): minted afresh, once, and the call goes through (19.822191ms) ✔ a token kept with write:admin by an earlier build is minted again without it at the next start, and the forge drops the old one (25.850927ms) ✔ a kept token lacking a scope the tools need: the forge refuses the call for the scope, the token is re-minted with the whole list, and the call goes through (18.669016ms) ✔ the kept file is gone but the forge still holds a token by that name: replaced, not refused (19.917302ms) ✔ concurrent first calls share one mint (12.271936ms) ✔ the admin account is refused: said plainly, nothing kept, and the next call fails the same way rather than crashing (11.14901ms) ✔ one process shares one source per kept file — the watcher and the tools never renew against each other (1.199585ms) ✔ a second process finds the token the first renewed, and reuses it instead of minting over it (21.150907ms) ✔ a configured token wins, and is reported rather than minted over when the forge rejects it (2.582903ms) ✔ nothing to mint with and no token: the client says what is missing (0.218633ms) [gitea] no tools — no Gitea token, and nothing to mint one with — set MESH_GITEA_TOKEN, or MESH_GITEA_ADMIN_USER, MESH_GITEA_ADMIN_PASSWORD_FILE, MESH_GITEA_STATE_DIR [gitea] no token kept — minting one [gitea] the forge already holds a token named "mesh-tools" — replacing it [gitea] minted a token for "mesh-admin" (write:repository, write:issue, read:user), kept at /tmp/gitea-eGKUrf/state/token ✔ the tools register once there is a way to a token, and the first call mints it (9.990156ms) [gitea] no token kept — minting one [gitea] the forge already holds a token named "mesh-tools" — replacing it [gitea] minted a token for "mesh-admin" (write:repository, write:issue, read:user), kept at /tmp/gitea-z19WcO/state/token ✔ a pull request can be closed, read and cleaned up through the tools (25.409571ms) [gitea] novox/mesh-host's main moved from a2c2c35bbbbb to d28ca95ccccc: 25 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323) [gitea] novox/mesh-host's main moved from d28ca95ccccc to ffffffffffff: 0 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323) [gitea] novox/mesh-host: whether a trunk moved could not be weighed, so it is weighed again on the next pass — the forge is away [gitea] novox/mesh-host's main moved from a2c2c35bbbbb to d28ca95ccccc: 0 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323) [gitea] novox/mesh-controller's feat/57-config-and-provisioning moved from eeeeeeeeeeee to d28ca95ccccc: 1 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323) ✔ both statuses say the head and the trunk commit the verdict judged, first, whatever the summary's length (2.288189ms) ✔ a trunk's move puts an open head's merge check out of date, naming both commits, unless a check is on its way (1.532879ms) ✔ a push to a trunk puts every open pull request into it out of date — twenty-five of them — and none into another (6.219829ms) ✔ a trunk that cannot be read is weighed again on the next pass, never recorded half (0.498007ms) ✔ the trunk's move takes its turn after a verdict in flight, and weighs what the forge holds then (0.589757ms) ✔ a verdict judged against a trunk newer than the pass's first read is not put out of date (0.356344ms) ✔ a verdict that landed out of date keeps its account on the pull request (0.344774ms) ✔ a release branch's move puts every open pull request into it out of date, as a trunk's does (ADR 0358 §5) (0.575997ms) ✔ a signed event is published on the bus and acted on once (60.249012ms) ✔ an unsigned event, or one whose signature does not verify, is refused and published nowhere (34.348294ms) ✔ an event and the poll seeing the same head announce it once (0.483136ms) ✔ each forge event is named in the module's stream and trimmed (0.73834ms) ✔ the system webhook is made when none points at the receiver, and corrected when one does (0.605018ms) ✔ the polls look every 30 s until events are heard, every five minutes while they are, and 30 s again on a miss (17.717364ms) ℹ tests 101 ℹ suites 0 ℹ pass 101 ℹ fail 0 ℹ cancelled 0 ℹ skipped 0 ℹ todo 0 ℹ duration_ms 648.044204 ```
mesh-admin merged commit 0e7d9e74d2 into main 2026-10-14 20:28:01 +00:00
mesh-admin deleted branch feat/729-the-forge-says-every-event-on-the-bus 2026-10-14 20:28:02 +00:00
Author
Contributor

Merge check at 1d8a244b
Judged: head 1d8a244ba42b merged into trunk 2edef5a00ae0; read beside it: mesh-controller 86057f455194, mesh-controller-main 5d22d7df86c7, mesh-host 1a2677882380, mesh-tools 5d70eb3e35a9

  • mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: gitea)
  • mesh/repo-check: PASS — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)

Delivery plan — builds gitea → novox; no bus step

  • tier 0: gitea
  • novox: receives gitea
  • gitea provides npm-package-registry, git: its consumers are sent again after it
  • gitea keeps data (ADR 0233): what it holds is backed up before it moves

Run by the build seat on novox as build-1792009518584651434 (builds --log build-1792009518584651434).

--- the gate: gitea
gitea: ok, keeps data (valuable), ready: server by http /api/healthz on web expecting 200 every 30s
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 0
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-14T20:20:33Z 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-14T20:20:33Z

modules the change moves:
  - gitea (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 1 module(s) in 1 tier(s): gitea
--- its merge-check.sh (go toolchain)
ok  	git.novox.be/novox/mesh-catalog/checks/words	0.003s
words: 12 retired words and 70 daemons' lines, none in the 47260 strings of 722 files
ok  	git.novox.be/novox/mesh-catalog/checks/agenthome	0.071s
agent-home: no archive and no file written into under the agent's home
ok  	git.novox.be/novox/mesh-catalog/checks/secrets	0.014s
secrets: no setting can replace a vault secret in a mergeable file (1 known, nested)
ok  	git.novox.be/novox/mesh-catalog/checks/paths	0.007s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 62, as kept
ok  	git.novox.be/novox/mesh-catalog/checks/deps	0.542s
testing modules/gitea
ok  	gitea/cmd/forge	1.558s
ok  	gitea/cmd/npm-registry	1.994s
?   	gitea/internal/forgehttp	[no test files]
--- its merge-check-typescript.sh (typescript toolchain)
type-checking modules/gitea (TypeScript)
testing modules/gitea (TypeScript)
✔ a pull request opened after the margin is looked at, by its own update time (48.910477ms)
✔ every open pull request is read with what its base requires and what its head has (gitea_open_pulls) (111.823933ms)
✔ a pull request or issue number that is not one is refused before the forge is asked (3.010587ms)
✔ a merged pull request whose branch was deleted is announced with its branch, not its pull ref (16.906507ms)
✔ a pull request's ready mark is read: the label and the head the newest listed ready comment names (25.099435ms)
✔ a ready comment by an account not listed is ignored, and said (0.481611ms)
✔ a ready comment older than the latest push, or than the label, never counts (53.591997ms)
[gitea] f cannot be read (gone); only mesh-admin may mark a pull request ready
[gitea] f names no account that may mark a pull request ready; only mesh-admin may
✔ a long thread hides nothing: every page of the timeline is read (21.073416ms)
✔ the accounts that may mark are the setting's, and only the mesh's own when it cannot be read (1.072823ms)
✔ the newest status of each context is kept, with what it said, when and by whom (32.044159ms)
✔ a commit merges only when every required status is a success; a warning blocks (0.752151ms)
✔ no rule requires nothing; a rule that cannot be read says nothing, never yes (0.352101ms)
✔ a commit is contained in another when the compare finds nothing on it the other lacks (1.117023ms)
✔ a note line is appended once, as the forge's user, in its own repository (31.753849ms)
✔ a note that cannot be written is said, never read as written (1.937275ms)
✔ one view per pull request, found by its marker; only the mesh's statuses (2.074334ms)
✔ a build machine taking the check is said on the head: building on which machine, since the local time (27.094819ms)
✔ the verdict heard while a 'building' write is in flight lands last and stays (10.428573ms)
[gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check now pending; not written
✔ the verdict written while a start's read of the forge is in flight stays the newest status (1.413963ms)
✔ the verdict heard while a 'building' write still waits its turn: the 'building' is never written (0.545321ms)
✔ a start heard after the verdict writes nothing (3.775378ms)
✔ a start from before the check now pending (a run before a recheck, the stream's history) writes nothing (0.587372ms)
✔ an old run's verdict redelivered after a recheck's pending is not written over it (0.964752ms)
[gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check the forge holds pending; not written
[gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check now pending; not written
✔ an old run's verdict in flight when the recheck comes lands before the recheck's pending (4.286129ms)
✔ a rechecked head says where its new run is: building on which machine (0.925452ms)
✔ the recheck's own verdict is written, even asked a little before the pending by another machine's clock (0.753282ms)
✔ after a restart, an old run's verdict is weighed against the check the forge's history holds open (1.387893ms)
✔ a recheck the forge does not take fails its caller, and the head is as it was (0.572351ms)
✔ the status tool writes the merge check's pending through the writer, and the mesh's other statuses as they were (5.864733ms)
✔ when a check was asked is read from its id; the opening of the check now pending from the gate's history (0.295491ms)
✔ a head this process did not announce (it restarted) is said only while the forge holds its gate pending (0.400271ms)
✔ a repository as the mesh clones it is told from another (0.28064ms)
✔ gitea_api refuses the forge's administration, a branch's protection and the merge check's status, and sends nothing (15.892564ms)
✔ gitea_api refuses a file written to the default branch or one a rule guards, and writes one on a branch of its own (84.964785ms)
✔ a protection rule covers a branch as the forge decides it: classes, alternatives, a plain name in any case (issue 539) (50.05673ms)
✔ gitea_api still writes what an author writes (10.341242ms)
✔ gitea_branch_protection_set only strengthens (19.680893ms)
✔ gitea_merge_pull_request merges only a head whose required statuses all succeeded, and only that head (56.911904ms)
✔ gitea_merge_pull_request refuses a verdict judged against an earlier trunk, and asks the check once (168.125076ms)
✔ gitea_merge_pull_request merges only the head it is named, and refuses one that is not the head (17.135477ms)
✔ gitea_merge_pull_request is loud when the forge merged a head other than the one it was handed (14.704552ms)
✔ gitea_merge_pull_request says the merge happened when reading back what landed fails (26.115877ms)
✔ gitea_merge_pull_request reads back a fast-forward, and says it cannot read back a squash or a rebase (68.80797ms)
✔ gitea_delete_repo deletes only the tools' own user's repository, unguarded, untouched for 30 days, named in full (22.87687ms)
✔ gitea_api sends the path it judged, and refuses moving a pull request's base (4.362399ms)
✔ gitea_merge_pull_request merges only into a branch whose protection requires the checks (7.946258ms)
✔ a rule named for a branch is not made weaker than the glob rule that guards it now (13.347169ms)
✔ a repository owner or name is never another path (0.241141ms)
✔ the judges, without a forge (0.327691ms)
✔ gitea_api never acts as another user: sudo, in any case, and any query key it does not send are refused (2.531765ms)
✔ gitea_api never approves a pull request nor requests changes: those are the operator's (1.168833ms)
✔ no tool's caller text becomes another path or another user: `..` and `?sudo=` are refused before the forge (5.241961ms)
✔ every page of a pull request's files is read, though the forge caps a page at fifty (36.83717ms)
✔ a pass asks only the repositories that moved since the last look, every one before the first (0.460711ms)
✔ the directories above a merge's files that hold a module at the commit are said, the root never (17.773439ms)
✔ a lookup the forge refuses is thrown, not read as no module (6.720425ms)
✔ a renamed file is said under its old name too, as gone (novox/hq ADR 0267) (10.099022ms)
✔ a new head beyond the newest 20 open pull requests is announced, exactly once (102.498733ms)
✔ a pass pages until it reaches back past its floor, and no further (35.071037ms)
✔ the statuses asked for replace the rule's, and an empty list requires none (10.778473ms)
✔ a new rule refuses direct pushes unless asked; an administrator's override only when said (0.475791ms)
✔ each open pull request's new head is announced once, and nothing closed or merged (23.14994ms)
✔ a verdict is the head commit's status; an error is the forge's error, never a success (1.234443ms)
✔ each layer is its own status: the gate with the modules it judged, the repository's own check beside it (1.005822ms)
✔ no verdict sets warning on a required check; only a person's decision fails (6.672104ms)
✔ a commit status is set on the commit, under the merge check's context (80.280385ms)
✔ a change plan is the gate's result: said on the status and, when it builds something, as a comment (0.772402ms)
✔ a head announced is pending in the build queue, since the local time it was announced (0.373011ms)
✔ the vault's token is used, a setting of it is ignored and said once, without its value (2.716266ms)
✔ a consumer that asks nothing, or write, publishes: the package team (1.600113ms)
✔ a consumer that asks to read joins the readers, who write no package (0.501871ms)
✔ a reader is made, put on the readers team, and taken off the package team (0.535021ms)
✔ a publisher is made and put on the package team, as before (0.20773ms)
✔ first start: mints with the admin account, keeps the token at 0600, asks for the tools' scopes only (33.058122ms)
✔ second start: reuses the kept token, mints nothing (29.046173ms)
✔ the forge rejects the kept token (its data was restored): minted afresh, once, and the call goes through (19.332662ms)
✔ a token kept with write:admin by an earlier build is minted again without it at the next start, and the forge drops the old one (23.812562ms)
✔ a kept token lacking a scope the tools need: the forge refuses the call for the scope, the token is re-minted with the whole list, and the call goes through (18.817211ms)
✔ the kept file is gone but the forge still holds a token by that name: replaced, not refused (34.585485ms)
✔ concurrent first calls share one mint (9.383541ms)
✔ the admin account is refused: said plainly, nothing kept, and the next call fails the same way rather than crashing (14.489161ms)
✔ one process shares one source per kept file — the watcher and the tools never renew against each other (1.352083ms)
✔ a second process finds the token the first renewed, and reuses it instead of minting over it (28.072301ms)
✔ a configured token wins, and is reported rather than minted over when the forge rejects it (2.680286ms)
✔ nothing to mint with and no token: the client says what is missing (0.16072ms)
[gitea] no tools — no Gitea token, and nothing to mint one with — set MESH_GITEA_TOKEN, or MESH_GITEA_ADMIN_USER, MESH_GITEA_ADMIN_PASSWORD_FILE, MESH_GITEA_STATE_DIR
[gitea] no token kept — minting one
[gitea] the forge already holds a token named "mesh-tools" — replacing it
[gitea] minted a token for "mesh-admin" (write:repository, write:issue, read:user), kept at /tmp/gitea-CxF9wB/state/token
✔ the tools register once there is a way to a token, and the first call mints it (8.454609ms)
[gitea] no token kept — minting one
[gitea] the forge already holds a token named "mesh-tools" — replacing it
[gitea] minted a token for "mesh-admin" (write:repository, write:issue, read:user), kept at /tmp/gitea-nWSefh/state/token
✔ a pull request can be closed, read and cleaned up through the tools (24.806264ms)
[gitea] novox/mesh-host's main moved from a2c2c35bbbbb to d28ca95ccccc: 25 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323)
[gitea] novox/mesh-host's main moved from d28ca95ccccc to ffffffffffff: 0 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323)
[gitea] novox/mesh-host: whether a trunk moved could not be weighed, so it is weighed again on the next pass — the forge is away
[gitea] novox/mesh-host's main moved from a2c2c35bbbbb to d28ca95ccccc: 0 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323)
[gitea] novox/mesh-controller's feat/57-config-and-provisioning moved from eeeeeeeeeeee to d28ca95ccccc: 1 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323)
✔ both statuses say the head and the trunk commit the verdict judged, first, whatever the summary's length (2.146184ms)
✔ a trunk's move puts an open head's merge check out of date, naming both commits, unless a check is on its way (1.282923ms)
✔ a push to a trunk puts every open pull request into it out of date — twenty-five of them — and none into another (6.642895ms)
✔ a trunk that cannot be read is weighed again on the next pass, never recorded half (0.453931ms)
✔ the trunk's move takes its turn after a verdict in flight, and weighs what the forge holds then (1.530323ms)
✔ a verdict judged against a trunk newer than the pass's first read is not put out of date (0.394851ms)
✔ a verdict that landed out of date keeps its account on the pull request (0.330111ms)
✔ a release branch's move puts every open pull request into it out of date, as a trunk's does (ADR 0358 §5) (0.487901ms)
✔ a signed event is published on the bus and acted on once (65.334882ms)
✔ an unsigned event, or one whose signature does not verify, is refused and published nowhere (36.333319ms)
✔ an event and the poll seeing the same head announce it once (0.575212ms)
✔ each forge event is named in the module's stream and trimmed (0.673871ms)
✔ the system webhook is made when none points at the receiver, and corrected when one does (0.532902ms)
✔ the polls look every 30 s until events are heard, every five minutes while they are, and 30 s again on a miss (0.475771ms)
ℹ tests 101
ℹ suites 0
ℹ pass 101
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 834.301538

Out of date when it landed: out of date: judged against trunk 2edef5a00a, the trunk is now 0e7d9e74d22a; judged again on a recheck or when it is merged

**Merge check** at `1d8a244b` Judged: head `1d8a244ba42b` merged into trunk `2edef5a00ae0`; read beside it: mesh-controller `86057f455194`, mesh-controller-main `5d22d7df86c7`, mesh-host `1a2677882380`, mesh-tools `5d70eb3e35a9` - `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: gitea) - `mesh/repo-check`: **PASS** — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript) **Delivery plan** — builds gitea → novox; no bus step - tier 0: gitea - novox: receives gitea - gitea provides npm-package-registry, git: its consumers are sent again after it - gitea keeps data (ADR 0233): what it holds is backed up before it moves Run by the build seat on novox as `build-1792009518584651434` (`builds --log build-1792009518584651434`). ``` --- the gate: gitea gitea: ok, keeps data (valuable), ready: server by http /api/healthz on web expecting 200 every 30s long-running resources without health: 0 files asking for a setting without saying whether it is trusted: 0 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-14T20:20:33Z 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-14T20:20:33Z modules the change moves: - gitea (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 1 module(s) in 1 tier(s): gitea --- its merge-check.sh (go toolchain) ok git.novox.be/novox/mesh-catalog/checks/words 0.003s words: 12 retired words and 70 daemons' lines, none in the 47260 strings of 722 files ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.071s agent-home: no archive and no file written into under the agent's home ok git.novox.be/novox/mesh-catalog/checks/secrets 0.014s secrets: no setting can replace a vault secret in a mergeable file (1 known, nested) ok git.novox.be/novox/mesh-catalog/checks/paths 0.007s paths: no module names another's state on its machine (3 known, listed to go) long-running resources without health: 62, as kept ok git.novox.be/novox/mesh-catalog/checks/deps 0.542s testing modules/gitea ok gitea/cmd/forge 1.558s ok gitea/cmd/npm-registry 1.994s ? gitea/internal/forgehttp [no test files] --- its merge-check-typescript.sh (typescript toolchain) type-checking modules/gitea (TypeScript) testing modules/gitea (TypeScript) ✔ a pull request opened after the margin is looked at, by its own update time (48.910477ms) ✔ every open pull request is read with what its base requires and what its head has (gitea_open_pulls) (111.823933ms) ✔ a pull request or issue number that is not one is refused before the forge is asked (3.010587ms) ✔ a merged pull request whose branch was deleted is announced with its branch, not its pull ref (16.906507ms) ✔ a pull request's ready mark is read: the label and the head the newest listed ready comment names (25.099435ms) ✔ a ready comment by an account not listed is ignored, and said (0.481611ms) ✔ a ready comment older than the latest push, or than the label, never counts (53.591997ms) [gitea] f cannot be read (gone); only mesh-admin may mark a pull request ready [gitea] f names no account that may mark a pull request ready; only mesh-admin may ✔ a long thread hides nothing: every page of the timeline is read (21.073416ms) ✔ the accounts that may mark are the setting's, and only the mesh's own when it cannot be read (1.072823ms) ✔ the newest status of each context is kept, with what it said, when and by whom (32.044159ms) ✔ a commit merges only when every required status is a success; a warning blocks (0.752151ms) ✔ no rule requires nothing; a rule that cannot be read says nothing, never yes (0.352101ms) ✔ a commit is contained in another when the compare finds nothing on it the other lacks (1.117023ms) ✔ a note line is appended once, as the forge's user, in its own repository (31.753849ms) ✔ a note that cannot be written is said, never read as written (1.937275ms) ✔ one view per pull request, found by its marker; only the mesh's statuses (2.074334ms) ✔ a build machine taking the check is said on the head: building on which machine, since the local time (27.094819ms) ✔ the verdict heard while a 'building' write is in flight lands last and stays (10.428573ms) [gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check now pending; not written ✔ the verdict written while a start's read of the forge is in flight stays the newest status (1.413963ms) ✔ the verdict heard while a 'building' write still waits its turn: the 'building' is never written (0.545321ms) ✔ a start heard after the verdict writes nothing (3.775378ms) ✔ a start from before the check now pending (a run before a recheck, the stream's history) writes nothing (0.587372ms) ✔ an old run's verdict redelivered after a recheck's pending is not written over it (0.964752ms) [gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check the forge holds pending; not written [gitea] novox/hq@a6b08de8: the verdict of build-1791680941000000000 is an older run's than the check now pending; not written ✔ an old run's verdict in flight when the recheck comes lands before the recheck's pending (4.286129ms) ✔ a rechecked head says where its new run is: building on which machine (0.925452ms) ✔ the recheck's own verdict is written, even asked a little before the pending by another machine's clock (0.753282ms) ✔ after a restart, an old run's verdict is weighed against the check the forge's history holds open (1.387893ms) ✔ a recheck the forge does not take fails its caller, and the head is as it was (0.572351ms) ✔ the status tool writes the merge check's pending through the writer, and the mesh's other statuses as they were (5.864733ms) ✔ when a check was asked is read from its id; the opening of the check now pending from the gate's history (0.295491ms) ✔ a head this process did not announce (it restarted) is said only while the forge holds its gate pending (0.400271ms) ✔ a repository as the mesh clones it is told from another (0.28064ms) ✔ gitea_api refuses the forge's administration, a branch's protection and the merge check's status, and sends nothing (15.892564ms) ✔ gitea_api refuses a file written to the default branch or one a rule guards, and writes one on a branch of its own (84.964785ms) ✔ a protection rule covers a branch as the forge decides it: classes, alternatives, a plain name in any case (issue 539) (50.05673ms) ✔ gitea_api still writes what an author writes (10.341242ms) ✔ gitea_branch_protection_set only strengthens (19.680893ms) ✔ gitea_merge_pull_request merges only a head whose required statuses all succeeded, and only that head (56.911904ms) ✔ gitea_merge_pull_request refuses a verdict judged against an earlier trunk, and asks the check once (168.125076ms) ✔ gitea_merge_pull_request merges only the head it is named, and refuses one that is not the head (17.135477ms) ✔ gitea_merge_pull_request is loud when the forge merged a head other than the one it was handed (14.704552ms) ✔ gitea_merge_pull_request says the merge happened when reading back what landed fails (26.115877ms) ✔ gitea_merge_pull_request reads back a fast-forward, and says it cannot read back a squash or a rebase (68.80797ms) ✔ gitea_delete_repo deletes only the tools' own user's repository, unguarded, untouched for 30 days, named in full (22.87687ms) ✔ gitea_api sends the path it judged, and refuses moving a pull request's base (4.362399ms) ✔ gitea_merge_pull_request merges only into a branch whose protection requires the checks (7.946258ms) ✔ a rule named for a branch is not made weaker than the glob rule that guards it now (13.347169ms) ✔ a repository owner or name is never another path (0.241141ms) ✔ the judges, without a forge (0.327691ms) ✔ gitea_api never acts as another user: sudo, in any case, and any query key it does not send are refused (2.531765ms) ✔ gitea_api never approves a pull request nor requests changes: those are the operator's (1.168833ms) ✔ no tool's caller text becomes another path or another user: `..` and `?sudo=` are refused before the forge (5.241961ms) ✔ every page of a pull request's files is read, though the forge caps a page at fifty (36.83717ms) ✔ a pass asks only the repositories that moved since the last look, every one before the first (0.460711ms) ✔ the directories above a merge's files that hold a module at the commit are said, the root never (17.773439ms) ✔ a lookup the forge refuses is thrown, not read as no module (6.720425ms) ✔ a renamed file is said under its old name too, as gone (novox/hq ADR 0267) (10.099022ms) ✔ a new head beyond the newest 20 open pull requests is announced, exactly once (102.498733ms) ✔ a pass pages until it reaches back past its floor, and no further (35.071037ms) ✔ the statuses asked for replace the rule's, and an empty list requires none (10.778473ms) ✔ a new rule refuses direct pushes unless asked; an administrator's override only when said (0.475791ms) ✔ each open pull request's new head is announced once, and nothing closed or merged (23.14994ms) ✔ a verdict is the head commit's status; an error is the forge's error, never a success (1.234443ms) ✔ each layer is its own status: the gate with the modules it judged, the repository's own check beside it (1.005822ms) ✔ no verdict sets warning on a required check; only a person's decision fails (6.672104ms) ✔ a commit status is set on the commit, under the merge check's context (80.280385ms) ✔ a change plan is the gate's result: said on the status and, when it builds something, as a comment (0.772402ms) ✔ a head announced is pending in the build queue, since the local time it was announced (0.373011ms) ✔ the vault's token is used, a setting of it is ignored and said once, without its value (2.716266ms) ✔ a consumer that asks nothing, or write, publishes: the package team (1.600113ms) ✔ a consumer that asks to read joins the readers, who write no package (0.501871ms) ✔ a reader is made, put on the readers team, and taken off the package team (0.535021ms) ✔ a publisher is made and put on the package team, as before (0.20773ms) ✔ first start: mints with the admin account, keeps the token at 0600, asks for the tools' scopes only (33.058122ms) ✔ second start: reuses the kept token, mints nothing (29.046173ms) ✔ the forge rejects the kept token (its data was restored): minted afresh, once, and the call goes through (19.332662ms) ✔ a token kept with write:admin by an earlier build is minted again without it at the next start, and the forge drops the old one (23.812562ms) ✔ a kept token lacking a scope the tools need: the forge refuses the call for the scope, the token is re-minted with the whole list, and the call goes through (18.817211ms) ✔ the kept file is gone but the forge still holds a token by that name: replaced, not refused (34.585485ms) ✔ concurrent first calls share one mint (9.383541ms) ✔ the admin account is refused: said plainly, nothing kept, and the next call fails the same way rather than crashing (14.489161ms) ✔ one process shares one source per kept file — the watcher and the tools never renew against each other (1.352083ms) ✔ a second process finds the token the first renewed, and reuses it instead of minting over it (28.072301ms) ✔ a configured token wins, and is reported rather than minted over when the forge rejects it (2.680286ms) ✔ nothing to mint with and no token: the client says what is missing (0.16072ms) [gitea] no tools — no Gitea token, and nothing to mint one with — set MESH_GITEA_TOKEN, or MESH_GITEA_ADMIN_USER, MESH_GITEA_ADMIN_PASSWORD_FILE, MESH_GITEA_STATE_DIR [gitea] no token kept — minting one [gitea] the forge already holds a token named "mesh-tools" — replacing it [gitea] minted a token for "mesh-admin" (write:repository, write:issue, read:user), kept at /tmp/gitea-CxF9wB/state/token ✔ the tools register once there is a way to a token, and the first call mints it (8.454609ms) [gitea] no token kept — minting one [gitea] the forge already holds a token named "mesh-tools" — replacing it [gitea] minted a token for "mesh-admin" (write:repository, write:issue, read:user), kept at /tmp/gitea-nWSefh/state/token ✔ a pull request can be closed, read and cleaned up through the tools (24.806264ms) [gitea] novox/mesh-host's main moved from a2c2c35bbbbb to d28ca95ccccc: 25 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323) [gitea] novox/mesh-host's main moved from d28ca95ccccc to ffffffffffff: 0 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323) [gitea] novox/mesh-host: whether a trunk moved could not be weighed, so it is weighed again on the next pass — the forge is away [gitea] novox/mesh-host's main moved from a2c2c35bbbbb to d28ca95ccccc: 0 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323) [gitea] novox/mesh-controller's feat/57-config-and-provisioning moved from eeeeeeeeeeee to d28ca95ccccc: 1 open pull request(s) into it put out of date, nothing run (novox/hq ADR 0323) ✔ both statuses say the head and the trunk commit the verdict judged, first, whatever the summary's length (2.146184ms) ✔ a trunk's move puts an open head's merge check out of date, naming both commits, unless a check is on its way (1.282923ms) ✔ a push to a trunk puts every open pull request into it out of date — twenty-five of them — and none into another (6.642895ms) ✔ a trunk that cannot be read is weighed again on the next pass, never recorded half (0.453931ms) ✔ the trunk's move takes its turn after a verdict in flight, and weighs what the forge holds then (1.530323ms) ✔ a verdict judged against a trunk newer than the pass's first read is not put out of date (0.394851ms) ✔ a verdict that landed out of date keeps its account on the pull request (0.330111ms) ✔ a release branch's move puts every open pull request into it out of date, as a trunk's does (ADR 0358 §5) (0.487901ms) ✔ a signed event is published on the bus and acted on once (65.334882ms) ✔ an unsigned event, or one whose signature does not verify, is refused and published nowhere (36.333319ms) ✔ an event and the poll seeing the same head announce it once (0.575212ms) ✔ each forge event is named in the module's stream and trimmed (0.673871ms) ✔ the system webhook is made when none points at the receiver, and corrected when one does (0.532902ms) ✔ the polls look every 30 s until events are heard, every five minutes while they are, and 30 s again on a miss (0.475771ms) ℹ tests 101 ℹ suites 0 ℹ pass 101 ℹ fail 0 ℹ cancelled 0 ℹ skipped 0 ℹ todo 0 ℹ duration_ms 834.301538 ``` **Out of date when it landed**: out of date: judged against trunk 2edef5a00ae0, the trunk is now 0e7d9e74d22a; judged again on a recheck or when it is merged
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-catalog#304