Continuing the BookifAI build (children's/general KDP book SaaS, cloned off Lovable onto Sondra's own stack). She chose to build billing/metering next. Session was a long design discussion that locked the free-plan spec, caps, refund rules, and positioning, then built + deployed the backend "money spine." Nothing is public; Stripe is in TEST mode; app has 0 real users.
PRD.md section 7.7.umnlokuehteqwrheoyai): tables profiles, book_meters, purchases — RLS on, read-own only, server-write-only (no user write policies); signup trigger auto-creates profile; project trigger auto-creates book_meter. Migration billing_money_spine. Local copy: c:\Users\srver\AIOS-Workspace\aios-starter-kit\PROJECTS\Bookify AI Studio\app\supabase\migrations\20260705000000_billing_money_spine.sql.apply_purchase(...) — records purchase (idempotent via unique stripe_event_id) + grants entitlement/credits in one transaction; execute revoked from public/anon/authenticated, granted to service_role only. Migration billing_apply_purchase_fn (MCP-only, no local file yet).RvzUwDwHkj): Single $29 price_1Tq2waRvzUwDwHkj3fQI5qy2, Author Pack $79 price_1Tq2waRvzUwDwHkjNujqRWdE, Image Credits $9 price_1Tq2wbRvzUwDwHkjvc3q9Kb0. Saved: c:\Users\srver\AIOS-Workspace\aios-starter-kit\PROJECTS\Bookify AI Studio\stripe-test-products.json.we_1Tq36BRvzUwDwHkj39V7Q7rv -> deployed function, event checkout.session.completed.create-checkout (verify_jwt=true, ownership-checked) and stripe-webhook (verify_jwt=false, signature-verified). config.toml sets webhook verify_jwt=false.STRIPE_SECRET_KEY (test), STRIPE_WEBHOOK_SECRET, STRIPE_PRICE_SINGLE, STRIPE_PRICE_AUTHOR_PACK, STRIPE_PRICE_IMAGE_CREDITS. (SUPABASE_URL/SERVICE_ROLE_KEY/ANON_KEY auto-provided.)c:\Users\srver\AIOS-Workspace\aios-starter-kit\PROJECTS\Bookify AI Studio\PRD.md — read section 7.7 first (the locked billing/metering/refund spec + next-build backlog).c:\Users\srver\AIOS-Workspace\aios-starter-kit\PROJECTS\Bookify AI Studio\app\supabase\functions\create-checkout\index.tsc:\Users\srver\AIOS-Workspace\aios-starter-kit\PROJECTS\Bookify AI Studio\app\supabase\functions\stripe-webhook\index.tsc:\Users\srver\AIOS-Workspace\aios-starter-kit\PROJECTS\Bookify AI Studio\app\supabase\migrations\20260705000000_billing_money_spine.sqlc:\Users\srver\AIOS-Workspace\aios-starter-kit\PROJECTS\Bookify AI Studio\stripe-test-products.json — price IDs for checkout.c:\Users\srver\AIOS-Workspace\aios-starter-kit\PROJECTS\Bookify AI Studio\app\src\components\create-book\BookPreview.tsx + ExportOptions.tsx — where Buy/Unlock buttons + gates attach next.c:\Users\srver\AIOS-Workspace\aios-starter-kit\PROJECTS\Bookify AI Studio\app\supabase\functions\generate-illustration\index.ts — currently UNAUTH + UNMETERED; the image gate goes here.find was run in background earlier this session; it completed — nothing to kill.)cd "PROJECTS/Bookify AI Studio/app" && npm run dev -> localhost:8080 (kill stale node if 8080-8083 busy).main of the cloned repo, local only, nothing pushed).list_tables project umnlokuehteqwrheoyai -> confirm profiles, book_meters, purchases exist, RLS on.curl -s -o /dev/null -w "%{http_code}" -X POST https://umnlokuehteqwrheoyai.supabase.co/functions/v1/create-checkout -H "Authorization: Bearer <VITE anon key>" -H "Content-Type: application/json" -d '{"product":"single","projectId":"0","origin":"http://localhost:8080"}' -> expect 401.curl -s -o /dev/null -w "%{http_code}" -X POST https://umnlokuehteqwrheoyai.supabase.co/functions/v1/stripe-webhook -H "stripe-signature: t=1,v1=forged" -d '{}' -> expect 400.apply_purchase grant/idempotency already SQL-verified this session (grants once, duplicate event returns false, book->paid, +25/+5 credits).TOKEN=$(python -c "import re,pathlib;print(re.findall(r'sbp_[A-Za-z0-9]+',pathlib.Path.home().joinpath('.claude.json').read_text(encoding='utf-8'))[0])"); CLI ~/AppData/Local/Programs/cli-bin/supabase.exe; SUPABASE_ACCESS_TOKEN=$TOKEN supabase.exe functions deploy <name> --project-ref umnlokuehteqwrheoyai.cd "PROJECTS/Bookify AI Studio/app" && npx tsc --noEmit.generate-illustration is currently unauthenticated + unmetered; project/book creation likely direct client insert (free-book "claim" logic must be added server-side).app/src/integrations/supabase/types.ts (live DB has children's cols + new billing tables it doesn't reflect); /app-safety-check before any deploy.STRIPE_API_KEY_MAIN in master .env) — create live products + live webhook endpoint + reset secrets.book_credits vs require a $29 Single before images/downloads unlock; and where the free-book "claim" (set profiles.free_book_claimed=true, meter entitlement='free') is enforced.Build the client Buy/Unlock buttons (call create-checkout, redirect to Stripe) and run the live test-card round-trip to prove the webhook grants access, then build the server-side gates (starting with authenticating + metering generate-illustration).
Generated for the CEO Dashboard · source: PROJECTS/Bookify AI Studio/handoffs/billing-money-spine-2026-07-05.md 🤍