71 lines
3.9 KiB
Markdown
71 lines
3.9 KiB
Markdown
<!-- markdownlint-disable MD024 -->
|
|
|
|
# Capability Spec Delta: api-events-worker-proxy (api-events-worker-proxy)
|
|
|
|
**Package**: `@suaveplan/api-events-worker-proxy`
|
|
**Status**: PROPOSED
|
|
|
|
> Every requirement below carries a `**Verified by:**` line at authoring time.
|
|
|
|
## ADDED Requirements
|
|
|
|
### Requirement: Proxy preserves the EventBusLike surface from `@suaveplan/events`
|
|
|
|
The package SHALL expose `createEventsProxyClient(port)` returning a value that satisfies `WorkerProxyOf<EventBusLike>` where `EventBusLike` is the EXISTING type from `@suaveplan/events`. No new contract layer SHALL be introduced — worker-side plugin code that worked against the direct bus MUST also work against the proxy with no source change beyond async-await wrapping (which `WorkerProxyOf` already enforces by promise-wrapping return types).
|
|
|
|
#### Scenario: proxy type matches WorkerProxyOf<EventBusLike>
|
|
|
|
- **WHEN** `expectTypeOf<ReturnType<typeof createEventsProxyClient>>().toEqualTypeOf<WorkerProxyOf<EventBusLike>>()` is checked
|
|
- **THEN** the assertion passes
|
|
|
|
**Verified by:** `src/client/client.spec-conformance.test.ts::"proxy type matches WorkerProxyOf<EventBusLike>"`
|
|
|
|
---
|
|
|
|
### Requirement: Disallowed-topic emit throws reconstructed SuaveplanError
|
|
|
|
The package SHALL marshal `emit(topic, payload)` calls to the main-process bus where topic-allow checks are enforced per design doc §5.2b. If the main side rejects with a disallow signal, the proxy MUST surface `EVENTS_PROXY_TOPIC_NOT_ALLOWED` as a `SuaveplanError` reconstructed via `api-worker-rpc`'s error-reconstruction.
|
|
|
|
#### Scenario: allowed topic emit round-trips
|
|
|
|
- **WHEN** a plugin manifests `publishes: ["billing.invoice.created"]` AND calls `emit("billing.invoice.created", payload)`
|
|
- **THEN** the main-side bus receives the event AND the call resolves successfully
|
|
|
|
#### Scenario: disallowed topic throws TOPIC_NOT_ALLOWED
|
|
|
|
- **WHEN** the plugin calls `emit("foreign.topic", payload)` with no matching manifest entry
|
|
- **THEN** the proxy call rejects with `SuaveplanError` of code `EVENTS_PROXY_TOPIC_NOT_ALLOWED`
|
|
|
|
**Verified by:** `src/publisher/publisher.test.ts::"allowed topic emit round-trips"` AND `src/publisher/publisher.test.ts::"disallowed topic throws TOPIC_NOT_ALLOWED"`
|
|
|
|
---
|
|
|
|
### Requirement: Subscription delivers events from main bus to worker handler with backpressure
|
|
|
|
The package SHALL marshal `on(topic, handler)` so that events emitted on the main-process bus are delivered to the worker-side handler. Worker-side handler throws MUST surface main-side as `EVENTS_PROXY_HANDLER_THROW`. The main-side dispatcher MUST respect `api-worker-rpc`'s backpressure budget — when the worker is slow, main-side delivery throttles rather than buffering unbounded.
|
|
|
|
#### Scenario: event delivered to worker handler
|
|
|
|
- **WHEN** the main bus emits `topic` AND the worker handler is registered
|
|
- **THEN** the handler observes the event payload
|
|
|
|
#### Scenario: slow handler backpressures producer
|
|
|
|
- **WHEN** the worker handler takes 100ms per call AND main emits 100 events in a burst
|
|
- **THEN** the main-side dispatcher pauses at the backpressure budget rather than buffering all 100 in memory
|
|
|
|
**Verified by:** `src/subscriber/subscriber.test.ts::"event delivered to handler"` AND `src/subscriber/subscriber.test.ts::"slow handler backpressures producer"`
|
|
|
|
---
|
|
|
|
### Requirement: Conformance suite passes against this proxy
|
|
|
|
The package SHALL be runnable as the surface argument to `runEventsBusConformance` from `@suaveplan/events/testing`. Every conformance scenario (FIFO ordering, interceptors, idempotent listeners) MUST pass identically to a direct in-process bus. This is the Stage-4-precondition gate.
|
|
|
|
#### Scenario: runEventsBusConformance passes
|
|
|
|
- **WHEN** `runEventsBusConformance("worker-proxy", makeFactory)` runs
|
|
- **THEN** every scenario passes
|
|
|
|
**Verified by:** `tests/conformance/run-events-bus-conformance.test.ts::"runEventsBusConformance passes against proxy"`
|