requireK99Admin & multi-tenancy

How K99 isolates tenant data with the requireK99Admin and requireKaturaAdmin guards.

Overview

Katura is multi-tenant by design β€” many stores, one codebase, one database. This article explains how K99 keeps tenant data isolated and how you, as a developer or integrator, should reason about it.

The tenancy model

  • Every meaningful row in the database has a tenantId column.
  • Routes under /admin/* resolve the active tenant from the session and pin it for the request.
  • Routes under /k99/* are explicitly cross-tenant and require the platform-level role.
  • Public storefront routes resolve the tenant from the host header (store.example.com) at the edge.

Server guards

Three named guards do almost all the heavy lifting:

GuardWhereReturns
requireKaturaAdmin()Every /admin/* route handler & server component{ user, tenant, role } or redirects to /login
requireK99Admin()Every /k99/* route handler{ user } or 404 (we 404, not 403, on purpose)
resolveTenant(req)Storefront edge middlewareThe tenant matching the host, or null

Warning

Never query the database directly without going through a tenant-aware client. The Prisma middleware will throw MissingTenantContext if you try.

Custom domains

Tenants can bring their own domain. The flow:

  1. Tenant adds the domain in /admin/settings/domains.
  2. Katura issues an SSL certificate via Vercel.
  3. Edge middleware learns the host β†’ tenant mapping at deploy time + via on-demand lookup.
  4. Storefront routes immediately resolve to that tenant.

Data export & portability

Every tenant can export 100% of their data at any time from /admin/account/data-export. Exports include products, customers, orders, CRM history, CAD files, Yen transcripts, and Outbound campaign history β€” in a documented JSON+CSV bundle.

Was this article helpful?

requireK99Admin & multi-tenancy β€” K99 Intelligence β€” KATURA Docs | K99