# Browser Your own browser, driven from Officer. Not a headless one — the browser you are already signed into. ## The shape ``` extension/ the Chrome extension: attaches the debugger to your tabs, talks to the relay sidecar/ the relay it connects to, on port 18792, plus the CDP bridge api/ pairing, status, and the target verbs db/ browser_pairings — one salt per account web/ the tab list and the preview panel ``` ## Why the relay is a sidecar now It was a second `Bun.serve` inside the platform process, on its own port. That is precisely why it was switched off on 2026-08-13, with the note "the platform serves one port". A sidecar is a process allowed its own listeners, so the objection stops applying rather than being argued with. Two listeners live there: the extension's WebSocket, and the registration socket back to the platform that `api/router.ts` asks questions over. **The boundary is deliberately small.** Only two things cross it — who is connected, and what tabs they have — because only those live in memory on the relay side. Screenshots, evaluation and navigation still go straight down `cdp.ts`'s own WebSocket to the relay's `/cdp` endpoint, exactly as before. Routing page bytes through the platform would be work for nothing. ## The port is a credential, not just an address `deriveRelayToken` is `HMAC(key, 'officer-browser-relay-v1:${port}:${userId}:${salt}')`. The port is an **input**. Move it and every paired browser fails authentication, reporting "Relay not reachable" — which SETUP.md attributes to a wrong address or token, so the real cause is invisible. It therefore cannot be kernel-assigned the way other sidecars' listeners are: the extension is configured by hand and stores the number. 18792 is what it was before the extraction and what it stays. ## Per-account, unlike desktop The desktop plugin mirrors one physical screen and is owner-only because there is only one and it is the owner's. This is the opposite: each account pairs **its own** browser, the relay resolves an extension's token to the account that minted it, and two people on one server drive two different browsers. So the permission is ordinarily grantable. ## What changed on the way out Three things that are normally breaking and were free exactly once — see `BLOCKERS.md` §1. Short version: its own signing key, its own table, and the same port on purpose. ## Iris `plugins/iris` captures pages using a browser profile at `~/.config/officer/browser-profile`. That is the **desktop** plugin's browser, not this one — iris drives a browser it launches itself, while this attaches to one a person is using. They are neighbours, not layers.