package.start/restart installs an app that isn't installed #167

Closed
opened 2026-10-24 19:40:12 +00:00 by ssmithx · 2 comments
Collaborator

Summary

package.start (and package.restart) on an app that is not installed silently installs it: it pulls images, creates containers and data directories under /var/lib/archipelago/<app>, and marks the app installed. Start/restart should refuse with an error such as " is not installed".

How it was found

While running the lifecycle gate (tests/lifecycle/run-gate.sh) on a test node, the per-app suites for bitcoin-knots, electrumx, immich and lnd ran their stop → start → restart tests against apps that were not installed. Instead of failing, the start step installed all four apps (≈24 GB of chain/index data was created before they were cleaned up). Installed-app set before the run had none of them; after the run, all four were in My Apps.

Code path (main @ fcc18b39)

  • api/rpc/package/runtime.rs package.start handler: validates the id, takes the lifecycle lock, resolves to_start from the manifest/stack membership, clears user-stopped markers — no check that the app is installed.
  • container/prod_orchestrator.rs start() (~L5245): when there is no installed quadlet unit it falls through, then
    • calls clear_user_uninstalled(app_id) and mark_installed(app_id) — actively reversing a prior uninstall, and
    • calls ensure_running(&lm), which uses ReconcileMode::InstallMissing → install_fresh when no container exists.
  • restart() (~L5404) ends up on the same path for a non-unit app, and the split-stack fallback ("member restart failed; falling back to start") does the same per member.

Expected

  • package.start / package.restart on an app with no installed record (not in installed/was_installed, no container, no quadlet unit) returns an error and changes nothing on disk.
  • start() should only mark_installed / clear_user_uninstalled for apps that are actually installed; installing is package.install's job.
  • Recovery of an installed app whose container vanished must keep working (that's the legitimate reason start reaches ensure_running with a missing container) — so the check should key on the durable installed record, not on container presence.

Suggested tests

  • start on an uninstalled app → error, no container created, no mark_installed.
  • start after uninstall (preserve_data) → error, user_uninstalled marker untouched.
  • start on an installed app whose container was removed → still recreates it.
  • Gate: per-app stop/start/restart suites should skip when the app isn't installed rather than relying on start to install it.

🤖 Generated with Claude Code

## Summary `package.start` (and `package.restart`) on an app that is **not installed** silently installs it: it pulls images, creates containers and data directories under `/var/lib/archipelago/<app>`, and marks the app installed. Start/restart should refuse with an error such as "<app> is not installed". ## How it was found While running the lifecycle gate (`tests/lifecycle/run-gate.sh`) on a test node, the per-app suites for bitcoin-knots, electrumx, immich and lnd ran their stop → start → restart tests against apps that were not installed. Instead of failing, the start step installed all four apps (≈24 GB of chain/index data was created before they were cleaned up). Installed-app set before the run had none of them; after the run, all four were in My Apps. ## Code path (main @ fcc18b39) - `api/rpc/package/runtime.rs` `package.start` handler: validates the id, takes the lifecycle lock, resolves `to_start` from the manifest/stack membership, clears user-stopped markers — no check that the app is installed. - `container/prod_orchestrator.rs` `start()` (~L5245): when there is no installed quadlet unit it falls through, then - calls `clear_user_uninstalled(app_id)` and `mark_installed(app_id)` — actively reversing a prior uninstall, and - calls `ensure_running(&lm)`, which uses `ReconcileMode::InstallMissing` → `install_fresh` when no container exists. - `restart()` (~L5404) ends up on the same path for a non-unit app, and the split-stack fallback ("member restart failed; falling back to start") does the same per member. ## Expected - `package.start` / `package.restart` on an app with no installed record (not in `installed`/`was_installed`, no container, no quadlet unit) returns an error and changes nothing on disk. - `start()` should only `mark_installed` / `clear_user_uninstalled` for apps that are actually installed; installing is `package.install`'s job. - Recovery of an installed app whose container vanished must keep working (that's the legitimate reason `start` reaches `ensure_running` with a missing container) — so the check should key on the durable installed record, not on container presence. ## Suggested tests - start on an uninstalled app → error, no container created, no `mark_installed`. - start after `uninstall` (preserve_data) → error, `user_uninstalled` marker untouched. - start on an installed app whose container was removed → still recreates it. - Gate: per-app stop/start/restart suites should `skip` when the app isn't installed rather than relying on start to install it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Collaborator

Mirrored on ngit: issue 2dabc976464ac7d2f52a2bd71a64d5749381fef9fc5e6d9b25a7cc9e6f20a414 — https://gitworkshop.dev/nevent1qqszm27fwery437j754zh4c6vn2hfyuplmulchndnvj60ny7dus2g9qpz3mhxue69uhhyetvv9ujumn8d96zuer9wc9q948m

Mirrored on ngit: issue `2dabc976464ac7d2f52a2bd71a64d5749381fef9fc5e6d9b25a7cc9e6f20a414` — https://gitworkshop.dev/nevent1qqszm27fwery437j754zh4c6vn2hfyuplmulchndnvj60ny7dus2g9qpz3mhxue69uhhyetvv9ujumn8d96zuer9wc9q948m
Collaborator

Closing this duplicate tracker record in favor of the canonical ngit issue. The full report and regression requirements are retained there.

The canonical issue remains open while the next-release verification is completed; this duplicate closure does not claim the bug is resolved.

Closing this duplicate tracker record in favor of the [canonical ngit issue](https://gitworkshop.dev/nevent1qqszm27fwery437j754zh4c6vn2hfyuplmulchndnvj60ny7dus2g9qpz3mhxue69uhhyetvv9ujumn8d96zuer9wc9q948m). The full report and regression requirements are retained there. The canonical issue remains open while the next-release verification is completed; this duplicate closure does not claim the bug is resolved.
chaum closed this issue 2026-11-09 12:31:38 +00:00
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: lfg2025/archy#167