ADR-0005: Per-window browser session isolation
Status: Active · Date: 2026-07-07
Context
Every browser tab in Tranquil shared Electron’s default session — no <webview> set a partition except HAR-replay tabs (ADR-0004). A login on a domain in
one tab was a login in every tab and every window, so you could not be signed into the same site
under two accounts at once (work vs. personal, multi-tenant testing, comparing two users’ views).
Upstream Pulsar offers nothing to build on: it uses an ephemeral nextId++ window counter, sets no
partition on any BrowserWindow, and persists windows keyed only on their project roots. Any
per-window-session mechanism is therefore something Tranquil invents.
Decision
An Electron window instance is a session. Every window is assigned a durable windowSessionId (a uuid) at creation; all its browser webviews use partition = persist:tb-window-<windowSessionId>,
so each window is its own cookie/storage/login jar. The id is persisted per-window in application.json and restored on relaunch, so sessions survive quit/restart. Isolation is automatic (every window, no opt-in) and needs no browser UI — no picker, registry, or per-tab
controls. Within one window all tabs share that window’s session; two accounts means two windows.
Options considered
- Option A: Per-tab named containers — a registry of named, colored containers picked per tab (Firefox Multi-Account Containers). Only option that supports two logins side by side in one window. Rejected: heavy UI surface (picker, registry, colored chips, five entry points, per-tab serialization) for a need that “two windows” already covers.
- Option B: Per-project window session — derive the partition from the window’s project roots
(
persist:tb-window-<sha1(projectRoots)>), reusing Pulsar’s owngetStateKeyidentity. Idiomatic and needs no new persisted state. Rejected: it’s really project-scoped — two windows on the same project would share a session (the opposite of the requirement), and no-folder browser-only windows would have no stable/isolated session. - Option C: Durable per-window id (chosen) — assign each window a uuid, persisted additively in
application.json. True per-window isolation independent of project, persisted across restart. Cost: a new persisted field (no upstream precedent) — but additive, reusing the existingapplication.jsonsave/restore path with no schema-version bump. - Ephemeral per-window (sub-variant, rejected) — a runtime-only id, no
persist:. Trivial, but every window resets to logged-out on restart, failing the “keep a second account logged in” goal.
Consequences
- Migration: once windows own their sessions, existing sites live in the old default jar, so there’s a one-time re-login. A cookie-copy migration was considered and left out of scope.
- No same-window dual login: two accounts require two windows (accepted — matches the chosen mental model).
- “Open Link/Tab in New Window” revived: the previously-dead
application:new-window-open-urlchannel now has a main-process handler (AtomApplication.openUrlInNewWindow) that opens a fresh window and has its renderer open the URL — making “open this link in a new isolated login” a one-click action. - Two same-project windows across restart: their sessions persist correctly (cookies live in
the partition, keyed by
windowSessionId), but Pulsar already keys tab-layout state on project paths alone, so two same-project windows can’t restore distinct tab arrangements — an unrelated pre-existing limitation. - Orphaned partitions: each window id creates on-disk partition data under
~/.tranquil; abandoned windows leave it behind. A cleanup that prunespersist:tb-window-*partitions absent fromapplication.jsonis a future item. - HAR replay unaffected: a tab with an explicit
opt.partition(HAR) still wins over the per-window default. - Re-evaluation triggers: if same-window dual login becomes necessary, revisit Option A; if orphaned partition storage grows unbounded, add lifecycle cleanup.
Validation
Verified live on Electron 30.5.1: with three windows open, application.json recorded three distinct windowSessionIds and ~/Library/Application Support/Tranquil/Partitions/ held a matching tb-window-<uuid> directory per window (1:1), confirming each window’s webviews load into their own
persistent session. The decision record is these docs; implementation notes are in Per-Window Session Isolation — Delivery Notes.