Skip to content

[WIP] Refactor multi-tenancy approach for service-tenant#1184

Closed
Copilot wants to merge 1 commit intomainfrom
copilot/refactor-multi-tenancy-model
Closed

[WIP] Refactor multi-tenancy approach for service-tenant#1184
Copilot wants to merge 1 commit intomainfrom
copilot/refactor-multi-tenancy-model

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 19, 2026

  • Run baseline validation (test/build/typecheck) to capture pre-existing failures
  • Implement spec updates for environment-based cloud schemas and tenant-router contract
  • Add new service-tenant control-plane objects and deprecate tenant_database object
  • Introduce environment-context and environment-provisioning services with backward-compatible aliases
  • Update tenant plugin registrations and add environment schema initializer flow
  • Extend plugin-auth session schema with active_environment_id
  • Add/adjust unit tests for new object definitions, context resolution, provisioning defaults, and credential rotation behavior
  • Add ADR 0002 and update README/ROADMAP/CHANGELOG/docs terminology
  • Run targeted tests, then full required validation commands, and finalize
Original prompt

Background

The current @objectstack/service-tenant (v4.0.4) implements multi-tenancy with a misleading "one-database-per-tenant" model where sys_tenant_database has organization_id as FK. This conflates "tenant" and "organization" terminology, lacks an environment dimension, and stores auth tokens inline in the main table.

After architectural review (see discussion summary below), we are adopting the Power Platform-style model:

  • One Organization ≠ one database.
  • One Environment = one database. (physical isolation)
  • Environment lives inside Organization. An Organization can have multiple Environments (Dev / Test / Prod / Sandbox ...).
  • Control Plane stores identity, organization, environment registry, DB connection metadata, credentials, subscriptions, audit.
  • Data Plane = per-environment dedicated database (Turso/libSQL by default, pluggable driver).

This gives physical isolation between environments (no cross-env leakage possible), simple Dev→Prod solution deployment (export/import across DBs), independent schema evolution per environment, and aligns with Turso's cost model (DB count is cheap, isolation is free).

Decisions (all confirmed by product owner)

# Decision
1 Database granularity = per-environment, not per-organization
2 sys_environment in Control Plane; sys_environment_database 1:1 with environment
3 Business tables do NOT need environment_id column (physical isolation makes it redundant)
4 sys_package_installation moves from Control Plane to Data Plane (lives inside each environment DB); tenant_id/environment_id columns removed — environment is implicit from the DB connection
5 better-auth session extended with active_environment_id only (organization reverse-looked-up from environment)
6 Old sys_tenant_database is deprecated: v4.x keeps a deprecation shim, v5.0 removes it
7 When provisioning a new organization, automatically create a default environment + its DB
8 Abstract driver field on sys_environment_database to support turso / postgres / sqlite

Scope of this PR

A. New ADR

  • docs/adr/0002-environment-database-isolation.md — record the full decision with rationale, trade-offs vs. per-organization model, Turso cost analysis, and migration path.

B. New objects in packages/services/service-tenant/src/objects/

  1. sys-environment.object.ts — environment registry in Control Plane

    • Fields: id, organization_id (FK), slug, name, description, env_type (default/sandbox/development/production/trial), region, is_default, is_protected, status (provisioning/active/suspended/archived), dlp_policy_id, created_by, metadata, created_at, updated_at
    • Indexes: UNIQUE (organization_id, slug), (organization_id, is_default)
  2. sys-environment-database.object.ts — 1:1 with environment, replaces sys-tenant-database.object.ts

    • Fields: id, environment_id (FK, UNIQUE), database_name (UUID-based, immutable), database_url, driver (turso/postgres/sqlite), region, storage_limit_mb, last_accessed_at, provisioned_at, metadata, created_at, updated_at
    • Indexes: UNIQUE environment_id, UNIQUE database_name
    • No auth_token column — decoupled into sys_database_credential
  3. sys-database-credential.object.ts — decoupled credentials with rotation support

    • Fields: id, database_id (FK → sys_environment_database), token_cipher, kms_key_id, scope (readwrite/readonly/admin), status (active/rotating/revoked), issued_at, expires_at, rotated_from
    • Indexes: (database_id, status), expires_at
  4. sys-environment-member.object.ts — environment-level RBAC

    • Fields: id, environment_id, organization_id (denormalised for auth checks), user_id, role (env_admin/env_maker/env_user/env_viewer), created_at
    • Indexes: UNIQUE (environment_id, user_id), user_id

C. Deprecate old objects

  • sys-tenant-database.object.ts — add deprecation JSDoc, keep file for v4.x compatibility, mark for removal in v5.0.
  • sys-package-installation.object.ts — move out of Control Plane registration. Keep an empty Data Plane variant (no tenant_id, no environment_id — environment is implicit from DB connection). This new object should live alongside other Data Plane system objects and be registered by the environment schema initializer instead of the tenant plugin.

D. Spec updates in packages/spec/src/cloud/tenant.zod.ts

  • Add EnvironmentSchema, EnvironmentDatabaseSchema, DatabaseCredentialSchema, EnvironmentMemberSchema Zod schemas.
  • Update TenantContextSchema to include environmentId and organizationId.
  • Keep TenantDatabaseSchema as a deprecated alias of EnvironmentDatabaseSchema for v4.x.
  • Add ProvisionEnvironmentRequestSchema / ProvisionEnvironmentResponseSchema.

E. Contract updates in `packages/spec/src/contracts...

This pull request was created from Copilot chat.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectstack-demo Ready Ready Preview, Comment Apr 19, 2026 7:20am
spec Ready Ready Preview, Comment Apr 19, 2026 7:20am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants