3.1 KiB
3.1 KiB
Tasks: enterprise-api-plugin-tenant
Change ID: enterprise-api-plugin-tenant
Package: @suaveplan/api-plugin-tenant
Target path: api/auth/api-plugin-tenant
Prerequisite packages on Verdaccio: @suaveplan/api, @suaveplan/api-shared, @suaveplan/api-plugin-auth, @suaveplan/api-plugin-database, @suaveplan/feature-flags, @suaveplan/audit-logging, @suaveplan/events, @suaveplan/rate-limiter, @suaveplan/error
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create directory with all subdirs;
package.jsonv0.0.0,"sideEffects": ["src/events.ts"];tsconfig.json+vitest.config.ts; standard scripts.
2. Types, errors, events
- Types:
Tenant,TenantMember,TenantInvite,TenantSettings,TenantPluginConfig(Zod). - Errors: 6-code
TenantErrorCodeunion + metadata + registration. Test + doc. - Events:
TenantEventMapmodule augmentation (tenant:created, tenant:suspended, tenant:deleted, tenant:member:invited, tenant:member:removed).
3. SurrealQL
surql/tenant.surql,tenant_member.surql,tenant_invite.surql,tenant_settings.surql.
4. TenantService
- All 11 methods from proposal.
suspendTenant/deleteTenant: emit events + write audit entries.inviteMember: generate signed token (expires 72 h); send email via plugin context service injection.- Per-tenant feature flag overrides:
getSettingsreturnsfeatureFlagsmap;FlagManagerreads these on tenant context. - OTel span per method.
.test.ts(all methods, error cases) +.md.
5. Routes
POST /tenants,GET /tenants/:id,PATCH /tenants/:id,DELETE /tenants/:id,POST /tenants/:id/suspend./tenants/:id/members— list, invite, accept-invite, remove./tenants/:id/settings— get, update.- All behind
requireAuth()+ appropriaterequireRole. - Rate limiting + idempotency on mutations.
- Route
.test.ts+.md.
6. Plugin factory + integration tests + publish
createTenantPlugin:definePlugin,dependencies: ["database", "auth"],migrationsPath: "./surql".- Integration: create tenant → invite member → accept invite → list members → remove (real SurrealDB).
bunx turbo lint typecheck test --filter=@suaveplan/api-plugin-tenant— green; 100% coverage.bun scripts/publish.ts --package @suaveplan/api-plugin-tenant.- Archive →
openspec/archive/2026-04-24-enterprise-api-plugin-tenant/.