Commit Graph

470 Commits

Author SHA1 Message Date
admin b7f0f7cef5 Grocy and LubeLogger: two new apps, each with its complete record
gates / gates (push) Failing after 14m4s
60 template directories, 58 offered. Records: onboarding/grocy.md and
onboarding/lubelogger.md, all 61 checks answered, none open. Evidence:
felhom.eu/documentation/audits/new-apps-2026-10-10/.

Grocy 4.7.1 from lscr.io/linuxserver/grocy (grocy publishes no image of its
own). SQLite in one volume, no HDD, ~30 MiB idle, amd64 + arm64, Hungarian UI
91.6 %. First admin class 3: it starts with its documented admin/admin and
after_install replaces that password with a generated one.

LubeLogger v1.7.3 from ghcr.io/hargata/lubelogger. LiteDB in one volume, no
HDD, ~60 MiB idle, amd64 + arm64. First admin class 1 — and it has to be: the
image ships EnableAuth=false, and with that the middleware mints a ticket with
the IsRootUser role for every visitor. Measured on a default start: a stranger
got 200 on /, on /api/vehicles and on /Home/Settings and CREATED A VEHICLE.
The compose entrypoint exports EnableAuth=true and the SHA-256 of a generated
name and password, so the app's own login is on before its first byte (at t+1 s
nothing listening, at t+2 s /api/vehicles already 401).

Two defects found by the walk and fixed before publishing:

1. An after_install command may not contain `$`. The controller runs every
   element through os.Expand and refuses one naming anything outside env:, so
   PHP cannot be inlined. On 9202 the first attempt came back
   `[pw argv dsn db i t e s n q h] not declared in env or has no value — not
   run` and the app sat behind its install hold with admin/admin in place. The
   code now lives in a file the compose entrypoint writes. Written into
   REUSE.md's after_install row as a trap.

2. Grocy's persisted config.php does not follow the image. The image copies
   config-dist.php only when that file is absent, so a volume written by 4.6.0
   and started under 4.7.1 answered HTTP 500 on every page — AUTH_CLASS names a
   class 4.7 moved — while its log said migrations done. The entrypoint now
   deletes the file at every start. The 4.6.0 -> 4.7.1 edge failed before this
   and is proven after it, on both venues.

Ladders, written by upgrade-test.py --write-ladder from both verdicts:
  grocy       4.6.0 -> 4.7.1   bench proven, box proven (guarded Update, 41 s)
  lubelogger  v1.7.2 -> v1.7.3 bench proven, box proven (25.6 s)
Checklist 6.3 came from a real failure, not a forced one: before the config.php
fix the product undid the same step in 346 s with the data intact.

REUSE.md: a fifth healthcheck family (bash /dev/tcp) for an image with no HTTP
client at all, measured in both directions.

Tool fixes made on the way: check-onboarding.py crashed on a Windows console
while printing which ids were open; upgrade-test.py's read_text/write_text used
the platform encoding and wrote a cp1250 em dash into a template full of
Hungarian.
2026-10-10 12:31:34 +02:00
admin b38aa92317 audits: PikaPods read against the catalog (read-only; no template touched)
gates / gates (push) Successful in 7s
NOTHING IN THE CATALOG CHANGED. No template, no .felhom.yml, no
templates.json, no image pin. Output is audits/pikapods-scan-2026-10-10/.

THE GREEN HEART, in PikaPods' own words. Hovering it shows the tooltip
"Project has a revenue sharing agreement." (verified by hovering the heart
beside Actual, A1-heart-tooltip.jpg). Their FAQ: "Open source developers have
the option to enter into a revenue sharing agreement to receive 20% of
revenues their app generates." The mark is NOT permission for Felhom -- it is
an agreement with PikaPods, on terms we have not seen. It only shows the
author is open to such an arrangement at all.

Finding the mark took reading the DOM: the hearts are not text and not a
title attribute. Each card carries three Vuetify icons, all three present on
every card, and the green one (rgb(76,175,80)) is display:none where there is
no agreement. Counting "hearts in the page text" would have returned zero on
all 126.

NUMBERS. 126 apps on PikaPods, 39 marked. 58 template dirs here (56 offered +
plant-it abandoned + wger hidden -- which reconciles with the website's 56 +
FileBrowser built-in). 25 on both, 33 of ours not there, 101 of theirs not
ours, 11 of the 25 shared carry the mark.

LICENCE COMFORT: one row moved, and I will not dress it up as more.
sparkyfitness is there WITH the mark, consistent with what its author already
told us (R-784) -- so he demonstrably does commercial-hosting agreements.
tandoor, emby, plex, outline, calcom and wanderer are NOT on PikaPods at all,
so the scan says nothing about them. n8n and docmost ARE hosted there WITHOUT
a mark: a fact about PikaPods' risk appetite, not a permission we can borrow.

TEN CANDIDATES, none added, each licence read at its own repo and cited:
Grocy (MIT), Firefly III (AGPL-3.0), Monica (AGPL-3.0), LubeLogger (MIT),
Storyteller (MIT), PdfDing (AGPL-3.0), Memos (MIT), Wealthfolio (AGPL-3.0),
Kavita (GPL-3.0), PhotoPrism (AGPL-3.0). Developer and company tools were
excluded wholesale. Each would still go through NEW-APP-CHECKLIST.md.

JOPLIN WAS SHORTLISTED AND DROPPED ON ITS LICENCE, which is the most useful
thing in this scan. Its repo root says AGPL-3.0-or-later "unless a directory
contains a LICENSE or LICENSE.md file" -- and packages/server, the part we
would host, carries the Joplin Server Personal Use License: "the Software may
be used for personal non-commercial purposes only", and the licensee may not
"grant others the right to use the Software for a fee". Same shape as
SparkyFitness: open client, restricted server. GitHub's repo-level licence
field says AGPL-3.0 and would have hidden it.

Two other reads worth keeping: PdfDing's GitHub mirror has NO licence file at
all (the project lives on Codeberg, where it is AGPL-3.0) -- trusting the
mirror would have called it unlicensed; and photoprism/joplin both report
NOASSERTION to the API, so both needed the file read rather than the badge.

Register: 0 opened, 0 closed. The brief expected a row only for a licence
problem in an app we already ship; none turned up. No contact with PikaPods or
any author.
2026-10-10 09:47:39 +02:00
admin 0a52dd6f28 rules: "The system poster stays true" (section 6, all five copies identical)
gates / gates (push) Successful in 7s
The shared rule file carries the same wording in felhom.eu, felhom-controller,
felhom-agent, app-catalog-felhom.eu and the workspace root on DooPlex --
"change all five or none" -- so this is this repo's copy of a rule added in
felhom.eu a08bd3cbd5.

A session that changes a fact listed in
architecture/felhom-system-poster.facts.md (a machine, a role, a traffic path,
a backup tier, a time, a retention, a key, a known gap) updates that file in
the same commit; fixes the poster's text if the change is text only; or adds
"System poster needs a refresh: <what changed>" to STATUS. The report names
which of the three it did.

The poster is drawn in Claude Design and nothing in the repo renders it, so
scripts/poster_facts_gate.py only WARNS when the facts outrun the drawing --
it never fails a push, because a refresh needs the operator and another tool.

Verified identical to the other four copies by diff, before and after.
2026-10-09 18:10:25 +02:00
admin 31e9651591 wger: install check asks for 256 MB (operator ruling D10, R-762 follow-up)
gates / gates (push) Successful in 5s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 14:22:48 +02:00
admin eec9a0d5af wger: gunicorn with 2 workers instead of the development server (R-762)
gates / gates (push) Successful in 6s
WGER_USE_GUNICORN=True + WEB_CONCURRENCY=2. Proven on bench 9401 (anon 44 %) and
scratch 9202 (anon 64.1 % of 384M, 0 oom_kill, 0 restarts; login, CSS and a photo
200). wger stays lifecycle: hidden. No ladder entry: no image moves.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 10:10:07 +02:00
admin 32d134639c REPORT/CHANGELOG: 2026-10-07 day
gates / gates (push) Successful in 6s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-07 14:21:20 +02:00
admin 0fab00bb86 Shared rule file: no hub image build or deploy in a session the operator does not attend (09 §3 decision 162)
gates / gates (push) Successful in 9s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-07 09:55:10 +02:00
admin 1f01f1a6d1 CHANGELOG + REPORT: the held branch merged
gates / gates (push) Successful in 6s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-07 09:31:53 +02:00
admin 872039d842 Merge night-held-2026-10-06: R-777, R-612, R-782, R-805, R-806, R-733 (09 §3 decision 161)
gates / gates (push) Successful in 6s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-07 09:09:34 +02:00
admin 57f15c3ac5 Shared rule file: rule 11 — every helper prompt carries the brief's fences in full (09 §3 decision 160)
gates / gates (push) Successful in 10s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-07 08:52:48 +02:00
admin e5a59848f1 R-777 (held): Jellyfin and Emby no longer treat every internet visitor as the home network
gates / gates (push) Successful in 5s
Jellyfin: KnownProxies 172.16.0.0/12 seeded into network.xml. Emby:
LocalNetworkSubnets 10.0.0.0/8 + 192.168.0.0/16 seeded into system.xml.
Fresh volume or empty list only. Measured on 9202 through the simulated
tunnel: remote-off user 200 -> 403; LAN household still 200.

Held on night-held-2026-10-06 (night fence); not for main tonight.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 21:10:48 +02:00
admin 3f4611cbb6 R-733: the memory watch records each container's swap peak and the venue's swap
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 21:09:26 +02:00
admin 18599037d3 R-806: gramps-web runs 2 gunicorn workers (held — not for main tonight)
The image's default 8 workers filled the 1024M limit; workers were
OOM-killed and :5000 mostly timed out. Measured on the bench both ways.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 21:07:59 +02:00
admin 816c5577fb R-805: the persistence gate names an empty bind (reported, not judged)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 20:53:38 +02:00
admin 093e5ed231 R-782: homepage allows the box's own host name (held — not for main tonight)
Without HOMEPAGE_ALLOWED_HOSTS every /api/* call under the box's name was
refused (400), so services and widgets stayed empty. Measured on the
bench. Glance's public page measured; its login is an operator question.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 20:52:28 +02:00
admin d4150d7377 R-612: wishlist's healthcheck reads the first-boot seed (held — not for main tonight)
A killed seed still started the app (upstream's `exec pnpm start` is on
its own line), so sign-ups failed while the box read healthy. Healthy
now needs the role rows and a group or user. Measured on the bench.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 20:47:54 +02:00
admin d63ea3591e box_walk: a target table (9202, 9201, tester-1 via a jump through the HP box); the Tester 1 guest is a test box for the admin seed (R-892, decision 158)
gates / gates (push) Successful in 5s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 19:04:57 +02:00
admin a5a5b51c77 wishlist: after_setup close/open commands for its own sign-up switch + min_controller 0.301.0 (R-717), proven live on 9202
gates / gates (push) Successful in 7s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 16:07:39 +02:00
admin cf1ed4389d wger: DJANGO_DEBUG=False + a wger-files nginx serving /static and /media (R-762); a definition step proven on the bench and on 9202, written by --write-ladder --to-definition
gates / gates (push) Successful in 8s
wger stays hidden. Bench 9401 proven (anon 50.3 %, files server 15.9 %); 9202 proven (done 59.4 s,
photo 404 -> 200, CSS 404 -> 200). Evidence: felhom.eu/documentation/audits/design-build-2026-10-06/F/.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 15:39:34 +02:00
admin c48a0db3a7 Bench: --move-to tests a step that adds a service; --write-ladder --to-definition writes it (R-762 tooling); rules copies line
gates / gates (push) Successful in 7s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 14:49:31 +02:00
admin ecb8552ee9 vaultwarden 1.36.0 -> 1.37.4: its first ladder step, proven on the bench and on 9202 (R-890); instruction files kept true (decision 150)
gates / gates (push) Successful in 8s
Written by upgrade-test.py --write-ladder from both verdicts. Bench 9401: harness v5,
anon peak 16.3 %, seed read back. Box 9202: guarded Update done in 12.3 s, seed read back,
seeded through the admin invite inside the box (decision 149).
CLAUDE.md: stale gate counts, the CI/R-161 and catalog_since-gate sentences, the checklist count,
steps/ in the layout, engine service counts, decoy gate path. Factual only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 13:50:39 +02:00
admin 6b4877d556 R-890: the test box (scratch 9202) may seed vaultwarden through its admin invite, inside the box
gates / gates (push) Successful in 7s
`09` §3 decision 149. box_admin_seed_allowed(): not the bench, FELHOM_BOX_ADMIN_SEED=1,
demo-hp/9202 only, an app this run installed, the box on the drill catalog. The token is read
inside the box and handed to curl on stdin; only HTTP codes come back.
Tests: BoxAdminSeedGuard (red-proved).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 13:39:48 +02:00
admin 65130c6c03 REPORT: the operator's ten answers (2026-10-06)
gates / gates (push) Successful in 3s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 12:29:01 +02:00
admin 1938921ae2 CHANGELOG: R-747, R-774, R-734, R-624 (operator rulings 144, 148, 145, 146)
gates / gates (push) Successful in 8s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 11:28:46 +02:00
admin aed80ee143 R-624: the bench (only) seeds vaultwarden through its admin invite; run secrets redacted and shredded
`09` §3 decision 146. vaultwarden's fixture tries the household's own
/identity/accounts/register first (400 while sign-up is closed, R-512); on
the BENCH ONLY it then signs in to /admin with the ADMIN_TOKEN the bench
generated for this run, invites the drill address and registers it — the
route measured on 9202 2026-09-15 (E1-vaultwarden-spike). The token goes to
curl on stdin, the admin cookie in a 0600 header file that is shredded.
The dead /api/accounts/register (404 on 1.36) is gone.

bench_admin_seed_allowed(): the venue is the bench's (upgrade_boxport.Venue
VENUE="bench"), FELHOM_BENCH_ADMIN_SEED=1, and /opt/docker/stacks does not
exist (every Felhom box has it). Any one missing refuses; the edge stays
inconclusive with what was tried.

upgrade-test.py: the run's .env is written 0600 and shredded after the
teardown; every printed line and every evidence file is redacted of the
generated deploy secrets and the fixture's own password/key.
zipline needs no held secret: its first-run /api/setup already makes the
SUPERADMIN with a per-run password (measured 2026-09-30), now redacted too.
Tests: BenchAdminSeedGuard, SecretHygiene (red-proved).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 11:27:35 +02:00
admin b0939cf309 R-734: the update test ignores an app's listed marker files, each with its reason
`09` §3 decision 145. MARKER_IGNORE in upgrade-test.py: per app, the files the
files_may_change mark does not count — first immich's six 13-byte
{encoded-video,library,backups,profile,thumbs,upload}/.immich folder markers,
rewritten at every start (bench measurement 2026-09-30). A listed file is
ignored only when changed/added and still <= 64 bytes; a removed or grown
marker, any unlisted file, and a moved tree the file walk cannot name still
mark the step. The verdict records files_ignored with the reasons.
HARNESS_VERSION 5. Tests: test_upgrade_bench.py MarkerIgnore (red-proved).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 11:27:35 +02:00
admin ec72c9dd5a R-747 + R-774: one sentence each on mealie's and Karakeep's page (hu + en)
mealie (09 §3 decision 144): five wrong logins lock the account for 1-2 hours,
even for the right password — wait, then sign in again.
Karakeep (decision 148): the official phone app sends crash reports to its
makers (Sentry).
Both are a new last first_steps entry (app_info has no notes field); the
Hungarian freeze admits them with the reason (check-copy-i18n --add-app).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 11:27:35 +02:00
admin d1a148408f REPORT: the morning after (2026-10-06)
gates / gates (push) Successful in 4s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 08:50:51 +02:00
admin 3896cb0089 R-776/R-613 proven on 9202 (with controls): comments point at the evidence; CHANGELOG
gates / gates (push) Successful in 7s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 08:46:42 +02:00
admin c5674ce332 R-613: nextcloud's probe asks for "installed":true — "installed" alone matched an install that never finished
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 08:17:49 +02:00
admin 1d3af8edfb R-776: nextcloud sees each visitor behind the tunnel (trusted docker networks; 9202 checklist 3.6 re-measure owed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 08:17:49 +02:00
admin 5f7bf7729e R-776: vikunja sees each visitor behind the tunnel (trusted docker networks; 9202 checklist 3.6 re-measure owed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 08:17:49 +02:00
admin ccc2be57f8 R-776: zipline sees each visitor behind the tunnel (trusted docker networks; 9202 checklist 3.6 re-measure owed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 08:17:49 +02:00
admin 462e66f0ca R-776: kimai sees each visitor behind the tunnel (trusted docker networks; 9202 checklist 3.6 re-measure owed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 08:17:49 +02:00
admin d955df1f15 REPORT: the burn-down night (2026-10-06)
gates / gates (push) Successful in 4s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 02:13:13 +02:00
admin 75f35842a5 CHANGELOG: R-426 decoys (image-pins holes closed, image-resolvable, volume-persistence)
gates / gates (push) Successful in 5s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 01:43:49 +02:00
admin 979ababb8f R-426: volume-persistence decoys - the injected-prober suite run from here, and a dead runtime end to end
test_gate_decoys.py runs test_check_volume_persistence.py (the blind and
crying-wolf probers refused rc=3, `wrote nothing` never CLEAN, the papra
signature convicted) and requires it green, so COVERS is a fact; and runs
the working-tree gate in a scratch catalog with PATH = ONLY a stub docker
that fails every call: a runtime that answers nothing, no docker, nothing
to judge are each HARNESS REFUSED rc=3, never 0. An always-succeeding stub
is deliberately not used - it would walk the prober into the host
filesystem. COVERS gains "volume-persistence".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 01:42:38 +02:00
admin 31d4f4e6de R-426: image-resolvable decoys, end to end through a PATH-stub docker
The gate's unit tests inject `resolver`, so docker_resolver - where both
live traps sit - never ran under test. test_gate_decoys.py now copies the
working-tree gate into a scratch catalog and runs it with PATH = ONLY a
stub docker (the real runtime acts on DooPlex and cannot be reached; no
network). 9 cases: a `manifest unknown` pin is convicted naming the app;
rc=0 carrying a throttle or any error text, a docker that resolves the
.invalid canary too, no docker, nothing to judge are INCONCLUSIVE or
HARNESS REFUSED, never 0; a throttle or unrecognised error on rc=1 is
never an accusation. COVERS gains "image-resolvable".
check-image-resolvable.py: the "same shape as check-image-pins.py"
comment was made false by the image-pins fix; it now says why the
narrower regex is safe.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 01:42:38 +02:00
admin d3e14eb961 R-426: image-pins gate gets a decoy suite (and three holes closed)
check-image-pins.py now refuses a QUOTED `"image":` key (was not read at
all), an interpolated `${APP_IMAGE:-nginx}` ref (the tag cannot be read),
and `@sha256:` with no 64-hex digest behind it (the label of a pin). It
takes --root=<dir> (the decoy seam) and accepts the runner's --all.

test_gate_decoys.py: 17 image-pins cases — nine facts that must be
refused (untagged, a registry port read as a tag, quoted/capital :latest,
:edge, a comment claiming a pin, the quoted key, interpolation, a fake
digest), seven inert/genuine shapes that must pass, and the real catalog.
COVERS gains "image-pins".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 01:42:38 +02:00
admin c265b371e2 CHANGELOG: the burn-down night (R-758, R-127a, R-798, R-763, R-764, R-786, R-731; R-776/R-613 held for 9202)
gates / gates (push) Successful in 6s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:50:24 +02:00
admin 181bc0dc3c R-731: the shape-switch control is standing — scripts/check-currency.py (stdlib) with fixture tests
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:05 +02:00
admin c67b809b6b R-786: SparkyFitness record — 1.6 done (every env read of the server source listed), 1.7 read in source (image read owed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:05 +02:00
admin 66d1abb101 R-127 (a): four data-encrypting keys flagged data_key (n8n, calcom, wanderer, bookstack APP_KEY) + gate data-key with decoys
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:05 +02:00
admin 84ced4478b R-798: grimmory sets the API-docs switch v3.5.0 reads (API_DOCS_ENABLED=false) instead of the dead SWAGGER_ENABLED
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:05 +02:00
admin 1b24d139bd R-758: mem_limit is the sum of the compose limits — eight figures corrected, gate mem-limit-sum (--fast, stdlib) with decoys
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:05 +02:00
admin 8940d768d3 check-probe-matches-compose: accept --all as a no-op (catalog_gates --all read INCONCLUSIVE on a clean tree)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:04 +02:00
admin db88ee94f6 R-764: wger sends its mail through the box's relay (smtp_mapping, plaintext :2526, ENABLE_EMAIL gate; hidden app, 9202 boots owed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:04 +02:00
admin 1968527a86 R-763: wger closes its own sign-up and guest users (hidden app; 9202 stranger walk owed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:04 +02:00
admin 51a3d81d55 test_gate_decoys: the ratchet ABOVE case removes English instead of adding it (stale since full coverage)
The case added privatebin's English and expected the gate to report coverage ABOVE a ceiling of 0;
since the catalog reached full coverage nothing was missing and the gate rightly said OK, so the
suite was red on its own premise. Red-proof: with check 5 disabled the case fails.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:04 +02:00
admin 4828dc754d burn-down round 2: R-593 papra field copy, R-760 vikunja healthcheck reason, R-594 English allow-list, R-605 refusal exit 3, R-781 onboarding decoy clone, R-806 scheme; stale runner test fixed
gates / gates (push) Successful in 4s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 19:15:02 +02:00