From 163f9e3d19fa9436e7fafb8cef61b53c83d7fa62 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Wed, 27 May 2026 08:52:17 -0700 Subject: [PATCH] fix(test): pin SSE sanitizer wiring to the v1.51 createSseEndpoint helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two `wiring invariants` tests grepped server.ts for `JSON.stringify(entry, sanitizeReplacer)` and `JSON.stringify(event, sanitizeReplacer)` — patterns that lived inline in /activity/stream and /inspector/events before the v1.51 refactor moved both endpoints behind createSseEndpoint. Sanitization still happens (the helper applies it inside its send() and live-event callback), but the static-grep was pinned to the old wiring and started failing on Windows free-tests after the refactor landed. Updated to check the new contract: - /activity/stream + /inspector/events route through createSseEndpoint (regex match of the route handler block ending in the helper call). - sse-helpers.ts contains JSON.stringify + sanitizeReplacer + imports stripLoneSurrogates from ./sanitize (catches drift to a private copy). - server.ts retains its own sanitizeReplacer for non-SSE egress paths (handleCommandInternal); the two replacers coexist by design. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../test/server-sanitize-surrogates.test.ts | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/browse/test/server-sanitize-surrogates.test.ts b/browse/test/server-sanitize-surrogates.test.ts index 156d9a3e9..d8abd1012 100644 --- a/browse/test/server-sanitize-surrogates.test.ts +++ b/browse/test/server-sanitize-surrogates.test.ts @@ -113,17 +113,45 @@ describe('sanitizeLoneSurrogates — wiring invariants', () => { expect(SERVER_SRC).toContain('result: sanitizeLoneSurrogates(cr.result)'); }); - test('SSE activity feed sanitizes outbound frames via sanitizeReplacer', () => { - // Replacer must run DURING stringify; post-stringify regex is ineffective - // because JSON.stringify converts \uD800 → "\\ud800" before our regex sees it. - expect(SERVER_SRC).toContain('JSON.stringify(entry, sanitizeReplacer)'); + test('SSE activity feed routes outbound frames through createSseEndpoint', () => { + // v1.51 refactor: /activity/stream no longer inlines its own + // ReadableStream/sanitizer wiring; it routes through createSseEndpoint + // which applies sanitizeReplacer to every JSON.stringify. The grep + // pins both halves of the contract: the endpoint uses the helper, + // and the helper does the sanitization. + const activityBlock = SERVER_SRC.match( + /if \(url\.pathname === '\/activity\/stream'\)[\s\S]*?createSseEndpoint\(/, + ); + expect(activityBlock).not.toBeNull(); }); - test('SSE inspector stream sanitizes outbound frames via sanitizeReplacer', () => { - expect(SERVER_SRC).toContain('JSON.stringify(event, sanitizeReplacer)'); + test('SSE inspector stream routes outbound frames through createSseEndpoint', () => { + // Same v1.51 refactor invariant for /inspector/events. + const inspectorBlock = SERVER_SRC.match( + /if \(url\.pathname === '\/inspector\/events'[\s\S]*?createSseEndpoint\(/, + ); + expect(inspectorBlock).not.toBeNull(); }); - test('sanitizeReplacer is a function defined in server.ts', () => { + test('createSseEndpoint applies sanitizeReplacer to every JSON.stringify', () => { + // The helper is the single source of truth for SSE sanitization now. + // If a future refactor moves stringify off the replacer (e.g. someone + // adds a fast-path encode), this test fails and the surrogate-escape + // class regresses across every SSE endpoint at once. + const helperPath = path.resolve(import.meta.dir, '..', 'src', 'sse-helpers.ts'); + const helperSrc = fs.readFileSync(helperPath, 'utf-8'); + expect(helperSrc).toContain('JSON.stringify('); + expect(helperSrc).toContain('sanitizeReplacer'); + // The sanitizer itself uses stripLoneSurrogates (the shared utility in + // sanitize.ts) — not a private copy. Re-confirms the helper is wired + // to the canonical sanitizer, not a drift'd duplicate. + expect(helperSrc).toContain("import { stripLoneSurrogates } from './sanitize'"); + }); + + test('sanitizeReplacer is a function defined in server.ts (for non-SSE egress)', () => { + // server.ts keeps its own sanitizeReplacer for the non-SSE JSON egress + // paths (handleCommandInternal etc.). The SSE path uses sse-helpers.ts's + // own sanitizeReplacer; both must exist independently. expect(SERVER_SRC).toContain('function sanitizeReplacer('); }); });