Skip to content

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

Open
dustywusty wants to merge 1 commit into
mainfrom
dustywusty/fix-leftover-volumes
Open

dustywusty wants to merge 1 commit into
mainfrom
dustywusty/fix-leftover-volumes

Conversation

@dustywusty

Copy link
Copy Markdown
Contributor

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.
  • Refuses Start and offers one confirmed reset ("Reset leftover data", or "Reset leftover database" when the database is among them) that names every volume and container. The reset re-detects and removes nothing if the set changed; removes containers first, then volumes, without --force. A running owned container blocks the reset with a sentence saying so, and nothing is removed.
  • 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".

&root,
&volume,
&volumes,
&[],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Pass the confirmed containers into the reset guard

When a previous installation leaves any stopped owned containers, the reset offer includes their names, but this command passes an empty slice to reset_leftover_database_with instead of the received containers. That helper requires the supplied container set to equal offer.containers, so every such confirmation is rejected as no longer current before removal is attempted. Retrying Start produces the same unusable offer, leaving the reinstall blocked even after all containers are stopped. Pass &containers here so the guard validates the same set that the UI confirmed and the reset closure will remove.

Useful? React with 👍 / 👎.

…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

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.

1 participant