b6340519bc
Session captured for a context reset. Six new detail entries. THE OPEN ITEM: Anaheim's IPsec tunnel delivers ~550 Mbit/s aggregate against a circuit measured at 2,153 Mbit/s. Not WireGuard (it is IPsec on ana-gw), not CPU (idle), not crypto exhaustion (NPU-offloaded), not the fibre. Both tunnels negotiate aes256-sha1; AES-GCM proposed. Operator signalled authorization; execution pending, untracked by operator choice. Also recorded: selene retired after losing a head-to-head on its own job with chat-judge moved to gen and the model name left to 404; the 7-alias collision on the gen seat that makes cross-alias corroboration an echo; hrafn adopted and its CI found to have been reporting green while deploying nothing for its whole life; all three Worldtree instances de-armed from a 69-day-stale :latest and the Matrix homeserver re-plumbed to personal; every secret-bearing .env on ana-docker tightened to 0600; the pfi org closing the repo-creation half of the credential-migration directive; booth kept-board deletion and link pruning. Two entries under Tried and abandoned: the CI checkout assertion that broke the pipeline twice and was removed, and my proposal to alias a retired model name at a different model, which the operator correctly overruled. Index 271 -> 282 lines, under the 300 cap, so no archival fired.
64 lines
3.1 KiB
Markdown
64 lines
3.1 KiB
Markdown
# [2026-08-23] hrafn adopted; its CI deploy reported green while deploying nothing
|
|
|
|
`hrafn` — genuine-Chromium browser-fetch behind a REST API, for bot-gated sites
|
|
(Reddit first). Built by nevermore-claude on ana-docker, handed to infra-ops for
|
|
uptime ownership. Internal-only on `traefik-net`, no host port; consumers reach
|
|
`http://hrafn:8080`. Canonical at `stacks/hrafn/`.
|
|
|
|
## Intake found a live credential exposure
|
|
|
|
`/opt/docker/compose/hrafn/.env` was mode **0644 with a live 57-char bearer token**
|
|
— verified as real exposure by reading it as `nobody` on a box with four
|
|
interactive accounts. Tightened to 0600. That triggered the wider sweep (see
|
|
[[2026-08-23-ana-docker-env-perms-sweep]]).
|
|
|
|
## The CI defect — the one worth remembering
|
|
|
|
I authored the deploy (elway playbook + gitea workflow) to replace a hand-rsync,
|
|
tagging the image with the commit SHA for provenance. nevermore-claude later found
|
|
v1.0.0 deploying "green" while the host still served 0.1.0.
|
|
|
|
**Root cause was mine and nastier than either hypothesis.** The staging dir was
|
|
`$compose_dir/.stage` — **inside** the rsync target. So
|
|
`rsync -a --delete $compose_dir/.stage/ $compose_dir/` deleted `.stage` from the
|
|
destination (absent from the source listing) **during** the transfer, destroying
|
|
its own source mid-copy. Reproduced exactly:
|
|
|
|
```
|
|
before: app.py="OLD" leftover.txt .stage/app.py="NEW"
|
|
after: app.py="OLD" leftover.txt GONE, .stage GONE
|
|
```
|
|
|
|
Deletion succeeded, the copy silently did not, rsync exited 0. So the directory
|
|
*looked* converged while host source stayed frozen at the first manual rsync —
|
|
and because the build's `COPY` inputs never changed, Docker full-cache-hit and
|
|
every SHA tag aliased one image. **The provenance the tagging existed to provide
|
|
was false for the pipeline's entire life.**
|
|
|
|
**The real failure is the verification.** The verify steps asserted the marker,
|
|
container health, and a 200 from `/readyz` — all of which pass against a
|
|
completely frozen host. None measured *content*. A deploy that reports success
|
|
without asserting the bytes changed is verifying an **uptime**, not a deploy.
|
|
|
|
## Fixes
|
|
|
|
- stage at `/tmp/hrafn-deploy-stage`, outside the target
|
|
- CI computes `context_sha256` over the shipped file list; the playbook recomputes
|
|
it **on the host after the converge** and fails on mismatch
|
|
- compare the running container's `src/**/*.py` against the host's, so a SHA tag
|
|
cannot name layers the image lacks
|
|
- **compare `*.py` only** — `pip install .` generates `src/*.egg-info/*` inside the
|
|
image and `__pycache__` appears at runtime, so a naive `find src -type f` compare
|
|
false-fails on every healthy deploy. Verified against a known-good container
|
|
before shipping (12 host files, 18 in container, 0 content differences).
|
|
- declined `--no-cache`: a cache hit is *correct* when the context is genuinely
|
|
unchanged; assert the property rather than brute-force it.
|
|
|
|
## Access
|
|
|
|
Operator granted claude-bot **write** on `vh/hrafn`, so infra-ops maintains the
|
|
pipeline it owns instead of routing patches through the repo holder. `vh/hrafn` is
|
|
canonical; `stacks/hrafn/ci/` is a verified mirror.
|
|
|
|
Commits `b6924de`, `b001d0c`, `11b9d18`, `b38c369`, `9642952`.
|