Questify

2.0.3

Released

Fixes

  • POST /api/billing/checkout refuses an account that already holds a Pro-granting subscription, with a 409 pointing at the Billing Portal. Hiding the buy buttons is not enforcement: a double click, a retry, or a direct call would open a second Checkout session, and Stripe will happily run two independent subscriptions for one customer (#486).

  • Stripe customer creation carries an idempotency key derived from the user id, so two concurrent first checkouts converge on one customer. Without it both saw no mapping, both created a customer, and the losing upsert left one holding a live Checkout session and its invoices that neither the mapping nor the Billing Portal could find again (#486).

  • Locked personas in the model picker render as plain cards rather than disabled buttons. The "Upgrade to Pro" link was interactive content nested inside a disabled <button> — invalid HTML, and unreachable by pointer and assistive technology alike, so the one control that could unlock the card was the one control that could not be used (#486).

  • The dev TUI re-checks for a live-mode context after an account switch. The guard ran before the switch was offered, so choosing a live account from the picker walked straight past it into fetching a live webhook signing secret into .env and forwarding production events at localhost (#486).

  • Relaxed Vercel deploy validation so CI only blocks on the public Supabase build-time variables pulled by vercel pull.

  • Downgraded missing SUPABASE_SERVICE_ROLE_KEY in the pulled Vercel env file to a warning because CI tokens may be unable to decrypt server-only runtime secrets even when the key is configured in Vercel.

  • Documented the difference between required public build-time Supabase values and the server-only service-role runtime secret.