feat(sessions): record each session's sandbox state and browser version - #24
Merged
Merged
Conversation
…rd (D-31, schema v4) Spec first for #19: sessions.sandboxed and sessions.browser_version (migration 0004, compatible), written once the browser has launched (latest launch wins), served as SessionSummary.browser for live and closed sessions alike; absent means not recorded, never not sandboxed. Dashboard Details shows sandboxed / not sandboxed / not launched / not recorded. MCP tool output unchanged.
…on at launch (schema v4) Migration 0004-session-browser (compatible) adds sessions.sandboxed (INTEGER CHECK IN (0,1)) and sessions.browser_version, NULL for existing rows. The Session aggregate keeps the launch facts it attached after teardown (latest launch wins); the session.updated patch writes them once known and never clears them. SessionSummary.browser falls back to the recorded launch in every builder: the aggregate (HTTP detail/list overlay, WS), the stored row and the live overlay. Absent still means not recorded. Fixture v4.db, golden schema-v4.json, db types regenerated.
… sessions too The Session panel's Sandbox row now shows for every session: a sandboxed pill or muted "not sandboxed" from SessionSummary.browser (live or recorded at launch), muted "not launched" when the browser never started, and muted "not recorded" with an explainer for sessions from before the record existed. It never reads "not sandboxed" without a record.
Measured on the real run: Chromium's persistent context exposes a Browser, so its version is recorded like any other. The spec, the contract comment and the port comment said it was always null; they now say null only when no Browser can be read.
… and upgrading guides; changeset
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #19
Every session now records, when its browser launches, whether that browser ran inside Chromium's sandbox and the browser's real version. Closed sessions keep showing both in the API, over WS and in the dashboard. Sessions from before this change, and sessions whose browser never started, read not recorded / not launched. They never read "no" or "not sandboxed".
Recording and display only: sandbox behaviour is unchanged.
Before / after
GET /sessions/{id},GET /sessionsbrowser: {version, sandboxed}only while the session is live; absent once closedsession.opened/updatedsessions.sandboxed INTEGER CHECK IN (0,1),sessions.browser_version TEXT, both nullable (migration0004-session-browser,compatible: true, nothing backfilled)launch_failed), or muted not recorded with an explainer ("Recorded for sessions launched with BrowserHive 0.2 or later … It does not mean the sandbox was off.", links to the security guide). The Browser row carries the version for closed sessions too.browserHow it works
Session.browserInfo: the aggregate keeps the launch facts it attached (handle.browserInfo), including afterdetach(). The latest launch wins. No code path relaunches a session's browser today, but the rule is in the spec.session.updatedpatch (toSessionPatch) carriessandboxed/browserVersiononly once a launch recorded them, so no patch ever clears a stored record. The first write is theregisterphase's update, when the session goes live. The insert at reserve time stores NULL.SessionSummarybuilder:toSessionSummary(aggregate, used by HTTP and WS),sessionRowToSummary(stored row), andoverlayLive(the live summary wins; the row fills in when the aggregate has nothing).Spec (committed first)
browserwire semantics. 03 §7: schema v4 DDL, migration paragraph,v4.db/schema-v4.json.versionisnullfor a persistent context, but Chromium's persistent context exposes aBrowser, and the real run recorded153.0.8010.12for one. Spec, contract comment and port comment now saynullonly when noBrowsercan be read.Verification
Real runs used the built package on a scratch data dir, port 9931. The previous release was
origin/maina7a79d8, built in a second worktree.Pre-migration upgrade. The old build (0.1.3, schema v3) launched and closed
legacy-chromiumandlegacy-chromeover MCP. At that point REST showedbrowserabsent. The new build then started on the same data dir:browserhive-v3-….dbbackup and applied migration 3 → 4;browserin the list and the detail, the DB holds NULL, and the dashboard shows "not recorded".New sessions under
--sandbox auto. Each was checked live and again afterclose_session, via REST list, REST detail and the DB:auto-chrome(kept live, then closed)/opt/google/chrome{154.0.8037.57, sandboxed: true}1auto-chrome-done/opt/google/chrome{154.0.8037.57, sandboxed: true}1auto-chromiumsandbox fell back … No usable sandbox!,{153.0.8010.12, sandboxed: false}0New sessions under
--sandbox off:off-chromium(live, then closed){153.0.8010.12, false}0off-chrome{154.0.8037.57, false}0off-persistent(persistent profile){153.0.8010.12, false}0no-edge(not installed,launch_failed)browserabsentMCP.
list_sessionsoutput is unchanged and has nobrowserkey, by design.Local gate:
bun run check: exit 0 (2642 server tests, 341 dashboard tests; openapi, docs and db-types fresh)test:goldens,build,package:check: exit 0test:integration: 67 passDashboard screenshots were reviewed at 1440 and 768 px, light and dark, in these states: live sandboxed, closed sandboxed, closed unsandboxed, pre-migration "not recorded" with the explainer open, and "not launched".
Tests added
test/persistence/session-browser-migration.test.ts:v3.db→ v4 keeps NULL and serves nobrowser;2.metadata.test.ts:detach;serializers.test.ts: the row and overlay fallback.sandboxRecordcovers all four states;v4.db, goldenschema-v4.json. The HTTPlistSessionsgolden gainsbrowseron the recorded seed session.Not done
interruptedwith no record, so it shows "not recorded" with the pre-0.2 wording. The wire has nolaunched_atto tell the two cases apart.Contract change: additive only. Schema v4: migration
0004-session-browser(compatible: true, somin_reader_versionstays 1) adds two nullablesessionscolumns. There is a new fixturev4.dband goldenschema-v4.json;v1–v3.dbstill upgrade to head and match a fresh install. TheSessionSummary.browsershape is unchanged ({version: string | null, sandboxed: boolean}, optional); it is now also present for closed sessions that have a record.packages/contracts/generated/openapi.jsonis unchanged (the field has no description in OpenAPI; only the TS doc comment changed). WS payloads have the same shape. Tool goldens are unchanged.