-- Pricing slot / beta-lock metadata. -- -- 2-product launch decision (Session 7h): VYNDR ($14.99/mo, tier=analyst) -- and VYNDR Desk ($44.99/mo, tier=desk). No early-bird tier — the beta -- price IS the locked-in price. -- -- This table exists so the frontend pricing page can read live counts -- ("147 of unlimited slots taken at beta price") and so the webhook -- can record which Stripe price a subscription was created on. Keep -- early_bird_limit nullable for now; we may slot it in later. -- -- RUN THIS IN THE SUPABASE SQL EDITOR. Do NOT add it to the migrations -- chain — it's intentionally out-of-band per session policy. CREATE TABLE IF NOT EXISTS public.pricing_slots ( tier text PRIMARY KEY, beta_price_id text, beta_price_usd numeric, -- Reserved for a future "first N seats" promo; null means no cap. early_bird_limit integer, early_bird_used integer NOT NULL DEFAULT 0, early_bird_price_id text, updated_at timestamptz NOT NULL DEFAULT now() ); ALTER TABLE public.pricing_slots ENABLE ROW LEVEL SECURITY; -- Public-read so the pricing page can query slot status without auth. -- Writes happen only from the Stripe webhook via the service role. DROP POLICY IF EXISTS "public reads pricing_slots" ON public.pricing_slots; CREATE POLICY "public reads pricing_slots" ON public.pricing_slots FOR SELECT USING (true); -- Seed rows for the two tiers Session 7h ships. Price IDs filled from -- the Stripe test-mode resources created at session end. When you cut -- over to live mode, repeat the create flow against the live key and -- swap these two values; everything else (events, structure) is the -- same. INSERT INTO public.pricing_slots (tier, beta_price_id, beta_price_usd) VALUES ('analyst', 'price_1TgpGxIp1Mec3r2E6Wh6oeaP', 14.99), ('desk', 'price_1TgpGyIp1Mec3r2EQq50KKhF', 44.99) ON CONFLICT (tier) DO NOTHING; -- --------------------------------------------------------------- -- tier CHECK constraint update — required ONLY if a future session -- introduces 'base' or 'pro' as canonical tier names. Current code + -- migrations 001/011 use ('free', 'analyst', 'desk') and Session 7h -- did not change that. Leaving the ALTER commented as documentation -- for whoever expands the tier set later. -- --------------------------------------------------------------- -- ALTER TABLE public.users DROP CONSTRAINT IF EXISTS users_tier_check; -- ALTER TABLE public.users -- ADD CONSTRAINT users_tier_check -- CHECK (tier IN ('free', 'analyst', 'pro', 'desk')); -- ALTER TABLE public.user_profiles DROP CONSTRAINT IF EXISTS user_profiles_tier_check; -- ALTER TABLE public.user_profiles -- ADD CONSTRAINT user_profiles_tier_check -- CHECK (tier IN ('free', 'analyst', 'pro', 'desk'));