Files
app-catalog-felhom.eu/REPORT.md
T

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-it returns to templates/ with lifecycle: 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.
  • --all includes 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.py closes it.
  • hidden has no user yet. Implemented and tested, but only abandoned is 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.