Issues 225, 226, 227 resolved with their live proofs; 232 opened and resolved

225: a grant secret is composed with the account that reads it — the node's
account for a bundle, the declared secrets-owner for a container. Zero EACCES
since 12:30:10 where there had been 4330, both users created, mongodb logging
Authentication succeeded for each. The harness also stops calling a permanent
refusal a race, which is the half that cost three hours.

226: normalising moved to the records, where the provenance is known, and a
reference the sweep will not address is skipped rather than ending the sweep.
The first build after the roll-out collected 200 and said 1126 remain — the
backlog falls with every build instead of standing at 1681 for ever.

227: the three photo modules publish the endpoint they declare, and a
catalogue-wide test makes it a rule: a container publishes only a port its
module declares, or the mesh has nothing to assign and the number escapes.

232 came out from under 225: photos asked for a database its user does not
live in, invisible while no user existed at all.
This commit is contained in:
2026-10-04 12:37:31 +02:00
parent 3f3fb99219
commit ab1bd5598e
3 changed files with 62 additions and 6 deletions
@@ -1,8 +1,8 @@
---
status: open
status: resolved
opened: 2026-10-04
located-in: [mesh-host internal/apply, mesh-controller internal/catalogue]
fixed-by:
fixed-by: mesh-controller#263
amended-design:
---
@@ -73,3 +73,25 @@ their containers and made a silent fault visible as a restarting one. The dates
is right once and wrong four thousand times is a message that hides its own meaning.
- Which other modules' files did the runtime move leave behind? The sweep is the same question
for every path the mesh writes for a module: directories, bundles, received files.
## Resolved, 2026-10-04
A grant secret is composed with the account that will read it: the node's account where the
module's code is a bundle the runtime runs, its declared `secrets-owner` where it is still a
container, root where it says neither. The same rule the module's own secrets already followed,
reaching the other kind of secret the mesh writes for a module (mesh-controller#263).
`givenTo` could not have reached these: it claims the files a bundle's *words* name, and the
harness composes a grant secret's path from the contributions file, which no word names.
And the harness stops calling a permanent refusal a race (mesh-sdk#22, 0.1.9). After about a
minute it says so plainly, rarely rather than every five seconds, and names what to look at —
who owns the file and who the process runs as. That is the half that cost three hours.
**How it was checked:** on the control machine, after the push — the grant secrets belong to the
operator's account, **zero `EACCES` since 12:30:10** where there had been 4330, both users were
created, and `mongodb-server` logs `Authentication succeeded` for each.
It also uncovered [issue 232](../232-a-consumer-authenticates-against-a-database-its-user-does-not-live-in/00-report.md),
which this fault had been hiding: with no user anywhere, "not found in admin" was a complete
account of *this* issue and said nothing about the consumer asking the wrong database.
@@ -1,8 +1,8 @@
---
status: open
status: resolved
opened: 2026-10-04
located-in: [mesh-controller cmd/mesh-controller/collect.go, mesh-controller internal/inventory/collection.go]
fixed-by:
fixed-by: mesh-controller#263
amended-design:
---
@@ -56,3 +56,21 @@ reports the right number while doing it, which is what made it look healthy.
- Only a refusal *by the store* ends a sweep.
- **How it is checked:** a sweep over records holding one address-recorded reference and one kept
one collects the second; a sweep against a store that refuses stops at the first.
## Resolved, 2026-10-04
Two changes, deliberately separate.
**Normalising moved to where the provenance is known.** Every reference the sweep handles came
from a build record, so every one is the mesh's own and `Recorded` may read an address-era
reference as the kept one. Not in `LetGo` — it cannot tell `docker.io` from the mesh's store, and
an attempt to put it there was caught at once by the test that says a foreign reference is never
asked about. The guard stays strict; the records speak the one vocabulary.
**A reference the sweep will not address is `ErrNotOurs`:** skipped, not marked collected, never
a reason to stop. Only the store refusing ends a sweep.
**How it was checked:** the first build after the roll-out printed *"the artifact store let go of
200 artifact(s) the mesh no longer keeps — 1126 more to collect; the next build asks again"*.
Two hundred is the per-sweep bound working as intended; the backlog is falling with every build
instead of standing at 1681 for ever.
@@ -1,8 +1,8 @@
---
status: open
status: resolved
opened: 2026-10-04
located-in: [mesh-catalog modules/photos]
fixed-by:
fixed-by: mesh-catalog#263, mesh-controller#263
amended-design:
---
@@ -42,3 +42,19 @@ gradually.
is composed, rather than failing on the machine every pass. The mesh assigns ports
([ADR 0038](../../02-DECISIONS/0038-the-mesh-assigns-the-port.md)); a fixed 80 beside a proxy is
a statement it could check.
## Resolved, 2026-10-04
The three photo modules publish the endpoint they declare — `4001:80`, `4012:80`, `4013:80` —
so the software's own port reaches the machine at the port the mesh assigned, and nothing asks
for 80.
**The rule, rather than three repairs.** A container may publish only a port its module declares:
the short form `"80"` means *publish what the software calls 80*, and the mesh fills in the
machine's half from the port it assigned — which it can only do for a port the module declared.
Four modules publish 80 quite safely because they declare 80. The difference is the declaration,
not the number. A catalogue-wide test in mesh-controller#263 says so, and names all three
offenders against the catalogue as it was.
**How it was checked:** `photos-admin-client` has been up since the push, where before it failed
on every pass.