docs(registry-manifest-design): stop describing the pre-Phase-1 state as "today"

The header says Phases 1-3 shipped, then §1 "Where we are today" described the
world before any of them: catalog carrying "version + image override only", the
manifest "never registry-distributed", counts of 48 disk manifests and 28
catalog entries. A reader hits the contradiction immediately and can't tell
which half is current.

Retitled §1 as the pre-Phase-1 baseline it is, and added the actual state:
`releases/app-catalog.json` has 66 entries and 56 embed a full `manifest` block
— one for every `apps/*/manifest.yml` in the tree (the stale counts were 48 and
28). What's genuinely left is Phase 4 (build-context apps) and Phase 5 (drop
`apps/` from the OTA rsync), which the phase list already marks .

Also:
- The install arrow claimed "render Quadlet unit"; same overstatement corrected
  in architecture.md and app-manifest-spec.md — Quadlet is opt-in, the default
  is podman create+start.
- §8's open question "generated_files with inline content — already supported?"
  is answered: `app.files[]` takes inline `content` with placeholder rendering.
  Marked answered rather than leaving a resolved question looking open.

Verified present and unchanged: `catalog_manifest_to_overlay`,
`install_stack_via_orchestrator`, `install_immich_stack`, and the catalog-wins
merge semantics.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-08-07 20:53:15 -04:00
co-authored by Claude Opus 5
parent 2c53a7d77f
commit a28b3b696d
+24 -9
View File
@@ -13,14 +13,26 @@ its "discovery/authenticity" layer).
---
## 1. Where we are today
## 1. Where we started (the pre-Phase-1 baseline)
Two distinct mechanisms, only one of which is registry-distributed:
This section is the problem statement the design was written against, kept for
context. **It no longer describes the running system** — Phases 13 shipped, so
see "Where we are now" below.
| Thing | Source | Reaches node via | Carries |
Two distinct mechanisms, only one of which was registry-distributed:
| Thing | Source | Reaches node via | Carried |
|-------|--------|------------------|---------|
| `apps/*/manifest.yml` (48) | repo working tree | **OTA**: `self-update.sh` rsyncs `apps/ → /opt/archipelago/apps/` | full manifest (the orchestrator's real source of truth) |
| `app-catalog.json` (28) | `releases/app-catalog.json` | **registry HTTP fetch**, hourly, **signed** (`app_catalog::refresh_catalog`) | version + image override only |
| `apps/*/manifest.yml` | repo working tree | **OTA**: `self-update.sh` rsyncs `apps/ → /opt/archipelago/apps/` | full manifest (the orchestrator's real source of truth) |
| `app-catalog.json` | `releases/app-catalog.json` | **registry HTTP fetch**, hourly, **signed** (`app_catalog::refresh_catalog`) | version + image override only |
### Where we are now
`releases/app-catalog.json` carries 66 entries, and 56 of them embed a full
`manifest` block — one for every `apps/*/manifest.yml` in the tree. So the
"catalog carries an image override only" gap below is closed for image-only
apps; what remains is build-context apps (Phase 4) and dropping `apps/` from the
OTA rsync (Phase 5).
- Orchestrator registry = in-memory `state.manifests: HashMap<app_id, LoadedManifest>`,
populated by `ProdContainerOrchestrator::load_manifests()` walking the disk dir.
@@ -44,7 +56,8 @@ binary OTA, no disk manifest.
publisher: apps/*/manifest.yml ──generate──▶ releases/app-catalog.json (embeds + signs)
node: refresh_catalog() ──fetch+verify──▶ <data_dir>/app-catalog.json
load_manifests() ──merge──▶ state.manifests (catalog wins; disk = fallback)
install(app_id) ──▶ render Quadlet unit (rootless, systemd-managed)
install(app_id) ──▶ create the rootless container (Quadlet unit when
use_quadlet_backends is on; podman create+start otherwise)
```
## 3. Schema change (`app_catalog::AppCatalogEntry`)
@@ -143,6 +156,8 @@ Add a generator (extend `create-release.sh` / a small `scripts/gen-app-catalog`)
separate signed blob? Inline is simplest for Phase 1; hashing aligns with the
DHT image-by-digest plan and keeps the catalog small. Lean inline now, revisit
at Phase 4 when build contexts (large) need addressing anyway.
- `generated_files` with inline content (vs. source-dir) — already supported in the
manifest schema? If so, registry manifests can carry small rendered files inline,
removing another disk dependency.
- ~~`generated_files` with inline content (vs. source-dir) — already supported in
the manifest schema?~~ **Answered: yes.** `app.files[]` takes inline `content`
(with `{{HOST_IP}}` / `{{NETWORK_GATEWAY}}` / `{{secret:NAME}}` rendering), so
registry manifests already carry small rendered files inline and that disk
dependency is gone. See [`app-manifest-spec.md`](app-manifest-spec.md).