Agent 0.159.1, the catalog allow-list (controller 0.328.0), break-glass rotation: report, register, design
gates / gates (push) Successful in 8m49s
gates / gates (push) Successful in 8m49s
Closed R-971, R-954, R-1124, R-1012 (174 -> 175 rows); opened R-1139..R-1143; R-895 READY with the design and hub slice 1; R-972 waits on the vouch. [DESIGN] "The catalog allow-list" in 02; the catalog trust line in 01; FELHOM_THINCHECK and unit-forget in 03. Evidence audits/agent-allowlist-rotation-2026-10-17/. Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
1 parent
d968f8490e
commit
5a5486104a
36 files changed
+816
-16
No files matched your search
+24
@@ -0,0 +1,24 @@
|
||||
== root@192.168.0.154
|
||||
felhom-agent 0.159.1
|
||||
Oct 17 17:38:26 felhom felhom-agent[1278]: time=2026-10-17T17:38:26.285+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=076f93320a4eddaa op=agent_update
|
||||
Oct 17 17:38:27 felhom felhom-os-apply[3912437]: os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False
|
||||
Oct 17 17:38:27 felhom felhom-agent[1278]: time=2026-10-17T17:38:27.406+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False"
|
||||
Oct 17 17:38:28 felhom felhom-agent[1278]: time=2026-10-17T17:38:28.285+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=73 total=73 degraded=""
|
||||
Oct 17 17:38:28 felhom felhom-agent[1278]: time=2026-10-17T17:38:28.285+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=8d9bf40b122037c7 op=agent_config_update
|
||||
Oct 17 17:39:31 felhom felhom-agent[3912599]: time=2026-10-17T17:39:31.112+02:00 level=WARN msg="selfupdate: update committed" version=0.159.1 wrapper=""
|
||||
Oct 17 17:53:42 felhom felhom-os-apply[3935466]: os-apply: BUNDLE DONE agent=0.159.1 written=3 same=27 self-check=ok signers-created=False
|
||||
Oct 17 17:53:42 felhom felhom-agent[3912599]: time=2026-10-17T17:53:42.245+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.1 written=3 same=27 self-check=ok signers-created=False"
|
||||
Oct 17 17:53:43 felhom felhom-agent[3912599]: time=2026-10-17T17:53:43.165+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=75 total=75 degraded=""
|
||||
Oct 17 17:53:43 felhom felhom-agent[3912599]: time=2026-10-17T17:53:43.165+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=33c061b404a445e1 op=agent_config_update
|
||||
== felhom-pve
|
||||
felhom-agent 0.159.1
|
||||
Oct 17 17:39:46 demo-felhom felhom-agent[1207]: time=2026-10-17T17:39:46.899+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=c994ded3d077a21b op=agent_update
|
||||
Oct 17 17:39:47 demo-felhom felhom-os-apply[2418991]: os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False
|
||||
Oct 17 17:39:47 demo-felhom felhom-agent[1207]: time=2026-10-17T17:39:47.651+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False"
|
||||
Oct 17 17:39:48 demo-felhom felhom-agent[1207]: time=2026-10-17T17:39:48.278+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=73 total=73 degraded=""
|
||||
Oct 17 17:39:48 demo-felhom felhom-agent[1207]: time=2026-10-17T17:39:48.278+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=0f93931bec704435 op=agent_config_update
|
||||
Oct 17 17:40:51 demo-felhom felhom-agent[2419165]: time=2026-10-17T17:40:51.620+02:00 level=WARN msg="selfupdate: update committed" version=0.159.1 wrapper=""
|
||||
Oct 17 17:55:00 demo-felhom felhom-os-apply[2438672]: os-apply: BUNDLE DONE agent=0.159.1 written=3 same=27 self-check=ok signers-created=False
|
||||
Oct 17 17:55:00 demo-felhom felhom-agent[2419165]: time=2026-10-17T17:55:00.806+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.1 written=3 same=27 self-check=ok signers-created=False"
|
||||
Oct 17 17:55:01 demo-felhom felhom-agent[2419165]: time=2026-10-17T17:55:01.446+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=75 total=75 degraded=""
|
||||
Oct 17 17:55:01 demo-felhom felhom-agent[2419165]: time=2026-10-17T17:55:01.446+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=1e7a09eb163bd82a op=agent_config_update
|
||||
@@ -0,0 +1,24 @@
|
||||
Oct 17 15:37:46 demo-hp felhom-agent[1266]: time=2026-10-17T15:37:46.203+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=e67e21347e268540 op=agent_update
|
||||
Oct 17 15:38:50 demo-hp felhom-agent[3044359]: time=2026-10-17T15:38:50.528+02:00 level=WARN msg="selfupdate: update committed" version=0.159.0 wrapper=""
|
||||
Oct 17 15:53:02 demo-hp felhom-os-apply[3098908]: os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False
|
||||
Oct 17 15:53:02 demo-hp felhom-agent[3044359]: time=2026-10-17T15:53:02.040+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False"
|
||||
Oct 17 15:53:03 demo-hp felhom-agent[3044359]: time=2026-10-17T15:53:03.082+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=73 total=75 degraded=thin-orphan-check,mount-unit-forget
|
||||
Oct 17 15:53:03 demo-hp felhom-agent[3044359]: time=2026-10-17T15:53:03.082+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=ed248025668b456b op=agent_config_update
|
||||
Oct 17 16:08:02 demo-hp felhom-os-apply[3151947]: os-apply: BUNDLE DONE agent=0.159.0 written=3 same=27 self-check=ok signers-created=False
|
||||
Oct 17 16:08:02 demo-hp felhom-agent[3044359]: time=2026-10-17T16:08:02.131+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.0 written=3 same=27 self-check=ok signers-created=False"
|
||||
Oct 17 16:08:03 demo-hp felhom-agent[3044359]: time=2026-10-17T16:08:03.154+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=75 total=75 degraded=""
|
||||
Oct 17 16:08:03 demo-hp felhom-agent[3044359]: time=2026-10-17T16:08:03.155+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=f6b59d99eaed6396 op=agent_config_update
|
||||
Oct 17 16:11:10 demo-hp felhom-agent[3044359]: time=2026-10-17T16:11:10.435+02:00 level=INFO msg="local-api: guest-bind recorded for startup re-assert" vmid=9201 where=/mnt/r1124test durable_id=uuid:5de8066f-0887-4dd1-a329-9b595e4c1d9e
|
||||
Oct 17 16:23:00 demo-hp felhom-agent[3044359]: time=2026-10-17T16:23:00.920+02:00 level=WARN msg="decommission: operator-signed decommission complete (drive will never auto-mount)" durable_id=uuid:5de8066f-0887-4dd1-a329-9b595e4c1d9e
|
||||
Oct 17 16:23:00 demo-hp felhom-agent[3044359]: time=2026-10-17T16:23:00.920+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=7eb567e3dff73267 op=decommission
|
||||
Oct 17 16:23:50 demo-hp felhom-agent[3044359]: time=2026-10-17T16:23:50.743+02:00 level=INFO msg="storage: forgot a decommissioned drive that is gone — its mount unit is removed" name=5de8066f-0887-4dd1-a329-9b595e4c1d9e where=/mnt/r1124test uuid=5de8066f-08
|
||||
Oct 17 16:40:55 demo-hp felhom-agent[3044359]: time=2026-10-17T16:40:55.234+02:00 level=INFO msg="backup: completed" vmid=9201 target=local archive=local:backup/vzdump-lxc-9201-2026_10_17-16_33_32.tar.zst size_bytes=6768484797 uncovered_volumes=2
|
||||
Oct 17 16:53:01 demo-hp felhom-agent[3044359]: time=2026-10-17T16:53:01.776+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=b3aa07f6104caae6 op=agent_update
|
||||
Oct 17 16:54:06 demo-hp felhom-agent[3320002]: time=2026-10-17T16:54:06.099+02:00 level=WARN msg="selfupdate: update committed" version=0.159.1 wrapper=""
|
||||
Oct 17 17:08:18 demo-hp felhom-os-apply[3376289]: os-apply: BUNDLE DONE agent=0.159.1 written=0 same=30 self-check=ok signers-created=False
|
||||
Oct 17 17:08:18 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:18.348+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.1 written=0 same=30 self-check=ok signers-created=False"
|
||||
Oct 17 17:08:19 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:19.386+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=75 total=75 degraded=""
|
||||
Oct 17 17:08:19 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:19.386+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=b5cc740c36f4bed2 op=agent_config_update
|
||||
Oct 17 17:08:19 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:19.402+02:00 level=INFO msg="decommission: drive removed from the guest's bind record" vmid=9201 durable_id=uuid:5de8066f-0887-4dd1-a329-9b595e4c1d9e
|
||||
Oct 17 17:08:19 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:19.402+02:00 level=WARN msg="decommission: operator-signed decommission complete (drive will never auto-mount)" durable_id=uuid:5de8066f-0887-4dd1-a329-9b595e4c1d9e
|
||||
Oct 17 17:08:19 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:19.402+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=e9303dec85a1f5bd op=decommission
|
||||
@@ -0,0 +1,19 @@
|
||||
== before unplug
|
||||
-rw-r--r-- 1 root root 292 Oct 17 16:11 /etc/systemd/system/mnt-r1124test.mount
|
||||
lrwxrwxrwx 1 root root 39 Oct 17 16:11 /etc/systemd/system/multi-user.target.wants/mnt-r1124test.mount -> /etc/systemd/system/mnt-r1124test.mount
|
||||
GET /disks 200 rows 5 r1124test listed: True
|
||||
16:23:42
|
||||
== unplug: unmount the bind and the drive, detach the loop device
|
||||
ls: cannot access '/dev/disk/by-uuid/5de8066f-0887-4dd1-a329-9b595e4c1d9e': No such file or directory
|
||||
== 45 s later
|
||||
ls: cannot access '/etc/systemd/system/mnt-r1124test.mount': No such file or directory
|
||||
ls: cannot access '/etc/systemd/system/multi-user.target.wants/mnt-r1124test.mount': No such file or directory
|
||||
GET /disks 200 rows 4 r1124test listed: False
|
||||
Oct 17 16:23:42 demo-hp systemd[1]: mnt-felhom\x2ddrives-r1124test.mount: Deactivated successfully.
|
||||
Oct 17 16:23:42 demo-hp systemd[1]: Unmounting mnt-r1124test.mount - Felhom storage mount 5de8066f-0887-4dd1-a329-9b595e4c1d9e...
|
||||
Oct 17 16:23:42 demo-hp systemd[1]: mnt-r1124test.mount: Deactivated successfully.
|
||||
Oct 17 16:23:42 demo-hp systemd[1]: Unmounted mnt-r1124test.mount - Felhom storage mount 5de8066f-0887-4dd1-a329-9b595e4c1d9e.
|
||||
Oct 17 16:23:50 demo-hp sudo[3208627]: felhom-agent : PWD=/ ; USER=root ; COMMAND=/usr/bin/systemctl disable -- mnt-r1124test.mount
|
||||
Oct 17 16:23:50 demo-hp sudo[3208690]: felhom-agent : PWD=/ ; USER=root ; COMMAND=/usr/local/sbin/felhom-priv-apply unit-forget mnt-r1124test.mount
|
||||
Oct 17 16:23:50 demo-hp felhom-priv-apply[3208698]: felhom-priv-apply: REMOVED unit-forget /etc/systemd/system/mnt-r1124test.mount (where=/mnt/r1124test)
|
||||
Oct 17 16:23:50 demo-hp felhom-agent[3044359]: time=2026-10-17T16:23:50.743+02:00 level=INFO msg="storage: forgot a decommissioned drive that is gone — its mount unit is removed" name=5de8066f-0887-4dd1-a329-9b595e4c1d9e where=/mnt/r1124test uuid=5de8066f-0887-4dd1-a329-9b595e4c1d9e unit=mnt-r1124test.mount
|
||||
@@ -0,0 +1,8 @@
|
||||
== red-proof: the prune loop removed
|
||||
decommission_test.go:120: 9201 record = [uuid:keep uuid:gone], want [uuid:keep]
|
||||
--- FAIL: TestDecommissionExecutor_PrunesTheGuestBindRecord (0.00s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-agent/internal/signedjobs 0.009s
|
||||
FAIL
|
||||
== restored
|
||||
ok gitea.dooplex.hu/admin/felhom-agent/internal/signedjobs 0.016s
|
||||
@@ -0,0 +1,24 @@
|
||||
== mutation A: ForgetRetiredDrives body = return 0
|
||||
--- FAIL: TestForgetRetiredDrives_DecommissionedAndGone_UnitRemovedAndNotListed (0.00s)
|
||||
--- FAIL: TestForgetRetiredDrives_AlreadyDisabled_NoDisableCall (0.00s)
|
||||
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit (0.00s)
|
||||
--- PASS: TestForgetRetiredDrives_NilIntent_ForgetsNothing (0.00s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-agent/internal/storage 0.011s
|
||||
FAIL
|
||||
== mutation B: the present-drive check removed
|
||||
--- PASS: TestForgetRetiredDrives_DecommissionedAndGone_UnitRemovedAndNotListed (0.00s)
|
||||
--- PASS: TestForgetRetiredDrives_AlreadyDisabled_NoDisableCall (0.00s)
|
||||
--- FAIL: TestForgetRetiredDrives_KeepsEveryOtherUnit (0.00s)
|
||||
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit/decommissioned_but_mounted (0.00s)
|
||||
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit/enrolled_and_absent (0.00s)
|
||||
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit/ejected_and_absent (0.00s)
|
||||
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit/no_intent (0.00s)
|
||||
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit/mount_table_unreadable (0.00s)
|
||||
--- FAIL: TestForgetRetiredDrives_KeepsEveryOtherUnit/decommissioned_but_present (0.00s)
|
||||
--- PASS: TestForgetRetiredDrives_NilIntent_ForgetsNothing (0.00s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-agent/internal/storage 0.010s
|
||||
FAIL
|
||||
== restored
|
||||
ok gitea.dooplex.hu/admin/felhom-agent/internal/storage 0.009s
|
||||
@@ -0,0 +1,25 @@
|
||||
== M1: Orphans() returns nil
|
||||
--- FAIL: TestParse_TheOrphanOf20261014 (0.00s)
|
||||
--- FAIL: TestCheck_OrphanOnBothReads_IsNamed (0.00s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-agent/internal/thincheck 0.006s
|
||||
FAIL
|
||||
== M2: explainFailure appends nothing
|
||||
--- FAIL: TestBackup_SnapshotFailure_NamesTheOrphan (0.00s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-agent/internal/backup 0.009s
|
||||
FAIL
|
||||
== M3: helper ignores a held snapshot
|
||||
FAIL: test_a_snapshot_someone_else_holds_is_never_touched (__main__.Refuses.test_a_snapshot_someone_else_holds_is_never_touched)
|
||||
FAILED (failures=1)
|
||||
== M4: helper without the release trap
|
||||
FAIL: test_thin_ls_failure_still_releases (__main__.Refuses.test_thin_ls_failure_still_releases)
|
||||
FAILED (failures=1)
|
||||
== M5: helper sends a delete
|
||||
FAIL: test_the_only_pool_messages_are_reserve_and_release (__main__.NeverDeletes.test_the_only_pool_messages_are_reserve_and_release)
|
||||
FAIL: test_healthy_pool_lists_both_sides_and_releases (__main__.Reads.test_healthy_pool_lists_both_sides_and_releases)
|
||||
FAILED (failures=2)
|
||||
== restored
|
||||
ok gitea.dooplex.hu/admin/felhom-agent/internal/thincheck (cached)
|
||||
ok gitea.dooplex.hu/admin/felhom-agent/internal/backup (cached)
|
||||
OK
|
||||
@@ -0,0 +1,23 @@
|
||||
== red-proof: the tests against the pre-R-1124 wrapper (HEAD)
|
||||
FAIL: test_F1_a_symlinked_unit_is_not_followed (__main__.UnitForget.test_F1_a_symlinked_unit_is_not_followed)
|
||||
FAIL: test_F2_a_network_unit_or_a_foreign_unit_is_not_removed (__main__.UnitForget.test_F2_a_network_unit_or_a_foreign_unit_is_not_removed)
|
||||
FAIL: test_F3_an_enabled_unit_is_not_removed (__main__.UnitForget.test_F3_an_enabled_unit_is_not_removed)
|
||||
FAIL: test_F4_a_mounted_drive_keeps_its_unit (__main__.UnitForget.test_F4_a_mounted_drive_keeps_its_unit)
|
||||
FAIL: test_F5_a_present_drive_keeps_its_unit (__main__.UnitForget.test_F5_a_present_drive_keeps_its_unit)
|
||||
FAIL: test_U3_a_unit_whose_name_lies_about_where_is_not_removed (__main__.UnitForget.test_U3_a_unit_whose_name_lies_about_where_is_not_removed)
|
||||
FAIL: test_already_gone_is_fine (__main__.UnitForget.test_already_gone_is_fine)
|
||||
FAIL: test_an_absent_disabled_unmounted_drive_unit_is_removed (__main__.UnitForget.test_an_absent_disabled_unmounted_drive_unit_is_removed)
|
||||
Ran 46 tests in 0.010s
|
||||
FAILED (failures=8)
|
||||
== mutation: F5 check disabled
|
||||
FAIL: test_F5_a_present_drive_keeps_its_unit (__main__.UnitForget.test_F5_a_present_drive_keeps_its_unit)
|
||||
Ran 46 tests in 0.007s
|
||||
FAILED (failures=1)
|
||||
== mutation: F4 check disabled
|
||||
FAIL: test_F4_a_mounted_drive_keeps_its_unit (__main__.UnitForget.test_F4_a_mounted_drive_keeps_its_unit)
|
||||
Ran 46 tests in 0.007s
|
||||
FAILED (failures=1)
|
||||
== mutation: F3 check disabled
|
||||
FAIL: test_F3_an_enabled_unit_is_not_removed (__main__.UnitForget.test_F3_an_enabled_unit_is_not_removed)
|
||||
Ran 46 tests in 0.008s
|
||||
FAILED (failures=1)
|
||||
@@ -0,0 +1,45 @@
|
||||
loop=/dev/loop2
|
||||
Physical volume "/dev/loop2" successfully created.
|
||||
Volume group "felhomscratch" successfully created
|
||||
Thin pool volume with chunk size 64.00 KiB can address at most <15.88 TiB of data.
|
||||
Logical volume "pool" created.
|
||||
Logical volume "t1" created.
|
||||
LV ThId Pool
|
||||
pool
|
||||
t1 1 pool
|
||||
== healthy read
|
||||
lvm-before 1 t1
|
||||
pool 1
|
||||
lvm-after 1 t1
|
||||
ok
|
||||
rc=0
|
||||
== make an orphan (kernel only, scratch pool): create_thin 7
|
||||
lvm-before 1 t1
|
||||
pool 1
|
||||
pool 7
|
||||
lvm-after 1 t1
|
||||
ok
|
||||
rc=0
|
||||
0 819200 thin-pool 1 113/1024 0/6400 - rw discard_passdown queue_if_no_space - 256
|
||||
== someone else holds a metadata snapshot
|
||||
felhom-thin-check: REFUSED: a metadata snapshot of felhomscratch-pool-tpool is already held (by someone else) — not touched 3
|
||||
rc=3
|
||||
held root: 30
|
||||
== demo-hp real pool pve/data (read only)
|
||||
lvm-before 1 vm-9201-disk-0
|
||||
lvm-before 2 vm-9201-disk-1
|
||||
pool 1
|
||||
pool 2
|
||||
lvm-after 1 vm-9201-disk-0
|
||||
lvm-after 2 vm-9201-disk-1
|
||||
ok
|
||||
rc=0
|
||||
held root after: -
|
||||
== teardown scratch
|
||||
Logical volume "t1" successfully removed.
|
||||
Logical volume "pool" successfully removed.
|
||||
Volume group "felhomscratch" successfully removed
|
||||
Labels on physical volume "/dev/loop2" successfully wiped.
|
||||
pve
|
||||
0
|
||||
0
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
== before
|
||||
79e7877dc3e8577d7623f9b5ba57d300eca7a2a0f86c27458385b97517f2c480 /opt/docker/stacks/privatebin/docker-compose.yml
|
||||
494270e42262ac772dd2033a0dc2c2530b52bf8132a5245c9bb3e2a9f9df9e3a 2026-10-17T14:34:24.634717373Z running
|
||||
== after the refused correction
|
||||
79e7877dc3e8577d7623f9b5ba57d300eca7a2a0f86c27458385b97517f2c480 /opt/docker/stacks/privatebin/docker-compose.yml
|
||||
0
|
||||
494270e42262ac772dd2033a0dc2c2530b52bf8132a5245c9bb3e2a9f9df9e3a 2026-10-17T14:34:24.634717373Z running
|
||||
2026/10/17 15:10:34 allowlist.go:122: [WARN] [stacks] privatebin: definition REFUSED by the allow-list (R-971), nothing written: the catalog definition of privatebin asks for container rights the box does not allow: priv
|
||||
2026/10/17 15:10:34 sync.go:511: [WARN] [sync] privatebin: catalog definition REFUSED by the allow-list — the app keeps its last good compose, nothing written: the catalog definition of privatebin asks for container ri
|
||||
2026/10/17 15:10:34 notifier.go:315: [DEBUG] PushEvent: type=app_definition_refused severity=warning url=https://hub.felhom.eu/api/v1/event
|
||||
2026/10/17 15:10:34 notifier.go:341: [DEBUG] PushEvent: app_definition_refused pushed OK (HTTP 200)
|
||||
2026/10/17 15:10:34 notifier.go:353: [INFO] Event pushed: app_definition_refused (warning) [hu-only] — privatebin: the box REFUSED a catalog definition — it asks for container rights not on the box's allow-list. Noth
|
||||
== hub
|
||||
2026/10/17 17:10:34 [INFO] Event from demo-hp: app_definition_refused (warning) — privatebin: the box REFUSED a catalog definition — it asks for container rights not on the box's allow-list. Nothing was written; the app keeps its last good compose. Check w
|
||||
2026/10/17 17:10:34 [INFO] Operator email sent for demo-hp/app_definition_refused
|
||||
/apps/privatebin 200 True True
|
||||
/apps/opengist 200 False False
|
||||
@@ -0,0 +1,14 @@
|
||||
2026/10/17 15:11:32 sync.go:318: [INFO] [sync] Cloning https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git → /opt/docker/felhom-controller/data/catalog-cache
|
||||
2026/10/17 15:11:33 sync.go:261: [INFO] [sync] catalog moved c3d0fb37df7f -> 45763e31c2fc (0 new, 0 stack dir(s) changed)
|
||||
2026/10/17 15:11:33 sync.go:299: [INFO] [sync] Catalog sync complete
|
||||
2026/10/17 15:11:33 sync.go:142: [INFO] [sync] Initial sync: Sablonok frissítve — a katalógus új változata betöltve; a telepített alkalmazások fájljai nem változtak
|
||||
|
||||
23: repo_url: https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git
|
||||
24: sync_interval: 15m
|
||||
-rw------- 1 root root 2989 Aug 31 08:32 /var/lib/docker/volumes/felhom-controller-data/_data/controller.yaml.pre-r971
|
||||
mirror main c3d0fb3 DRILL privatebin: privileged: true — the box must REFUSE this correction (R-971 proof on 9201)
|
||||
cache HEAD 45763e3 CHANGELOG: the privileges gate's round-2/3 changes
|
||||
https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git
|
||||
|
||||
/apps/privatebin 200 False False
|
||||
/apps/opengist 200 False False
|
||||
@@ -0,0 +1,38 @@
|
||||
== M1: Admit admits everything
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/network_mode_host (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/pid (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/uts (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/volumes_from (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/extends_file (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/devices (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/seccomp_off (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/apparmor_off (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/sysctls (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/env_file_outside (0.00s)
|
||||
--- FAIL: TestAdmit_EveryClassIsRefused/interpolated (0.00s)
|
||||
== M2: copyTemplates asks nothing
|
||||
--- FAIL: TestR971_RefusedCorrectionWritesNothing (0.00s)
|
||||
--- FAIL: TestR971_RefusedTemplateOfAnAppNotInstalled (0.00s)
|
||||
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/sync 0.010s
|
||||
--- FAIL: TestAllowList_IsWiredIntoEveryComposeWriter (0.20s)
|
||||
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.208s
|
||||
== M3: a NEW compose writer nobody gated
|
||||
allowlist_wiring_test.go:124: internal/stacks/zz_redproof_writer.go:redproofNewWriter writes a file and names the compose file, and the allow-list guard does not know it — gate it (admitCompose before the write) or add it to `writers` as exempt with the reason
|
||||
--- FAIL: TestAllowList_IsWiredIntoEveryComposeWriter (0.23s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.237s
|
||||
== M4: no once-per-definition
|
||||
--- FAIL: TestAllowList_OneEventPerRefusedDefinition (0.00s)
|
||||
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.007s
|
||||
== M5: the app page line removed
|
||||
--- FAIL: TestR971_AppPage_SaysTheDefinitionWasRefused (0.28s)
|
||||
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.296s
|
||||
== M6: the install asks nothing
|
||||
--- FAIL: TestAllowList_IsWiredIntoEveryComposeWriter (0.24s)
|
||||
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.251s
|
||||
== restored
|
||||
ok gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy (cached)
|
||||
ok gitea.dooplex.hu/admin/felhom-controller/internal/sync (cached)
|
||||
ok gitea.dooplex.hu/admin/felhom-controller/internal/stacks 423.793s
|
||||
13
|
||||
@@ -0,0 +1,14 @@
|
||||
== catalog gate red-proof: the allow-list check never refuses
|
||||
XX FACT: privileged true rc=0 (expected 1)
|
||||
XX FACT: cap_add rc=0 (expected 1)
|
||||
XX FACT: the host root bound rc=0 (expected 1)
|
||||
XX FACT: a bind through another variable rc=0 (expected 1)
|
||||
XX FACT: homepage's socket READ-WRITE rc=0 (expected 1)
|
||||
XX FACT: the allowed socket in ANOTHER app rc=0 (expected 1)
|
||||
XX FACT: network_mode host rc=0 (expected 1)
|
||||
XX FACT: a driver_opts bind volume rc=0 (expected 1)
|
||||
XX FACT: a ${VAR} in a privileged key rc=0 (expected 1)
|
||||
XX FACT: privileged in a steps/ file rc=0 (expected 1)
|
||||
fails: 10
|
||||
== restored
|
||||
check-privileges: 123 files judged, every class-setting on the allow-list
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
== live finding (9201, rc.4) red-proof: roots resolved only when they exist
|
||||
privpolicy_test.go:438: binds under roots that do not exist yet were refused: the catalog definition of app asks for container rights the box does not allow: app: bind /mnt/felhom-drives/check/felhom-data/appdata/app -> /c rw; app: bind /mnt/felhom-drives/check/felhom-data/userdata/media -> /m rw
|
||||
--- FAIL: TestAdmit_RootsThatDoNotExistYet (0.00s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.006s
|
||||
FAIL
|
||||
== restored
|
||||
ok gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.147s
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
== security-review fixes, red-proofs
|
||||
-- F1: the image/start binding removed
|
||||
--- FAIL: TestAdmit_TheAllowedSettingIsBoundToItsImageAndStart (0.00s)
|
||||
--- FAIL: TestAdmit_TheAllowedSettingIsBoundToItsImageAndStart/another_image (0.00s)
|
||||
--- FAIL: TestAdmit_TheAllowedSettingIsBoundToItsImageAndStart/added_entrypoint (0.00s)
|
||||
--- FAIL: TestAdmit_TheAllowedSettingIsBoundToItsImageAndStart/added_command (0.00s)
|
||||
-- F2: Resolve ignored
|
||||
--- FAIL: TestAdmit_ASymlinkOutOfARootIsOutside (0.00s)
|
||||
-- F3: the later classes removed
|
||||
--- FAIL: TestAdmit_TheLaterClasses (0.00s)
|
||||
--- FAIL: TestAdmit_TheLaterClasses/provider (0.00s)
|
||||
--- PASS: TestAdmit_TheLaterClasses/post_start (0.00s)
|
||||
--- PASS: TestAdmit_TheLaterClasses/cgroup_parent (0.00s)
|
||||
--- PASS: TestAdmit_TheLaterClasses/runtime (0.00s)
|
||||
--- FAIL: TestAdmit_TheLaterClasses/gpus (0.00s)
|
||||
--- PASS: TestAdmit_TheLaterClasses/device_request (0.00s)
|
||||
-- F4: any /mnt/ path a root again
|
||||
--- FAIL: TestAdmit_ARootElsewhereUnderMntIsNoRoot (0.00s)
|
||||
== restored
|
||||
ok gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.137s
|
||||
ok gitea.dooplex.hu/admin/felhom-controller/internal/sync 0.388s
|
||||
ok gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.236s
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
== security review round 2, red-proofs
|
||||
-- same-file extends not refused
|
||||
--- FAIL: TestAdmit_Round2 (0.00s)
|
||||
--- FAIL: TestAdmit_Round2/a_second_service_extends_the_allowed_one (0.00s)
|
||||
-- healthcheck not bound
|
||||
--- FAIL: TestAdmit_Round2 (0.00s)
|
||||
--- FAIL: TestAdmit_Round2/the_allowed_service's_healthcheck_runs_a_shell (0.00s)
|
||||
-- image variable not refused
|
||||
--- FAIL: TestAdmit_Round2 (0.00s)
|
||||
--- FAIL: TestAdmit_Round2/the_allowed_service's_image_through_a_variable (0.00s)
|
||||
-- options variable allowed
|
||||
--- FAIL: TestAdmit_Round2 (0.00s)
|
||||
--- FAIL: TestAdmit_Round2/a_variable_in_a_bind's_options (0.00s)
|
||||
-- a missing path judged by name again (fail open)
|
||||
--- FAIL: TestAdmit_ANotYetCreatedPathBehindASymlink (0.00s)
|
||||
== restored
|
||||
ok gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.123s
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
== round 3 red-proof: HDD_PATH whole again
|
||||
privpolicy_test.go:416: " - ${HDD_PATH}:/drive\n" was admitted
|
||||
--- FAIL: TestAdmit_HDDPathRootIsAppdataOnly (0.00s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.005s
|
||||
FAIL
|
||||
== restored
|
||||
ok gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy (cached)
|
||||
@@ -0,0 +1,41 @@
|
||||
FILES 123
|
||||
SET audiobookshelf final audiobookshelf security_opt ["no-new-privileges:true"]
|
||||
SET audiobookshelf step audiobookshelf security_opt ["no-new-privileges:true"]
|
||||
SET crafty-controller final crafty-controller ports ["25565-25575:25565-25575"]
|
||||
SET komga final komga security_opt ["no-new-privileges:true"]
|
||||
SET komga step komga security_opt ["no-new-privileges:true"]
|
||||
BIND audiobookshelf audiobookshelf ${USERDATA_PATH}/media/audiobooks:/audiobooks 2
|
||||
BIND audiobookshelf audiobookshelf ${USERDATA_PATH}/media/podcasts:/podcasts 2
|
||||
BIND calibre-web calibre-web ${IMPORT_PATH}/calibre:/cwa-book-ingest 1
|
||||
BIND calibre-web calibre-web ${USERDATA_PATH}/media/books:/calibre-library 1
|
||||
BIND emby emby ${USERDATA_PATH}/media:/media:ro 3
|
||||
BIND grimmory grimmory ${HDD_PATH}/appdata/grimmory/data:/app/data 1
|
||||
BIND grimmory grimmory ${IMPORT_PATH}/grimmory:/bookdrop 1
|
||||
BIND grimmory grimmory ${USERDATA_PATH}/media/grimmory:/books 1
|
||||
BIND homepage homepage /var/run/docker.sock:/var/run/docker.sock:ro 1
|
||||
BIND immich immich-server ${HDD_PATH}/appdata/immich:/usr/src/app/upload 3
|
||||
BIND immich immich-server ${USERDATA_PATH}/media/photos:/external/photos:ro 3
|
||||
BIND jellyfin jellyfin ${USERDATA_PATH}/media:/media:ro 1
|
||||
BIND komga komga ${USERDATA_PATH}/media/comics:/data 2
|
||||
BIND metube metube ${USERDATA_PATH}/media/metube:/downloads 1
|
||||
BIND navidrome navidrome ${USERDATA_PATH}/media/music:/music:ro 3
|
||||
BIND nextcloud nextcloud ${HDD_PATH}/appdata/nextcloud:/var/www/html/data 3
|
||||
BIND nzbget nzbget ${USERDATA_PATH}/media/nzbget:/downloads 1
|
||||
BIND paperless-ngx paperless-webserver ${HDD_PATH}/appdata/paperless/export:/usr/src/paperless/export 1
|
||||
BIND paperless-ngx paperless-webserver ${HDD_PATH}/appdata/paperless/media:/usr/src/paperless/media 1
|
||||
BIND paperless-ngx paperless-webserver ${IMPORT_PATH}/paperless:/usr/src/paperless/consume 1
|
||||
BIND plex plex ${USERDATA_PATH}/media:/media:ro 1
|
||||
BIND qbittorrent qbittorrent ${USERDATA_PATH}/media/torrents:${USERDATA_PATH}/media/torrents 1
|
||||
BIND qbittorrent qbittorrent ${USERDATA_PATH}/media/torrents:/downloads 1
|
||||
BIND radarr radarr ${USERDATA_PATH}/media:${USERDATA_PATH}/media 1
|
||||
BIND romm romm ${HDD_PATH}/appdata/romm/resources:/romm/resources 3
|
||||
BIND romm romm ${USERDATA_PATH}/roms:/romm/library 2
|
||||
BIND romm romm ${USERDATA_PATH}/roms:/romm/library/roms 1
|
||||
BIND romm romm ${USERDATA_PATH}/roms-bios:/romm/library/bios 1
|
||||
BIND sabnzbd sabnzbd ${USERDATA_PATH}/media/usenet:/downloads 1
|
||||
BIND sonarr sonarr ${USERDATA_PATH}/downloads:/downloads 1
|
||||
BIND sonarr sonarr ${USERDATA_PATH}/media:${USERDATA_PATH}/media 1
|
||||
BIND sonarr sonarr ${USERDATA_PATH}/media/tv:/media/tv 1
|
||||
BIND transmission transmission ${USERDATA_PATH}/media/transmission:${USERDATA_PATH}/media/transmission 1
|
||||
BIND transmission transmission ${USERDATA_PATH}/media/transmission:/downloads 1
|
||||
BIND transmission transmission ${USERDATA_PATH}/media/transmission/watch:/watch 1
|
||||
@@ -0,0 +1,36 @@
|
||||
# R-971 survey — every container right the catalog asks for (2026-10-17)
|
||||
|
||||
Catalog `app-catalog-felhom.eu` at `1af6ea7` (the survey) and `d5a443d` (the gate). **123 files: 65 `templates/<app>/docker-compose.yml`
|
||||
and 58 ladder `steps/*.yml`.** Read with PyYAML (`survey-raw.txt`, the raw scan) and again with the controller's own
|
||||
check (`privpolicy.Check` on the placeholder env, the test `TestAllowList_TheWholeCatalogPasses`).
|
||||
|
||||
Classes looked for: `privileged`, `cap_add`, `devices`, `device_cgroup_rules`, `network_mode`, `pid`, `ipc`, `uts`,
|
||||
`userns_mode`, `cgroup`, `security_opt`, `sysctls`, `volumes_from`, `build`, `include`, `extends`, `env_file`, top-level
|
||||
volumes with `driver`/`driver_opts`/`external`/`name`, `configs`/`secrets` with `file:`, and every bind source.
|
||||
|
||||
## The allow-list (what the catalog needs)
|
||||
|
||||
| app | service | setting | why the app needs it | upstream doc |
|
||||
|---|---|---|---|---|
|
||||
| homepage | homepage | `bind /var/run/docker.sock -> /var/run/docker.sock ro` | the Docker widget and Docker service discovery list the household's containers and their state | https://gethomepage.dev/configs/docker/ |
|
||||
|
||||
That is the whole list. **No template or step asks for any other class member.** Note (security review C5-5, R-782): a
|
||||
read-only socket mount does not limit the Docker API; the entry keeps today's behaviour, it does not bless it — a
|
||||
read-only socket proxy for homepage stays a separate catalog change.
|
||||
|
||||
## Seen and NOT a class member (no entry needed)
|
||||
|
||||
| app | setting | why it passes |
|
||||
|---|---|---|
|
||||
| audiobookshelf, komga (final + step) | `security_opt: [no-new-privileges:true]` | a hardening, not a relaxation |
|
||||
| every bind (35 distinct) | `${HDD_PATH}/…`, `${USERDATA_PATH}/…`, `${IMPORT_PATH}/…` | inside the data roots the box gives |
|
||||
| crafty-controller | `ports: 25565-25575` | not in the brief's classes: a published port is LAN reach of the guest, not a right on the host (documented in `01-topology-and-trust.md`) |
|
||||
| vikunja | `user: 0:0` | root INSIDE the container; not a host right |
|
||||
| karakeep-chrome | `init: true` | a tini init, no privilege |
|
||||
| 94 compose files | `networks: traefik-public: external: true` | a network, not a volume; not a class |
|
||||
|
||||
## The controller's infra stacks (out of scope, stated)
|
||||
|
||||
traefik (holds the Docker socket at the internet edge), cloudflared, filebrowser and samba (`network_mode: host` for LAN
|
||||
discovery) are rendered by the controller from its own code, not the catalog. Since v0.328.0 the sync also refuses to
|
||||
copy a catalog template named like one of them into its directory.
|
||||
@@ -0,0 +1,15 @@
|
||||
== before
|
||||
demo-felhom-8363b5 HTTP 200 user root@pam set_at 2026-07-18T16:30:41Z password_len 32
|
||||
192.168.0.162 PVE ticket HTTP 200 ticket_issued True
|
||||
== rotate (installer step 4b alone, on demo-felhom)
|
||||
[STEP] 4b/8 break-glass credential (root@pam console password → hub vault)
|
||||
[OK] root@pam password set + vaulted to the hub (retrieve via the operator /admin path; never logged here)
|
||||
[WARN] NOTE: the root@pam password just CHANGED — the old one now fails at the PVE web GUI (:8006).
|
||||
[WARN] Retrieve the new one at hub → host page (vaulted recovery credential).
|
||||
== after (hub 0.157.0: set_at should move now)
|
||||
demo-felhom-8363b5 HTTP 200 user root@pam set_at 2026-10-17T15:10:04Z password_len 32
|
||||
== the NEW vaulted value logs in
|
||||
192.168.0.162 PVE ticket HTTP 200 ticket_issued True
|
||||
== the OLD value no longer does
|
||||
192.168.0.162 PVE ticket HTTP 401
|
||||
values differ: yes
|
||||
@@ -0,0 +1,14 @@
|
||||
== before
|
||||
demo-hp-bb76ea HTTP 200 user root@pam set_at 2026-07-21T16:24:27Z password_len 32
|
||||
== rotate (installer step 4b alone, on demo-hp)
|
||||
[STEP] 4b/8 break-glass credential (root@pam console password → hub vault)
|
||||
[OK] root@pam password set + vaulted to the hub (retrieve via the operator /admin path; never logged here)
|
||||
[WARN] NOTE: the root@pam password just CHANGED — the old one now fails at the PVE web GUI (:8006).
|
||||
[WARN] Retrieve the new one at hub → host page (vaulted recovery credential).
|
||||
== after
|
||||
demo-hp-bb76ea HTTP 200 user root@pam set_at 2026-07-21T16:24:27Z password_len 32
|
||||
== the NEW vaulted value logs in
|
||||
192.168.0.104 PVE ticket HTTP 200 ticket_issued True
|
||||
== the OLD value no longer does
|
||||
192.168.0.104 PVE ticket HTTP 401
|
||||
values differ: yes
|
||||
@@ -0,0 +1,8 @@
|
||||
== red-proof: the upsert without set_at
|
||||
r954_revault_set_at_test.go:31: credential set_at = 2025-10-17 10:00:00 +0000 UTC — the re-vault kept the first vault's time
|
||||
--- FAIL: TestHostRecovery_ReVaultMovesSetAt (0.04s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-hub/internal/store 0.045s
|
||||
FAIL
|
||||
== restored
|
||||
ok gitea.dooplex.hu/admin/felhom-hub/internal/store 0.044s
|
||||
@@ -0,0 +1,14 @@
|
||||
== before
|
||||
tester-1-d70be4 HTTP 200 user root@pam set_at 2026-10-04T19:40:27Z password_len 32
|
||||
== rotate (installer step 4b alone, on Tester 1)
|
||||
[STEP] 4b/8 break-glass credential (root@pam console password → hub vault)
|
||||
[OK] root@pam password set + vaulted to the hub (retrieve via the operator /admin path; never logged here)
|
||||
[WARN] NOTE: the root@pam password just CHANGED — the old one now fails at the PVE web GUI (:8006).
|
||||
[WARN] Retrieve the new one at hub → host page (vaulted recovery credential).
|
||||
== after
|
||||
tester-1-d70be4 HTTP 200 user root@pam set_at 2026-10-04T19:40:27Z password_len 32
|
||||
== the NEW vaulted value logs in
|
||||
192.168.0.154 PVE ticket HTTP 200 ticket_issued True
|
||||
== the OLD value no longer does
|
||||
192.168.0.154 PVE ticket HTTP 401
|
||||
values differ: yes
|
||||
@@ -0,0 +1,65 @@
|
||||
# R-895 — the hub counts a box's off-site snapshots itself (option B, updated with the measurement) — 2026-10-17
|
||||
|
||||
Baselines: felhom.eu `8f97b800` (hub v0.157.0 code), design origin `audits/night-burndown-2026-10-06/design-R-822.md`
|
||||
option B. Architecture: `07-backup-architecture.md` (the off-site tier; decision 68 — the box-trusted count; decision
|
||||
69 — the hub writes the pinned key line), `06-offsite-connectivity.md`.
|
||||
|
||||
## 1. The question
|
||||
|
||||
The clean-up window's drop alarm (`EventWindowDrop`) compares counts the BOX reports before and after a window. A box
|
||||
that was broken into, or fakes planted with its add-only key, keep the count level while the real history shrinks.
|
||||
Option B: the hub counts the files in the box's restic `snapshots/` directory itself, over a login of its own.
|
||||
|
||||
## 2. The measurement (read-only, demo-hp's repository folder only)
|
||||
|
||||
**What login would the hub need?** None new. The hub already logs in to every provisioned sub-account once a day with
|
||||
the sub-account PASSWORD (sealed at rest, R-821) for the `authorized_keys` audit (`offsitekeys.Registrar.Audit`,
|
||||
port 23, host key pinned). That login can list `snapshots/`. **It is NOT read-only** — the same password can `rm`,
|
||||
`mv` and rewrite `authorized_keys` (measured 2026-10-03, `audits/offsite-append-only-2026-10-03/live/`). The listing
|
||||
itself only reads (`ls -l`), and adds no capability the hub does not already hold.
|
||||
|
||||
**Does the provider show upload times?** Yes, by prior measurement on this very sub-account: on 2026-09-01 the
|
||||
password login on demo-hp's sub-account (`u629488-sub3`) listed entries with their modification time to the minute
|
||||
over SFTP (`ls -la` → `Sep 1 12:12`), and the port-23 shell offers `ls|ll`, `stat`
|
||||
(`audits/evidence-drill-r95-recovery-2026-09-01/phase1-find-the-snapshot/01-probe-tree.txt`, `03-shell-capabilities.txt`).
|
||||
A restic snapshot file is written once and never changed, so its mtime is its upload time.
|
||||
|
||||
**Today's re-measurement from DooPlex: NOT done — and why, with what was tried.** Since decision 69 no box holds the
|
||||
sub-account password; the hub alone holds it, sealed. Tried: (a) CC's secret store (`sec list`) — no Storage Box
|
||||
credential; (b) the box's own key — pinned to `rclone serve restic --append-only`, it reaches only restic's REST API
|
||||
(names and sizes, no times, and it is the box's key, which is exactly what the hub must not rely on); (c) the hub — it
|
||||
has no command or endpoint that lists. Reading the sealed password out of the hub DB to measure by hand was not done:
|
||||
it would put a delete-capable credential of a customer sub-account on DooPlex for a measurement the hub can make
|
||||
itself. **So the measurement ships as code:** hub v0.157.0's daily audit lists `snapshots/` read-only and LOGS the
|
||||
count, the newest and the oldest upload time (`internal/offsitekeys/snapshots.go`). The first daily run after the
|
||||
deploy IS the measurement; compare its count with the box's own (`offsite.snapshot_count` in the host report) — a
|
||||
control from a different channel.
|
||||
|
||||
## 3. The design (the alarm slice, after the measurement)
|
||||
|
||||
1. **Before/after a window, the hub's own count** (`OpenWindowFor` / `CloseWindowFor` take the listing, the box's
|
||||
numbers logged beside). `EventWindowDrop` fires on the hub's numbers. Red test first (design-R-822 §5): a fake
|
||||
listing 17 → 3 while the box reports 17 → 15 must fire; today it does not.
|
||||
2. **Files no box run explains:** each box run reports its time (manual runs, catch-ups and crash retries included —
|
||||
they are runs). A snapshot file whose upload time falls outside every reported run (± a slack), or more files than
|
||||
runs, is the injection signature → an operator-only event; the next window is refused while such files exist.
|
||||
3. **Snapshots that vanished outside a window:** today's list minus yesterday's, when no window was open → an
|
||||
operator-only event. The hub keeps only names and times (custody unchanged, `07` §8a: never contents).
|
||||
|
||||
## 4. Costs
|
||||
|
||||
| | cost |
|
||||
|---|---|
|
||||
| credential | none new; the existing sealed password (write-capable — a fact today, not a new exposure) |
|
||||
| per box | one more SSH login per day (the listing), and the stored list (≈ 70 names × 100 bytes) |
|
||||
| build | slice 1 (this release, ~1 h: list + log); slice 2 (§3.1–3.3, ~1 day with the red tests); a live proof on scratch 9202's sub-account |
|
||||
| what can go wrong | `ls -l` output differing on the provider (slice 1 logs it before anything alarms); a run that does not report its time (false alarm — every run path must report) |
|
||||
|
||||
**A read-only login would be better, and costs a per-box sub-account:** a second sub-account with `readonly=true`
|
||||
on the same directory (Hetzner API) would let the hub list without holding delete rights for this purpose. It adds
|
||||
one provisioning step and one sealed secret per box. Not built; named as the alternative.
|
||||
|
||||
## 5. State
|
||||
|
||||
R-895 stays OPEN (READY) with this design. Slice 1 (the listing, log-only) is in hub v0.157.0 — deployed only on the
|
||||
operator's yes. Slice 2 (the alarms) needs: the first logged listings on real boxes (the measurement), then about a day.
|
||||
@@ -0,0 +1,8 @@
|
||||
== red-proof: every line counted as a snapshot
|
||||
snapshots_test.go:44: files=3 other=0, want 2 and 1
|
||||
--- FAIL: TestListSnapshots_CountsTheBoxSnapshotFilesReadOnly (0.00s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-hub/internal/offsitekeys 0.008s
|
||||
FAIL
|
||||
== restored
|
||||
ok gitea.dooplex.hu/admin/felhom-hub/internal/offsitekeys 0.262s
|
||||
@@ -0,0 +1,21 @@
|
||||
=== demo-hp (enkisfelhom.hu)
|
||||
containers: 24 not-healthy/running:
|
||||
2026/10/17 15:21:35 updater.go:855: [INFO] [selfupdate] Post-update startup: update successful (0.328.0-rc.5 → 0.328.0)
|
||||
allow-list refusals since start: 0
|
||||
2026/10/17 15:21:35 sync.go:142: [INFO] [sync] Initial sync: Sablonok naprakészek — nincs változás
|
||||
public https://felhom.enkisfelhom.hu/login: 200
|
||||
public https://files.enkisfelhom.hu/: 200
|
||||
=== demo-felhom (demo-felhom.eu)
|
||||
containers: 9 not-healthy/running:
|
||||
2026/10/17 15:21:24 [INFO] [selfupdate] Post-update startup: update successful (0.327.1 → 0.328.0)
|
||||
allow-list refusals since start: 0
|
||||
2026/10/17 15:21:25 [INFO] [sync] Initial sync: Sablonok naprakészek — nincs változás
|
||||
public https://felhom.demo-felhom.eu/login: 200
|
||||
public https://files.demo-felhom.eu/: 200
|
||||
=== tester-1 (enkicsifelhom.hu)
|
||||
containers: 10 not-healthy/running:
|
||||
2026/10/17 15:21:34 [INFO] [selfupdate] Post-update startup: update successful (0.327.1 → 0.328.0)
|
||||
allow-list refusals since start: 0
|
||||
2026/10/17 15:21:35 [INFO] [sync] Initial sync: Sablonok naprakészek — nincs változás
|
||||
public https://felhom.enkicsifelhom.hu/login: 200
|
||||
public https://files.enkicsifelhom.hu/: 200
|
||||
@@ -0,0 +1,12 @@
|
||||
== global floor
|
||||
HTTP/1.1 303 See Other
|
||||
Location: /configuration?flash=floor_set
|
||||
clear tester-1:
|
||||
HTTP/1.1 303 See Other
|
||||
Location: /customers/tester-1?flash=floor_set
|
||||
clear demo-hp:
|
||||
HTTP/1.1 303 See Other
|
||||
Location: /customers/demo-hp?flash=floor_set
|
||||
clear demo-felhom:
|
||||
HTTP/1.1 303 See Other
|
||||
Location: /customers/demo-felhom?flash=floor_set
|
||||
@@ -0,0 +1,7 @@
|
||||
integrity: ok
|
||||
('min_controller_version', '0.328.0')
|
||||
('min_controller_version_declared_min_agent', '0.328.0=0.158.1')
|
||||
per-box floor columns: ['min_controller_version', 'min_controller_declared_min_agent', 'min_controller_set_at']
|
||||
min_controller_version set: []
|
||||
min_controller_declared_min_agent set: []
|
||||
min_controller_set_at set: []
|
||||
@@ -0,0 +1,8 @@
|
||||
OK http://files.demo-felhom.eu/r1033-check?q=1 -> 301 https://files.demo-felhom.eu/r1033-check?q=1
|
||||
OK http://gist.demo-felhom.eu/r1033-check?q=1 -> 301 https://gist.demo-felhom.eu/r1033-check?q=1
|
||||
OK http://no-such-name-r1033.demo-felhom.eu/r1033-check?q=1 -> 301 https://no-such-name-r1033.demo-felhom.eu/r1033-check?q=1
|
||||
OK http://prowlarr.demo-felhom.eu/r1033-check?q=1 -> 301 https://prowlarr.demo-felhom.eu/r1033-check?q=1
|
||||
OK http://radarr.demo-felhom.eu/r1033-check?q=1 -> 301 https://radarr.demo-felhom.eu/r1033-check?q=1
|
||||
OK http://sonarr.demo-felhom.eu/r1033-check?q=1 -> 301 https://sonarr.demo-felhom.eu/r1033-check?q=1
|
||||
OK http://torrent.demo-felhom.eu/r1033-check?q=1 -> 301 https://torrent.demo-felhom.eu/r1033-check?q=1
|
||||
== every public name redirects http -> https
|
||||
Reference in new issue
Block a user