catalog: the lifecycle implementation itself (fixes the previous commit)
The previous commit landed only the new test/badge files: a 'git stash' used to compare REUSE.md ref-check output silently dropped the staged index, so every modification to an existing file was left behind and that commit does not build. This adds the metadata field, the predicates, the fail-closed deploy gate, the catalog filter, the funcmap entries, the template edits and the docs that those tests exercise.
This commit is contained in:
@@ -248,6 +248,40 @@ Running apps on the Vezérlőpult now show a "Megnyitás ↗" button that opens
|
||||
|
||||
The optional `.felhom.yml` **`open_path`** field (`Metadata.OpenPath`) is appended to that URL for apps whose UI isn't at `/` — e.g. `gokapi` → `/admin`, `ghost` → `/ghost/`. Empty = bare root. Rendered via `.Meta.OpenPath` in `dashboard.html`, `deploy.html`, and `app_info.html` (the same field flows through all three open-link sites; no handler change needed). Must start with `/`; cosmetic only (does not affect routing).
|
||||
|
||||
#### App lifecycle — withdrawing an app without orphaning anyone (v0.158.0)
|
||||
|
||||
`.felhom.yml` carries an optional top-level **`lifecycle:`** (`Metadata.Lifecycle`), the catalog's
|
||||
answer to "stop offering this app" that does not punish the customers already running it.
|
||||
|
||||
| value | offered for new installs? | shown to someone already running it |
|
||||
|---|---|---|
|
||||
| `available` (default; absent/empty ≡ this) | yes | nothing special |
|
||||
| `hidden` | **no** | nothing — "we stopped offering this" is not their problem |
|
||||
| `abandoned` | **no** | „Nem karbantartott" badge + a notice on the app page that updates and security fixes will no longer arrive |
|
||||
|
||||
**A deployed instance keeps full function in every state.** Lifecycle governs what is OFFERED, never
|
||||
what runs — deleting a template instead would mark every deployed instance `Elavult` and offer a
|
||||
Törlés button for working software.
|
||||
|
||||
Three predicates on `Metadata` are the single interpretation of the field — every surface goes
|
||||
through them: `EffectiveLifecycle()`, `CanInstall()`, `IsAbandoned()`.
|
||||
|
||||
- **Listing** — `web.visibleCatalogStacks` drops a template that is not installable AND not deployed
|
||||
here (`Deployed || Protected || CanInstall()`).
|
||||
- **Deploy gate** — `api.deployStack` refuses server-side before any mutation with
|
||||
„Ez az alkalmazás jelenleg nem telepíthető." (409). `stacks.DeployStack` repeats the check for any
|
||||
caller that does not route through the API. Hiding the button is not a gate.
|
||||
- **Unknown values fail OPEN** (→ `available` + one WARN), deliberately opposite to the gate's
|
||||
fail-closed posture: a typo, or a state from a newer catalog than this controller, must never pull
|
||||
a working app out of every customer's catalog. Both read the same `EffectiveLifecycle`, so they
|
||||
cannot disagree.
|
||||
- **Orphan detection must never see this field.** `getCatalogTemplateSlugs` keys on directory +
|
||||
compose presence only; withdrawn templates stay in the catalog tree. Asserted by
|
||||
`TestCatalogTemplateSlugs_IgnoresLifecycle` with a red-proof.
|
||||
- **Badges are generic plumbing**: `web.MetaBadge` + the `meta_badge` template partial + the
|
||||
`lifecycleBadge` funcmap entry. R-56's difficulty labels are intended as a sibling funcmap
|
||||
function returning the same `*MetaBadge` — no new markup or CSS.
|
||||
|
||||
#### App Info Pages
|
||||
|
||||
Each app can define rich metadata in `.felhom.yml`:
|
||||
|
||||
Reference in New Issue
Block a user