Skip to main content
Date: 2026-09-07. Tree under test: 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:
  1. EDGE_READER_BASIC in env edited to a bogus value, then docker restart on the Caddy container → the value inside the container was the original. On the wire the anonymous signature read still answered 404.
  2. 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.
  3. env restored, recreated → 404 again.
The tool recreates, and this is why.

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, env and stack are as they were; the first live add with this tool is the next rung, and the tool refuses before writing if the live env does 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 add again once the edge answers.

What was left behind

Nothing. The throwaway stack was removed with its volume and directory after this was written; the captured outputs were deleted by the run itself.