Slice 1 of the Resource Manager (see docs/resource-manager.md + plan in ~/.claude/plans/stateful-juggling-pike.md). Lays down the read-only half: a JSON manifest schema with namespacing, a scanner that walks /var/lib/furtka/apps/, and a `furtka` CLI with `app list` and `reconcile --dry-run`. Reconciler / volume creation / docker compose calls land in the next slice. - furtka.manifest: dataclass + load_manifest with required-field + type validation. volume_name() injects the furtka_<app>_<vol> namespace so apps can each declare a "data" volume without colliding. - furtka.scanner: tolerant — broken manifest = ScanResult with error, not an exception. Lets reconcile log + skip rather than abort. - furtka.cli: text + --json output. argparse with `app list` and `reconcile --dry-run`. main() returns int for clean exit codes. - furtka.paths: FURTKA_APPS_DIR env override so tests don't need root. - 19 new tests covering valid manifests, every validation branch, scanner edge cases (missing root, broken manifest, sort order), and the CLI subcommands. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.4 KiB
Resource Manager — Design Notes
Scaffold for the conversation between Daniel and Robert. Captures what Robert already sketched in chat on 2026-04-15 and lists the open questions that need an answer before we write code.
Status: Draft 2026-04-15. Nothing implemented. First app to consume this will be a LAN fileshare (SMB/NFS) — that's the forcing function.
What's the Resource Manager?
The layer between Furtka apps and the underlying system (disk, Docker, network, users). Apps don't touch Docker or the filesystem directly — they declare what they need, the Resource Manager provisions and tracks it.
Robert's framing (2026-04-15): "żeby później można było manipulować wszystkimi peryferiami" — so we can manipulate all peripherals from one place later.
Decided (Robert, 2026-04-15)
- An app is a folder. A Furtka app is defined as a directory containing:
- a manifest
- a
docker-compose.yaml - a
.envfile
- A registration script reads that folder and wires the app into the backend.
- Each app gets its own named Docker volume. Sharing between apps is possible but opt-in, not default.
- Filesystem is the source of truth (for now). No SQL database yet — the Resource Manager reads current state from Docker and the OS ad-hoc. DB gets added when we actually need to store intent the OS doesn't know (e.g. "this share belongs to App X, readable by User Y").
These are locked; don't re-litigate without Robert.
Open questions
These need an answer before the first line of code.
Q1 — What's in the manifest?
This is the contract between app authors and Furtka. Changing it later is expensive. Known candidates:
name(machine id, must match folder name?)display_name(shown in UI)version(semver? calver?)descriptionvolumes(list of named volumes the app needs)ports(which ports the app wants exposed; needed for reverse proxy later)icon(path or URL)- ... anything else?
Format: YAML / TOML / JSON — not decided.
Q2 — Where do apps live on disk?
Suggested-but-not-decided: /var/lib/furtka/apps/<app-name>/. Robert: confirm path?
Q3 — What does the registration script actually do?
Robert said "Skript do rejestrowania w backendzie". Concretely that means some subset of:
- Validate manifest (schema check, required fields, volume names unique)
- Create any declared named volumes that don't exist yet
- Run
docker compose up -dinside the app folder - Record the app in whatever passes for the backend index (right now: nothing — we'd just re-scan the folder each time)
Sub-question: is registration a one-shot on install, or does something (systemd unit?) re-scan /var/lib/furtka/apps/ on every boot so the filesystem really is authoritative?
Q4 — How does the user actually install an app?
Out of scope for the first cut, but needed to know the shape of the CLI:
- Admin UI with a button "Install Fileshare"?
- CLI:
furtka app install <tarball>/<git repo>/<name-from-catalog>? - Catalog = a separate repo with app folders?
Q5 — Upgrades and removal
- Upgrade strategy: replace folder + re-run compose? Preserve volumes across upgrades (yes obviously, but needs stating)?
- Removal: does it delete the volume or keep it? Robert's "apki się dzielą" implies a volume can outlive its original app.
Q6 — Volume sharing semantics
Robert: "jak będzie trzeba to będą mogły się dzielić". Open:
- Who requests the share — the sharing app's manifest, or an admin action?
- What's the permission model (read-only, read-write, per-user)?
- This is probably the first piece of "intent not reflected in OS state" — might be what finally motivates the DB.
Q7 — Backend API surface
Once the filesystem model is clear, the Resource Manager's backend still needs some Python/whatever surface that the web UI and the register script both call. Rough shape:
list_apps()— scan/var/lib/furtka/apps/, return manifests + running statusinstall_app(folder)— validate + compose upremove_app(name)— compose down, optionally rm volumelist_volumes()— from Dockerlist_shares()— ???
Not decided whether this lives in the existing webinstaller Flask app, a new backend service, or a thin CLI that the Flask app shells out to.
First consumer — Fileshare
The point of doing this now is to unblock the fileshare app (see ../memory/project_first_app_fileshare.md for the conversation context). Walking it through the model above:
/var/lib/furtka/apps/fileshare/
manifest.??? # see Q1 — what exactly goes here?
docker-compose.yaml
.env
- App declares a volume (e.g.
files). - Compose runs a Samba/NFS container mounting that volume.
- On Mac/Windows/Android you mount
smb://furtka.local/files.
If we can get this end-to-end through the Resource Manager, we've validated the whole model with the simplest possible app. Nextcloud, Jellyfin, etc. are the same shape with more knobs.
What we do NOT do yet
- No database. (Decided.)
- No user/permissions model beyond what Samba/OS already give us.
- No reverse proxy / TLS integration in the manifest. (Tracked separately — see
../memory/project_ssl_local_deferred.md.) - No app catalog / store UI. Manual install first.
- No auto-updates.
These all become easier once Q1–Q7 are answered — adding them to an existing model is straightforward; guessing them now is expensive.