Founder price — $149 for the first 50 buyers · Full source code

A Next.js 16 + Supabase starter for multi-tenant B2B SaaS — with the hardening tests included.

Organizations, PostgreSQL RLS, RBAC, invitations, Stripe billing, API keys, usage limits and audit logs — already wired. Ships with nine executable hardening suites that exercise defined failure modes against a real PostgreSQL database.

Already shipped? Check your architecture →

Next.js 16 · React 19 · Supabase · Stripe · TypeScript

npm run test:hardening

$ npm run test:hardening

 

cross-tenant-isolation.......... attacks cross-tenant isolation

security-definer-boundaries..... attacks security definer boundaries

rbac-privilege-escalation....... attacks rbac privilege escalation

anon-auth-boundary.............. attacks anonymous / auth boundary

invitation-lifecycle............ attacks invitation lifecycle

stripe-webhook-reliability...... attacks stripe webhook reliability

data-integrity.................. attacks data integrity / owner protections

api-key-validation.............. attacks api key validation

billing-enforcement............. attacks billing enforcement

 

# these attacks caught 3 of them. a manual review caught the 4th.

# all four fixed. the regression tests ship with the product.

01 · Who it's for

Built for people starting a B2B SaaS.

Not a framework, not a course — a working multi-tenant foundation for teams that would rather build their product than their tenancy layer.

You're starting a multi-tenant B2B SaaS

You have the product idea and early users asking for team features. You don't want to spend the next month hand-rolling organizations, invitations and RLS — you want them wired end-to-end, with the boundaries verified by executable tests.

You're a studio shipping client SaaS

One license covers unlimited projects for you and your clients. Start every engagement from a tenant-isolated, Stripe-ready foundation instead of an empty repo — and hand over code the client can audit.

You take tenant boundaries seriously

You've read the RLS docs, so you know “RLS enabled” and “RLS verified” are different claims. The nine hardening suites exist so you can check the second one yourself — in a dedicated test environment, against the included implementation.

02 · What's included

The foundation B2B SaaS needs on day one.

Every piece of multi-tenant infrastructure a B2B product needs before its first paying customer — already connected, already migrated, already tested.

  • Multi-tenant organizations from migration zero
  • Deny-by-default PostgreSQL RLS policies
  • RBAC — Owner / Admin / Member
  • Auth: email, OAuth (Google & GitHub), resets
  • Stripe checkout, portal, idempotent webhooks
  • API keys, audit logs, enforced usage limits
  • The adversarial hardening suite itself
  • Full source code + documentation

03 · The hardening suite

Nine suites. Every row is a shipped test file.

Not a test count — the actual failure modes. Every row below is an executable test file that ships in supabase/tests/hardening and runs against a real PostgreSQL database in a dedicated test environment — actual migrations and RLS policies, not mocks.

Cross-tenant isolation

cross-tenant-isolation.test.ts

attacks: Cross-organization reads and writes, tampered IDs, cross-project access.

SECURITY DEFINER boundaries

security-definer-boundaries.test.ts

attacks: Privileged functions being tricked into acting across tenants.

RBAC privilege escalation

rbac-privilege-escalation.test.ts

attacks: Members promoting themselves; role changes constrained at the database level.

Anonymous / auth boundary

anon-auth-boundary.test.ts

attacks: Unauthenticated requests reaching anything tenant-owned.

Invitation lifecycle

invitation-lifecycle.test.ts

attacks: Token reuse, expiry, race conditions, duplicate memberships.

Stripe webhook reliability

stripe-webhook-reliability.test.ts

attacks: Duplicate deliveries, retries, out-of-order events, poison messages.

Data integrity / owner protections

data-integrity.test.ts

attacks: Deleting the last owner, orphaning organization data.

API key validation

api-key-validation.test.ts

attacks: Expired and revoked keys still authenticating.

Billing enforcement

billing-enforcement.test.ts

attacks: Client-side subscription writes, forged entitlement, plan-limit bypass.

Executable, not aspirational. Nine executable hardening suites exercise defined failure modes in the included implementation against real PostgreSQL. You can inspect the tests, run them in a dedicated, disposable test environment, and adapt them as your application evolves.

npm run test:hardening

The same suite that found these bugs ships with the product. Run it in a dedicated, disposable test environment as your schema and policies evolve.

04 · Four real findings

Found by attacking our own app.

Not theoretical vulnerabilities from a checklist — four bugs that existed in this very codebase, in exactly the places multi-tenant SaaS breaks. Three were caught by the hardening suite; one by a manual security review and then covered by a regression test.

BUG 01Fixed · regression-tested

Cross-tenant SECURITY DEFINER

RLS was enabled. But a privileged SECURITY DEFINER function used to record usage ran with elevated rights and trusted a client-supplied tenant identifier — without independently verifying that the caller owned that tenant. A bug in the one code path that bypasses RLS.

BUG 02Fixed · regression-tested

Stripe event ordering

Stripe re-delivers events, and delivery order is not guaranteed. An out-of-order event could overwrite newer subscription state with older state — downgrading a customer who had already upgraded.

BUG 03Fixed · regression-tested

Webhook retry poisoning

A webhook processing attempt that failed partway left the event recorded as already seen. When Stripe retried — exactly as designed — the retry failed because the event record already existed. The recovery path itself was broken.

BUG 04Fixed · regression-tested

Subscription forgery

The subscriptions table was client-writable: an organization owner could insert a paid-plan row through the REST API and grant themselves Pro without paying. Entitlement now flows only through the service role — webhook writes, read-only clients.

All four findings were fixed. The three automated findings are covered by the hardening suite; the fourth has regression coverage added after manual discovery.

05 · Evidence

Read the actual code before you pay.

Three excerpts from the package: a fix migration with its authorization helper, the webhook ordering guard, and one of the nine hardening tests. No mockups — this is the shipped source. Nothing on this page is independently audited; it's our code, our bugs and our tests, shown so you can judge the engineering first.

supabase/migrations/000027 + 000007 — excerpt

The Bug 01 fix: the org id is an argument, but membership is verified server-side — the helper compares the caller's auth.uid() from the JWT against organization_members. Supplying another tenant's org id fails the check.

supabase/migrations/000027 + 000007 — excerptsql
-- supabase/migrations/000027_fix_usage_rpc_security.sql (the fix)
-- FIX 1: Tenant Authorization
-- Verify the caller is a member of the organization they are reporting usage for.
IF NOT public.is_organization_member(p_org_id) THEN
  RAISE EXCEPTION 'FORBIDDEN: You are not a member of this organization.';
END IF;

-- supabase/migrations/000007_authorization_functions.sql (the helper)
create or replace function public.is_organization_member(target_organization_id uuid)
returns boolean
language sql
stable
security definer
set search_path = ''
as $$   select exists (
    select 1
    from public.organization_members m
    where m.organization_id = is_organization_member.target_organization_id
      and m.user_id = auth.uid()
  );
 $$;

lib/billing/sync.ts

The Bug 02 fix: a late Stripe event is compared against stored state before it can overwrite anything.

lib/billing/sync.tstypescript
// 3. Out-of-order protection: ignore stale events.
if (existing?.last_stripe_event_at) {
  if (new Date(existing.last_stripe_event_at) > new Date(eventCreatedAt)) {
    console.log(
      `[stripe-sync] Ignoring stale event for sub ${subscription.id}.`
    );
    return;
  }
}

supabase/tests/hardening/security-definer-boundaries.test.ts

One of the nine hardening suites: the cross-tenant attack that catches the bug class above, shipped so you can re-run it.

supabase/tests/hardening/security-definer-boundaries.test.tstypescript
// 2. CROSS-TENANT ATTACK (Tenant A -> ORG_B)
await client.query("SET LOCAL ROLE authenticated");
await client.query(
  `SELECT set_config('request.jwt.claims',
    '{"sub":"${TENANT_A_USER}","role":"authenticated"}', true)`
);

await expectRpcError(`
  SELECT public.check_and_record_usage(
    p_org_id := '${ORG_B}',
    p_metric := 'maxApiRequests',
    p_limit := 1000000,
    p_amount := 1
  )
`, "sp_cross_tenant");

32

SQL migrations

9

hardening suites

27

app pages

4

API routes

The complete file inventory ships in the ZIP — this page shows excerpts, not the whole product. Full write-ups →

06 · Demo

Click through the dashboard before you decide.

The demo runs the actual dashboard shell with clearly-labeled sample data — organization switching, team, billing, usage, API keys, activity and settings. It's static on purpose: no backend, no secrets, nothing leaves your browser. What it can't show — real auth, live Stripe webhooks, RLS under attack — the docs and the hardening suites cover.

  • Dashboard shell — the same layout the source ships
  • Sample org, team, billing, usage and API-key data
  • Labeled demo data — nothing pretends to be real
  • Mobile-friendly: try it on your phone

07 · Pricing

One-time purchase. Perpetual commercial licence.

No seats on the boilerplate, no revenue share, no runtime license checks.

B2B SaaS OS

One-time payment

$149$249once

Founder price — $149 for the first 50 buyers

Full source code, yours forever. One license, unlimited projects for you and your clients.

Instant download via Gumroad · one-time payment · no refunds once the download is accessed · installation support included

  • Full source code
  • Multi-tenancy
  • PostgreSQL RLS
  • Authentication
  • Organizations
  • RBAC
  • Team invitations
  • Stripe billing
  • API keys
  • Audit logs
  • Usage limits
  • Documentation
  • Updates

08 · Installation

From ZIP to running app.

Node.js 20+, a Supabase project (free tier works) and a Stripe account. No Docker required.

1

Install

unzip b2b-saas-os.zip && cd b2b-saas-os
npm install
2

Configure

cp .env.example .env.local
# fill in Supabase + Stripe values
3

Push the schema

npx supabase login
npx supabase link --project-ref <ref>
npx supabase db push
4

Run — then attack it

npm run dev
# then, against a dedicated test database:
npm run test:hardening

Full environment-variable reference, Stripe setup and troubleshooting live in the documentation.

09 · FAQ

Questions, answered.

Anything else, the documentation covers setup through deployment.

What exactly do I get?

A ZIP with the complete source: the Next.js 16 application (27 pages plus 4 API routes), 32 SQL migrations with the RLS policies inline, the nine executable hardening suites, unit and billing tests, and documentation. $149 founder price (regularly $249), one-time.

Is this a subscription?

No. One payment of $149 during the founder launch (regularly $249), buys a perpetual commercial licence — updates included while the product is actively maintained.

How does this compare to free starters or the bigger commercial kits?

The free official Next.js SaaS starter is a fine way to learn — it ships Stripe checkout and portal, team CRUD and basic Owner/Member RBAC. The commercial kits are broader: Supastack advertises a $149 Single Stack launch price across web, mobile and desktop targets (PostgreSQL via Drizzle); MakerKit's Supabase edition is $299 lifetime (promotional; regularly $349) with i18n and admin tooling; supastarter's Next.js + Supabase boilerplate is $349 Solo with i18n and Playwright E2E configured (prices checked November 2026 — sources linked on the pricing page). B2B SaaS OS is smaller on purpose: Supabase-native RLS tenancy from migration zero, documented Stripe webhook reliability handling, and nine adversarial suites you can run against a dedicated test database — at $149 one-time. If you need i18n and admin tooling today, buy the bigger kit. If you need tenant boundaries you can verify, this is built for that.

Can I use it for client projects?

Yes. You can build and deploy unlimited projects for your own company or your clients. What you can't do is resell the boilerplate itself or redistribute the source.

What about refunds and support?

Because the product is source code, the purchase is final once the download has been accessed — no refunds. That's stated up front on the pricing and license pages, not buried. For support: if you can't get the product running, email support is included to get you unblocked (installation help). Custom development and consulting on your app are not included.

Does this mean my SaaS is secure if I buy it?

No — and be suspicious of any foundation that claims that. What this gives you is a multi-tenant foundation that was attacked against specific failure modes, four real bugs that those attacks and a security review surfaced (now fixed), and the executable tests that ship so you can re-run the attacks yourself.

How customizable is it?

Everything is plain TypeScript, Tailwind tokens and shadcn/ui components. Rebrand in config/site.ts, extend the schema with normal SQL migrations, and wire your own product features on top.

What is the hardening suite, exactly?

Nine executable test files that run against a real PostgreSQL database — a dedicated, disposable test environment (a separate Supabase project), with the actual migrations and RLS policies, not mocks. Never point them at a production database. They attack tenant isolation, SECURITY DEFINER functions, RBAC, invitations, webhook reliability, API keys, data integrity and billing enforcement, and run with npm run test:hardening.

Separate service · 3 slots

Already shipped a Next.js + Supabase SaaS?

Free adversarial architecture review — 3 slots.

You get findings and practical fixes across the five areas where multi-tenant SaaS actually breaks. The trade: permission to publish sanitized findings — no secrets, no customer data, no proprietary code. A limited 3-slot founder experiment, not a guaranteed service.

This is a manual architecture review, not a penetration test.

Request a free review

Application required — live app, stack, and publishing permission.

What we look at

  • RLS / tenant isolation
  • SECURITY DEFINER functions
  • RBAC and privilege boundaries
  • Stripe webhook handling
  • API keys

The trade

Free in exchange for permission to publish sanitized findings. Your data stays yours.

The foundation — and the red team that tried to break it.

The multi-tenant SaaS foundation that ships with the red team that tried to break it. One payment, full source, tests included.