Files
vdm/extension
samiandClaude Sonnet 5 801bcaae12 ext: capture/headers.ts — request-header stash
onHeadersReceived (where shouldCapture runs) doesn't carry the headers the
browser actually sent; signed-URL and referrer-gated CDNs need them. Stash
from onBeforeSendHeaders keyed by requestId, read back at capture time.

This map sees every request, so it is bounded both ways — oldest-out past a
size cap (default 2048) and a 5-minute TTL, swept on a 60 s timer and on read
— and attach() clears an entry the moment its request completes or errors.

normalizeHeaders(): Array<{name,value}> -> lower-cased map, repeats joined
with ", ". 13 tests: eviction order, redirect re-put refresh, TTL expiry,
sweep, and the onBeforeSendHeaders/onCompleted/onErrorOccurred wiring.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012Y9RU58hD1BuwP82DySUHk
2026-09-10 13:52:07 +04:00
..

Owner: lane EXT. See ../docs/agents/AGENT-EXT.md and ../docs/05-extension-spec.md. Firefox MV3, TypeScript. Zero download logic.

Layout

src/background/transport/   Transport interface + WebSocket and native-messaging impls,
                            runtime picker. See docs/adr/0003 for why there are two.
src/shared/protocol/        GENERATED from ../contracts — never hand-edit.
tests/                      vitest; webextension-polyfill is mocked in tests/setup.ts.

Develop

npm ci
npm run typecheck        # tsc --noEmit, strict
npm test                 # vitest run
npm run lint             # web-ext lint (AMO rules) — needs manifest.json

Build against tools/mockd over the WebSocket transport; veloxd is not required.

Transport quick start

import { createTransport } from './src/background/transport/index.js';

const t = await createTransport();            // reads the Options override; default 'auto'
t.onStateChange((s) => renderDot(s));
const rules = await t.call('capture.getRules', {});

createTransport resolves with a live, self-reconnecting transport. When veloxd is not up yet it still resolves (WebSocket, status disconnected, retrying) — callers render the red dot. It rejects only when the user explicitly forced native messaging and that failed. Capture code treats every call() rejection as fail-open.