Skip to content

Subdomain Provisioning

Each tenant gets a dedicated subdomain per assigned app. Provisioning is handled exclusively by dot-portal-api.

Subdomain Pattern

{tenant-slug}.{app-base-domain}

Examples:
  acme-corp.foot-factory.dotevolve.net
  acme-corp.cos.dotevolve.net

The Demo Tenant (dotevolve) uses the App Base Domain directly and is never provisioned.

Provisioning Flow

flowchart TD
    A[Tenant created / payment confirmed] --> B[provisionTenantApps]
    B --> C{For each app slug}
    C --> D[Vercel API\nRegister subdomain]
    C --> E[Cloudflare API\nCreate CNAME record]
    D --> F{Both succeed?}
    E --> F
    F -->|Yes| G[Add origin to app CORS\nSet domain_status: active]
    F -->|No| H[Set domain_status: pending\nReturn 207 Partial Content]
    G --> I[Create alert: subdomain_provisioned]
    H --> J[Create alert: subdomain_failed]

Retry

A pending subdomain can be retried from the Admin Portal:

POST /api/v1/tenants/:tenantId/apps/:appSlug/retry-domain

Deprovisioning

When a tenant is deleted, all subdomains are deprovisioned:

  • Remove subdomain from Vercel project
  • Delete Cloudflare CNAME record
  • Remove origin from app CORS policy
  • Failures are logged but do not abort the deletion
  • 404 responses from Vercel/Cloudflare are treated as already-removed

App Registry

The App Registry is an environment-level config in dot-portal-api:

{
  'foot-factory': {
    slug: 'foot-factory',
    baseDomain: 'foot-factory.dotevolve.net',
    vercelProjectId: process.env.FOOT_FACTORY_VERCEL_PROJECT_ID,
    corsEndpoint: process.env.FOOT_FACTORY_CORS_ENDPOINT,
    allowSelfSignup: true,
  },
  'dot-cos': {
    slug: 'dot-cos',
    baseDomain: 'cos.dotevolve.net',
    vercelProjectId: process.env.DOT_COS_VERCEL_PROJECT_ID,
    corsEndpoint: process.env.DOT_COS_CORS_ENDPOINT,
    allowSelfSignup: true,
  },
}

CORS Origin Management

dot-portal-api exposes an internal endpoint that returns all active domains for an app:

GET /api/v1/internal/cors-origins/:appSlug
x-service-secret: <secret>

dot-foot-factory-api fetches this list on startup and refreshes it periodically, replacing the old MongoDB GlobalConfig collection.