3.5 KiB
@suaveplan/api-tenant-provider-memory — In-memory TenantProvider
Package: @suaveplan/api-tenant-provider-memory
Status: PROPOSED
Type: new-package
Stage: 4 (Base adapters) — see umbrella openspec/changes/api-plugin-foundation/
Why
Per design doc §5.4, perTenant: true cron jobs require the host to enumerate tenants. tenant.provider is the capability that exposes that enumeration. Shipping a v1 in-memory reference implementation matters for two reasons:
- It pins the contract — every later DB-backed adapter (Stage 8 or later) implements the same
TenantProviderinterface, so retrofitting tenant enumeration into a stable contract doesn't have to happen later (§5.4 last sentence). - It's the default for the testing kit (
createTestHostStage 5) and for any deployment whose tenant list is small + static.
The provider returns an iterable/async-iterable of TenantContext. Designed to be both production-grade for static deployments AND a reference for the more elaborate Stage-8 DB-backed adapter.
Stage 4 invariant: ships direct AND worker-proxy surfaces; both pass runTenantProviderConformance (§5.2a, §13.4). (Conformance suite is owned by api-conformance-suites this stage.)
What changes
Net-new package depending on @suaveplan/api-tenant-provider (contract), @suaveplan/api-types, @suaveplan/api-worker-rpc, @suaveplan/error, zod.
- ADDED:
createMemoryTenantProvider(opts)— direct-surface factory returning aTenantProvider. - ADDED:
createMemoryTenantProviderWorkerProxy(port, opts)— proxy-surface factory. - ADDED:
MemoryTenantProviderOptions— Zod schema withtenants: TenantContext[](initial set),mutable: boolean(default true — allow runtimeadd/remove/update). - ADDED: Mutation API (when
mutable: true):add(tenant),remove(tenantId),update(tenantId, patch). - ADDED:
list()returns an array snapshot;listAsync()returns anAsyncIterable<TenantContext>for symmetry with future DB-backed adapter. - ADDED:
get(tenantId)returnsTenantContext | undefined. - ADDED:
TENANT_PROVIDER_MEMORY_*error codes (TENANT_PROVIDER_MEMORY_DUPLICATE_ID,TENANT_PROVIDER_MEMORY_NOT_FOUND,TENANT_PROVIDER_MEMORY_IMMUTABLE,TENANT_PROVIDER_MEMORY_INVALID_OPTIONS).
Out of scope
- DB-backed enumeration — Stage 8 (or later)
api-tenant-provider-postgres/api-tenant-provider-surrealdb. - Hierarchical tenants — flat model only at this stage.
- Tenant-level feature flags —
@suaveplan/feature-flagsconsumes the provider, not the other way round.
Source mapping
Genesis-original. Source of design intent: docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md.
| Requirement | Design doc section |
|---|---|
tenant.provider ships in v1 |
§5.4 |
| In-memory reference impl | §5.4 |
| Worker-proxy variant | §5.2a |
| Conformance both surfaces | §13.4 |
Verification approach
src/factory/create-memory-tenant-provider.test.ts— list, get, mutation, duplicate-id rejection, immutability whenmutable: false.src/factory/create-memory-tenant-provider.spec-conformance.test.ts—runTenantProviderConformance("memory-direct", ...).src/proxy/create-memory-tenant-provider-worker-proxy.test.ts— proxy unit tests; async iteration across MessagePort.src/proxy/create-memory-tenant-provider-worker-proxy.spec-conformance.test.ts—runTenantProviderConformance("memory-worker-proxy", ...).
Migration impact
None — additive only.