--- phase: 09-faster-write-back reviewed: 2026-06-12T21:05:00Z depth: standard files_reviewed: 5 files_reviewed_list: - apps/api/src/lib/outboxTrigger.ts - apps/api/src/broker/outboxWorker.ts - apps/api/src/routes/events.ts - apps/api/src/index.ts - apps/api/tests/broker/outboxWorker.test.ts findings: critical: 0 warning: 0 info: 2 total: 2 status: issues_found --- # Phase 09: Code Review Report **Reviewed:** 2026-06-12 **Depth:** standard **Status:** issues_found (2 Info; no Blockers, no Warnings) ## Summary Iteration-2 re-review of the phase-09 write-back trigger wiring after a fixer pass addressed all seven iteration-1 findings (WR-01..03, IN-01..04). I re-traced the four high-risk areas the prompt called out and verified each fix is correct AND complete, and scanned for new defects the fixes could have introduced. Tooling: `vitest run` (30/30 pass) and `tsc --noEmit` (exit 0, both clean). **Fix verification — all four focus areas confirmed correct:** 1. **`queueMicrotask` deferral (WR-01).** `signalOutboxDrain()` now defers the emit: `queueMicrotask(() => emitter.emit('drain'))` (outboxTrigger.ts:37). This preserves fire-and-forget (the caller never blocks) and moves listener execution off the route handler's stack, so a synchronous throw in the listener chain can no longer corrupt the enqueue response. Trailing-re-drain semantics are intact: in the D-05 test two mid-drain signals each queue a microtask; both microtasks run (and collapse to one `drainRequested=true`) before the test's `setImmediate`-based flushes, yielding exactly 2 dispatches — the test still passes. The stale "Synchronous" JSDoc claim flagged in iteration 1 is gone; the new comment block (lines 24-35) accurately describes the deferral. **Correct and complete.** 2. **`initOutboxTrigger()` idempotency (WR-02).** Now guarded by a retained module-level `unsubscribeDrain` handle (outboxWorker.ts:858-863): a second call short-circuits (`if (unsubscribeDrain) return`), so no double-`'drain'`-listener and no `MaxListenersExceededWarning`. `stopOutboxTrigger()` (871-874) calls the retained unsubscribe and nulls the handle, allowing a clean re-`init`. The unsubscribe closure passed to `emitter.off('drain', handler)` is the exact handler registered by `emitter.on('drain', handler)` (outboxTrigger.ts:45-46), so removal-by-reference is correct. A `stop → init` cycle registers a fresh closure and captures a fresh handle — no stale-listener leak. **Genuinely safe.** 3. **`resolveFinalRrule()` extraction (IN-02) — byte-identical output.** Highest regression risk (two previously independent write paths merged). I diffed the extraction commit (d3163f2) line-by-line: the original `update` and `create` decision trees were **already character-identical**, and both now call `resolveFinalRrule(fields, hasExplicitRecurrence, rruleFromPayload, preservedRrule)` with identical argument order (outboxWorker.ts:476-481 and 554-559). The only per-branch difference — the *source* of `preservedRrule` (update re-reads `rawVevent`; create reads `_preservedRrule`) — is computed before the call and passed in, exactly as before. The bound-strip regex `/;(UNTIL|COUNT)=[^;]*/g`, the COUNT-over-UNTIL precedence, and the `recurrence:'none' → undefined` clearing are all preserved verbatim. The CR-01 create-branch tests (`_preservedRrule` → RRULE present; `recurrence:'none'` → no RRULE) and the D-07 FREQ-persistence lock all pass. **No behavioral change; byte-identical for both branches.** 4. **`__resetDrainState()` test-only hook (IN-03).** Exported from the production module but confirmed to have NO production caller (`grep` shows only the declaration and test imports). It resets `isDraining`/`drainRequested` to false, which is correct for the `beforeEach` quiescent-state reset and harmless in the test process. The only residual concern is the unguarded production export (see IN-01 below). The stale RED `@ts-ignore` removal (IN-04) and the `afterAll(stopOutboxTrigger)` teardown (WR-03) are both present and the suite is green, confirming no leaked listener bleeds across describe blocks under `fileParallelism:false`. **No new BLOCKER or WARNING defects were introduced by the fixes.** The two findings below are Info-level robustness notes; both are pre-existing or latent, neither blocks shipping. ## Narrative Findings (AI reviewer) ### IN-01: `__resetDrainState()` is a production export with no environment guard **File:** `apps/api/src/broker/outboxWorker.ts:883-886` **Issue:** `__resetDrainState()` is exported from a production module and unconditionally clears the entire single-process concurrency contract (`isDraining = false; drainRequested = false;`). Its only protection against misuse is a JSDoc line ("Not for production use"). If any future code path imports and calls it while a drain is in flight, it would clear `isDraining` mid-cycle and allow `scheduleOutboxDrain()`/`runOutboxDrain()` to start a concurrent drain that double-dispatches the same still-`pending` outbox row — exactly the CR-05 hazard the guard exists to prevent. Today there is no such caller (grep confirms test-only usage), so this is latent, not active. **Fix:** Gate the body on a non-production check so an accidental production call is a no-op, keeping the contract enforced by code rather than by comment: ```ts export function __resetDrainState(): void { if (process.env.NODE_ENV === 'production') return; // test-only; never clear the guard in prod isDraining = false; drainRequested = false; } ``` (Alternatively, move the reset behind a test-only entry point not reachable from the production import graph. The env guard is the smaller change.) ### IN-02: Signal arriving in the `isDraining=false` → `.finally` window starts a fresh drain rather than collapsing via `drainRequested` **File:** `apps/api/src/broker/outboxWorker.ts:237-253` (in concert with the `isDraining=false` reset at line 838) **Issue:** `runOutboxDrain` clears `isDraining` in its own `finally` (line 838), and the `.finally()` callback in `scheduleOutboxDrain` (line 246) runs in a *later* microtask. A `signalOutboxDrain()` whose deferred emit lands in that gap finds `isDraining === false` and starts a brand-new `runOutboxDrain()` directly instead of being collapsed into the single trailing re-drain via `drainRequested`. The just-completed drain's `.finally` may then *also* observe `drainRequested` (if a still-earlier signal set it) and kick a second pass. The net effect can be two near-back-to-back drains instead of one collapsed trailing drain. This is NOT a correctness bug — the re-entrant `isDraining` guard (line 658) keeps every concrete `runOutboxDrain` body strictly serialized, so no row is double-dispatched — but it weakens the documented "collapse any number of mid-drain signals into exactly one trailing drain" guarantee (lines 216-219) at this specific boundary, and can produce one extra Fastmail-facing drain pass under rapid edits. It is pre-existing (the `queueMicrotask` deferral did not create it; it only shifts the emit by one microtask) and was not flagged in iteration 1. **Fix:** Reset `isDraining` and check/consume `drainRequested` in the *same* synchronous step so the gap cannot be observed — e.g. fold the trailing-re-drain decision into `runOutboxDrain`'s own `finally` (snapshot `const shouldRedrain = drainRequested`, reset both flags atomically before releasing `isDraining`), rather than splitting the reset (`runOutboxDrain.finally`) from the re-drain trigger (`scheduleOutboxDrain.finally`). Low priority given the guard makes the worst case one redundant — not unsafe — drain pass. --- _Reviewed: 2026-06-12T21:05:00Z_ _Reviewer: Claude (gsd-code-reviewer)_ _Depth: standard_