Merge pull request 'Issues 079 and 080, found by running the large mesh bed; 074's addendum' (#71) from multiple-fixes into main
This commit was merged in pull request #71.
This commit is contained in:
@@ -47,3 +47,14 @@ its long idleness had hidden: the consumer fixture's login exceeded a backend's
|
||||
upstream artifact by bare image ID, which a registry copy cannot fetch since ADR 0096 — retired,
|
||||
since genesis installs the catalogue's builder and proves the same. The large test as a whole has
|
||||
not been run end to end; its renamed tests and the tests around them have.
|
||||
|
||||
*2026-09-22.* The large mesh test was run end to end, for the first time in weeks: 12 of 25 passed.
|
||||
Everything that failed was the bed lagging the mesh, and one defect of the mesh's own. The bed now
|
||||
derives the anchor's filter after placing it on the overlay (ADR 0088), declares the ports its
|
||||
fixtures listen on, waits for an image pulled at apply, starts the hand-started host and builder
|
||||
once on a warm return, and reads the resolver modules from the catalogue instead of the example
|
||||
modules that moved there. Three more tests were retired for the catalogue beds that prove them
|
||||
(the modules resolving together and the forge, whole-mesh-novox; the cache grant, the grant bed)
|
||||
and one for what every later test proves (the hub filtered without severing the mesh). The
|
||||
defect: every machine named twice over in the files the mesh writes
|
||||
([issue 079](../079-every-machine-is-named-twice-over/00-report.md)).
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
status: resolved
|
||||
opened: 2026-09-22
|
||||
located-in: [mesh-controller internal/catalogue (facts)]
|
||||
fixed-by: mesh-controller multiple-fixes (the facts take a name as the control plane keys it, internal or bare, and write each machine once); a unit test holds both keyings to the same files
|
||||
---
|
||||
|
||||
# 079 — Every machine is named twice over in the hosts file and the resolver's zones
|
||||
|
||||
## Symptom
|
||||
|
||||
The hosts file the mesh writes on every machine, and the zones file it hands a resolver, name each
|
||||
machine as `<machine>.internal.internal`, with the intended name `<machine>.internal` in the
|
||||
hosts file's second column. Names still resolve on the machine itself, because the second column
|
||||
matches, so nothing noticed. A resolver serving the zones answers for `*.<machine>.internal.internal`
|
||||
and for nothing under `<machine>.internal`, so a service named under a machine does not resolve
|
||||
from anywhere.
|
||||
|
||||
Found by running the large mesh bed end to end for the first time since the mesh's knowledge became
|
||||
a fact a module asks for: its name test read the zones back. No smaller bed reads them.
|
||||
|
||||
## Why it matters beyond the instance
|
||||
|
||||
Two functions agreed on a contract nobody wrote down: the caller keyed the map by the internal name,
|
||||
the facts appended the suffix to a bare one. Each was tested alone, with its own keying, and both
|
||||
passed. A file the mesh writes and nothing reads back in a test is a file that can be wrong for
|
||||
as long as it takes someone to look.
|
||||
|
||||
## What would close it
|
||||
|
||||
The facts take either keying and write each machine once, held by a test that feeds both. And a bed
|
||||
reads the files back — the large mesh bed does now.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Diagnosis — 2026-09-22
|
||||
|
||||
1. The control plane collects every placed machine's name and address for a resolution keyed by
|
||||
the internal name (`homer.internal`), because that is the map every container is given as its
|
||||
hosts. The facts that render the hosts file and the resolver's zones took the same map as bare
|
||||
names and appended `.internal` to each — their unit tests fed them bare names and passed.
|
||||
2. Fixed in the facts: a name is read as either form, and each machine is written once as
|
||||
`<machine>.internal` with its bare name beside it. A test feeds both keyings and holds the files
|
||||
equal, and holds the zones free of a doubled suffix.
|
||||
|
||||
**Located in:** the facts. Not a decision. Proven by the unit test and by the large mesh bed's name
|
||||
tests, once its controller image is rebuilt from the fix.
|
||||
|
||||
*On review.* The first fix wrote the suffix a second time, in the facts, which is the shape that
|
||||
produced the defect: two places composing one name. The control plane now hands the suffix it
|
||||
composed the names with down to the facts, so an operator who chose another gets that one and
|
||||
nothing appended. What remains unproven by a bed is a mesh with a suffix other than the default.
|
||||
|
||||
*Later.* With the suffix right, the large bed's name test asked the second half of its question:
|
||||
a machine that leaves the private network must not be answered for. The names were every placed
|
||||
machine with an address, while the resolver's "on the private network" is a machine that also
|
||||
runs the module that puts it there. The names follow the resolver's rule now — one predicate,
|
||||
used by both — held by a controller test that unassigns one machine's networking and reads the
|
||||
names back.
|
||||
|
||||
Two consequences of the one predicate, on review. The filter's "from the mesh" set is that same
|
||||
set now, so a rule admits exactly the machines the mesh names. And a machine whose assigned set
|
||||
fails to resolve is no longer on the network in the mesh's eyes: its name leaves every other
|
||||
machine's hosts file and every resolver's zones on the next push, and the mesh's report of that
|
||||
machine's failure is what says why — the stated preference for a name that fails at once over a
|
||||
connection that hangs, at the cost of one machine's failure being visible mesh-wide.
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
status: resolved
|
||||
opened: 2026-09-22
|
||||
located-in: [mesh-catalog modules/redis (the provisioner's ACL)]
|
||||
fixed-by: mesh-catalog multiple-fixes (the consumer's ACL user loses the dangerous command category); proven by the grant end-to-end bed, which now asserts a write outside the consumer's keys and FLUSHALL are refused
|
||||
---
|
||||
|
||||
# 080 — A cache grant lets the consumer flush the server
|
||||
|
||||
## Symptom
|
||||
|
||||
The cache provider's provisioner creates each consumer an ACL user confined to keys under its own
|
||||
login and allowed every command. A key pattern confines only commands that name keys. `FLUSHALL`,
|
||||
`FLUSHDB`, `CONFIG`, `SHUTDOWN` and the rest of the dangerous category name none, so a consumer
|
||||
granted "its own keys" could wipe every other consumer's, or stop the server.
|
||||
|
||||
Found by carrying the large mesh bed's retired tenancy assertions into the grant end-to-end bed:
|
||||
`FLUSHALL` as the consumer answered `OK`.
|
||||
|
||||
## Why it matters beyond the instance
|
||||
|
||||
A grant is the mesh's promise that a consumer gets what it asked for and nothing else. The
|
||||
promise was checked on the key pattern and never on the command set, and the one bed that had
|
||||
asked was retired before it was run against the catalogue's module.
|
||||
|
||||
## What would close it
|
||||
|
||||
The ACL user is allowed the ordinary command set minus the dangerous category, and the grant bed
|
||||
asserts a write outside the consumer's keys and a `FLUSHALL` are both refused.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Diagnosis — 2026-09-22
|
||||
|
||||
1. The provisioner's `ACL SETUSER` gave `~<login>:*` and `+@all`. Redis applies a key pattern to
|
||||
commands that take keys; a command taking none is governed by the command categories alone,
|
||||
and `@all` includes `@dangerous`.
|
||||
2. Fixed with `-@dangerous` after `+@all`. `KEYS` goes with the category; `SCAN` stays, and is
|
||||
what a consumer scoped to a prefix should use.
|
||||
|
||||
**Located in:** the redis module's client. Not a decision. Proven by the grant end-to-end bed.
|
||||
|
||||
*On review.* `INFO` is in the dangerous category and several client libraries ask it at connect;
|
||||
it reads nothing a consumer keeps, so it is allowed back. Whether the catalogue's two cache
|
||||
consumers need anything else the category removes is unverified — and moot until they present the
|
||||
login they were granted ([issue 081](../081-a-cache-consumer-does-not-use-the-login-it-was-granted/00-report.md)).
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
status: open
|
||||
opened: 2026-09-22
|
||||
located-in: [mesh-catalog modules/n8n, mesh-catalog modules/baserow]
|
||||
---
|
||||
|
||||
# 081 — A cache consumer does not use the login it was granted
|
||||
|
||||
## Symptom
|
||||
|
||||
Two catalogue modules require the cache and are given a login and a password under a keyspace of
|
||||
their own ([issue 080](../080-a-cache-grant-lets-the-consumer-flush-the-server/00-report.md)),
|
||||
and neither tells its software the login: each hands it the host, the port and the password only,
|
||||
so the software authenticates as the server's default user and writes wherever it likes — or is
|
||||
refused, if the default user is closed. The grant is honoured by the provider and ignored by the
|
||||
consumer.
|
||||
|
||||
Found on review of issue 080, by reading the two manifests. Not run: no bed installs either
|
||||
module against the catalogue's cache and reads what it wrote.
|
||||
|
||||
## Why it matters beyond the instance
|
||||
|
||||
A grant is two ends agreeing. The provider's end is checked by the grant bed; the consumer's end,
|
||||
that the software actually presents what it was given, is checked by nothing but the module
|
||||
working — and a module that works as the default user works.
|
||||
|
||||
## What would close it
|
||||
|
||||
Each module passes the login it was bound (`${bound:redis-cache:as}`) to its software's username
|
||||
setting, and a bed installs one of them against the catalogue's cache and reads back that its keys
|
||||
sit under its login.
|
||||
Reference in New Issue
Block a user