Commit 48a6f6b
Fix: allow Free saved_workspace upsert (Codex P1 finding)
The saved_workspaces quota gate was rejecting every re-save from a
Free user (cap=1) because it checked `existing_count >= cap` without
distinguishing UPDATES to an existing slot from creation of NEW slots.
Today's store upserts on user_id (one row per user), so any "existing
row" means the save is an update — not a new slot — and the cap
shouldn't apply.
Real-world impact: the frontend autosave path calls /workspace/save
directly without pre-delete. Once a Free user has one saved workspace,
every subsequent autosave got rejected with a 429, breaking the
snapshot-refresh UX for every Free user past their first save.
Fix splits the gate into two questions:
* is_existing_slot_update — does the user already own the slot?
* is_creating_new_slot — would this save add to the slot count?
The cap fires only on the second case. Today, with one-row-per-user
storage, the gate is effectively dormant (existing_count == 1 always
means update, existing_count == 0 with cap >= 1 always passes). It
will start firing correctly the moment we migrate to per-slot rows
(future PR with slugs/labels), without revisiting this code path.
test_2nd_saved_workspace_on_free_returns_429 was inverted to
test_free_re_save_upserts_existing_workspace and now pins the
correct UX: re-saving is allowed because it's an update, not a new
slot. test_saved_workspace_delete_then_save_works was updated to
drop the intermediate 429 assertion (no longer fires under the
fix) and instead pin that DELETE + save round-trips cleanly.
Found by ChatGPT Codex review on PR #2 (May 2026).
Full backend suite: 501 passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 8dacf9c commit 48a6f6b
2 files changed
Lines changed: 60 additions & 47 deletions
File tree
- backend/services
- tests/backend
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | | - | |
121 | | - | |
| 117 | + | |
| 118 | + | |
122 | 119 | | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
128 | 126 | | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
134 | 138 | | |
135 | 139 | | |
136 | 140 | | |
| |||
140 | 144 | | |
141 | 145 | | |
142 | 146 | | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
| 147 | + | |
| 148 | + | |
147 | 149 | | |
148 | | - | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
149 | 153 | | |
150 | 154 | | |
151 | 155 | | |
| |||
Lines changed: 36 additions & 27 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
527 | 527 | | |
528 | 528 | | |
529 | 529 | | |
530 | | - | |
531 | | - | |
532 | | - | |
533 | | - | |
534 | | - | |
535 | | - | |
536 | | - | |
537 | | - | |
538 | | - | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
539 | 546 | | |
540 | 547 | | |
541 | 548 | | |
542 | 549 | | |
543 | 550 | | |
544 | | - | |
545 | | - | |
| 551 | + | |
| 552 | + | |
546 | 553 | | |
547 | | - | |
548 | | - | |
549 | | - | |
550 | | - | |
551 | | - | |
552 | | - | |
553 | | - | |
554 | | - | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
555 | 558 | | |
556 | 559 | | |
557 | 560 | | |
| |||
579 | 582 | | |
580 | 583 | | |
581 | 584 | | |
582 | | - | |
583 | | - | |
584 | | - | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
585 | 592 | | |
586 | 593 | | |
587 | 594 | | |
588 | | - | |
589 | | - | |
590 | | - | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
591 | 599 | | |
592 | | - | |
593 | | - | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
0 commit comments