Rulings 66 (licences) + 67 (userdata stays on remove, 07 §6.5); R-789..R-795 ruled, R-802 (lawyer review) opened; R-800 live proof on 9202 (0.288.0); floor 0.288.0; golden 0.288.0 baked + vouched
gates / gates (push) Successful in 29s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-02 14:16:41 +02:00
parent 2633dc1654
commit 5ed44ada6e
14 changed files with 618 additions and 6 deletions
@@ -0,0 +1,10 @@
## RP-R788: the new test against the OLD classify (catalog febf58c) — 2026-10-02T11:43:05Z
test_both_written_is_clean (__main__.TestEmptyDeclaredVolume.test_both_written_is_clean) ... ok
test_empty_declared_volume_is_undetermined_even_when_another_mount_has_data (__main__.TestEmptyDeclaredVolume.test_empty_declared_volume_is_undetermined_even_when_another_mount_has_data)
R-788: one mount holds data, the DECLARED volume is empty — the old rule called this CLEAN. ... FAIL
FAIL: test_empty_declared_volume_is_undetermined_even_when_another_mount_has_data (__main__.TestEmptyDeclaredVolume.test_empty_declared_volume_is_undetermined_even_when_another_mount_has_data)
AssertionError: 'CLEAN' != 'UNDETERMINED'
FAILED (failures=1)
## the new rule:
OK
@@ -0,0 +1,20 @@
## RP-R800-1 the dialog's source lists no userdata (userdataKept returns nothing) (2026-10-02T12:01:04Z)
=== RUN TestRemoveStack_R800_UserdataKeptIsNamed
delete_r442_test.go:443: hdd-data userdata_kept = [], want [/tmp/TestRemoveStack_R800_UserdataKeptIsNamed39760160/001/userdata/media/app] — the dialog must be able to name the household's folder
--- FAIL: TestRemoveStack_R800_UserdataKeptIsNamed (0.00s)
=== RUN TestRemoveStack_R800_SSDAppUserdataKeptEmpty
--- PASS: TestRemoveStack_R800_SSDAppUserdataKeptEmpty (26.01s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 26.025s
FAIL
## RP-R800-2 the note still claims no drive data when userdata stays (2026-10-02T12:01:33Z)
=== RUN TestRemoveStack_R800_UserdataKeptIsNamed
delete_r442_test.go:457: hdd_note = "Az alkalmazás nem tárolt saját adatot külső meghajtón, így ott nem volt mit törölni." — false: the app's files are on the drive and stay
--- FAIL: TestRemoveStack_R800_UserdataKeptIsNamed (26.02s)
=== RUN TestRemoveStack_R800_SSDAppUserdataKeptEmpty
--- PASS: TestRemoveStack_R800_SSDAppUserdataKeptEmpty (26.02s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 52.046s
FAIL
## restored
ok gitea.dooplex.hu/admin/felhom-controller/internal/stacks 52.047s
@@ -0,0 +1,14 @@
##### R-800 on 9202 — controller gitea.dooplex.hu/admin/felhom-controller:0.288.0 | catalog febf58c Grimmory + MeTube records: row 2.6 with the demo-hp with-data | 2026-10-02T12:05:56Z
deploy metube -> True
metube: POST /add http=200 {"status": "ok"}
metube: the download finished (991017 bytes)
metube: history has it=True; GET /download/<file> http=200
the seed reads back: True
the download on the drive: /mnt/felhom-drives/scratch_hdd/userdata/metube/userdata/media/metube/Big_Buck_Bunny_360_10s_1MB.mp4
the dialog's source GET /api/stacks/metube/hdd-data -> 200 {"stack": "metube", "hdd_paths": null, "has_hdd_data": false, "userdata_kept": [{"path": "/mnt/felhom-drives/scratch_hdd/userdata/metube/userdata/media/metube", "size_bytes": 995113, "size_human": "972K", "exists": true}]}
the stacks page (hu) carries the dialog line: True | negative control 'no-such-sentence-xyz': False
the stacks page (en) carries the dialog line: True | negative control 'no-such-sentence-xyz': False
remove WITH data -> 409 {'ok': False, 'error': 'A(z) /mnt/felhom-drives/scratch_hdd/userdata/metube tárhely jelenleg nem elérhető — az alkalmazás nem távolítható el, amíg a meghajtó vissza nem csatlakozik.'} (9202 has no host agent: R-442 refuses, app kept — the with-data result is pinned by TestRemoveStack_R800_UserdataKeptIsNamed)
remove KEEPING data -> 200 {"removed": "metube", "volumes_removed": ["metube_metube_state"], "hdd_paths_removed": [], "hdd_paths_preserved": [], "userdata_kept": ["/mnt/felhom-drives/scratch_hdd/userdata/metube/userdata/media/metube (972K)"], "verified": true}
the file after the remove: STILL THERE
the harness removed its own test folder /mnt/felhom-drives/scratch_hdd/userdata/metube by hand (scratch box)
@@ -0,0 +1,7 @@
## 2026-10-02T12:07:47Z BEFORE: name="min_controller_version" value="0.287.0" name="min_agent" value="0.131.0"
demo-hp 9201: gitea.dooplex.hu/admin/felhom-controller:0.287.0 | demo-felhom 9201: gitea.dooplex.hu/admin/felhom-controller:0.287.0
## 2026-10-02T12:07:52Z POST /configuration/global-floor min_controller_version=0.288.0 min_agent=0.131.0 (the v0.288.0 CHANGELOG header)
HTTP/1.1 303 See Other
Location: /configuration?flash=floor_set
## AFTER: name="min_controller_version" value="0.288.0" name="min_agent" value="0.131.0"
2026-10-02T12:08:12Z both on 0.288.0: demo-hp gitea.dooplex.hu/admin/felhom-controller:0.288.0 | demo-felhom gitea.dooplex.hu/admin/felhom-controller:0.288.0
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
"""r800_live.py — R-800 / decision 67 on scratch 9202 (controller 0.288.0, the LIVE catalog: MeTube is published): MeTube
installed through the product, one download through its own API, then what the remove dialog reads
(`GET /api/stacks/metube/hdd-data` — the call the dialog makes), the dialog text on the page in both languages, the
remove (with data: R-442 refuses on 9202 — no host agent; keeping data: the result), and the file still there.
Endpoint-level method (no browser on DooPlex). Secrets never printed. Env: SC, EV."""
import json, os, re, subprocess, sys, time
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
import box_walk as w
import upgrade_fixtures_box as fixtures
MT = fixtures.FIXTURES["metube"]
log = open(f"{w.EV}/B/r800-9202.txt", "a", buffering=1)
def say(*a):
w.say(*a); log.write(" ".join(map(str, a)) + "\n")
w.login()
say(f"##### R-800 on 9202 — controller {w.guest('docker inspect felhom-controller --format {{.Config.Image}}').strip()} | catalog "
+ w.guest("cd /var/lib/docker/volumes/felhom-controller-data/_data/data/catalog-cache && git log --oneline -1").strip()[:70]
+ f" | {time.strftime('%FT%TZ', time.gmtime())}")
say("deploy metube ->", w.deploy("metube", "video"))
t = MT.seed(w, "video", say)
say("the seed reads back:", MT.verify(w, "video", t, say) if t else "NO SEED")
f = w.guest("find /mnt/felhom-drives -path '*userdata*metube*' -name '*.mp4' | head -1").strip()
say("the download on the drive:", f)
code, d = w.ctl("GET", "/api/stacks/metube/hdd-data")
say("the dialog's source GET /api/stacks/metube/hdd-data ->", code, json.dumps(d.get("data"), ensure_ascii=False)[:400])
for lang, q, frag in (("hu", "", "fajljaid ezekben a mapp"), ("en", "?lang=en", "Your files in these folders stay")):
page = w.page(f"/stacks{q}")
ascii_page = page.encode("ascii", "ignore").decode()
pos = frag.replace("fajljaid", "fjljaid") if lang == "hu" else frag
say(f" the stacks page ({lang}) carries the dialog line: {pos in ascii_page} | negative control 'no-such-sentence-xyz': {'no-such-sentence-xyz' in ascii_page}")
w.ctl("POST", "/api/stacks/metube/stop")
for _ in range(24):
time.sleep(5)
if w.stack("metube").get("state") != "running": break
code, d = w.ctl("POST", "/api/stacks/metube/remove", {"remove_hdd_data": True, "remove_backups": True})
say("remove WITH data ->", code, str(d)[:220], "(9202 has no host agent: R-442 refuses, app kept — the with-data result is pinned by TestRemoveStack_R800_UserdataKeptIsNamed)")
code, d = w.ctl("POST", "/api/stacks/metube/remove", {"remove_hdd_data": False, "remove_backups": True})
say("remove KEEPING data ->", code, json.dumps(d.get("data"), ensure_ascii=False)[:500])
say("the file after the remove:", "STILL THERE" if w.guest(f"test -f '{f}' && echo yes").strip() == "yes" else "GONE")
w.guest("rm -rf /mnt/felhom-drives/scratch_hdd/userdata/metube")
say("the harness removed its own test folder /mnt/felhom-drives/scratch_hdd/userdata/metube by hand (scratch box)")