Files
felhom.eu/REPORT-gate-rollout-2026-09-29.md

91 lines
7.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# REPORT — 2026-09-29 afternoon: the setup gate on the other 30 apps; "Done" asks the app first; open sign-up closed after the first admin; claper's password never in code
Architecture read first: `09` §3 decisions 45–47, `01-topology-and-trust.md` §5, `audits/login-gate-2026-09-29/B/B-VERDICT.md`,
`app-catalog-felhom.eu/FIRST-ADMIN.md`, rows R-707, R-711, R-713. Controller **v0.281.0** (one release). Floor 0.281.0;
both demo boxes run it. Catalog `6faf432`. Evidence: `documentation/audits/gate-rollout-2026-09-29/`
(0 = Part 0, A, B = per-app, C = sign-up, D = claper, redproofs).
## The Parts
| Part | Step | State | Note |
|---|---|---|---|
| — | decision 47 recorded first | done | `09` §3 + `01` §5 before any work |
| 0 | installed app never gated by a catalog change | done — **holds** | 9202: vikunja installed ungated and set up, then the drill catalog added `setup_gate: true`, synced, two loop ticks, a controller restart: still answered strangers, no gate file, no record (`0/P0-1`, `P0-2`). Code: the gate is set only in `DeployStack`. Pinned by `TestSignupBlock_NeverOnAnAppThisBoxDidNotGate` (RP23). After the live push, the demo boxes' installed class-4 apps (adventurelog, docmost, opengist, romm; opengist) got no gate and no block (`0/P0-3`) |
| A1 | "Done" asks the probe first | done | refuses while the app says not done and when it cannot be read (409 + the sentence). Live: zipline pressed before its setup → 409, twice (`A/`, `B/B2-zipline-probe-before.txt`) |
| A2 | confirm for an app without a probe | done | in-page `felhomConfirm` with the sentence (native confirm is banned by a gate) |
| A3 | tests + red-proofs | done | RP17, RP18 |
| B | the gate on the other 30 | done — **28 gated (25 fully proven, 3 opening not provable here), 2 not gated** | per-app table below |
| C1 | spike: how sign-up can be closed | done, **mechanism changed** | opengist, wishlist: only in their own admin settings; vikunja: an env, but then no way to add a user but its CLI. Chosen: a box-side block of the app's own sign-up address + a household 15-minute window (CC-unattended decision, `09` §3 decision 47) |
| C2 | per app | done | 11 apps let a stranger sign up after the setup → blocked and refused; 11 more refuse by themselves; window proven (gitea, calcom, vikunja) and closes again (gitea, calcom) |
| C3 | apps that cannot close sign-up | **1: wanderer** | not gated at all (R-714) — STATUS asks |
| D | R-713 | done | code-bound values refused; `${NAME|base64}`; claper proven live with a typed password holding `"` and `#{` (default refused, typed signs in). RP24 |
**Recommendation not followed, one line why (standing rule 4):** the ruling says "only the admin adds people, from the
app's own user page"; for apps with no such page (opengist, vikunja, termix, sparkyfitness, adventurelog) the page
says to open sign-up for 15 minutes instead — the only way a family member can join those apps at all.
### Part B / C — one row per app (9202, controller 0.281.0, drill catalog)
| app | gate proven (stranger refused · household reached setup · opened · answered after) | opened by | sign-up after the setup |
|---|---|---|---|
| actualbudget | yes | probe `data.bootstrapped` (M) | refused by the app |
| komga | yes | probe `isClaimed` (M) | refused by the app |
| jellyfin | yes | probe `StartupWizardCompleted` (M) | refused by the app |
| romm | yes | probe `SYSTEM.SHOW_SETUP_WIZARD` (M) | refused by the app |
| zipline | yes | probe `/api/server/public firstSetup` (M) | refused by the app (`userRegistration: false`) |
| termix | yes | probe `setup_required` (M) | **was open → blocked** |
| emby | yes | button | refused by the app |
| navidrome | yes | button (no JSON status) | refused by the app |
| ghost | yes | button (status is a list — R-715) | refused by the app |
| home-assistant | yes | button (status is a list — R-715) | refused by the app |
| gitea | yes | button | **was open → blocked** |
| docmost | yes | button | no public sign-up |
| calcom | yes | button | **was open (a stranger's account was created) → blocked** |
| tandoor | yes | button | "Sign Up Closed" by the app |
| gramps-web | yes | button (its status answers 405 — R-715) | answered 500 → blocked anyway |
| adventurelog | yes | button | **was open → blocked** |
| homebox | yes | button | **was open → blocked** |
| papra | yes | button | **was open → blocked** |
| sparkyfitness | yes | button | **was open → blocked** |
| vikunja | yes | button | **was open → blocked**; window let a family member in |
| opengist | yes | button | **was open → blocked** |
| wishlist | yes | button | **was open → blocked** |
| radarr, sonarr | yes | button | single user; their API key was public BEFORE the setup — the gate hides it |
| recipe-importer | yes | button | our own app, open until a password is set — the confirm says so |
| seerr | stranger refused, household reached setup | **opening not proven** (needs a media server) | not measured |
| outline | stranger refused, household reached setup | **opening not proven** (needs e-mail / SSO) | not measured |
| rallly | stranger refused, household reached setup | **opening not proven** (e-mail) | not measured |
| wanderer | **not gated** | — | open (R-714) |
| plant-it | not installable (`lifecycle: abandoned`); the template carries the gate | — | — |
## Claims in the brief that turned out wrong (or right), named
- **"A catalog change never gates an installed app"** — **right** (measured on 9202 and read on both demo boxes).
- **"14 of the 34 have a probe"** — **wrong**: 9 have a probe that works (3 from the morning, 6 today); 3 more have a
status the box cannot read (ghost, home-assistant — lists; gramps-web — 405, R-715); zipline's upstream route was
wrong (`/api/setup` answers 403 after the setup; `/api/server/public` works).
- **"The first admin is the first registered user on opengist and wishlist"** — **right** (measured: the household's
sign-up became the admin; after it, a stranger could still sign up).
- **"Each app in R-711's list can close sign-up"** — **wrong** as a per-app switch: opengist and wishlist keep it only
in their admin settings, vikunja only as a start-up env; and wanderer cannot be closed at all today. The box-side
block closes all but wanderer.
- **"An env switch needs a restart"** — **right** for vikunja (read at start); not used — the block needs no restart.
- **"Register 346 rows"** — was **350** at the start of this session (the morning session ended at 350).
## Also found
- A probe that never flips blocks the household's press (fail closed; measured on gramps-web) → R-715.
- calcom created a stranger's account after the setup (measured) — closed.
- Apps installed before today keep their open sign-up (demo boxes only) → R-716, needs an operator word.
## Rows
Closed: R-707, R-711, R-713. Opened: R-714 (wanderer), R-715 (probe shapes), R-716 (installed apps' sign-up, operator).
**Register 350 → 353 rows.**
## Teardown
Machines: 9202 — every test app removed through the product (the scratch drive keeps some app folders, R-442's
refusal as before); no gate or block file left; back on the live catalog; the drill catalog reset to live `main`.
Demo boxes — read only (plus the floor). Host: nothing. Hub: floor 0.281.0. ep0: untouched.