You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(folders): fix migration-breaking prod data collision and KB unlock bug
- The backfill INSERT for workflow_folder assumed (workspace_id, parent_id,
name) was unique, but that table has no such constraint -- verified
against production via PlanetScale: 33 groups of genuine active
duplicates exist today (up to 8x in one workspace), which would have
aborted the entire migration with a unique-violation the moment it ran
against prod data. Backfill now deduplicates active rows deterministically
(ordered by created_at, then id) appending " (N)" per collision, matching
the app's own "New folder (N)" dedup convention -- archived rows are
exempt from the new constraint and are never renamed. Verified live: a
reproduction of the exact prod collision shape backfills correctly, and
the full 0000-0258 sequence still applies cleanly from scratch
- Knowledge base unlock was completely broken: PUT /api/knowledge/[id]
always builds a full literal update object with every field present
(unset ones as `undefined`), so Object.keys(updates) always included
name/description/etc regardless of what was actually sent, making the
"is this a lock-only update" check permanently true -- an admin could
never unlock a KB once locked (directly or via an ancestor folder), since
the mutability check ran against the still-locked current row before the
unlock could apply. Fixed to check `!== undefined` per field, matching
the isLockOnlyUpdate pattern already used correctly by renameTable() and
performRenameWorkspaceFile(). Added a regression test using the exact
object shape the route actually constructs -- the existing test never
caught this since it called the function with a clean `{ locked: false }`
object that doesn't reproduce the route's actual literal-object shape
- Trimmed 3 files' leftover WHAT-comments (pure restatement of the code
below them) as part of a full comment-quality pass across the diff
0 commit comments