Phase 1: billing usage visibility, Stripe portal, tenant-auth binding - #8
Merged
Merged
Conversation
vorflux Bot
pushed a commit
that referenced
this pull request
Jul 22, 2026
…uare OAuth, images (#9) * Phase 3: multi-location bi-directional menu sync, canonical store, Square OAuth, images * Phase 4: Maps Local Pack rank, competitor structured data, GBP provisioning, Yelp posting (#7) Co-authored-by: crewcricle <280911048+crewcricle@users.noreply.github.com> * Phase 1: billing usage visibility, Stripe portal, tenant-auth binding (#8) Co-authored-by: crewcricle <280911048+crewcricle@users.noreply.github.com> --------- Co-authored-by: crewcricle <280911048+crewcricle@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Billing usage visibility, Stripe Billing Portal, tenant-auth binding, and durable trial email sends.
Changes
require_client_iddependency derivesclient_idfrom JWT identity viauser_client_map, never from request input. Strictverify_supabase_jwt_strictrejects with 401 whenSUPABASE_JWT_SECRETis unset (no anonymous fallback). Migration013_user_client_map.sqlwith RLSservice_role_all.GET /billing/usage: returns per-job-type{used, cap, remaining}fromTRIAL_CAPS(single source intrial_gate.py). Active subscriptions report unlimited (cap/remaining= null). Handles missing keys (0), missing client (404), cross-tenant rejection.POST /billing/portal: creates Stripe Billing Portal session, parametrized withconfiguration(notconfiguration_id), return URL → dashboard settings. Missing customer → 422, Stripe error → 502.jobs/trial_emails.pyResend sends now enqueue via arqsend_email_task. Idempotency recorded before enqueue, rolled back on enqueue failure (no phantom records blocking future sends).STRIPE_PORTAL_CONFIG_IDandDASHBOARD_URLdocumented inDEPLOY.mdandbackend/.env.example.Testing
cd backend && uv run pytest tests/ -quv run pytest tests/unit/test_{tenant_auth,billing_usage,billing_portal,trial_emails_enqueue}.py -q001→013on freshpostgres:15user_client_mapPK, FK, RLS verifiedCross-tenant denial, empty-secret rejection, active-sub unlimited, idempotency rollback all verified in unit tests. Live Stripe portal and real JWT deferred to post-deploy per agreed workflow.
Artifacts
Attached Images
[phase1_test_results.log]
Session Details
(aside)to your comment to have me ignore it.