Commit d1cdc6a
committed
fix(folders): close the findings from the line-by-line audit of the PR
Data integrity
- Workspace fork copied `folderId` verbatim onto the child's tables and knowledge bases. The
column carries no workspace, so a forked row pointed at a folder owned by the SOURCE
workspace — invisible in the fork, and mutated from under it when the source later deleted
that folder (`ON DELETE SET NULL`). Latent until now because nothing wrote a non-null
`folderId` for those two resources; this PR is what makes it reachable. Forked resources land
at the root, like forked files already did
Interaction bugs
- Clearing a dead `?folderId=` wrote through the params' default `history: 'push'`, so Back
returned to the dead URL, which healed and pushed again — the Back button was dead on that
page. It replaces now: opening a folder is navigation, correcting a URL that never pointed
anywhere is not
- That same heal keyed off `isLoading`, which is false for a DISABLED query, false for an
ERRORED one, and false while `keepPreviousData` is showing the previous workspace's folders.
In all three the list is empty or stale, so a transient fetch failure — or a workspace switch
— threw away a perfectly good open folder. Gated on `isSuccess && !isPlaceholderData`
- "New folder" while a search was active created the folder but never showed it: the search
filters folders too, so the new row did not match, the rename field never appeared, and the
create read as a no-op. Both pages clear the search so the thing just created is on screen
- The drag ghost was removed only by `dragend`, which fires on the source row. The table is
virtualized, so scrolling the source out of view mid-drag unmounted it, the event never
arrived, and the ghost stayed on the page with every row stuck at drag opacity. Cleaned up on
unmount as the backstop
- A drag begun in another mount highlighted every folder as a valid target — including the
dragged folder itself — then silently did nothing on drop. It only highlights when the source
is known and was actually checked
Correctness
- The folder-duplicate route caught 23505 across the WHOLE handler, so a unique violation
raised while copying the workflows inside the folder was relabelled "a folder with this name
already exists". Scoped to the folder INSERT, which is the only place the two conflicts the
caller can act on (client-supplied `newId` replay, concurrent name take) actually arise
- The optimistic folder create derived its sort order from the workspace's WORKFLOWS regardless
of resource type. Only the workflow tree interleaves folders and resources in one ordering
space, so a knowledge-base or table folder was placed against an unrelated one
- A table archived between `checkAccess` and the move surfaced as a 500 with a "not found"
body; it is a 404
- `FOLDER_RESOURCE_TYPE_BY_RESTORABLE` was a `Partial` record, so adding a folder tree without a
mapping would compile and silently restore into the workflow tree. Total record now
- Recently Deleted paired query results to folder trees by ARRAY POSITION; reordering the const
would have filed knowledge folders under Tables with no type error. Keyed by type
- The knowledge move's no-op guard compared against the snapshot taken when the menu opened
rather than the live row
Performance — the module split now actually does what it claimed
- `knowledge-keys.ts` justified itself as keeping server prefetches off the ~1000-line
`kb/knowledge` module, but `knowledge/prefetch.ts` still imported its stale-time constant from
exactly that module, whose first line pulls the `@sim/emcn` barrel. Worse, this PR had ADDED
the same class of edge to four prefetches via `FOLDER_LIST_STALE_TIME`/`mapFolder`
- `FOLDER_LIST_STALE_TIME`, `mapFolder`, and `KNOWLEDGE_BASE_LIST_STALE_TIME` now live beside
their key factories, so all four server prefetches import only keys-and-constants modules.
`mapFolder` keeps its explicit field list rather than a spread, so the cached shape cannot
drift from a client fetch
Honesty in comments
- The KB retention `deleteFilter` narrows the restore race but does not close it — documents
hard-deleted by `onBatch` do not come back, so a restore landing mid-batch returns an emptied
base. Said so
- A failed folder restore leaves children active while their folders are still archived. They
are reachable (both lists fall an unresolvable `folderId` back to the root) but they sit at
the root until the restore is retried. Said so
Product policy made visible
- Restore deliberately does not re-enable schedules, webhooks, or chats, because archive
overwrites their state without recording it — on production ~47% of live schedules sit at
`disabled` and ~12% of live webhooks at `isActive: false`, so reactivating to a constant would
be wrong far more often than right. Recently Deleted now says so at the moment of restore
instead of leaving it to be discovered
Smaller
- Pin glyph: dropped the doubled gap, added `role='img'` so the state is announced
- "Move here" carries the folder glyph its sibling leaves do
- `useMoveTable` had stolen `useDeleteTable`'s doc block
- Dead `.returning` column and a `?? null` on a non-nullable param in `moveTableToFolder`
- Tables reads one sort source for both blocks, matching Knowledge
- New test pins that `updateFolder` refuses an archived folder — the guard that stops a delete
from unlocking its locked subfolders1 parent 01dc6a9 commit d1cdc6a
25 files changed
Lines changed: 279 additions & 104 deletions
File tree
- apps/sim
- app
- api
- folders/[id]/duplicate
- table/[tableId]
- workspace/[workspaceId]
- components
- folders
- resource
- home
- knowledge
- settings/components/recently-deleted
- tables
- background
- ee/workspace-forking/lib/copy
- hooks/queries
- kb
- utils
- lib
- folders
- resources/orchestration
- table
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
123 | 123 | | |
124 | 124 | | |
125 | 125 | | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
136 | | - | |
137 | | - | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
138 | 158 | | |
139 | 159 | | |
140 | 160 | | |
| |||
201 | 221 | | |
202 | 222 | | |
203 | 223 | | |
204 | | - | |
205 | | - | |
206 | | - | |
207 | | - | |
208 | | - | |
209 | | - | |
210 | | - | |
211 | | - | |
212 | | - | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | 224 | | |
219 | 225 | | |
220 | 226 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
196 | 196 | | |
197 | 197 | | |
198 | 198 | | |
199 | | - | |
200 | | - | |
201 | | - | |
202 | | - | |
203 | | - | |
204 | | - | |
205 | | - | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
206 | 215 | | |
207 | 216 | | |
208 | 217 | | |
| |||
Lines changed: 3 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
1 | 2 | | |
2 | 3 | | |
3 | 4 | | |
| |||
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
11 | | - | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| 50 | + | |
49 | 51 | | |
50 | 52 | | |
51 | | - | |
52 | | - | |
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| |||
Lines changed: 9 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
45 | 50 | | |
46 | 51 | | |
47 | 52 | | |
| |||
131 | 136 | | |
132 | 137 | | |
133 | 138 | | |
134 | | - | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
135 | 143 | | |
136 | 144 | | |
137 | 145 | | |
| |||
Lines changed: 25 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
55 | | - | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
56 | 71 | | |
57 | 72 | | |
58 | 73 | | |
| |||
80 | 95 | | |
81 | 96 | | |
82 | 97 | | |
83 | | - | |
84 | | - | |
85 | | - | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
86 | 107 | | |
87 | 108 | | |
88 | 109 | | |
| |||
Lines changed: 21 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
84 | 98 | | |
85 | 99 | | |
86 | 100 | | |
| |||
146 | 160 | | |
147 | 161 | | |
148 | 162 | | |
149 | | - | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
150 | 169 | | |
151 | 170 | | |
152 | 171 | | |
| |||
Lines changed: 8 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
64 | 64 | | |
65 | 65 | | |
66 | 66 | | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
67 | 70 | | |
68 | 71 | | |
69 | 72 | | |
| |||
526 | 529 | | |
527 | 530 | | |
528 | 531 | | |
529 | | - | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
530 | 537 | | |
531 | 538 | | |
532 | 539 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
| 5 | + | |
7 | 6 | | |
8 | 7 | | |
9 | 8 | | |
| |||
Lines changed: 11 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
691 | 691 | | |
692 | 692 | | |
693 | 693 | | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
694 | 701 | | |
695 | 702 | | |
696 | 703 | | |
| |||
834 | 841 | | |
835 | 842 | | |
836 | 843 | | |
837 | | - | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
838 | 848 | | |
839 | 849 | | |
840 | 850 | | |
| |||
Lines changed: 2 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
| 5 | + | |
| 6 | + | |
9 | 7 | | |
10 | 8 | | |
11 | 9 | | |
| |||
0 commit comments