Skip to main content

max / makenotwork

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>
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
@@ -0,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;
@@ -0,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;
@@ -0,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;
@@ -0,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;
@@ -0,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;