catalog_gates — apps: plex  [--fast]
  --fast SKIPPED: image-resolvable, volume-persistence, gate-decoys — they need network and a container runtime and take minutes
  per app (gate-decoys: ~3 minutes on its own), so they are NEVER in a hook. They
  remain deliberate periodic runs: start
  of a catalog campaign, before a publish train, or when a template's volumes:/image
  changes. Run them with no --fast, on a scratch host.

==============================================================================
== gate: image-pins   (check-image-pins.py)
==============================================================================
image-pin gate OK — 65 templates, 0 unpinned images

==============================================================================
== gate: engine-major   (check-engine-major.py)
==============================================================================
engine-major gate — range origin/main..HEAD: 0 compose file(s) changed, 0 engine pin(s) compared
engine-major gate OK — no forbidden engine major, and no engine major bundled with another image move (rule: CLAUDE.md, amended by R-469 2026-09-21)

==============================================================================
== gate: catalog-since   (check-catalog-since.py)
==============================================================================
catalog-since gate — range origin/main..HEAD: 0 compose file(s) changed, 0 image move(s) dated
catalog-since gate OK — every image move in the range carries a catalog_since on or after its commit day

==============================================================================
== gate: copy-i18n   (check-copy-i18n.py plex)
==============================================================================
copy-i18n: matcher controls OK (positive „Jelentkezz be…" convicts, negative „Encrypted notes…" does not)
copy-i18n: retrieval-promise vocabulary matches the sibling clone
copy-i18n: 65 apps · 3391 Hungarian copy strings frozen · 3391 with English
copy-i18n: translated so far — actualbudget 52/52, adventurelog 53/53, audiobookshelf 54/54, bentopdf 47/47, bookstack 56/56, calcom 56/56, calibre-web 60/60, claper 52/52, code-server 52/52, crafty-controller 57/57, dawarich 54/54, docmost 51/51, emby 22/22, ghost 54/54, gitea 54/54, glance 43/43, gokapi 48/48, grafana 50/50, gramps-web 53/53, grimmory 57/57, grocy 54/54, home-assistant 50/50, homebox 50/50, homepage 42/42, immich 59/59, jellyfin 54/54, karakeep 52/52, kimai 53/53, komga 56/56, lubelogger 57/57, mealie 53/53, metube 51/51, n8n 45/45, navidrome 55/55, nextcloud 60/60, nzbget 55/55, onlyoffice 52/52, opengist 49/49, outline 53/53, paperless-ngx 66/66, papra 50/50, plant-it 48/48, plex 57/57, privatebin 45/45, prowlarr 44/44, qbittorrent 54/54, radarr 55/55, radicale 51/51, rallly 48/48, recipe-importer 52/52, romm 74/74, sabnzbd 60/60, seerr 50/50, sonarr 55/55, sparkyfitness 54/54, tandoor 49/49, termix 46/46, transmission 52/52, uptime-kuma 49/49, vaultwarden 56/56, vikunja 50/50, wanderer 50/50, wger 52/52, wishlist 47/47, zipline 52/52
copy-i18n: OK

==============================================================================
== gate: probe-matches-compose   (check-probe-matches-compose.py plex)
==============================================================================
probe-matches-compose: 1 app(s), mode: full

probe-matches-compose: OK — every probe dials the port (and, where it can fail, the path) that the app's own compose healthcheck dials

==============================================================================
== gate: probe-measured   (check-probe-measured.py plex)
==============================================================================
probe-measured: OK — 0 probes, each with a measured before/after

==============================================================================
== gate: test-record   (check-test-record.py plex)
==============================================================================
test-record gate — 1 template(s) read, 0 carry a ladder, 0 convicted

==============================================================================
== gate: test-record-move   (check-test-record-move.py)
==============================================================================
test-record-move gate — range origin/main..HEAD: 0 compose file(s) changed

==============================================================================
== gate: onboarding   (check-onboarding.py)
==============================================================================
onboarding gate — 63 checklist ids; 65 template dirs: 53 exempt (published before 2026-10-01), 12 new; 2 exempt app(s) with a record (shape-checked): sparkyfitness, wger
  NOT CHECKED here (sibling repository absent — the pre-push hook on DooPlex checks them): 11 path(s)
    https://github.com/nzbgetcom/nzbget
    the app needs the internet for the one thing it exists to do (reach the household's Usenet provider), and for nothing else. No account with us, no token, no call home once the update check is off
    NNTP, usually 563 with TLS, and OUTGOING ONLY
    https://github.com/qbittorrent/qBittorrent
    https://github.com/sabnzbd/sabnzbd
    the app needs the internet for the one thing it exists to do (reach the household's Usenet provider), and for nothing else. No account with us, no token, no call home
    NNTP, usually 563 with TLS, and OUTGOING ONLY
    https://github.com/transmission/transmission
    gunicorn with 2 workers since 2026-10-08 (`WGER_USE_GUNICORN=True`, `WEB_CONCURRENCY=2`, R-762): 2 × „Booting worker" in the log; login page, CSS and a photo 200; 10-min watch 0 oom_kill, 0 restarts
    DJANGO_DEBUG=False` (R-762, 2026-10-06): `collectstatic` runs at start; the static files are served by `wger-files` (nginx)
onboarding gate OK

==============================================================================
== gate: family-gate   (check-family-gate.py)
==============================================================================
family-gate: newest baked golden 0.344.0 >= 0.287.0
family-gate gate OK: 4 family-gated template(s) ['glance', 'grimmory', 'homepage', 'metube']

==============================================================================
== gate: mem-limit-sum   (check-mem-limit-sum.py plex)
==============================================================================
mem-limit-sum gate OK: 1 template(s), every mem_limit is the sum of its compose limits

==============================================================================
== gate: db-credentials   (check-db-credentials.py plex)
==============================================================================
db-credentials gate OK: 1 template(s), 0 database password reference(s), each a `type: secret` field

==============================================================================
== gate: data-key   (check-data-key.py plex)
==============================================================================
data-key gate OK: 1 template(s), 0 data key(s), every flag agrees with the name rule and REGISTRY

==============================================================================
== gate: unclean-boot-images   (check-unclean-boot-images.py plex)
==============================================================================
unclean-boot-images gate OK: 0 after_unclean_boot block(s) on a proven image []

==============================================================================
== gate: guide-version   (check-guide-version.py plex)
==============================================================================
guide-version: 1 app(s) · 1 guide(s) current · 0 may be STALE · 0 hidden (checked_version empty) · 0 without a guide
guide-version: advisory — never fails a push

==============================================================================
== gate: login-kind   (check-login-kind.py)
==============================================================================
check-login-kind gate OK — 8 login_kind key(s), each one of first_visit, email, none

==============================================================================
== gate: image-volumes   (check-image-volumes.py)
==============================================================================
check-image-volumes gate OK — 4 registered data path(s) mounted

==============================================================================
== gate: redis-persistence   (check-redis-persistence.py)
==============================================================================
check-redis-persistence gate OK — 7 Redis service(s), none append-only

==============================================================================
== gate: privileges   (check-privileges.py)
==============================================================================
allow-list copy: byte-identical to the controller's
check-privileges: 120 files judged, every class-setting on the allow-list

==============================================================================
== gate: download-binds   (check-download-binds.py)
==============================================================================
download-binds gate OK — 6 download folder(s), every one `excluded` or `optional` by a named ruling (metube): metube:media/metube=optional, nzbget:media/nzbget=excluded, qbittorrent:media/torrents=excluded, sabnzbd:media/usenet=excluded, transmission:media/transmission=excluded, transmission:media/transmission/watch=excluded

==============================================================================
== gate: security-scan   (check-security-scan.py)
==============================================================================
security-scan (R-986, WARN-FIRST — it lists, it never refuses): /mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu
  govulncheck: no Go module in this repo — nothing to scan
  gitleaks 8.24.3 on -n 1 HEAD (the newest commit; nothing unpushed): 0 hit(s)
security-scan: 0 new hit(s), 0 accepted — warn-first, the push goes on

==============================================================================
== gate: upstream   (check-upstream.py)
==============================================================================
upstream gate OK: 97 pins, every one names its upstream (21 stated gaps)

==============================================================================
== summary
==============================================================================
  image-pins           OK            (exit 0)
  engine-major         OK            (exit 0)
  catalog-since        OK            (exit 0)
  copy-i18n            OK            (exit 0)
  probe-matches-compose OK            (exit 0)
  probe-measured       OK            (exit 0)
  test-record          OK            (exit 0)
  test-record-move     OK            (exit 0)
  onboarding           OK            (exit 0)
  family-gate          OK            (exit 0)
  mem-limit-sum        OK            (exit 0)
  db-credentials       OK            (exit 0)
  data-key             OK            (exit 0)
  unclean-boot-images  OK            (exit 0)
  guide-version        OK            (exit 0)
  login-kind           OK            (exit 0)
  image-volumes        OK            (exit 0)
  redis-persistence    OK            (exit 0)
  privileges           OK            (exit 0)
  download-binds       OK            (exit 0)
  security-scan        OK            (exit 0)
  upstream             OK            (exit 0)

all catalog gates OK
