OUT-4029 | Scope task/label deletion by id + workspace (fix cross-workspace collateral deletes) - #1399
OUT-4029 | Scope task/label deletion by id + workspace (fix cross-workspace collateral deletes)#1399SandipBajracharya wants to merge 3 commits into
Conversation
… Labels rows softDeleteAllSubtasks and deleteAllAssigneeTasks deleted rows keyed on the task label string with no workspaceId filter. Labels has no workspaceId and prefixes derive from brand/company names, so strings like THE10-001 collide across workspaces and deletes wiped other workspaces' tasks. - softDeleteAllSubtasks: select id (not label) and deleteMany by id + workspaceId - deleteAllAssigneeTasks: drop the unscoped label.deleteMany - Remove LabelMappingService.deleteLabel and its call sites; Labels is a next-number registry where orphan rows are harmless and deleting them rolls the counter back, causing duplicate label reissue Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Unit: softDeleteAllSubtasks and deleteAllAssigneeTasks delete by id/assignee scoped to workspaceId and never touch Labels rows - Integration: two workspaces sharing a label string; deleting one workspace's tree soft-deletes only its own subtree and leaves the other untouched - seedTask: optional label so integration tests can seed colliding labels Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
authenticate.test.ts failed to load: p-retry and is-network-error are pure ESM and next/jest only transforms packages listed in transpilePackages. - next.config.js: transpile p-retry / is-network-error (also adds ngrok dev origin) - authenticate.test.ts: update the public-route source fallback assertion from "public" to "platform" to match the intentional change in commit eb76729 (was hidden while the suite couldn't load) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThe PR prevents task deletion from affecting other workspaces and preserves the global label registry’s monotonic counters.
Confidence Score: 5/5The PR appears safe to merge, with deletion correctly constrained to task IDs in the acting workspace and label counters preserved. The changed recursive deletion retains the existing Prisma soft-delete behavior, all production callers first delete the parent and then select its live ltree descendants, and the resulting update is constrained by both descendant IDs and workspace ID; no actionable regression remains. Important Files Changed
Sequence DiagramsequenceDiagram
participant Caller as Task deletion caller
participant DB as PostgreSQL / Prisma
participant Subtasks as SubtaskService
Caller->>DB: Soft-delete parent in workspace
Caller->>Subtasks: softDeleteAllSubtasks(parentId)
Subtasks->>DB: Select live descendant IDs by ltree path + workspaceId
DB-->>Subtasks: Descendant task IDs
Subtasks->>DB: deleteMany by IDs + workspaceId
Note over DB: Prisma extension converts deleteMany to deletedAt update
Note over DB: Labels registry remains unchanged
Reviews (1): Last reviewed commit: "OUT-4029 | Fix authenticate test suite (..." | Re-trigger Greptile |
priosshrsth
left a comment
There was a problem hiding this comment.
@SandipBajracharya Let's not create label too.
What & why
SubtaskService.softDeleteAllSubtasks(anddeleteAllAssigneeTasks) deleted DB rows keyed on the tasklabelstring with noworkspaceIdfilter.Labelshas noworkspaceIdcolumn and prefixes derive from brand/company names, so strings likeTHE10-001collide across workspaces — deleting a task in one workspace soft-deleted tasks (and Labels rows) in other workspaces.Prod impact (read-only queries, 2026-08-06): 2,390 tasks soft-deleted as collateral across 263 workspaces; worst offender
THE10-001spanned 121 workspaces.Linear: OUT-4029
Changes
Core fix
softDeleteAllSubtasks: selectid(notlabel) from the ltree query anddeleteManybyid+workspaceId.deleteAllAssigneeTasks: drop the unscopedlabel.deleteMany.LabelMappingService.deleteLabeland all call sites.Labelsis a next-number registry — orphan rows are harmless, and deleting them rolls the counter back and causes duplicate label reissue. This also makes the OUT-4027 null-guard (OUT-4027 | Fix 500 when deleting a task whose label row is missing #1397) moot.Tests
workspaceIdand never touchLabels.THE10-001; deleting one workspace's tree soft-deletes only its own subtree and leaves the other untouched. Verified to fail against the old string-keyed code and pass with the fix.Test infra (incidental)
next.config.js:transpilePackages: ['p-retry', 'is-network-error']sonext/jestcan load these pure-ESM deps (fixes a pre-existingauthenticate.test.tsload failure). Also carries a ngrok dev-origin line.authenticate.test.ts: corrected a stale public-routesourceassertion (public→platform) that matched an intentional earlier change (eb76729f), previously hidden while the suite couldn't load.Not included / follow-ups
src/cmd/script + product sign-off (per the ticket's open question).Labelstable now accumulates orphan rows on delete/reassign (agreed tradeoff) — worth a follow-up if the table grows large.Verification
yarn tscclean,yarn lint:checkclean.🤖 Generated with Claude Code