Files
2026-05-27 23:29:53 +01:00

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:

  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<TenantContext> 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.