Rulings 2026-10-01 built: report, STATUS (standing monthly line), decision 57 (mealie lockout, decided by CC unattended), R-747 narrowed, evidence
gates / gates (push) Successful in 26s
gates / gates (push) Successful in 26s
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:
@@ -621,6 +621,21 @@ R-636's louder repeated alarm.
|
||||
**Why:** about 50 old controller versions sat on each demo box (R-745); a release is ~400 MB unpacked and several ship
|
||||
a day. Registry tags are never deleted by this.
|
||||
|
||||
### 2026-10-01 — decided by CC unattended, operator may reverse
|
||||
|
||||
57. **mealie's account lock lasts 1 hour (in practice 1–2 h), not 24** — *decided by CC unattended 2026-10-01 (R-747) —
|
||||
operator may reverse.* **Question:** how long may a stranger's five wrong passwords lock the household out of mealie?
|
||||
**Options:** (a) keep mealie's default 24 h — the strongest guard against guessing, and a stranger who knows the public
|
||||
login (`admin` / `changeme@example.com`) locks the household out for a day; (b) `SECURITY_USER_LOCKOUT_TIME=1` — the
|
||||
unit's minimum; mealie's hourly job lifts it, so 1–2 h; still 5 tries per lock against guessing; (c) no lock (a huge
|
||||
attempt limit) — strangers cannot lock anyone out, and nothing slows guessing but the hash; (d) rename the login to
|
||||
something unguessable after install — the guard stays and strangers cannot aim it, but it changes what the household
|
||||
types and what the app page shows. **Why (b):** the brief prefers a short lockout over none; a household would not
|
||||
notice the weaker guard (5 tries per 1–2 h against a generated 30-character first password); (d) changes a promise on
|
||||
the page and stays open as an option. **Measured on 9202:** 5 wrong → the right password 423 for 120 min, then 200; a
|
||||
wrong one 401 after. **Limit, stated:** the lock is per account and the name is public, so a stranger can renew it
|
||||
every hour. Catalog `a4597cd`.
|
||||
|
||||
### 2026-09-30 (day) — operator notes, recorded before the work
|
||||
|
||||
- **The day brief runs by day.** Every backup and automatic-update test is started by hand — the night chain's debug
|
||||
|
||||
@@ -28,3 +28,64 @@
|
||||
06:34:53 +18 min right password: 423
|
||||
06:36:53 +20 min right password: 423
|
||||
06:38:53 +22 min right password: 423
|
||||
06:40:53 +24 min right password: 423
|
||||
06:42:53 +26 min right password: 423
|
||||
06:44:53 +28 min right password: 423
|
||||
06:46:53 +30 min right password: 423
|
||||
06:48:53 +32 min right password: 423
|
||||
06:50:53 +34 min right password: 423
|
||||
06:52:53 +36 min right password: 423
|
||||
06:54:53 +38 min right password: 423
|
||||
06:56:53 +40 min right password: 423
|
||||
06:58:53 +42 min right password: 423
|
||||
07:00:53 +44 min right password: 423
|
||||
07:02:53 +46 min right password: 423
|
||||
07:04:53 +48 min right password: 423
|
||||
07:06:53 +50 min right password: 423
|
||||
07:08:53 +52 min right password: 423
|
||||
07:10:53 +54 min right password: 423
|
||||
07:12:53 +56 min right password: 423
|
||||
07:14:53 +58 min right password: 423
|
||||
07:16:53 +60 min right password: 423
|
||||
07:18:53 +62 min right password: 423
|
||||
07:20:53 +64 min right password: 423
|
||||
07:22:53 +66 min right password: 423
|
||||
07:24:53 +68 min right password: 423
|
||||
07:26:54 +70 min right password: 423
|
||||
07:28:54 +72 min right password: 423
|
||||
07:30:54 +74 min right password: 423
|
||||
07:32:54 +76 min right password: 423
|
||||
07:34:54 +78 min right password: 423
|
||||
07:36:54 +80 min right password: 423
|
||||
07:38:54 +82 min right password: 423
|
||||
07:40:54 +84 min right password: 423
|
||||
07:42:54 +86 min right password: 423
|
||||
07:44:54 +88 min right password: 423
|
||||
07:46:54 +90 min right password: 423
|
||||
07:48:54 +92 min right password: 423
|
||||
07:50:54 +94 min right password: 423
|
||||
07:52:54 +96 min right password: 423
|
||||
07:54:54 +98 min right password: 423
|
||||
07:56:54 +100 min right password: 423
|
||||
07:58:54 +102 min right password: 423
|
||||
08:00:54 +104 min right password: 423
|
||||
08:02:54 +106 min right password: 423
|
||||
08:04:54 +108 min right password: 423
|
||||
08:06:54 +110 min right password: 423
|
||||
08:08:54 +112 min right password: 423
|
||||
08:10:54 +114 min right password: 423
|
||||
08:12:54 +116 min right password: 423
|
||||
08:14:54 +118 min right password: 423
|
||||
08:16:55 +120 min right password: 200
|
||||
08:16:55 RESULT: locked for 120 min (last answer 200)
|
||||
08:16:55 right password again: 200 | a wrong one after: 401
|
||||
08:16:58 INFO 2026-10-01T10:12:54 - [192.168.0.180:0] 423 Locked "POST /api/auth/token HTTP/1.1"
|
||||
ERROR 2026-10-01T10:14:54 - User is locked out from 192.168.0.180
|
||||
ERROR 2026-10-01T10:14:54 - User is locked out from 192.168.0.180
|
||||
INFO 2026-10-01T10:14:54 - [192.168.0.180:0] 423 Locked "POST /api/auth/token HTTP/1.1"
|
||||
INFO 2026-10-01T10:16:22 - locked users reset
|
||||
|
||||
10:17:00 [X] stop -> 200 {'ok': True, 'message': 'Stack mealie stop completed'}
|
||||
10:17:32 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'mealie', 'volumes_removed': ['mealie_mealie_data'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'Az alkalm
|
||||
10:17:40 [X] after remove: deployed=False leftovers='/opt/docker/stacks/mealie'
|
||||
08:17:40 removed: False
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# The operator's three rulings of 2026-10-01 built (day session)
|
||||
|
||||
Report and Part table: `felhom.eu/REPORT-rulings-2026-10-01.md`. Monthly run evidence: `../retest-2026-10/`. Golden:
|
||||
`documentation/tests/golden-0.285.0-2026-10-01/`.
|
||||
|
||||
| folder | what |
|
||||
|---|---|
|
||||
| `A/` | the bench created (60 GB, swap 0), the drill reset, 9202 pointed at the drill, 9202's containers before |
|
||||
| `B/` | controller image retention: `B0` the boxes before, `B1` red-proofs, `B2` 9202 deploy + pass (`B2-9202-selfupdate.txt` is empty: that attempt found self-update off on 9202 and was stopped), `B3`/`B4`/`B5` demo boxes before, the floor, after |
|
||||
| `C/` | mealie: `C0` the drill-only commit, `C1` the 1-hour lock measured as a stranger (120 min) |
|
||||
| `D/` | `D1` R-746 digest resolver (unit red + live registry), `D2` R-744 outline fixture on 9202 |
|
||||
| `T/` | teardown: bench destroyed, 9202 back on live, drill reset |
|
||||
| `tools/` | `walk.py`, `repoint.py` (this folder's paths), `b_9202.py`, `b_selfupdate.py`, `c_mealie.py`, `d_outline.py` |
|
||||
@@ -0,0 +1,15 @@
|
||||
git:
|
||||
branch: main
|
||||
repo_url: https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git
|
||||
sync_interval: 15m
|
||||
token: <redacted>
|
||||
username: ""
|
||||
hub:
|
||||
0
|
||||
|
||||
felhom-controller gitea.dooplex.hu/admin/felhom-controller:0.285.0
|
||||
filebrowser gtstef/filebrowser:1.3.3-stable
|
||||
paperless-postgres postgres:18-alpine
|
||||
paperless-redis redis:7-alpine
|
||||
paperless-webserver ghcr.io/paperless-ngx/paperless-ngx:2.20.15
|
||||
traefik traefik:v3.6.7
|
||||
@@ -0,0 +1,5 @@
|
||||
# drill reset 2026-10-01T08:18:54Z
|
||||
drill before: df5a2a2; live: a4597cd
|
||||
df5a2a2 DRILL mealie: SECURITY_USER_LOCKOUT_TIME=1 (R-747 proof on 9202)
|
||||
drill after: a4597cd
|
||||
image lines IDENTICAL
|
||||
@@ -858,7 +858,7 @@ class (an image `VOLUME` at an unmounted path) is still live — `immich-server`
|
||||
| **R-744** | **[P3-LOW] outline's fixture cannot seed outline 1.10.1: no `csrfToken` cookie after `installation.create`.** MEASURED 2026-09-30 on both venues (bench and 9202, the end-to-end re-test's first attempt): `POST /api/installation.create` answered 302 with the session, and `GET /home` set no `csrfToken` cookie (1.9.1 did; the 1.9.1 → 1.10.1 step read back that afternoon because its read-back uses the API key made at 1.9.1). So the NEXT outline step, and any re-test of outline, stops at C1 with „no csrfToken cookie from GET /home". **Needs:** the fixture reads outline 1.10.1's CSRF the way its page does (measure first). `audits/night-rulings-2026-09-30/A/e2e/*outline-attempt*` **-- 2026-10-01:** Outline 1.10 names the cookie `__Host-csrfToken` on a secure request (`server/utils/csrf.ts`); the fixture accepts both names (catalog `9fc7052`). Proven on 9202 at the live pin 1.10.1: seed, read back, unknown id and wrong key refused. Outline has no newer release than 1.10.1, so no step. `audits/rulings-2026-10-01/D/D2-outline-fixture-9202.txt` | **CLOSED 2026-10-01 — fixture fixed, proven on 9202** |
|
||||
| **R-745** | **[P3-LOW] Old CONTROLLER images are never deleted: ~50 versions on each demo box.** MEASURED 2026-09-30 after v0.284.2's one-time sweep: every image no container uses on demo-hp and on the N100 is a `felhom-controller` tag (0.201.0 … 0.283.1); the N100 still reads 3.6 GB reclaimable. Decision 53 covers APP images, and the sweep leaves the controller's own images alone on purpose (the self-update may need the previous one). A release is ~150 MB and there are several a day. **Needs:** the same rule for the controller — keep the running and the previous tag — as a decision (the self-update's rollback reads which image?). `audits/night-rulings-2026-09-30/E/` **-- 2026-10-01:** Decision 56 built: controller v0.285.0 keeps the running image + the previous (the swap record; version order as fallback), deletes older/untagged ones. **Measured first:** the agent rolls back to the RUNNING image (what `/etc/felhom-controller-image` named), never to a previous one the controller hands it. After the floor: demo-hp 84 → 2 controller images (Docker images 15.2 → 11.65 GB), the N100 76 → 2 (6.07 → 1.11 GB), 9202 5 → 2. `audits/rulings-2026-10-01/B/` | **CLOSED 2026-10-01 — controller v0.285.0, floor 0.285.0** |
|
||||
| **R-746** | **[P3-LOW] `image_digest.resolve` ignores a `@digest` in its argument — it answers the TAG's current digest.** MEASURED 2026-09-30: `resolve('redis:7-alpine@sha256:000…0')` returned `sha256:858f…` (the tag's), while a manifest request for that digest answers 404. Every gate today passes it a plain tag, so no gate is wrong; a caller that passes `ref@digest` to ask "is THIS digest still served" gets a false yes. **Needs:** refuse a digest-carrying ref, or ask for the manifest by digest (with a test). `scripts/image_digest.py` **-- 2026-10-01:** `resolve()` asks the registry for the manifest BY DIGEST when the ref carries one; a malformed digest is refused without a request (catalog `804884a`, `scripts/test_image_digest.py`; red: the old resolver fails 3 of 4). Live: `redis:7-alpine@sha256:000…0` → HTTP 404 (was the tag's digest). `audits/rulings-2026-10-01/D/D1-r746-digest.txt` | **CLOSED 2026-10-01 — catalog 804884a** |
|
||||
| **R-747** | **[P3-LOW] A stranger can lock the household out of mealie with five wrong logins.** MEASURED 2026-09-30 on 9202 (the R-741 proof): after the install hold opened, a stranger's default-login tries were refused (401) and after five of them mealie answered 423 (locked) to every login — the generated, correct password included. mealie's own brute-force guard, on an app published on the internet; the setup gate and the install hold do not cover an app after its first setup. Not measured: how long the lock lasts. **Needs:** measure the lock's length; decide whether the page tells the household what to do. `audits/night-rulings-2026-09-30/C/C3-mealie-poll.txt` | **READY — rank P3-LOW; owner: CC** |
|
||||
| **R-747** | **[P3-LOW] A stranger can lock the household out of mealie with five wrong logins.** MEASURED 2026-09-30 on 9202 (the R-741 proof): after the install hold opened, a stranger's default-login tries were refused (401) and after five of them mealie answered 423 (locked) to every login — the generated, correct password included. mealie's own brute-force guard, on an app published on the internet; the setup gate and the install hold do not cover an app after its first setup. Not measured: how long the lock lasts. **Needs:** measure the lock's length; decide whether the page tells the household what to do. `audits/night-rulings-2026-09-30/C/C3-mealie-poll.txt` **-- 2026-10-01:** Measured at v3.28.0 (source + 9202): 5 wrong logins lock the ACCOUNT (not the IP) for `SECURITY_USER_LOCKOUT_TIME` hours (default 24); the lock is lifted by an hourly job; an admin can unlock others via `POST /api/admin/users/unlock`, but the household's only admin is the locked account. Both login names are public (`admin`, `changeme@example.com`). **Fixed** (`09` §3 decision 57, decided by CC unattended — operator may reverse): `SECURITY_USER_LOCKOUT_TIME=1`, catalog `a4597cd`; on 9202 the right password answered 423 for 120 min, then 200; a wrong one still 401 (`audits/rulings-2026-10-01/C/`). **Left:** a stranger can renew the lock every hour (per account, public name — option (d) in decision 57 would end that); the page does not tell the household why it is locked; an INSTALLED mealie takes the new setting only when its compose is rendered again (not measured which act does that). | **NARROWED — the lock is 1–2 h; renewal and the page remain; owner: CC** |
|
||||
| **R-748** | **[P3-LOW] The register-shape gate skipped every row whose id has a letter suffix — so R-88a, R-88b and R-209a were never shape-checked, and its count read 3 short.** FOUND 2026-09-30 (late) while counting the register: `register_shape_gate.py` matched `R-\d+` only; the brief's „the reviewer's regex undercounted by 3” is the same three rows. Fixed the same session: `R-\d+[a-z]?`; decoy `suffix-row-eaten-state` (a suffixed row with its state cell eaten) seen passing with the old pattern and convicted with the new. The register is **382** rows by either count now. | **CLOSED 2026-09-30 — `scripts/register_shape_gate.py`** |
|
||||
| **R-749** | **[P3-LOW] `retest-floating.py` could never start on a fresh bench: it checked for `/opt/upg/upgrade-test.py` on the bench BEFORE the step that copies it there.** FOUND 2026-10-01 at the first full monthly run (decision 55): bench 9401 freshly created by the runbook, the run answered „CANNOT START — missing: the bench LXC 9401 on demo-hp with /opt/upg” in one minute. The runbook says the command syncs the bench itself — it does, but only after the check. On 2026-09-30 the bench had been synced by hand earlier, so nobody saw it. **Needs:** the check asks for what the bench must bring (docker, python3), the sync then provides `/opt/upg`. `audits/rulings-2026-10-01/A/` **-- 2026-10-01:** Fixed the same session (catalog `9e53205`): the check asks for docker + python3; after the sync `/opt/upg/upgrade-test.py` is required. The re-run started at once and finished both apps. | **CLOSED 2026-10-01 — catalog 9e53205** |
|
||||
| **R-750** | **[P3-LOW] The registry no longer holds controller releases older than 0.213.0 (2026-08-12) — something removed them, and nothing records what.** MEASURED 2026-10-01 (anonymous registry API, `audits/rulings-2026-10-01/B/`): `felhom-controller` has 91 tags, the oldest release 0.213.0; `0.201.0` answers 404; Gitea's package list starts 2026-08-12. No runbook, row or memory names a clean-up. Today nothing needs those versions: a box runs a newer one, a whole-guest restore brings the guest's own Docker store back (mp0 `backup=1`), and decision 56 deletes only on the box. **But** a box or a backup that names a removed version cannot pull it again (R-698's shape, for the controller). **Needs:** find what removed them (a Gitea clean-up rule?), and record the rule — or say it was a one-time act. Read-only on DooPlex. | **OPEN — rank P3-LOW; owner: operator (Gitea settings), CC measures** |
|
||||
|
||||
Reference in New Issue
Block a user