Skip to content

fix(desktop): never reattach a previous installation's volumes on a fresh install - #821

Open
dustywusty wants to merge 3 commits into
mainfrom
dustywusty/fix-leftover-volumes
Open

dustywusty wants to merge 3 commits into
mainfrom
dustywusty/fix-leftover-volumes

Conversation

@dustywusty

@dustywusty dustywusty commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

What this changes

A desktop installation set up again after its folder was deleted silently reattaches what the previous installation left in the container engine. Only the Postgres volume was guarded. Observed on a real machine (Apple silicon, Docker Desktop): after deleting ~/OpenBot and reinstalling, openbot_agent-workspace, openbot_agent-profiles and the per-Bot openbot-workspace-picked-harness / openbot-profile-picked-harness volumes from the earlier install were reused by the new one, without a prompt.

This PR:

  • On Start for a verified-fresh installation (the existing test: no usable KEY_ENCRYPTION_KEY, no DATABASE_URL, no saved model), lists every leftover the deployment can prove it owns:
    • Compose project volumes (<project>_<name>, local, not external, no driver_opts, labels matching this project and source);
    • supervisor per-Bot volumes (<ns>-profile-<bot>, <ns>-workspace-<bot>) carrying all three labels openbot.supervisor=true, openbot.bot-id=<bot>, openbot.namespace=<ns>, with the namespace resolved the way supervisor/src/names.ts resolves it;
    • stopped containers with the same ownership (<ns>-computer-<bot> with the supervisor labels, or this Compose project), which would otherwise keep those volumes attached.
  • Offers the leftovers as a choice, not a failure: Start fresh deletes exactly the volumes and containers shown, then carries on into Start. Keeping the data (restore the previous folder) is explained underneath, and every volume and container is listed behind a disclosure. The deletion re-detects and removes nothing if the set changed; removes containers first, then volumes, without --force. A running owned container blocks it with a sentence saying so, and nothing is removed or started.
  • Follow-up (FOR-345): start a fresh install under its own Compose project name and supervisor namespace, so nothing is reused and nothing has to be deleted; leftovers become an optional cleanup.
  • Installations that have their saved key are never probed; returning installs keep their data exactly as before.
  • Problem gains leftover_reset / leftover_containers (skipped when empty); database_reset is unchanged. reset_leftover_database takes volumes and containers.

Root cause

  • Where it entered: the guard added in fix(desktop): improve setup, local startup and provider OAuth #633 (6014b39, 21 Sep) protects only the database, because only the database is tied to the encryption key. The other volumes predate it: Compose's agent-profiles/agent-workspace (40cef15) and the supervisor's per-Bot volumes (f238ce9, supervisor/src/names.ts).
  • How: volumes outlive the install folder. A new install has the same Compose project name (the folder name) and the same supervisor namespace, and default Bot ids are stable (general-assistant, knowledge, picked-harness), so the new install derives the same volume names and Docker hands back the old volumes. agent-profiles and the per-Bot profile volumes are Chromium user-data directories ("so logins survive container restarts"), so a reused profile carries the previous installation's website sign-ins.
  • Evidence: on the affected machine, openbot_postgres-data was created at the new install's first Start (the database guard did its job), while openbot_agent-workspace/openbot_agent-profiles and both picked-harness volumes carried creation times from the earlier install; the new database's Bots are general-assistant, knowledge, picked-harness.
  • Why it went undetected: the database guard reads like the whole answer, and a reinstall test that deletes everything (or nothing) never exercises a folder removed while the engine keeps its volumes.
  • How this prevents recurrence: detection is by ownership labels, not by a list of known volume names, so a future Compose volume or supervisor volume is covered automatically; tests cover each owner, each refusal, and the exact-set binding.

Where it runs

  • New state that outlives a request? None on the server. Desktop-only.
  • What happens on the second replica? Not applicable: no server code changes.
  • Anything serialised? The reset is bound to the exact confirmed set and re-checked before any removal.
  • Anything fanned out to a browser? No.
  • New listener, port, or schedule? No.

Boundary and audit

  • Every acting call still goes through the gateway: unchanged, no server code touched.
  • New refusals and new failures each write a row: not applicable (desktop installer).
  • Nothing new is trusted from the client: the window sends back the set it was shown, and native code re-detects and compares before removing anything.

Changelog

  • A line in CHANGELOG.md under Unreleased ("A reinstall no longer picks up the previous installation's Bot files and sign-ins").

Proof

  • New Rust tests (each failed first): leftover_volumes_are_only_volumes_this_project_or_namespace_provably_owns, leftover_volume_reset_removes_exactly_the_confirmed_owned_set, leftover_reset_removes_stopped_owned_containers_before_their_volumes, a_running_owned_container_blocks_the_reset_and_removes_nothing, a_fresh_root_refuses_to_reattach_any_leftover_volume, leftover_reset_is_bound_to_the_exact_offered_set, a_refused_start_offers_exactly_the_containers_and_volumes_it_named; plus an App test for the multi-volume confirmation. Fake engine only; no real volumes were touched.
  • cargo fmt --check, cargo clippy --locked --all-targets -- -D warnings, cargo test --locked --lib --bins (542 lib, 152 bin), bun test desktop/src (150), desktop typecheck and build, Biome on changed files: pass on macOS arm64. Windows and Linux left to CI.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-21T18:49:44.681536Z 2de468b PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2de468bf7c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src-tauri/src/main.rs Outdated
…resh install

A desktop install set up again after its folder was deleted refused to
reuse only the old database. Every other volume the previous install
left was reattached silently: Compose project volumes (agent-workspace,
agent-profiles, spire-*) and the supervisor's per-Bot volumes
(<ns>-workspace-<bot>, <ns>-profile-<bot>). Default Bot ids are stable
across installs, so a new Bot opened the old Bot's files and Chromium
profile, including its website sign-ins.

On Start, a verified-fresh installation (no usable key, no database URL,
no saved model) now lists every leftover it can prove it owns: Compose
volumes and containers by project label, supervisor volumes and
containers by all three supervisor labels in this namespace. Start is
refused with one confirmed reset that removes the stopped containers,
then the volumes, bound to the exact set shown. A running owned
container blocks the reset and nothing is removed. Installations with
their saved key keep their data as before.
@dustywusty
dustywusty force-pushed the dustywusty/fix-leftover-volumes branch from 2de468b to ebc8e04 Compare October 21, 2026 20:14
@guidovizoso

Copy link
Copy Markdown
Collaborator

Agree with the goal: a new install must never pick up the previous install's browser sign-ins or Bot files. The ownership detection (labels, tied to the exact confirmed set, no --force) is solid.

The concern is the experience. Someone deletes ~/OpenBot because they want a fresh start, reinstalls, presses Start, and Start is refused until they choose "Reset leftover data". For a non-technical person that's an error during normal startup plus a question we could answer for them, both of which we're trying to remove from the product.

Suggestion: a verified-fresh install starts right away under new names (a new Compose project name and supervisor namespace, e.g. with a short suffix), so nothing old is reattached and nothing is deleted. The leftovers then show up as an optional, quiet cleanup ("A previous installation left 2.1 GB of data. Remove it?"). It's safe by default, nothing blocks, and nothing is lost if they meant to restore the old folder. The detection and reset code here would power that cleanup.

If that's too big for this PR, the smaller fix is to present it as a choice rather than a failure: "Start fresh" as the main action, with "Keep previous data" explained underneath, instead of a refused Start.

The reset command checked the confirmed containers as an empty list, so
any offer that named a stopped container was always refused as no longer
current. The removal now receives the matched offer itself, so it can
only remove the set the check accepted.
A fresh install that found a previous installation's data refused Start
and asked for a separate, two-step reset. For somebody who deleted the
folder to start over, that read as an error during normal startup.

The screen now offers one choice instead: Start fresh deletes exactly the
data shown and carries on into Start. How to keep the data (restore the
previous folder) is explained under it, and the volumes and containers it
removes stay listed behind a disclosure. The failure alert is no longer
shown for this case. Errors from the deletion itself are still shown as
failures, and nothing starts.

Starting under new names, so nothing is reused and nothing must be
deleted, is tracked in FOR-345.
@dustywusty

Copy link
Copy Markdown
Collaborator Author

Took the smaller fix here and tracked the bigger one.

In this PR (3e675dc): leftover data is no longer a refused Start. The screen offers one choice. Start fresh is the main action: it deletes exactly the data shown and then carries on into Start, with no second confirmation. Underneath, it explains how to keep the data: restore the previous installation's folder (and, for the database, its original encryption key) and choose it under Installation options. The volumes and containers it removes are listed behind a "What Start fresh deletes" disclosure, and the "That did not finish" alert is no longer shown for this case. If the deletion itself fails (for example, a container from the previous install is still running), that is still shown as a failure and nothing starts.

I didn't add a "Keep previous data" button, because keeping the data where it is can't be offered safely. The database can't be opened without the lost key, and reattaching the profile volumes is exactly how the previous install's browser sign-ins leak into the new one. So keeping it means restoring the folder, and the screen explains that.

Follow-up: FOR-345. This is your suggestion: a verified-fresh install creates its own suffix, saves it as COMPOSE_PROJECT_NAME / COMPUTER_NAMESPACE in .env, and starts right away. Leftovers from other OpenBot namespaces become a quiet, optional cleanup with a size. That also removes the start refusal the #633 database guard has today. The detection and reset code from this PR would power the cleanup.

This branch has not been deployed

No deployments
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.

2 participants