# `@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: 1. It pins the contract — every later DB-backed adapter (Stage 8 or later) implements the same `TenantProvider` interface, so retrofitting tenant enumeration into a stable contract doesn't have to happen later (§5.4 last sentence). 2. It's the default for the testing kit (`createTestHost` Stage 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 a `TenantProvider`. - ADDED: `createMemoryTenantProviderWorkerProxy(port, opts)` — proxy-surface factory. - ADDED: `MemoryTenantProviderOptions` — Zod schema with `tenants: TenantContext[]` (initial set), `mutable: boolean` (default true — allow runtime `add`/`remove`/`update`). - ADDED: Mutation API (when `mutable: true`): `add(tenant)`, `remove(tenantId)`, `update(tenantId, patch)`. - ADDED: `list()` returns an array snapshot; `listAsync()` returns an `AsyncIterable` for symmetry with future DB-backed adapter. - ADDED: `get(tenantId)` returns `TenantContext | 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-flags` consumes 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 when `mutable: 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.