Skip to content

pilotctl: uninstall keeps the app's state in the backups instead of deleting it - #524

Merged
TeoSlayer merged 2 commits into
mainfrom
fix/uninstall-keeps-state
Oct 8, 2026
Merged

TeoSlayer merged 2 commits into
mainfrom
fix/uninstall-keeps-state

Conversation

@TeoSlayer

@TeoSlayer TeoSlayer commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

pilotctl appstore uninstall <id> --yes deleted the app's dir, and with it the app's state:

  • the wallet's EVM private key, and with it the funds at its address;
  • smol's secrets;
  • each metered app's identity.

There was no backup and no way back.

Fix

  • The dir goes to the app backups. It moves to ~/.pilot/app-backups/<id>/ (or $PILOT_APPSTORE_BACKUP_ROOT), the way upgrades already retire a replaced install, without the binary. The command prints where it went, and --json carries backup.
  • New backup kind uninstall. It is pinned, so retention never removes it.
  • Nothing is ever deleted.
    • If no backup location takes the dir, retireAppDir keeps it in the install root as <id>.previous-<time> with its manifest disabled.
    • If even that fails, the command fails with "nothing was deleted" and leaves the dir in place, its manifest already gone so the daemon does not run it.
  • Help text now says the state is kept. The output says to delete the backup by hand once it is no longer needed; only the wallet, from 0.4.0, restores its keys from there.
  • Processes still running from the app's files are looked for in the backup too: on Linux their executable path follows the move.

The wallet (pilot-protocol/wallet#47) looks in these backups, and in its own copy under ~/.pilot/keys/io.pilot.wallet, before it would create a key. So installing it again brings the old key back.

Tests

  • TestUninstallKeepsTheAppsStateInABackup: the key lands byte for byte in a pinned uninstall backup under app-backups/<id>/, and the binary is not kept.
  • TestUninstallNeverDeletesTheKeyWhenBackupsFail: with every backup rename refused, the key still exists afterwards, in <id>.previous-<time>.
  • TestUninstallFailsWhenTheDirCannotBeMoved: with the install root read-only, the command fails, says nothing was deleted, and the key is untouched.

All three fail on main. go test -race ./cmd/pilotctl passes.

🤖 Generated with Claude Code

Teo Calin and others added 2 commits October 8, 2026 15:08
…eleting it

appstore uninstall deleted the app's dir and with it the app's state:
the wallet's EVM private key, and the funds at its address, smol's
secrets, each metered app's identity. The dir now goes to the app
backups like a replaced install (without the binary), as a new
"uninstall" kind that retention never removes, and the command prints
where. If no backup location takes it, retireAppDir keeps it in the
install root with its manifest disabled; if even that fails the command
stops with the dir in place. Nothing is deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…findable name

Review fixes:
- When even the in-place rename fails, retireAppDir hands back the dir
  itself; uninstall reported success with the app still installed. It
  now fails with "nothing was deleted".
- A dir parked beside the install (no backup location worked) is named
  <appID>.previous-<stamp>, the name backup listings and the wallet's
  key restore look for, instead of <appID>-<stamp>.
- Processes still running from the app's files are looked for in the
  backup too: on Linux their executable path follows the move.
- The output no longer says any app picks its keys back up; only the
  wallet, from 0.4.0, does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@TeoSlayer
TeoSlayer merged commit 718fc92 into main Oct 8, 2026
15 checks passed
@TeoSlayer
TeoSlayer deleted the fix/uninstall-keeps-state branch October 8, 2026 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant