Files
suaveplan/openspec/archive/2026-05-25-api-events-worker-proxy/proposal.md
2026-05-27 23:29:53 +01:00

2.9 KiB

@suaveplan/api-events-worker-proxy — worker-side proxy to main-process @suaveplan/events bus

Package: @suaveplan/api-events-worker-proxy Status: PROPOSED Type: new-package Stage: 3 (Worker isolation infrastructure)

Why

Per design doc §5.2a, every capability ships a proxy surface for worker-tier plugins. The events capability is special: there is no abstract api-events contract package — the host injects the existing @suaveplan/events bus directly into PluginContext.events. So this proxy is a worker-side surface over the existing @suaveplan/events EventBusLike interface, NOT a new contract layer. Worker-side ctx.events.emit(...) / ctx.events.on(...) calls marshal across MessagePort to the main-process bus.

Per §5.2b sandboxed gating: only manifested publishes topics are emittable; only manifested subscribes topics deliverable. That gating is enforced MAIN-SIDE; this proxy is the transport.

What changes

Net-new package.

ADDED exports:

  • ./client — createEventsProxyClient(port): WorkerProxyOf<EventBusLike>.
  • ./subscriber — on(topic, handler) / off / once; handlers run worker-side; backpressure carried by api-worker-rpc so a slow worker-side subscriber cannot exhaust main-side memory.
  • ./publisher — emit(topic, payload) marshals payload; main-side does the topic-allow check + actual bus publish; emit-not-allowed returns EVENTS_PROXY_TOPIC_NOT_ALLOWED (rebuilt SuaveplanError).
  • ./error-codes — EVENTS_PROXY_* codes (EVENTS_PROXY_TOPIC_NOT_ALLOWED, EVENTS_PROXY_HANDLER_THROW, EVENTS_PROXY_PORT_CLOSED, EVENTS_PROXY_BACKPRESSURE_DROP).
  • ./testing — paired MessageChannel + stub bus.

Out of scope

  • Topic allowlisting policy — enforced main-side per §5.2b.
  • Cross-host fan-out — @suaveplan/events's job (and api-ws-broker-redis for WS specifically).
  • Bounded-queue capability — events.bounded-queue capability flag is honored main-side; the proxy only marshals.

Source mapping

Genesis-original. Design doc sections: §5.2a (worker-RPC variants), §5.2b (sandboxed gating), §6 (capability scoping).

Requirement Design doc section
Proxy surface over existing @suaveplan/events bus (no new contract) §5.2a
Topic allow-check on main side; proxy rejects with reconstructed error §5.2b
Handler throws reconstructed via api-worker-rpc §5.2a

Verification approach

  • src/publisher/publisher.test.ts — emit allowed topic round-trips; disallowed topic throws.
  • src/subscriber/subscriber.test.ts — handler invocation; off cancels; backpressure throttles main → worker.
  • tests/conformance/run-events-bus-conformance.test.ts — runEventsBusConformance from @suaveplan/events/testing passes against the proxy as surface. Required before Stage 4 can complete.

Migration impact

None — additive only.