Add migrations 072-076: sandbox accounts, pending uniqueness, promo tracking, content removal, termination
072: sandbox account columns (is_sandbox, sandbox_expires_at) with partial index
073: partial unique indexes preventing duplicate pending checkouts per buyer
074: promo_code_id on transactions for stale reservation cleanup
075: per-item admin content removal fields (removed_by_admin, removal_reason, removed_at)
076: terminated_at column for 30-day export window before account deletion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 files changed,
+35 insertions,
-0 deletions
|
1 |
+ |
-- Sandbox accounts: ephemeral creator accounts for exploring the dashboard.
|
|
2 |
+ |
-- Sandbox users are real rows with is_sandbox = TRUE, auto-deleted after expiry.
|
|
3 |
+ |
|
|
4 |
+ |
ALTER TABLE users ADD COLUMN is_sandbox BOOLEAN NOT NULL DEFAULT FALSE;
|
|
5 |
+ |
ALTER TABLE users ADD COLUMN sandbox_expires_at TIMESTAMPTZ;
|
|
6 |
+ |
|
|
7 |
+ |
-- Partial index for the cleanup query (only sandbox rows).
|
|
8 |
+ |
CREATE INDEX idx_users_sandbox_expires ON users (sandbox_expires_at) WHERE is_sandbox = TRUE;
|
|
1 |
+ |
-- Prevent duplicate pending transactions for the same buyer+item or buyer+project.
|
|
2 |
+ |
-- This closes a TOCTOU race where two concurrent checkout requests both pass
|
|
3 |
+ |
-- the has_purchased_item check and create separate pending transactions.
|
|
4 |
+ |
|
|
5 |
+ |
CREATE UNIQUE INDEX idx_transactions_buyer_item_pending
|
|
6 |
+ |
ON transactions (buyer_id, item_id)
|
|
7 |
+ |
WHERE status = 'pending' AND item_id IS NOT NULL;
|
|
8 |
+ |
|
|
9 |
+ |
CREATE UNIQUE INDEX idx_transactions_buyer_project_pending
|
|
10 |
+ |
ON transactions (buyer_id, project_id)
|
|
11 |
+ |
WHERE status = 'pending' AND project_id IS NOT NULL;
|
|
1 |
+ |
-- Track which promo code was used for a transaction so the scheduler can
|
|
2 |
+ |
-- release reserved use_count slots when stale pending transactions are cleaned up.
|
|
3 |
+ |
ALTER TABLE transactions ADD COLUMN promo_code_id UUID REFERENCES promo_codes(id) ON DELETE SET NULL;
|
|
1 |
+ |
-- Per-item content removal by admin, separate from user unpublish.
|
|
2 |
+ |
-- Fulfills the enforcement ladder's "content removal" step (item hidden,
|
|
3 |
+ |
-- account stays active, creator notified with reason).
|
|
4 |
+ |
|
|
5 |
+ |
ALTER TABLE items ADD COLUMN removed_by_admin BOOLEAN NOT NULL DEFAULT false;
|
|
6 |
+ |
ALTER TABLE items ADD COLUMN removal_reason TEXT;
|
|
7 |
+ |
ALTER TABLE items ADD COLUMN removed_at TIMESTAMPTZ;
|
|
1 |
+ |
-- Account termination with 30-day export window.
|
|
2 |
+ |
-- terminated_at marks when the admin permanently terminated the account.
|
|
3 |
+ |
-- The user can still log in and use export endpoints for 30 days.
|
|
4 |
+ |
-- After 30 days, the scheduler deletes the account.
|
|
5 |
+ |
|
|
6 |
+ |
ALTER TABLE users ADD COLUMN terminated_at TIMESTAMPTZ;
|