Multi-tenancy
Roles
Customer, tenant admin, superadmin — what each can do.
NShop has three first-class roles, all expressed as Firebase Auth custom claims.
Customer (no claim)
A signed-in shopper with no admin claims. Can:
- Read and write their own
/users/{uid}doc and subcollections (addresses, wishlist). - Read their own orders.
- Write reviews (one per product).
- Use both AI assistants.
Cannot read other customers' data. Cannot read or write admin collections.
Tenant admin (admin: true, tenantId: "<slug>")
Full access inside one tenant. Can:
- CRUD products, variants, categories.
- Read and update their tenant's share of any order (only the
tenantStatus,fulfillment, andupdatedAtfields — the rule usesdiff().affectedKeys().hasOnly(...)to enforce this). - CRUD coupons.
- Invite teammates.
- Read their tenant's customers (aggregated from orders).
- Use the admin AI tools.
Cannot read or write any other tenant's data — the auth claim and the Firestore rules both refuse it.
Superadmin (superadmin: true)
Global, read-only. Used for support, observability, and platform operations. Can:
- List all tenants and read their settings.
- Read any product or order, across tenants.
- Create new tenants.
Cannot mutate orders or catalog data for tenants — that's the tenant admin's job.
Where claims are set
Custom claims are only set via the Admin SDK in server-side code:
scripts/seed.ts(--admin,--superadminflags) for initial setup.src/server/team.tsfor the invite flow.src/app/api/auth/session/route.tsfor applying pending invites on first sign-in.
No client-callable code can grant admin status. There is no "become admin" endpoint.