# OpenSpec Change: enterprise-api-plugin-tenant - **Change ID**: enterprise-api-plugin-tenant - **Package**: `@suaveplan/api-plugin-tenant` - **Category**: api/auth - **Target path**: `api/auth/api-plugin-tenant` - **Status**: PROPOSED - **Date**: 2026-04-24 --- ## Summary Deliver `@suaveplan/api-plugin-tenant` on the genesis branch from scratch at enterprise quality. The plugin provides multi-tenant management: tenant provisioning (create/update/suspend/delete), member invitation and role management, per-tenant feature flag overrides via `@suaveplan/feature-flags`, per-tenant settings/branding, and a tenant-scoped audit trail. Routes mounted under `/tenants`. Events: `tenant:created`, `tenant:suspended`, `tenant:deleted`, `tenant:member:invited`, `tenant:member:removed`. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/api` (`workspace:^`) | `definePlugin` | | `@suaveplan/api-shared` (`workspace:^`) | Helpers | | `@suaveplan/api-plugin-auth` (`workspace:^`) | `requireAuth`, `requireRole` | | `@suaveplan/api-plugin-database` (`workspace:^`) | SurrealDB | | `@suaveplan/feature-flags` (`workspace:^`) | Per-tenant flag overrides | | `@suaveplan/audit-logging` (`workspace:^`) | Tenant audit trail | | `@suaveplan/events` (`workspace:^`) | Event bus | | `@suaveplan/error` (`workspace:^`) | `TenantError` hierarchy | | `@suaveplan/rate-limiter` (`workspace:^`) | Rate limits | | `hono` + `@hono/zod-openapi` + `zod` | Routes/schemas | | `@opentelemetry/api` | OTel | --- ## Public API surface ```ts function createTenantPlugin(config?: TenantPluginConfig): PluginDescriptor class TenantService { createTenant(data: CreateTenantInput): Promise getTenant(id: string): Promise updateTenant(id: string, data: UpdateTenantInput): Promise suspendTenant(id: string, reason: string): Promise deleteTenant(id: string): Promise inviteMember(tenantId: string, email: string, role: string): Promise acceptInvite(token: string): Promise removeMember(tenantId: string, userId: string): Promise listMembers(tenantId: string): Promise getSettings(tenantId: string): Promise updateSettings(tenantId: string, settings: Partial): Promise } ``` ### Error codes ```ts type TenantErrorCode = | "TENANT_NOT_FOUND" | "TENANT_SUSPENDED" | "TENANT_INVITE_EXPIRED" | "TENANT_INVITE_INVALID" | "TENANT_MEMBER_NOT_FOUND" | "TENANT_MEMBER_ALREADY_EXISTS" ``` --- ## File layout ```text api/auth/api-plugin-tenant/ package.json tsconfig.json vitest.config.ts surql/ (tenant, tenant_member, tenant_invite, tenant_settings tables) src/ index.ts events.ts types/ errors/ services/tenant/ routes/tenants/ tests/integration.test.ts ``` --- ## Impact Prerequisites: `@suaveplan/api`, `@suaveplan/api-plugin-auth`, `@suaveplan/api-plugin-database`, `@suaveplan/feature-flags`, `@suaveplan/audit-logging`.