Files
felhom.eu/documentation/audits/update-night-2026-09-21/probe_redproof.py
T
admin a975cfde5b
gates / gates (push) Successful in 28s
probe fix, the gate, and the promotion train (R-618 closed, R-630..632 opened)
Part 1: tandoor/zipline/wger probes corrected in the catalog and red-proofed live on 9202 in both
directions - "Nem egeszseges" with the front door serving 200, then "Fut" after the real sync with
no redeploy. tandoor's failed edge re-walked: done at +41.1s where it was failed at +361.9s.

Part 2: fifteen proven versions on the live catalog, one commit per app; the guarded Update pressed
on four apps on demo-hp, all four done.

Opened: R-630 (paperless-ngx's probe has never run on any box - a silent absence, worse than the
wrong probe that was found in one night), R-631 (five templates no static rule can judge),
R-632 (28 of 53 templates never deployed by any drill). Closed: R-618.

Register 318 -> 321. No product code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-22 11:10:58 +02:00

66 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""Red-proof for R-618, live on 9202 through the product.
The claim: three templates name a health probe the app does not answer. The proof must show BOTH
halves at the same moment, or it shows nothing:
(a) the PRODUCT says the app is unhealthy — the controller's state, and the app page's badge;
(b) the APP is fine — its own front door answers 200, and docker's healthcheck reads healthy.
A reading of (a) alone is equally consistent with "the app really is broken", which is exactly the
mistake this whole exercise exists to stop making.
"""
import json, re, sys, time
sys.path.insert(0, '.')
import walk as w
OUT = "../probe-fix-2026-09-22"
APPS = [("tandoor", "tandoor", "/accounts/login/"),
("zipline", "zipline", "/"),
("wger", "wger", "/")]
def observe(name, sub, path, tag):
st = w.stack(name)
ac = st.get("app_config") or {}
rc, code, body = w.app_curl(sub, path)
dk = w.guest(f"docker inspect --format '{{{{.State.Health.Status}}}}' "
f"$(docker ps -q --filter name={name}) 2>&1 | head -3").strip()
bg = w.badges(name)
# The health word the HOUSEHOLD reads, in both languages — the version badge is a different
# element and quoting it instead would prove nothing about health (it says "Naprakesz" either
# way). Taken from the rendered page, scripts and styles stripped first: a `<script>` block on
# this page contains the same words and an unstripped scan picks them up (measured 2026-09-21).
health = {}
for lang, suffix in (("hu", ""), ("en", "?lang=en")):
h = w.page(f"/apps/{name}{suffix}")
h = re.sub(r"<script.*?</script>|<style.*?</style>", "", h, flags=re.S)
txt = re.sub(r"\s+", " ", re.sub(r"<[^>]+>", " ", h))
m = re.search(r"\u2190 Alkalmaz\u00e1sok .{0,80}?\s(Nem eg\u00e9szs\u00e9ges|Eg\u00e9szs\u00e9ges|Fut|Le\u00e1ll\u00edtva|Indul|Hib\u00e1s)\s", txt) or \
re.search(r"\u2190 (?:Apps|Alkalmaz\u00e1sok) .{0,80}?\s(Not healthy|Healthy|Running|Stopped|Starting|Failed)\s", txt)
health[lang] = m.group(1) if m else None
health[lang + "_context"] = txt[txt.find("\u2190"):txt.find("\u2190") + 220] if "\u2190" in txt else None
rec = {"when": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "tag": tag, "app": name,
"controller_state": st.get("state"), "deployed": st.get("deployed"),
"pinned_images": ac.get("pinned_images"), "installed_images": ac.get("installed_images"),
"front_door_rc": rc, "front_door_code": code, "front_door_bytes": len(body),
"docker_health": dk, "version_badge": bg, "health_word": health}
print(json.dumps(rec, ensure_ascii=False, indent=2))
return rec
if __name__ == "__main__":
w.login()
tag = sys.argv[1] if len(sys.argv) > 1 else "before"
only = sys.argv[2:] or [a[0] for a in APPS]
recs = []
for name, sub, path in APPS:
if name not in only:
continue
print(f"\n=== {name} ({tag})")
if tag == "before":
ok = w.deploy(name, sub)
print(f" deploy ok={ok}")
w.wait_app(sub, path)
recs.append(observe(name, sub, path, tag))
open(f"{OUT}/probe-{tag}.json", "w").write(json.dumps(recs, ensure_ascii=False, indent=2))
print(f"\nwritten {OUT}/probe-{tag}.json")