Skip to content

Tenant Management

Tenants are organisations that subscribe to one or more DotEvolve products. The Central Registry (tenants table in Supabase PostgreSQL) is the single source of truth.

Tenant Lifecycle

stateDiagram-v2
    [*] --> pending_payment : Self-Signup
    [*] --> active : Admin Create
    pending_payment --> active : Razorpay subscription.activated
    active --> suspended : Admin suspends
    suspended --> active : Admin reactivates
    pending_payment --> suspended : Payment failed / halted

Tenant Fields

Field Type Description
id uuid Primary key
name text Display name
slug text URL-safe unique identifier used in subdomains
status text active, suspended, pending_payment
plan text References plans.slug
signup_source text ADMIN, SELF_SIGNUP_PORTAL, SELF_SIGNUP_FOOT_FACTORY, SELF_SIGNUP_COS
settings jsonb Per-tenant overrides: { maxUsers, maxWorkers } — takes precedence over plan defaults
contact jsonb Contact info: { email, phone, address }
razorpay_subscription_id text Set at self-signup
razorpay_customer_id text Set at self-signup

settings and contact were added via scripts/01-add-tenant-fields.sql. Run this migration if upgrading from an earlier schema.

Tenant Settings vs Plan Limits

Tenants have two layers of limits:

  1. Plan defaults — defined in the plans table (max_users, max_workers, etc.)
  2. Tenant overrides — stored in tenants.settings JSONB ({ maxUsers, maxWorkers })

When dot-foot-factory-api fetches plan limits from dot-portal-api, the internal endpoint merges both layers — tenant settings take precedence over plan defaults.

App Assignments

Each tenant can be assigned one or more apps. An assignment record in tenant_app_assignments controls:

  • enabled — whether the app is visible to end users
  • domain — the provisioned subdomain (e.g. acme-corp.foot-factory.dotevolve.net)
  • domain_statuspending, active, failed

User Roles

user_tenant_roles links a user to a tenant and app with a role:

(user_id, tenant_id, app_slug) → role

Roles are tenant-admin or user. super-admin is set directly on app_metadata and is never stored in this table.

Scoped Delegation

A Tenant_Admin can only grant app access to users for apps the Tenant_Admin themselves has access to. Attempting to grant access to an app outside their own access returns 403 Forbidden.

Tenant Isolation

Every downstream service enforces tenant isolation:

  • dot-foot-factory-api — MongoDB queries include { tenantId: req.user.activeTenantId }
  • dot-cos-workflow-service — Prisma queries include where: { tenantId }
  • dot-portal-api — path param :tenantId is validated against activeTenantId in the JWT

Demo Tenant

The pre-seeded dotevolve tenant (slug: dotevolve) is the platform's own demo tenant. It uses App Base Domains directly (foot-factory.dotevolve.net, cos.dotevolve.net) rather than subdomain patterns, and never triggers subdomain provisioning.

Email Notifications

When a tenant is created by a Super Admin and a contact.email is provided, a welcome email is sent via Resend (noreply@dotevolve.net).