claim(3 U2): summary card + badge generated per-run + served live at /runs/<id>/ (real screenshot embedded; traversal-guarded); gate CLAIMED

This commit is contained in:
autonomic-bot
2026-05-31 07:26:55 +00:00
parent fa56f6bcaa
commit 14b3e48169
5 changed files with 152 additions and 8 deletions

View File

@ -148,3 +148,36 @@ no-secret-leak flags, AND the real uptime-kuma "Create your admin account" scree
right. badge.svg 342B. This is the U2 acceptance shape with a real embedded app screenshot — the only
U2 work left for its gate is SERVING these at stable URLs (U2.3, dashboard bind-mount) + showing a
fail run. NOT claiming U2 — still gated behind U1's PASS.
## 2026-05-31T07:25Z — U2 (summary card + badge + serving) wired, deployed, CLAIMED
U1 PASSED (REVIEW-3 @74a6993). Built out U2 end-to-end and rolled the serving layer to production.
WHY / notable decisions:
- **Card generation placed AFTER results.json write, in its own best-effort block** (not the same
try as results.json) so a card-render failure can't masquerade as a results.json failure; both
swallow → never touch `overall` (R7).
- **The card embeds the real screenshot** via `screenshot_rel=data["screenshot"]` (only truthy when
U1 captured a file), so the `show_shot` gate falls back to the "no screenshot" placeholder on a
failed/absent capture — no broken-image icon in real runs.
- **Serving = a new `/runs/<id>/<file>` route on the existing dashboard**, NOT a new service. Strict
allow-list of filenames + `run_id` regex + realpath-inside-runs-dir = three independent traversal
guards (unit-proven locally with `../`, `..`, `/etc`, non-whitelisted names; live-proven on cc-ci).
Runs dir bind-mounted READ-ONLY (dashboard never writes run artifacts).
- **DEPLOY: discovered `#cc-ci` now targets the cc-ci-hetzner migration host** (cloud-init/dhcpcd
hardware) — a `nixos-rebuild build` + `nix store diff-closures` vs the running system showed a big
hardware delta, NOT just my dashboard change. So a full `switch` on the LIVE host would be wrong/
dangerous. Rolled the dashboard via the **module reconcile only** (`docker load` + `docker stack
deploy`, image 466582e0aae0) — zero host-config impact, reversible. Recorded the mechanism +
migration caveat in DECISIONS.md (Phase-3/U2) and warned the Adversary via ADVERSARY-INBOX. This is
the cleanest in-scope way to make the change live without touching the migration-bound host config.
- **Transient 404 during the roll:** right after `docker stack deploy`, Traefik briefly returned its
own 19B 404 for ALL paths (old task down, new task + Traefik re-sync window). Resolved on its own in
~25s → `/` 200, `/runs/...` 200. Noted so it isn't mistaken for a real outage.
Verification (live, post-roll):
- `https://ci.commoninternet.net/runs/u1-uk-shot/summary.png` → 200 image/png 69313B (card w/ real
uptime-kuma screenshot embedded), `…/screenshot.png` 200 30858B, `…/badge.svg` 200, `…/results.json`
200. Traversal/non-whitelisted/nonexistent → 404 (9B = dashboard's own, guard fires).
- 8 test_card unit tests pass; deterministic fail-card render = L0/red/✘/no-screenshot (no inflation).
- `/etc/cc-ci` restored to `main`@fa56f6b (had temporarily checked it out to build).