Commit 7ceebd1
committed
feat(admin): move a workspace between organizations
The admin workspace move was restricted to personal/grandfathered sources;
`assertWorkspaceMovable` refused anything already owned by an organization, so
support could only re-home a workspace with manual SQL.
Relax that guard to a drift-only check and handle the source organization.
`changeWorkspaceStoragePayerInTx` already accepted an arbitrary source payer,
so the storage-ledger rebalance needed no change.
Moving a workspace between organizations is the first operation capable of
separating an artifact from the organization that owns it, so two invariants
nothing has ever had to defend are enforced here:
- A custom block and its bound workflow always share an organization.
`getCustomBlockAuthority` resolves by the consumer's org and
`admitCustomBlockChildExecution` skips its concurrency reservation on the
strength of that, so a stranded row would run a foreign tenant's workflow
under its owner's credentials, billed to the wrong payer. The move
unpublishes those blocks through the product's own `deleteCustomBlock` and
records the loss in the source organization's audit view.
- A fork parent and child always share an organization. `resolveForkEdge` has
no org check at all, so the move refuses while a cross-org edge would result.
Enforcing them at move time is not enough on its own: `publishCustomBlock` and
fork creation wrote without the organization mutation lock, so either could
commit after the move's scans and produce exactly the artifact the move
refused to create. Both now take that lock, which is what actually makes the
invariants hold under concurrency.
Pending invitations block too. Re-stamping an org-scoped invitation would
convert a pending membership in the source org into one in the destination,
consuming a seat for an invitation the destination never issued.
An entitlement downgrade blocks: `isOrganizationOnEnterprisePlan` gates
permission groups, SSO domains, data retention, session revocation, forking,
and custom blocks, and losing them silently is not recoverable. That check
resolves before the transaction — it reads through the global client with no
executor seam, and a plan lapsing in the intervening seconds is recoverable by
moving the workspace back, unlike a cross-organization artifact.
Both organizations are locked, ascending by id, mirroring
`acquireOrganizationUserMutationLocks`. The source id is read optimistically
before the transaction and re-verified under the locks, retrying through the
existing loop when it moved.1 parent e4c0a9f commit 7ceebd1
6 files changed
Lines changed: 1766 additions & 78 deletions
File tree
- apps/sim
- ee/workspace-forking/lib
- lib
- api/contracts/v1/admin
- workflows/custom-blocks
- workspaces
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
161 | 162 | | |
162 | 163 | | |
163 | 164 | | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
164 | 176 | | |
165 | 177 | | |
166 | 178 | | |
| |||
Lines changed: 97 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
| 62 | + | |
| 63 | + | |
62 | 64 | | |
63 | 65 | | |
64 | 66 | | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
65 | 139 | | |
66 | 140 | | |
67 | 141 | | |
68 | 142 | | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
69 | 153 | | |
70 | 154 | | |
71 | 155 | | |
| |||
80 | 164 | | |
81 | 165 | | |
82 | 166 | | |
| 167 | + | |
| 168 | + | |
83 | 169 | | |
84 | 170 | | |
85 | 171 | | |
| |||
91 | 177 | | |
92 | 178 | | |
93 | 179 | | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
94 | 191 | | |
95 | 192 | | |
96 | 193 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
| 16 | + | |
15 | 17 | | |
16 | 18 | | |
17 | 19 | | |
| |||
495 | 497 | | |
496 | 498 | | |
497 | 499 | | |
498 | | - | |
499 | | - | |
500 | | - | |
501 | | - | |
502 | | - | |
503 | | - | |
504 | | - | |
505 | | - | |
506 | | - | |
507 | | - | |
508 | | - | |
509 | | - | |
510 | | - | |
511 | | - | |
512 | | - | |
513 | | - | |
514 | 500 | | |
515 | 501 | | |
516 | 502 | | |
517 | 503 | | |
518 | | - | |
519 | | - | |
520 | | - | |
521 | | - | |
522 | | - | |
523 | | - | |
524 | | - | |
525 | | - | |
526 | | - | |
527 | | - | |
528 | | - | |
529 | | - | |
530 | | - | |
531 | | - | |
532 | | - | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
533 | 553 | | |
534 | 554 | | |
535 | 555 | | |
| |||
588 | 608 | | |
589 | 609 | | |
590 | 610 | | |
591 | | - | |
592 | | - | |
593 | | - | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
594 | 621 | | |
595 | 622 | | |
596 | 623 | | |
| |||
0 commit comments