VOYAGE
Voyage / TECHNICAL / Tenant Provisioning

Tenant Provisioning

Tenant provisioning is split between the control-plane APIs in this repository and tenant-specific deploy automation in peer forks such as the Meridian reference implementation (workers/control-plane/src/routes/tenant...

Tenant Provisioning

Current Shape

Tenant provisioning is split between the control-plane APIs in this repository and tenant-specific deploy automation in peer forks such as the Meridian reference implementation (workers/control-plane/src/routes/tenants.ts:47-84, ../voyage-bank/scripts/deploy/deploy-all.ts:76-146).

The control plane creates tenants with slug, name, optional root company ID, plan, region hint, provisioning status, schema version 0, and timestamps (workers/control-plane/src/routes/tenants.ts:12-18, workers/control-plane/src/routes/tenants.ts:47-84).

Tenant updates can change name, root company ID, status, plan, and region hint after validating that at least one field is present (workers/control-plane/src/routes/tenants.ts:20-28, workers/control-plane/src/routes/tenants.ts:131-196).

Tenant Identity and Domains

Tenant lookup by domain joins tenant_domains to tenants and requires the domain record to be verified (workers/control-plane/src/routes/tenants.ts:87-113).

The edge tenant resolver supports custom domain lookup, path slug lookup, API key lookup, and auth-token tenant lookup with caching (workers/edge-gateway/src/middleware/tenant-resolver.ts:6-177).

The edge tenant resolver blocks suspended or provisioning tenants from normal request routing (workers/edge-gateway/src/middleware/tenant-resolver.ts:179-205).

Database Registration

Tenant database records support config, ops, and ops_archive database types, store a D1 database ID, and optionally carry an archive year (workers/control-plane/src/routes/tenants.ts:8-10, workers/control-plane/src/routes/tenants.ts:30-34).

The control plane lists database records for a tenant only after confirming the tenant exists (workers/control-plane/src/routes/tenants.ts:198-219).

The control plane inserts active tenant database records with database type, D1 database ID, optional year, and created timestamp (workers/control-plane/src/routes/tenants.ts:221-260).

The shared binding helper attaches tenant config, tenant ops, and optional customer D1 handles to request environments after tenant context is known (workers/_shared/tenant-bindings.ts:38-67).

Feature Catalog Registration

Feature registration accepts feature key, deployed version, integration provider, customization JSON, and last migration timestamp metadata (workers/control-plane/src/routes/catalog.ts:7-15).

Feature catalog registration requires the tenant to exist, validates an array of feature records, upserts each feature row, and returns the tenant's feature catalog (workers/control-plane/src/routes/catalog.ts:51-114).

Feature catalog update validates that the feature exists and then updates only the supplied metadata fields (workers/control-plane/src/routes/catalog.ts:116-186).

OIDC Auth Provisioning

The auth worker exposes OIDC discovery, JWKS, authorize, token, userinfo, verify, account session, and logout routes (workers/auth/src/index.ts:35-115).

OIDC discovery advertises authorization, token, JWKS, userinfo, response types, scopes, claims, ES256 signing, authorization code and refresh token grants, and PKCE methods (workers/auth/src/routes/discovery.ts:5-30).

The token route supports authorization-code and refresh-token grant paths, validates client and redirect data, verifies PKCE, signs access and ID tokens, stores hashed tokens, and rotates refresh tokens (workers/auth/src/routes/token.ts:25-188).

The auth client builds PKCE S256 authorize URLs, refreshes sessions, validates callback state, exchanges authorization codes, fetches userinfo, and persists sessions (packages/auth-client/src/index.ts:105-209).

Peer Deploy Automation

The Meridian reference deploy-all script supports dry-run and execute modes, reads the deploy manifest, resolves active environment values, provisions D1, KV, R2, queues, syncs Wrangler bindings, ensures Pages projects, deploys Workers, builds Pages apps, deploys Pages apps, and writes deployment state (../voyage-bank/scripts/deploy/deploy-all.ts:16-163).

The deploy shared helper defines Worker and Pages deploy manifest entry types plus account, environment, and deployment-state structures (../voyage-bank/scripts/deploy/shared.ts:7-50).

The deploy shared helper defaults to dry-run mode and only executes commands when --execute is passed (../voyage-bank/scripts/deploy/shared.ts:69-111, ../voyage-bank/scripts/deploy/shared.ts:137-166).

The D1 provisioning script reads the D1 manifest, validates declared database count, writes placeholder IDs in dry-run mode, creates D1 databases in execute mode, parses returned database IDs, and writes ID files progressively (../voyage-bank/scripts/provision-d1.ts:65-164).

The Wrangler binding sync script replaces D1 database IDs and KV namespace IDs in each configured Worker wrangler.toml based on generated ID files (../voyage-bank/scripts/deploy/sync-wrangler-bindings.ts:19-85).

Service-Role Matrix and Role-Lane Generator

The Meridian reference service-role matrix maps staff roles to services, daily targets, queue handling, and event types (../voyage-bank/config/tenant/service-role-matrix.json:1-91).

The service-role matrix implementation plan requires service eligibility to come from the matrix, skips unqualified staff instead of falling back to the whole roster, and aligns to the ten-service catalog (../voyage-bank/docs/architecture/voyage-bank-factories/f34-service-role-matrix.md:122-138).

The role-lane generator plan defines per-staff daily lanes composed of appointments, queue assignments, events, and fill blocks (../voyage-bank/docs/architecture/voyage-bank-factories/f35-role-lane-generator.md:11-26).

The role-lane generator plan snaps appointment starts to :00 and :30 and allows off-grid walk-ins (../voyage-bank/docs/architecture/voyage-bank-factories/f35-role-lane-generator.md:28-60).

The Meridian backfill script loads the service-role matrix, maps services to eligible roles, filters staff candidates by matrix eligibility, warns and returns null when no qualified staff exists, uses daily targets, snaps appointment times, and marks generated rows with event_follow_up or f35_role_lane source metadata (../voyage-bank/scripts/backfill-day.ts:368-429, ../voyage-bank/scripts/backfill-day.ts:1127-1149, ../voyage-bank/scripts/backfill-day.ts:3516-3563, ../voyage-bank/scripts/backfill-day.ts:3638-3643).

Corrections From Frozen HTML

The frozen page's tenant-provisioning workflow should now include OIDC auth migration, gateway tenant resolution, D1 database registration, feature-catalog metadata, and peer-fork deploy automation because all of those are current code or reference automation paths (workers/auth/src/index.ts:35-115, workers/edge-gateway/src/middleware/tenant-resolver.ts:6-205, workers/control-plane/src/routes/tenants.ts:221-260, workers/control-plane/src/routes/catalog.ts:51-114, ../voyage-bank/scripts/deploy/deploy-all.ts:16-163).

The frozen page should not describe tenant provisioning as creating a runtime app builder because the architecture explicitly excludes operator-editable app builders and broad runtime behavior stores (docs/architecture/anti-goals.md:9-12, docs/architecture/anti-goals.md:29-31).


last verified: 2026-04-24 voyage HEAD: 14f3b190db8817399dcd30e1dc4e1ae7674bbf8a voyage-bank HEAD: ef4d7d4f9a66a05d68c265debc681d506a0606c6