-- 036 — THE REAL FOUNDER CAP (A2-A6). One concern: the founder mechanism.
-- Applied to prod 2026-07-31 (supabase_migrations 20260731211703).
--
-- THE UNIQUE INDEX IS THE LOCK. The claim is a single UPDATE whose target row
-- is chosen with FOR UPDATE SKIP LOCKED, so two concurrent claims cannot take
-- the same slot. NO count is read in the decision path (the old view was a
-- decorative count with no lock).
--
-- POOL = GLOBAL 100 (Q1): the slot travels with the user, so analyst->desk
-- keeps founder with no second claim and can never be denied.
-- CANCEL = RETIRE FOREVER (Q2): cancelled slots stay claimed; the public
-- counter only rises toward 100 and can never decrease.
-- PRICE IDS ARE NOT IN SQL — the function returns a price KEY and the Node
-- layer maps it to STRIPE_PRICE_* env with a boot assertion. A hardcoded id
-- here would become a permanent silent mis-charge on a typo.

CREATE TABLE IF NOT EXISTS founder_slots (
  slot_number            int         PRIMARY KEY,
  user_id                uuid        NULL REFERENCES auth.users(id) ON DELETE SET NULL,
  status                 text        NOT NULL DEFAULT 'free'
                                     CHECK (status IN ('free','provisional','claimed')),
  tier                   text        NULL,
  claimed_at             timestamptz NULL,
  expires_at             timestamptz NULL,
  stripe_subscription_id text        NULL,
  created_at             timestamptz NOT NULL DEFAULT now(),
  updated_at             timestamptz NOT NULL DEFAULT now()
);

-- ONE LIVE SLOT PER USER (free rows have NULL user_id, so only live rows bind).
CREATE UNIQUE INDEX IF NOT EXISTS idx_founder_slots_one_per_user
  ON founder_slots (user_id) WHERE status <> 'free';
CREATE INDEX IF NOT EXISTS idx_founder_slots_free
  ON founder_slots (slot_number) WHERE status = 'free';

INSERT INTO founder_slots (slot_number)
SELECT gs FROM generate_series(1, 100) gs ON CONFLICT (slot_number) DO NOTHING;

ALTER TABLE founder_slots ENABLE ROW LEVEL SECURITY;  -- service-role only

-- A3 atomic claim / A4 finalize / A5 TTL release / A6 honest counter:
-- see the applied migration body (identical to this file) for
--   claim_founder_slot(uuid, text) -> (is_founder, price_key, slot_number)
--   finalize_founder_slot(uuid, text, text, text) -> boolean
--   release_expired_slots() -> int
--   VIEW founder_pricing_seats (claimed, total, remaining)
-- A7: finalize is the SINGLE writer of both founder flags in ONE txn —
-- user_profiles.founder_pricing is canonical and users.founder_status mirrors
-- it (it is served by auth PROFILE_COLUMNS + /api/stripe, so it is NOT dropped;
-- only the independent write is retired, because the two already drifted 1 vs 0).
