# Capability Spec Delta: api-logger-worker-proxy (api-logger-worker-proxy) **Package**: `@suaveplan/api-logger-worker-proxy` **Status**: PROPOSED > Every requirement below carries a `**Verified by:**` line at authoring time. ## ADDED Requirements ### Requirement: Proxy preserves LoggerLike surface with plugin pre-tagging The package SHALL expose `createLoggerProxyClient(port, { plugin: { name, version } })` returning a `WorkerProxyOf`. 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"`