Permanent-gate spike: exit test written BEFORE the spike runs (decision 63)
gates / gates (push) Successful in 28s
gates / gates (push) Successful in 28s
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:
@@ -0,0 +1,52 @@
|
||||
# Permanent household gate with family accounts — EXIT TEST (written before the spike ran)
|
||||
|
||||
Written 2026-10-01 ~19:30 UTC, before anything below was built or measured. Model: `audits/login-gate-2026-09-29/B/B-VERDICT.md`.
|
||||
Operator ruling `09` §3 decision 63: option A (extend the box's own gate), measured before any build; the build waits for the
|
||||
operator's go.
|
||||
|
||||
## What is tested
|
||||
|
||||
A gate that stands IN FRONT OF an app permanently (not only until its first setup), letting in only members of the
|
||||
household's family list, each with their OWN login. Apps: **Grimmory** (e-book library; e-readers sync over OPDS / Kobo /
|
||||
KOReader) and **MeTube** (yt-dlp web UI with NO login of its own — its fit verdict R-767 was "stop: no login at all").
|
||||
|
||||
## Venue and method (fences: the spike ships nothing)
|
||||
|
||||
- Scratch guest **9202** only, through its traefik (`https://192.168.0.114` + Host). Grimmory and MeTube are started BY HAND
|
||||
with `docker compose` from throwaway files in `/root/spike/` on 9202 (Grimmory from the held template in
|
||||
`audits/new-apps-2026-10-01/wip/grimmory/`, MeTube from upstream's image) — never the live catalog, never a release.
|
||||
- The gate is a **throwaway auth service** on 9202 (a small Go program in a container on `traefik-public`) answering traefik
|
||||
`forwardAuth`, with a family list of two members, a sign-in page, a session cookie, logout, and a per-visitor lock that
|
||||
reads the visitor by the SAME rule as controller v0.286 (`clientaddr.go`). Its source is kept in this folder as evidence.
|
||||
- The tunnel hop is simulated as in Part A (a container at `172.16.253.2`); one outside address on the real tunnel is not
|
||||
needed for the gate's logic, which is the same code.
|
||||
- Everything is removed afterwards (containers, files, traefik labels, images).
|
||||
|
||||
## Exit items — each PASS or FAIL, measured
|
||||
|
||||
1. **A stranger reaches nothing** of Grimmory or MeTube: every path tried (the front page, the API, static files, an unknown
|
||||
path, MeTube's socket.io websocket upgrade and its download/add API) answers the gate (302 to the sign-in for a browser
|
||||
GET, 401 otherwise) and never the app. Pass = 0 app answers.
|
||||
2. **A family member with their OWN login** (not the dashboard password) gets in; the session lasts **days** (cookie
|
||||
lifetime ≥ 7 days, survives a gate restart); **logout** works (the old cookie is refused afterwards).
|
||||
3. **A stranger's wrong guesses lock only the stranger**: after N wrong sign-ins from one visitor (through the simulated
|
||||
tunnel, rotating a forged leftmost address), that visitor is refused; a family member from another address signs in at
|
||||
once. Pass = both.
|
||||
4. **Grimmory's e-reader paths** (OPDS, Kobo sync, KOReader sync) work for a faithful `curl` of the client through a per-app
|
||||
PATH EXCEPTION — and on those paths **the app's own authentication stays in force**: a stranger there meets the app's
|
||||
own 401 (not the app's data). Pass = the client answers 200 with its own credentials, the stranger 401.
|
||||
5. **The family login cannot reach the box dashboard**: the gate cookie is host-only to the app host; the dashboard does not
|
||||
accept it; the family password does not work at the dashboard login.
|
||||
6. **Cost**, measured: the added time per gated request (ms, gated vs ungated, same request, median of ≥ 50); what happens
|
||||
while the gate's answerer is DOWN (stop it: the gated app must be refused — closed, not open); the build's cost in
|
||||
sessions (estimated from the spike's code size and what the controller already has).
|
||||
|
||||
## Also answered (in the verdict)
|
||||
|
||||
Where family accounts live and who manages them; one sign-in for all gated apps on the domain or per app; how
|
||||
Radicale/Dawarich-style API clients are excepted; whether MeTube becomes publishable behind it.
|
||||
|
||||
## Verdict rule
|
||||
|
||||
The spike PASSES only if items 1–5 all pass. Item 6 is a cost, reported, not a pass/fail. A failed item is reported as
|
||||
measured, with what a build would have to do about it.
|
||||
Reference in New Issue
Block a user