Files
felhom.eu/documentation/audits/night-2026-09-23/r640_live.py
T
admin 3e58c184f6
gates / gates (push) Successful in 27s
night shift 2026-09-23: the record, the register, the morning note
DRILL-night-2026-09-23.md: Parts A-E. 09 §3 decisions 21 (operator word),
22 and 23 (CC unattended, operator may reverse); §6.4 parts 4 and 6
(catalog half) shipped; §6.1a residuals R-658/R-659. Register 330 -> 336:
R-651..R-660 opened (R-658 and R-659 P1), R-650/R-640/R-499/R-626 closed.
Capability map, nightly rotation (opengist), STATUS (one question: the
floor), CONTEXT, REPORT. The floor stays 0.266.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-24 00:24:04 +02:00

63 lines
3.7 KiB
Python

#!/usr/bin/env python3
"""R-640 live on 9202 (v0.267.0): a CUT-OFF database copy in docmost's local unit must be refused by
the household's own restore button, BEFORE anything is touched.
The copy is cut to half its size (the exact shape measured on 2026-09-23 morning: a copy that ends
inside a COPY block, no completion marker). Positive observables: the restore's own answer carries
the „csonka" sentence; docmost's containers keep their start times (nothing was stopped); seed A still
reads back. Negative control: the whole copy is put back byte for byte and the same button then
restores (so the refusal is about the cut, not about the button)."""
import json, sys, time
sys.path.insert(0, ".")
import walk as w
from chaos import load, sub_of, SIX
w.login()
s = load()
out = {}
find = w.guest("ls -la /mnt/sys_drive/felhom-data/backups/primary/docmost/db-dumps/ 2>&1; "
"find / -xdev -path '*backups/primary/docmost*' -name 'docmost-postgres.sql' 2>/dev/null | head -3")
w.say("the unit's dump:\n" + find)
paths = [l for l in find.splitlines() if l.endswith("docmost-postgres.sql") and l.startswith("/")] or \
["/mnt/sys_drive/felhom-data/backups/primary/docmost/db-dumps/docmost-postgres.sql"]
if not paths:
sys.exit("no docmost dump found in a local unit")
dump = paths[0]
out["dump"] = dump
starts0 = w.guest("docker ps --filter label=com.docker.compose.project=docmost --format '{{.Names}} {{.RunningFor}}'; "
"for c in docmost docmost-postgres; do docker inspect -f '{{.Name}} {{.State.StartedAt}}' $c; done")
w.say("before:\n" + starts0)
cut = w.guest(f"""set -e
cp -p {dump} /root/r640-whole.sql
n=$(stat -c %s {dump}); head -c $((n/2)) /root/r640-whole.sql > {dump}
echo "whole=$n cut=$(stat -c %s {dump})"; tail -c 200 {dump} | tail -2; echo; grep -c 'dump complete' {dump} || true""")
w.say("cut:\n" + cut)
out["cut"] = cut
res = w.restore("docmost")
code, st = w.ctl("GET", "/api/backup/restore-status")
w.say(f"restore-status after the refused restore: {json.dumps(st, ensure_ascii=False)[:600]}")
out["refused_restore"] = {"result": {k: res.get(k) for k in ("http", "location", "seconds", "state_after", "hold_after")},
"status": st}
for lang in ("hu", "en"):
h = w.page(f"/backups?lang={lang}")
import re, html
m = re.findall(r"[^<>]{0,160}(?:csonka|cut off)[^<>]{0,200}", html.unescape(h))
out[f"page_{lang}"] = m[:2]
w.say(f" /backups ({lang}) carries the sentence: {m[:1]}")
starts1 = w.guest("for c in docmost docmost-postgres; do docker inspect -f '{{.Name}} {{.State.StartedAt}}' $c; done")
w.say("after:\n" + starts1)
out["untouched"] = [l for l in starts0.splitlines() if "StartedAt" not in l and l.startswith("/")] == \
[l for l in starts1.splitlines() if l.startswith("/")]
out["readback_A"] = SIX["docmost"]["fx"].verify(w, sub_of("docmost"), s["apps"]["docmost"]["A"], w.say)
w.say(f"container start times unchanged: {out['untouched']}; seed A: {out['readback_A']}")
# negative control: the whole copy back, the same button restores
w.guest(f"cp -p /root/r640-whole.sql {dump}; rm -f /root/r640-whole.sql; grep -c 'dump complete' {dump}")
res2 = w.restore("docmost")
code, st2 = w.ctl("GET", "/api/backup/restore-status")
out["control_restore"] = {"result": {k: res2.get(k) for k in ("http", "seconds", "state_after", "hold_after")},
"status": st2}
out["control_readback_A"] = SIX["docmost"]["fx"].verify(w, sub_of("docmost"), s["apps"]["docmost"]["A"], w.say)
w.say(f"control (whole copy): status {json.dumps(st2, ensure_ascii=False)[:300]}; seed A {out['control_readback_A']}")
json.dump(out, open("E1-r640-live.json", "w"), indent=2, ensure_ascii=False)
open("E1-r640-live.log", "w").write("\n".join(w.LOG) + "\n")