Files
felhom.eu/.claude/rules/live-probes.md
T
admin 95c10954ae
gates / gates (push) Successful in 23s
docs: localisation slice 2 CLOSED (controller v0.254.0) — R-577, R-578, and a probe rule
10-localisation.md §10.3: the saved notes follow the box language at write time, with the
one-night consequence stated rather than hidden; the globe, and the table of WHO reads which
page and where its globe posts — getting that wrong makes the button do nothing, which it did
on /recovery until the live probe found it. Decision 6 superseded a second time; decision 8
(a claim carries the visitor's language) recorded. Decision 5 of §11's anonymous-surface line:
changing what a VISITOR reads is within what an anonymous request may do; changing anything the
household owns is not, and POST /lang can do only the first.

R-578 — the deadlock, and why it is a row rather than a fixed bug: UpdateOffboxStatus holds the
settings write lock while running its callback, boxLang() wants the read lock, sync.RWMutex is
not reentrant. On a real box an off-site run would have hung FOREVER holding that lock. The
symptom was a test suite going from 8 minutes to a 25-minute timeout. Fixed and guarded, but the
guard covers one package and three helper names; the class needs a gate.

R-577 — a guest share visitor still has no way to pick a language, and the household's setting
is the wrong default for a stranger. Deliberately left, pinned by a test, and the operator's to
decide because it is a promise the share feature makes.

.claude/rules/live-probes.md, unconditional: never send a deploy request for an app that is not
installed, not even expecting a refusal — the endpoint accepts first and validates later. Two
sessions made that mistake in two days, the second WITH a prompt line forbidding it. A prompt is
read once; a rule file is loaded every session.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-18 14:31:49 +02:00

2.5 KiB

unconditional
unconditional
true

Live probes — what a probe may touch on a real box

One rule, earned twice in two days by two different sessions, both of which had a prompt line telling them not to. A prompt is read once; a rule file is loaded every session, which is the whole reason this file exists.

Never send a deploy request for an app that is not installed — not even expecting a refusal

POST /api/stacks/<name>/deploy ACCEPTS FIRST AND VALIDATES LATER. It answers 202 Telepítés elindítva and runs the validation inside a goroutine, so a probe that expects a refusal gets a 202 — and if the app happens to need no required field, it is now installed on the box.

  • 2026-09-17: a session probing the required-field refusal picked an app that needed no field. It installed. Recorded in STATUS.md.
  • 2026-09-18: a session that had read that record, and had a prompt line forbidding it, did the same thing with vaultwarden. Recorded in documentation/audits/i18n-slice2-2026-09-18/B/live/README.md.

The lesson that sticks is narrower than "pick a different app": the deploy endpoint cannot be used to probe a refusal at all.

Instead, use a request that is refused BEFORE anything is created:

you want to see use
a deploy-path refusal an app that is ALREADY installed → 409 already deployed
a not-found path a name that exists nowhere → 404
a validator's sentence POST /sharing/shares with a bad name, POST /api/disks/assign with a bad mount point — both refuse before they write
a protected-resource refusal POST /api/stacks/felhom-controller/remove → 403

If a probe does create something, remove it through the product

Not by hand, and not by docker rm: stop it, then POST /api/stacks/<name>/remove with remove_hdd_data and remove_backups, and then verify — no container, no /opt/felhom/stacks/<name>, no volume. Say in the report that it happened. A tidy-up nobody is told about is how the next session learns nothing.

The general shape

Before sending anything to a live box, ask which side of the write the refusal happens on. A refusal that comes after the write is not a refusal you can probe — it is a change you are making.