Files
suaveplan/openspec/specs/api-logger-worker-proxy/spec.md
2026-05-27 23:29:53 +01:00

3.8 KiB

Capability Spec: api-logger-worker-proxy

Package: @suaveplan/api-logger-worker-proxy Status: SHIPPED

Every requirement below carries a **Verified by:** line.

Requirements

Requirement: Proxy preserves LoggerLike surface with plugin pre-tagging

The package SHALL expose createLoggerProxyClient(port, { plugin: { name, version } }) returning a WorkerProxyOf<LoggerLike>. Every emitted record SHALL carry the plugin's name and version as pre-tagged fields per design doc §5.1. Every log level (trace, debug, info, warn, error, fatal) MUST round-trip through the proxy.

Scenario: every level round-trips with plugin tags

  • WHEN the worker calls log.info({ msg: "x" })
  • THEN the main-side stub sink receives a record with plugin === { name, version } AND msg === "x" AND level === "info"

Verified by: src/client/client.test.ts::"every level round-trips with plugin tags"


Requirement: Batched send flushes on size, idle, or error level

The package SHALL batch outbound log records. A batch SHALL flush when ANY of three conditions hold: (a) maxBatchSize records buffered (default 100); (b) flushIntervalMs elapsed since the first buffered record (default 50); (c) the record's level is error or fatal (immediate flush). Buffered records MUST persist across the immediate flush — flushing for an error record does NOT discard lower-level records buffered before it.

Scenario: batch flushes at max size

  • WHEN 100 records are buffered
  • THEN the batch is sent on the next microtask

Scenario: error level flushes immediately AND preserves earlier records

  • WHEN 5 info records are buffered AND a log.error(...) is called
  • THEN the batch flushes within 1 microtask AND the main side receives all 6 records in order

Verified by: src/batching/batching.test.ts::"batch flushes at max size" AND src/batching/batching.test.ts::"error flushes immediately and preserves earlier records"


Requirement: Backpressure drops records and emits a counter rather than throwing

The package SHALL enforce a bounded outstanding-batch budget per port. When the budget is exhausted, new records MUST be dropped silently AND a LOGGER_PROXY_BACKPRESSURE_DROP counter MUST be incremented. The proxy MUST NOT throw on log calls — logging is best-effort by design, and an application MUST NOT break because the log sink is slow.

Scenario: over-budget records drop without throwing

  • WHEN the stub sink is paused AND 10000 records are emitted
  • THEN no exception is thrown AND LOGGER_PROXY_BACKPRESSURE_DROP counter is incremented above 0

Verified by: src/batching/backpressure.test.ts::"over-budget records drop without throwing"


Requirement: Control channel can disable and re-enable worker logs

The package SHALL accept disable and enable messages on the control channel from the main process. After disable, every level method on the worker side MUST become a no-op (records discarded without buffer or batch). After enable, normal flow resumes. The main host calls disable during plugin shutdown so a worker that is being torn down stops producing records after the main-side sink has been disposed (per design doc §5.5 disposal-in-reverse-order).

Scenario: disable makes level methods no-op

  • WHEN the main sends disable AND the worker subsequently calls log.info(...)
  • THEN no record reaches the main-side sink AND no batch is queued

Scenario: enable restores normal flow

  • WHEN the main sends enable after a prior disable
  • THEN subsequent log.info(...) calls reach the sink normally

Verified by: src/control-channel/control-channel.test.ts::"disable makes level methods no-op" AND src/control-channel/control-channel.test.ts::"enable restores normal flow"