docs(report): lifecycle replaces retired/, live-proven on 9201
This commit is contained in:
@@ -1,87 +1,60 @@
|
||||
# REPORT — catalog honesty pass (TASK-E Part 3), 2026-07-21
|
||||
# REPORT — app lifecycle replaces the `retired/` move (TASK-F Part 1, catalog half), 2026-07-21
|
||||
|
||||
## What ran
|
||||
Baseline `857ba53`, clean tree.
|
||||
|
||||
Diagnose-and-re-pin for the two Campaign 7 apps whose images "do not resolve at all", plus R-41
|
||||
slice 1 (a standing resolvability gate). Baseline `34d50a3`, clean tree.
|
||||
## What changed and why
|
||||
|
||||
## wanderer — RE-PINNED (upstream is alive; the template pointed at a ghost)
|
||||
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 |
|
||||
|---|---|
|
||||
| Old pin | `ghcr.io/flomp/wanderer:0.16.0` — **does not resolve** (verified `docker manifest inspect`) |
|
||||
| Failure class | **repo split + registry move + org rename**, all at once |
|
||||
| New pins | `flomp/wanderer-web:v0.20.0`, `flomp/wanderer-db:v0.20.0`, `getmeili/meilisearch:v1.36.0` |
|
||||
| Evidence | upstream `docker-compose.yml` at tag `v0.20.0` (github.com/open-wanderer/wanderer); latest release 2026-07-07; all three tags confirmed present |
|
||||
| `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 |
|
||||
|
||||
Compose restructured from 1 service to 3 (web + PocketBase + Meilisearch), per upstream. Notable
|
||||
consequences, none of them cosmetic:
|
||||
## The resolvability gate is now lifecycle-aware
|
||||
|
||||
- **A second public hostname was unavoidable.** `PUBLIC_POCKETBASE_URL` is browser-side, so
|
||||
PocketBase must be publicly reachable; added `SUBDOMAIN_DB` (default `hike-db`). Upstream's own
|
||||
proxy example does the same.
|
||||
- **New required volume** `/data/plugins` — v0.20.0 moved the Strava/Komoot/Hammerhead integrations
|
||||
into a WASM plugin sandbox.
|
||||
- **New generated secret** `POCKETBASE_ENCRYPTION_KEY` (`hex:16` → exactly 32 chars, as required).
|
||||
- **Meilisearch pinned DOWN v1.49 → v1.36.0**, applying the R-42 ruling (sidecar follows the app
|
||||
template's proposed pin). Campaign 7 had bumped it while the app image was dead.
|
||||
- `mem_limit` 384M → 1024M = the exact sum of the three services (REUSE.md §2 rule).
|
||||
- Probe container name kept equal to the stack dir (`wanderer`), or the health probe would hit the DB.
|
||||
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.
|
||||
|
||||
**Not deployed live.** This is a from-scratch 3-service restructure of an app that has never once
|
||||
deployed successfully; it wants a real deploy on the demo box before anyone is invited to it.
|
||||
- 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.
|
||||
|
||||
## plant-it — RETIRED (operator ruling 2026-07-21)
|
||||
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.
|
||||
|
||||
The pin was only slightly wrong — repository is `msdeluise/plant-it-server`, and `0.10.0` was the
|
||||
right version. Correcting the name would have been the wrong fix:
|
||||
## Gates
|
||||
|
||||
- Upstream **discontinued self-hosting**: `backend/` and `deployment/` are deleted from `main`; the
|
||||
project is now an Android app on F-Droid/Obtainium, maintainer notes development has slowed.
|
||||
- Last server image pushed **2024-12-10** — a security-frozen Spring Boot 3.4.0.
|
||||
- Requires **MySQL 8.0 + Redis**. The template claimed "Database: None (file-based)" — never true.
|
||||
`check-image-pins.py` → OK, 53 templates, 0 unpinned. `test_check_image_resolvable.py` → 19/19.
|
||||
|
||||
Moved to `retired/plant-it/` rather than deleted: the controller discovers apps by directory, so this
|
||||
un-offers it while keeping it revivable with one `git mv`. Catalog is now **52 apps**.
|
||||
## Remaining
|
||||
|
||||
## R-41 slice 1 — `scripts/check-image-resolvable.py`
|
||||
|
||||
Complements the syntactic pin gate, which cannot see rot. Resolves each unique pin one image at a
|
||||
time; exit 0 / 1 (GONE) / 2 (inconclusive). 14 fixture tests, no network.
|
||||
|
||||
**Two traps encoded, both hit live during this change:**
|
||||
|
||||
1. `docker manifest inspect` prints `toomanyrequests: …` and **still exits 0** — the same
|
||||
exits-0-on-failure shape as the ISO tooling's `validate-answer`. stderr is therefore checked
|
||||
even on rc=0.
|
||||
2. The inverse, and the more dangerous one: the **first full sweep called 24 of 65 pins dead**,
|
||||
including `postgres:16-alpine` and `redis:7-alpine`, purely because Docker Hub throttled it
|
||||
partway through. Ambiguity now resolves to INCONCLUSIVE, never to an accusation.
|
||||
|
||||
### Sweep result — INCOMPLETE, and that is the honest answer
|
||||
|
||||
The full 65-pin sweep **could not be completed**: DooPlex is not logged in to Docker Hub, and the
|
||||
anonymous limit was exhausted partway. The pre-throttle probes are trustworthy and are what the
|
||||
findings above rest on:
|
||||
|
||||
| Image | Result | When |
|
||||
|---|---|---|
|
||||
| `ghcr.io/flomp/wanderer:0.16.0` | **GONE** | pre-throttle |
|
||||
| `msdeluise/plant-it:0.10.0` | **GONE** | pre-throttle |
|
||||
| `getmeili/meilisearch:v1.49` | resolves | pre-throttle |
|
||||
| `flomp/wanderer-web:latest`, `flomp/wanderer-db:latest` | resolve | pre-throttle |
|
||||
| `msdeluise/plant-it-backend/-frontend:latest` | resolve | pre-throttle |
|
||||
| `flomp/wanderer-{web,db}:v0.20.0`, `getmeili/meilisearch:v1.36.0`, `msdeluise/plant-it-server:0.10.0` | exist (Hub tag API, HTTP 200) | post-throttle cross-check |
|
||||
|
||||
**Follow-up for the operator:** re-run `python3 scripts/check-image-resolvable.py` after
|
||||
`docker login` to get the complete 52-app table. The gate now reports the throttle as INCONCLUSIVE
|
||||
(exit 2) instead of inventing 24 dead images, so a repeat is safe to trust.
|
||||
|
||||
## Observations (recorded, not acted on)
|
||||
|
||||
- `REUSE.md` cited `felhom-controller/internal/stacks/healthprobe.go`; the real path has an extra
|
||||
`controller/` segment. Corrected, but `reuse_refs_check.py` still flags it — it resolves citations
|
||||
against the repo root and cannot follow a cross-repo pointer. Pre-existing checker limitation.
|
||||
- The `-app`-suffixed wanderer tags (`v0.20.0-app`) are undocumented upstream; deliberately not used.
|
||||
- 6 apps' `.felhom.yml` still carry `mem_limit` values that do not equal the sum of their services'
|
||||
limits. wanderer is now correct; the others were out of scope.
|
||||
- **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.
|
||||
|
||||
Reference in New Issue
Block a user