MiqromanageSupport

Multi-tenancy

One app serves the operator and every customer. There is no per-tenant deployment and no per-tenant codebase — tenancy is a data + identity concern, not a routing one.

Identity decides scope, not the URL

A signed-in user carries a Supabase JWT whose tenant_id (mirrored on profile.tenant_id) determines what they can see:

  • Operator (tenant_id = the operator org) → the whole fleet: every business, every agent, every run.
  • Customer → only their own business: their site analytics, their agents, their tickets, their connectors.

The same code paths and the same SPA serve both. The dashboard subdomain (design.miqromanage.app, <tenant>.miqromanage.app) is a vanity entry point; it does not by itself grant access — the JWT does.

Two columns, two meanings

Each tenant has two distinct host fields, and conflating them is the classic bug:

Field Meaning Example
subdomain the private dashboard host acme.miqromanage.app
custom_domain the public website host acme.com

Published customer sites are served path-based at miqrodesign.com/site/{slug} or on the customer's own custom_domainnever on a *.miqromanage.app dashboard subdomain.

Data isolation

Tenant data lives in shared Postgres tables (Supabase) and is isolated by row-level security. Queries are constrained to the caller's tenant_id, so a customer cannot read another customer's rows even though the rows share a table. Server-to-server and agent code uses a privileged path and must pass the tenant_id explicitly — there is no ambient "current tenant."

Provisioning a tenant

A new tenant is created with a slug. Before the slug becomes <slug>.miqromanage.app, it is checked against the reserved-subdomain set so it can't collide with an infrastructure or product host. The provisioner agent folds the same set into its slug-uniqueness check so auto-naming never round-trips a 409.

The known scaling shortcut

Today the apex (miqromanage.app) redirects management-view paths to design.miqromanage.app because miqrodesign is currently the only business — a single-tenant shortcut (a 302, deliberately not cached). The correct end-state, for when a second business onboards, is: the apex serves the SPA and the SPA redirects post-auth to the signed-in user's own <tenant>.miqromanage.app. This is a routing detail, not a data-model change.