b091e67, the first commit of
#42. Where: a
throwaway compose stack on the build host, operated from the publisher’s
laptop over SSH exactly as the live host is — $CHANNEL_REGISTRY_SSH pointed at
the build host, $CHANNEL_ROOT at the throwaway directory, $CHANNEL_EDGE_URL
at an SSH tunnel to the throwaway’s Caddy. Issues:
vexa-delivery-internal#46
(private; the standalone-host rewrite this ports) and
vexa-delivery-internal#35
(private; the EDGE_READER_BASIC manual step).
Why a throwaway. Until this change the tool wrote the in-cluster path —
finding 1 of the
edge deploy receipt — and
the founder’s instruction was explicit: verify against a throwaway, do not
touch the live channel host. Every proof below is therefore about the tool’s
behaviour against a stack of the live host’s shape, not about the live host.
1 · The throwaway
Before anything ran:
/healthz 200, anonymous /v2/ 401, the seeded pilot
credential 200, and all three hashes 60 characters long inside the Caddy
container — the escaping was right before the tool touched it.
2 · The proofs
Every credential the tool printed was captured to a file, used from there, and deleted; none appears here or in any log. Status codes are what curl saw through the tunnel.
Each
add printed exactly one credential-shaped line to stdout and reported
live auth verified on stderr after the recreate and the proof, never
before.
3 · The control: docker restart does not re-read env_file
The instruction that came with this task was to remember it. It was measured:
EDGE_READER_BASICinenvedited to a bogus value, thendocker restarton the Caddy container → the value inside the container was the original. On the wire the anonymous signature read still answered 404.docker compose up -d --force-recreate→ the value inside the container was the edited one, and the anonymous signature read answered 401 — which is what a stale edge credential looks like from outside, and what RUNBOOK § 5.3 promises: loud, not open.envrestored, recreated → 404 again.
4 · The refusals write nothing
The last row is the one that earned a code change during this work. The
first draft read the edge URL only where it is used — after the recreate — so
a missing variable would have rotated the account and then refused, leaving
it with no working credential and nothing printed: the self-inflicted outage
park_preflight already guards against on its own inputs. All three site
coordinates are now demanded up front, and the unit test for it asserts zero
remote commands.
5 · --park on top of the host path
add rehearsal-park --park, with a throwaway edge key, a local spool and a
scratch ledger: two lines on stdout — the credential, then a six-digit code;
the parked credential answered 200 on /v2/; the park’s ciphertext,
opened with the throwaway edge key, equals the printed credential; the
ledger row records event: park for the account and does not contain the
password. The four park functions are byte-identical to main; this proves
the two halves compose, not the park itself — that was proven on the live
edge on 2026-09-06.
6 · What this does not prove
- Nothing here touched the live channel host. The live
htpasswd,envand stack are as they were; the first liveaddwith this tool is the next rung, and the tool refuses before writing if the liveenvdoes not carry the keys it expects. - The anonymous signature-read probe used a manifest that does not exist: 404 against 401 discriminates whether the edge’s upstream credential was accepted, which is the question; it does not exercise a real signature.
- One run before this one refused at the health proof because the SSH tunnel
from the laptop had dropped between the recreate and the probe. The tool
behaved as designed — rotated, could not prove, printed nothing — and the
observation is worth carrying: the operator’s own path to the edge is part
of the proof. A proof that fails after the recreate means the account is
rotated with nothing printed; run
addagain once the edge answers.