# Capability Spec Delta: api-events-in-memory (api-events-in-memory) **Package**: `@suaveplan/api-events-in-memory` **Status**: PROPOSED ## ADDED Requirements ### Requirement: Wraps the real @suaveplan/events bus The factory SHALL construct an `EventBusLike` by delegating to `@suaveplan/events`'s `createEventBus`. Subscribers receive events as the real bus delivers them; this package only adds a recording layer around publish. #### Scenario: subscriber receives published payload - **WHEN** a subscriber is registered on `"billing.invoice.created"` AND a payload is published - **THEN** the subscriber is invoked with the exact payload **Verified by:** `src/factory/create-in-memory-events-bus.test.ts::"subscriber receives published payload"` --- ### Requirement: published(topic) returns history `host.events.published(topic)` SHALL return an array of every payload published to `topic` since the last `reset()` (or since construction), in publish order. #### Scenario: history captures every publish in order - **WHEN** three payloads `[A, B, C]` are published to `"x"` - **THEN** `host.events.published("x")` returns `[A, B, C]` in that order #### Scenario: reset clears history - **WHEN** `host.events.reset()` is called after publishes - **THEN** `host.events.published("x")` returns `[]` AND already-registered subscribers stay registered #### Scenario: history bounded by maxHistoryPerTopic - **WHEN** `maxHistoryPerTopic: 10` is configured AND 11 payloads are published - **THEN** publish either throws `EVENTS_IN_MEMORY_HISTORY_OVERFLOW` OR drops the oldest payload (the chosen policy is documented and tested both ways) **Verified by:** `src/factory/create-in-memory-events-bus.test.ts::"history captures every publish in order"` AND `src/factory/create-in-memory-events-bus.test.ts::"reset clears history without unregistering subscribers"` AND `src/history/history.test.ts::"bounds history at maxHistoryPerTopic"` --- ### Requirement: Conforms to EventsBus contract The factory SHALL pass `runEventsBusConformance` from `@suaveplan/api-events/testing` (which itself wraps the conformance defined for `@suaveplan/events` plus any API-foundation specifics — error semantics, payload-id idempotency). #### Scenario: conformance suite passes - **WHEN** `runEventsBusConformance("in-memory-direct", () => createInMemoryEventsBus(...))` runs - **THEN** every invariant passes **Verified by:** `src/factory/create-in-memory-events-bus.spec-conformance.test.ts::"in-memory-direct conforms to EventsBus contract"` --- ### Requirement: Registered in `api-host/testing` adapter table #### Scenario: createTestHost resolves the sentinel - **WHEN** `createTestHost({ adapters: { events: "in-memory" } })` - **THEN** the resulting `host.events` is an instance produced by this factory AND has a `published(topic)` method **Verified by:** `tests/integration/integration.test.ts::"createTestHost resolves events:\"in-memory\" to this adapter and exposes published()"`