Skip to content

fix(db,desktop): cascade host's workspaces on host delete - #5727

Merged
Kitenite merged 1 commit into
mainfrom
fix/host-delete-cascade-workspaces
Jul 17, 2026
Merged

Kitenite merged 1 commit into
mainfrom
fix/host-delete-cascade-workspaces

Conversation

@Kitenite

@Kitenite Kitenite commented Jul 17, 2026 •

Copy link
Copy Markdown
Member

Problem

Deleting a host from Settings → Hosts fails whenever the host still owns workspace rows. v2_workspaces_host_fk was defined without an onDelete clause (defaults to NO ACTION), so the DELETE FROM v2_hosts in v2Host.delete is rejected by Postgres and the raw FK-violation message lands in the error toast.

This is unavoidable for stale duplicate devices: repo-root (main) workspaces can't be deleted through the normal workspace-delete action, so they pin the dead host forever.

Reported by a user (support, 2026-07-16) with a stale host left behind by an uninstalled build; they confirmed cascade-deleting the dead host's workspaces is the desired behavior.

Fix

  • Add .onDelete("cascade") to v2_workspaces_host_fk (matches the existing cascade on v2_users_hosts_host_fk). Migration 0061_v2_workspaces_host_fk_cascade drops and re-adds the constraint.
  • Update the delete-host dialog copy, which previously promised "Workspaces, files, conversations, and automations stay" — impossible under the old FK and wrong under the new behavior. It now says the host's workspaces are removed and files on the machine stay.

Downstream is safe: chat_sessions.v2_workspace_id is SET NULL, and nothing else hard-references v2_workspaces.

Notes

  • Migration generated with drizzle-kit generate; no hand-edits to packages/db/drizzle/.
  • Should be applied via the API/cloud deploy before any desktop build leans on it (standard ordering).

Verification

  • bun run typecheck passes; Biome clean on changed files.
  • Root bun run lint currently fails on unrelated pre-existing nested .conductor/* Biome root configs, not on this change.

Open in Stage

Summary by cubic

Fixes host deletion by cascading the host’s v2_workspaces on delete. Updates the desktop delete-host dialog to clarify that the host’s workspaces are removed and files on the machine stay.

  • Migration
    • Apply 0061_v2_workspaces_host_fk_cascade before shipping desktop; it recreates v2_workspaces_host_fk with ON DELETE CASCADE.
    • Downstream is safe: chat_sessions.v2_workspace_id uses SET NULL.

Written for commit 1bde5e7. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • User Experience

    • Updated host deletion messaging to clearly explain that deleting a host also removes its access and associated workspaces.
    • Clarified that files remain on the machine after deletion.
    • Added a warning that a running host may reappear and that deletion cannot be undone.
  • Bug Fixes

    • Ensured associated workspaces are automatically removed when their host is deleted, keeping host and workspace data consistent.

v2_workspaces_host_fk had no ON DELETE behavior, so deleting a host
with remaining workspaces (e.g. undeletable repo-root workspaces on a
stale duplicate device) failed with a raw Postgres FK violation
surfaced straight into the error toast.

Add ON DELETE CASCADE to the FK (migration 0061) and update the
delete-host dialog copy, which previously promised workspaces stay.
@ghost

ghost commented Jul 17, 2026

Copy link
Copy Markdown

Ready to review this PR? Stage has broken it down into 3 individual chapters for you:

Title
1 Enable cascade delete for workspace host foreign key
2 Generate database migration for cascade deletion
3 Update host deletion UI copy
Open in Stage

Chapters generated by Stage for commit 1bde5e7 on Jul 17, 2026 1:49am UTC.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Host deletion now removes associated workspaces through a cascading database relationship. Host settings confirmation text describes removal of the host, access, and workspaces while retaining files on the machine.

Changes

Host deletion

Layer / File(s) Summary
Cascade workspace deletion
packages/db/src/schema/schema.ts, packages/db/drizzle/0061_v2_workspaces_host_fk_cascade.sql, packages/db/drizzle/meta/*
The v2_workspaces foreign key now cascades deletes from v2_hosts, with the migration snapshot and journal updated accordingly.
Update deletion confirmation
apps/desktop/src/renderer/routes/_authenticated/settings/hosts/$hostId/components/HostSettings/components/DeleteHostSection/DeleteHostSection.tsx
Inline and modal descriptions now state that host access and workspaces are removed, machine files remain, and the action cannot be undone.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • superset-sh/superset#5566: Updates host deletion confirmation messaging and the related workspace-to-host cascading foreign key.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, conventional, and accurately summarizes the main change: cascading host workspace deletion.
Description check ✅ Passed The description covers the problem, fix, notes, and verification, so it is mostly complete despite not using the exact template headings.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/host-delete-cascade-workspaces

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the FK violation that blocked host deletion by adding ON DELETE CASCADE to v2_workspaces_host_fk, and updates the delete-host dialog copy to accurately reflect that workspaces are removed along with the host.

  • Migration 0061: drops and re-adds v2_workspaces_host_fk with ON DELETE CASCADE, matching the existing pattern on v2_users_hosts_host_fk. The SQL is correct; the Drizzle snapshot and journal are consistent.
  • Schema change: v2Workspaces table gains .onDelete(\"cascade\") on its host foreign key. chat_sessions.v2WorkspaceId is properly SET NULL, but automations.v2WorkspaceId and automation_runs.v2WorkspaceId are unconstrained UUID columns that will hold stale IDs after a cascade workspace delete.
  • UI copy: both the inline hint and the confirmation dialog now correctly state that workspaces are removed and files on the machine stay.

Confidence Score: 4/5

Safe to merge; the FK fix and dialog copy are correct, with one pre-existing soft-reference gap in automations worth tracking.

The core change — adding cascade to the host FK and updating the confirmation dialog — is correct and well-scoped. The only gap is that automations.v2WorkspaceId and automation_runs.v2WorkspaceId are unconstrained UUIDs with no nullification on workspace delete, so they will silently point to deleted rows after a host is removed. This was dormant before (host deletion was always blocked), but this PR makes it reachable in production.

packages/db/src/schema/schema.ts — specifically whether automations.v2WorkspaceId and automation_runs.v2WorkspaceId should receive SET NULL FK constraints or be cleaned up by the host-delete handler.

Important Files Changed

Filename Overview
packages/db/drizzle/0061_v2_workspaces_host_fk_cascade.sql Drops and re-adds v2_workspaces_host_fk with ON DELETE CASCADE; migration is correct and minimal.
packages/db/src/schema/schema.ts Adds .onDelete("cascade") to v2_workspaces_host_fk — correct fix; however, automations.v2WorkspaceId and automation_runs.v2WorkspaceId are unconstrained UUID columns that will become stale after a cascade workspace delete.
apps/desktop/src/renderer/routes/_authenticated/settings/hosts/$hostId/components/HostSettings/components/DeleteHostSection/DeleteHostSection.tsx Dialog copy accurately updated to reflect that workspaces are now deleted alongside the host; logic is unchanged.
packages/db/drizzle/meta/_journal.json Journal entry for migration 0061 added at the correct index; timestamps and tag are consistent.
packages/db/drizzle/meta/0061_snapshot.json Drizzle-generated schema snapshot for migration 0061; no hand-edits detected.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant UI as Desktop UI
    participant API as API / DB
    participant PG as Postgres

    UI->>API: DELETE /hosts/:hostId
    API->>PG: "DELETE FROM v2_hosts WHERE machine_id = ?"
    Note over PG: v2_workspaces_host_fk ON DELETE CASCADE (new)
    PG-->>PG: "cascade DELETE v2_workspaces WHERE host_id = ?"
    Note over PG: chat_sessions.v2_workspace_id → SET NULL ✓
    Note over PG: automations.v2_workspace_id → stale UUID (no FK)
    Note over PG: automation_runs.v2_workspace_id → stale UUID (no FK)
    PG-->>API: OK
    API-->>UI: 200 OK
    UI->>UI: Navigate to /settings/hosts
    UI-->>UI: Toast "Deleted hostName"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant UI as Desktop UI
    participant API as API / DB
    participant PG as Postgres

    UI->>API: DELETE /hosts/:hostId
    API->>PG: "DELETE FROM v2_hosts WHERE machine_id = ?"
    Note over PG: v2_workspaces_host_fk ON DELETE CASCADE (new)
    PG-->>PG: "cascade DELETE v2_workspaces WHERE host_id = ?"
    Note over PG: chat_sessions.v2_workspace_id → SET NULL ✓
    Note over PG: automations.v2_workspace_id → stale UUID (no FK)
    Note over PG: automation_runs.v2_workspace_id → stale UUID (no FK)
    PG-->>API: OK
    API-->>UI: 200 OK
    UI->>UI: Navigate to /settings/hosts
    UI-->>UI: Toast "Deleted hostName"
Loading

Comments Outside Diff (1)

  1. packages/db/src/schema/schema.ts, line 779 (link)

    P2 Stale v2WorkspaceId in automations after host delete

    automations.v2WorkspaceId and automation_runs.v2WorkspaceId (line 825) hold workspace IDs with no FK constraint — they are bare uuid() columns with no .references() call. chat_sessions.v2WorkspaceId is correctly handled with onDelete: "set null", but automations and automation_runs are not. When a host is deleted, its workspace rows cascade-delete (the fix this PR introduces), leaving these two columns pointing to deleted workspace IDs. Any app code that looks up a workspace by automations.v2WorkspaceId or automation_runs.v2WorkspaceId will get a missing row without any nullification signal from the DB.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: packages/db/src/schema/schema.ts
    Line: 779
    
    Comment:
    **Stale `v2WorkspaceId` in automations after host delete**
    
    `automations.v2WorkspaceId` and `automation_runs.v2WorkspaceId` (line 825) hold workspace IDs with no FK constraint — they are bare `uuid()` columns with no `.references()` call. `chat_sessions.v2WorkspaceId` is correctly handled with `onDelete: "set null"`, but automations and automation_runs are not. When a host is deleted, its workspace rows cascade-delete (the fix this PR introduces), leaving these two columns pointing to deleted workspace IDs. Any app code that looks up a workspace by `automations.v2WorkspaceId` or `automation_runs.v2WorkspaceId` will get a missing row without any nullification signal from the DB.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/db/src/schema/schema.ts:779
**Stale `v2WorkspaceId` in automations after host delete**

`automations.v2WorkspaceId` and `automation_runs.v2WorkspaceId` (line 825) hold workspace IDs with no FK constraint — they are bare `uuid()` columns with no `.references()` call. `chat_sessions.v2WorkspaceId` is correctly handled with `onDelete: "set null"`, but automations and automation_runs are not. When a host is deleted, its workspace rows cascade-delete (the fix this PR introduces), leaving these two columns pointing to deleted workspace IDs. Any app code that looks up a workspace by `automations.v2WorkspaceId` or `automation_runs.v2WorkspaceId` will get a missing row without any nullification signal from the DB.

Reviews (1): Last reviewed commit: "fix(db,desktop): cascade host's workspac..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/db/src/schema/schema.ts (1)

576-576: 🗄️ Data Integrity & Integration | 🔵 Trivial | 🏗️ Heavy lift

Add DB-backed coverage for the host-delete cascade. The mocked router test only covers the SQL call, so it can’t catch a broken v2_hosts -> v2_workspaces -> chat_sessions cascade. Assert that deleting a host removes its workspaces and sets linked chat_sessions.v2_workspace_id to null.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/db/src/schema/schema.ts` at line 576, Add database-backed test
coverage for the host deletion cascade defined by the schema relation. Insert a
host with associated workspaces and linked chat sessions, delete the host
through the database, then assert the workspaces are removed and each affected
chat_sessions.v2_workspace_id is null; keep the existing mocked router test
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/db/src/schema/schema.ts`:
- Line 576: Add database-backed test coverage for the host deletion cascade
defined by the schema relation. Insert a host with associated workspaces and
linked chat sessions, delete the host through the database, then assert the
workspaces are removed and each affected chat_sessions.v2_workspace_id is null;
keep the existing mocked router test unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7d7be529-c924-49b4-9e60-d2045c7b0ee2

📥 Commits

Reviewing files that changed from the base of the PR and between 953e8fb and 1bde5e7.

📒 Files selected for processing (5)
  • apps/desktop/src/renderer/routes/_authenticated/settings/hosts/$hostId/components/HostSettings/components/DeleteHostSection/DeleteHostSection.tsx
  • packages/db/drizzle/0061_v2_workspaces_host_fk_cascade.sql
  • packages/db/drizzle/meta/0061_snapshot.json
  • packages/db/drizzle/meta/_journal.json
  • packages/db/src/schema/schema.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 5 files

Re-trigger cubic

@github-actions

github-actions Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

@Kitenite
Kitenite merged commit b13a92c into main Jul 17, 2026
19 checks passed

This branch was previously deployed

1 inactive deployment
preview — 1bde5e73 Deployed Jul 17, 2026 by Kitenite via Deploy Docs #6567
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