Skip to main content

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-ByClaude Opus 4.6 (1M context) <noreply@anthropic.com>

Author: Max J. <87768334+MaxJMath@users.noreply.github.com> - 2026-04-26 19:39 UTC

Commit:

69240f66ec2e78e65287ea441e696694192e04c9

Parent:

d0d6fa7

5 files changed,

+35 insertions,

-0 deletions

OldNewLine
@@ -1,0 +1,8 @@
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;
OldNewLine
@@ -1,0 +1,11 @@
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;
OldNewLine
@@ -1,0 +1,3 @@
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;
OldNewLine
@@ -1,0 +1,7 @@
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;
OldNewLine
@@ -1,0 +1,6 @@
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;