3.2 KiB
REPORT — app lifecycle replaces the retired/ move (TASK-F Part 1, catalog half), 2026-07-21
Baseline 857ba53, clean tree.
What changed and why
The retired/ directory mechanism shipped earlier the same day is withdrawn. It un-offers an app
correctly, but the controller discovers catalog templates by directory — so removing one makes the
orphan detector see the template as GONE for anyone already running the app, flagging their working
install Elavult and offering a Törlés button. Withdrawing an app must never take a working app away
from a customer.
Replaced by an optional top-level lifecycle: in .felhom.yml (controller v0.158.0/.1):
available (default, absent/empty ≡ this) / hidden / abandoned.
plant-itreturns totemplates/withlifecycle: abandoned— the first user of the mechanism and the case that motivated it.retired/is removed. Catalog: 53 apps (52 offered).- Its compose is deliberately unchanged. It pins
msdeluise/plant-it:0.10.0, a repository that does not exist (the real one is-server), and the app is not installable — rewriting it would imply it is. The evidence for abandonment is recorded in the template's own header comment.
Live-proven on 9201
Through the normal git-sync and the real endpoints, not a hand-copy:
| check | result |
|---|---|
lifecycle: abandoned present in /opt/docker/stacks/plant-it/.felhom.yml |
yes |
| plant-it on the Alkalmazások page | 0 occurrences (control bookstack: 10) |
direct POST /api/stacks/plant-it/deploy |
HTTP 409 „Ez az alkalmazás jelenleg nem telepíthető." |
/apps/plant-it |
200, permanent abandoned notice, no Telepítés button |
The resolvability gate is now lifecycle-aware
An abandoned app's dead image is the expected end state, not a finding. Left unhandled, plant-it would have made the gate permanently exit 1 — and a gate that is always red is a gate nobody reads, which is the same lesson as yesterday's throttle false-alarm.
- Non-available apps are skipped by default and REPORTED, never silently dropped.
--allincludes them again.- An all-skipped run is a pass (0), not the "no images found" error — that would have been a false alarm of its own.
6 new fixture tests (19 total, no network), including the lifecycle: line-parse table: absent,
quoted, unknown (→ available), and an indented lifecycle: that must NOT match because it is not a
top-level key.
Gates
check-image-pins.py → OK, 53 templates, 0 unpinned. test_check_image_resolvable.py → 19/19.
Remaining
- The full resolvability table is still owed — Part 4 was skipped by operator ruling (no Docker
Hub login on DooPlex), so the sweep would still hit the anonymous throttle and exit 2. One
docker login+python3 scripts/check-image-resolvable.pycloses it. hiddenhas no user yet. Implemented and tested, but onlyabandonedis exercised end to end.- wanderer is still undeployed (from the previous session): re-pinned to a 3-service upstream shape with a second public hostname, and never once deployed. It wants a real deploy on the demo box before anyone is invited to it.