claim(3 U5): FINAL gate — per-recipe level badge endpoint LIVE (R6), docs complete (R8), render-kill verdict-unaffected + broad leak scan clean + screenshot call-site hardening (R7); on Adversary U5 PASS → DONE
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
autonomic-bot
2026-05-31 10:14:57 +00:00
parent 799cceb54a
commit 97418c822e
3 changed files with 98 additions and 5 deletions

View File

@ -0,0 +1,25 @@
# ADVERSARY-INBOX (Builder → Adversary)
## 2026-05-31T10:15Z — U5 CLAIMED (Badges + docs + hardening — FINAL gate); artifact map
U5 claimed in STATUS-3 (`claim(3 U5)`); full WHAT/HOW/EXPECTED/WHERE there. Pointers:
- **R6 per-recipe level badge (live):** `https://ci.commoninternet.net/badge/custom-html.svg`
`cc-ci: custom-html | level 4` (msg-box fill `#a0b93f`); `…/badge/uptime-kuma.svg` → level 4;
`…/badge/keycloak.svg` (no runs) → status-fallback `cc-ci | unknown`. Embed snippet: docs §5.
- **R8 docs:** `docs/results-ux.md` §1-5 complete (ladder, schema, card/screenshot, PR comment, badges).
- **R7 render-kill (verdict unaffected):** `/var/lib/cc-ci-runs/u5-renderkill3` — I forced BOTH cosmetic
renderers (card + screenshot) to raise with the real test browser intact → exit 0, install pass,
results.json intact (screenshot=null), NO summary.png/screenshot.png. Method + how to reproduce in
STATUS HOW §3. Also note `u5-renderkill2` (global browser-path break) which fails install — that's a
REAL browser test (`test_serving_and_content`) failing correctly, NOT a cosmetics datapoint.
- **R7 hardening:** `799cceb` adds a defense-in-depth try/except around the screenshot call site
(`run_recipe_ci.py:976`) — previously the call site relied solely on `capture()`'s internal swallow
(U1-verified), now belt-and-suspenders so a screenshot can never crash the run even if that regresses.
- **R7 leak scan (my own pre-claim; you are the authority):** scan of every `/var/lib/cc-ci-runs/*/`
results.json + summary.html + badge.svg, AND all bot comments on custom-html PR#2 → the ONLY `secret`
matches are the `no_secret_leak` field / `✔ no secret leak` label; **zero real secret values**.
- **Heads-up:** dashboard rolled via the module reconcile (`nixos-rebuild build` non-activating +
`cc-ci-reconcile-dashboard`), NOT `switch`; build needs `?submodules=1` (secrets submodule).
On your U5 PASS + REVIEW-3 showing all R1R8 verified <24h with no VETO, I flip STATUS-3 to `## DONE`.

View File

@ -71,9 +71,14 @@ Milestones U0U5 (plan §5); each ends with an Adversary gate. DoD items R1
Built + unit-tested; pending live deploy+verify.
- [x] U5.2 — `docs/results-ux.md` §1-5 complete: level ladder + tier→rung mapping, results.json schema,
card/screenshot generation, PR-comment shape, badge endpoints + README embed snippet (R8).
- [ ] U5.3 — Hardening: render failure degrades to text (R7); secret-scan over published
images/screenshots/comments finds nothing; killing the renderer doesn't affect the verdict.
- GATE U5: Adversary leak-scan clean; graceful degradation proven; flip STATUS-3 to `## DONE`.
- [x] U5.3 — Hardening: render failure degrades to text (comment `artifact_available` HEAD →
text, unit-covered) + cosmetic render-kill proven verdict-unaffected (`u5-renderkill3`: card +
screenshot forced to raise → exit 0, install pass, results.json intact, no card/screenshot) +
new defense-in-depth try/except on the screenshot call site (`799cceb`); broad secret scan over
ALL published text artifacts + PR comments → zero real secret values (only `no_secret_leak`
flag name/label).
- GATE U5: **CLAIMED** (awaiting Adversary) — R6 badge live, R8 docs complete, R7 render-kill +
leak-scan clean. On Adversary U5 PASS + all R1R8 verified <24h, no VETO → flip STATUS-3 `## DONE`.
## Adversary findings
(Adversary owns this section — Builder does not edit.)

View File

@ -280,9 +280,72 @@ The cardinal U4 invariant: the grid + history are a faithful, never-greener proj
`results.json`; a failed/levelless run is shown as such (no inflated level, no screenshot it didn't
produce); rendering is read-only over the RO-bind-mounted artifacts.
## Gate: U5 — CLAIMED, awaiting Adversary (Badges + docs + hardening; R6, R7, R8 — FINAL gate)
**WHAT.** The last milestone: (a) **R6** — a per-recipe **latest-level badge** endpoint
`/badge/<recipe>.svg` (shields-style, coloured by level, embeddable in a recipe README; falls back to
a status badge for a recipe with no level yet); (b) **R8** — `docs/results-ux.md` now fully explains
the level ladder + tier→rung mapping, results.json schema, card/screenshot generation, the PR-comment
shape, and the badge endpoints + README embed snippet; (c) **R7 hardening** — render failure degrades
to text/omission and **never affects the verdict**, proven by a forced render-kill run; a broad secret
scan over every published artifact + all PR comments finds **zero** real secret values; plus a new
defense-in-depth try/except around the screenshot call site so a screenshot can never crash the run.
**WHERE (commits / files).**
- `91a69b8` `dashboard/dashboard.py` — `render_level_badge` + `_badge_svg`; `/badge/<recipe>.svg`
route prefers the latest-run level (from results.json), status fallback. Deployed
`cc-ci-dashboard:8acd8b9cc51c` (== `sha256(dashboard.py)`, confirmed live). `tests/unit/test_dashboard.py`
(+2 badge tests → 11 total).
- `91a69b8` `docs/results-ux.md` §1-5 complete (R8).
- `799cceb` `runner/run_recipe_ci.py` — defense-in-depth try/except around `screenshot_mod.capture`
call site (R7); a screenshot raise is now caught + logged non-fatal, verdict unaffected.
**HOW to verify (cold, from your clone / the VM).**
1. **R6 per-recipe level badge (live):**
`curl -s https://ci.commoninternet.net/badge/custom-html.svg` → SVG `cc-ci: custom-html | level 4`,
message-box `fill="#a0b93f"` (= `level_color(4)`); `…/badge/uptime-kuma.svg` → `level 4`;
`…/badge/keycloak.svg` (no runs) → 200, status-fallback `cc-ci | unknown`. README embed snippet in
`docs/results-ux.md` §5.
2. **R8 docs:** read `docs/results-ux.md` — §1 ladder + tier→rung mapping, §2 schema, §3 card+screenshot
+ stable URLs, §4 PR comment, §5 badges + embed snippet. No remaining TODOs.
3. **R7 render-kill degradation (verdict unaffected) — reproduce:** drive `run_recipe_ci.main()` with
the orchestrator-side cosmetic renderers forced to raise but the real (subprocess) test browser
intact — monkeypatch `run_recipe_ci.card_mod.render_card_html`/`render_card_png` and
`run_recipe_ci.screenshot_mod.capture` to raise, `RECIPE=custom-html STAGES=install`. Result
(`/var/lib/cc-ci-runs/u5-renderkill3` from my run): **EXIT 0**, install **pass** (test_serving +
test_serving_and_content PASSED — real browser unaffected), `results.json` written
(`level=1, install=pass, screenshot=null`), and **NO summary.png / NO screenshot.png** — both
cosmetic failures swallowed (`screenshot capture raised (non-fatal…)` + `summary card/badge render
failed (non-fatal)`). A renderer kill cannot change the verdict or block the run.
(Note: globally breaking the *browser path* instead — `/var/lib/cc-ci-runs/u5-renderkill2` — fails
the install tier, because custom-html's `test_serving_and_content` is a REAL browser test; that is a
real test failing correctly, NOT a cosmetics-vs-verdict datapoint. The clean isolation above breaks
ONLY the cosmetic renderers.)
4. **R7 broad leak scan:** over every published text artifact —
`for f in $(find /var/lib/cc-ci-runs -maxdepth 2 \( -name results.json -o -name summary.html -o -name badge.svg \)); do grep -EaoH 'password|passwd|secret|token|api_key|privkey|BEGIN [A-Z ]*PRIVATE KEY|AKIA[0-9A-Z]{16}|[0-9a-f]{40}' "$f"; done`
→ the ONLY matches are the `no_secret_leak` JSON field + the `✔ no secret leak` card label (a
flag name, not a value); **zero real secret values**. Same scan over all bot comments on
custom-html PR#2 → **0**. The embedded screenshots are the U1/U4-verified secret-safe setup/landing
pages (empty credential fields). (You are the R7 leak authority — this is my own pre-claim scan.)
5. **R7 comment text-fallback** (render fail → text, not a broken image): unit-covered
(`tests/unit/test_bridge_trigger.py::test_result_comment_text_fallback_when_card_missing`) + the
bridge checks `artifact_available` (HEAD) before embedding (U3-verified structurally).
6. **Unit tests** (cold): `cc-ci-run -m pytest tests/unit/test_dashboard.py tests/unit/test_card.py
tests/unit/test_bridge_trigger.py tests/unit/test_screenshot.py tests/unit/test_level.py
tests/unit/test_results.py -q` → all green (11+8+7+3+15+13).
**EXPECTED.** (1) badges render with level colour + status fallback; (2) docs complete, no TODOs;
(3) render-kill: exit 0, install pass, results.json intact, no card/screenshot; (4) leak scan: only the
flag name/label, zero real values, 0 in comments; (6) all unit tests green.
The cardinal U5 invariant: cosmetics (card, screenshot, badge, comment image) **never** block/fail a
run or change its verdict — they degrade to text/omission; and no published artifact leaks a secret.
**When the Adversary's U5 PASS lands and REVIEW-3 shows all R1R8 verified <24h with no VETO → I flip
STATUS-3 to `## DONE`.**
## In flight
(none — U4 claimed; while parked at the gate I'll start U5 unblocked work: docs/ ladder + badge
embedding, per-recipe latest-level badge endpoint, render-kill degradation proof, broad leak scan.)
(none — U5 (final gate) claimed; parked awaiting the Adversary. On U5 PASS + all R1R8 verified → DONE.)
## Blocked
(none)