[PR #2346] [MERGED] feat(browser): attach passive tools to browsers without HTTP discovery #5179

Closed
opened 2026-10-31 01:04:35 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2346
Author: @all-black-493
Created: 10/12/2026
Status: ✅ Merged
Merged: 10/13/2026
Merged by: @morluto

Base: main ← Head: feat/browser-websocket-endpoint


📝 Commits (3)

  • 4efd6e4 feat(browser): attach passive tools to browsers without HTTP discovery
  • 4706bb9 test(browser): match browser-socket captures against HTTP discovery
  • 616f8f8 fix(browser): bound browser-socket handshake and report discovery timeouts

📊 Changes

22 files changed (+960 additions, -179 deletions)

View changed files

📝 docs/browser-observation.md (+48 -3)
➕ scripts/lib/browser-socket-e2e.mjs (+100 -0)
📝 scripts/verify-real-browser.mjs (+9 -0)
📝 src/application/BrowserEvidence.ts (+1 -1)
📝 src/browser/CdpBrowserProvider.ts (+96 -132)
📝 src/browser/CdpEndpoint.ts (+103 -0)
📝 src/browser/CdpTargetSession.ts (+67 -0)
📝 src/cli/browserAdvancedCommands.ts (+6 -2)
📝 src/cli/browserCommands.ts (+12 -4)
📝 src/domain/browserObservation.test.ts (+54 -0)
📝 src/domain/browserObservation.ts (+103 -24)
📝 src/domain/browserSession.ts (+2 -2)
📝 src/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.ts (+11 -3)
📝 src/domain/webMcpDiscovery.ts (+2 -2)
📝 src/domain/webScreenshot.ts (+2 -2)
➕ tests/boundary/browser/cdpBrowserProvider.browserSocket.test.ts (+232 -0)
📝 tests/boundary/browser/cdpBrowserProvider.targetInventory.test.ts (+7 -4)
📝 tests/boundary/cli/browserCli.test.ts (+48 -0)
📝 tests/boundary/mcp/browserMcp.test.ts (+41 -0)
📝 tests/fixtures/fakeCdpBrowser.ts (+3 -0)

...and 2 more files

📄 Description

Summary

Implements option 2 from #2288. The passive browser tools can now attach to a browser that serves a loopback browser WebSocket but no HTTP discovery. Before this change, every passive call read /json/version and /json/list first, so such a browser failed with endpoint_unreachable.

The maintainer scope decision for #2288 is still pending. This PR is open for review, but per CONTRIBUTING it should not be merged until that decision covers it. The proposal and evidence are in this comment.

Problem and expected behavior

Since Chrome 136, --remote-debugging-port is ignored for the default profile (Chrome blog). Chrome 144+ can instead enable remote debugging on a running browser from chrome://inspect/#remote-debugging (Chrome blog). A third-party report (trycua/cua#2916, Chrome 151) says this mode writes the port and a /devtools/browser/<id> path to DevToolsActivePort and returns 404 for /json/version.

Expected: a caller can pass ws://127.0.0.1:PORT/devtools/browser/<id> and get the same targets and inspection results as HTTP discovery.

Change and scope

  • Endpoint contract. cdp_endpoint on the six passive tools also accepts ws://127.0.0.1:PORT/devtools/browser/<id> or ws://[::1]:PORT/.... The port must be explicit, the id one path segment, and credentials, query and fragment are rejected. The HTTP form is unchanged. localhost, LAN, wss: and /devtools/page/ sockets stay invalid. The domain parses the endpoint once into { transport, url, recorded }.
  • Tools. list_browser_targets, inspect_web_page, analyze_web_bundle, observe_web_session, discover_webmcp_tools, capture_web_screenshot. Electron, web runtime, scenario attach and V8 Inspector endpoints keep browserEndpointSchema and stay HTTP-only.
  • One socket per call. Socket discovery sends Browser.getVersion and Target.getTargets, then the target session adopts the same socket for Target.attachToTarget (flat). Consent is reportedly requested per WebSocket upgrade, so a second socket would prompt twice. Unadopted sockets are closed on failure and on cancellation.
  • Evidence redaction. Chrome refuses a browser-socket upgrade with the wrong id (HTTP 404, checked on Chrome 138), so the id gates access. Evidence records ws://127.0.0.1:PORT/devtools/browser/[REDACTED]. JavaScript runtime reconciliation accepts that recorded form for browser captures. HTTP-endpoint Evidence is unchanged.
  • Refactor. CdpBrowserProvider repeated the same discover → authorize → session → cleanup block in five operations. All five needed the new transport, so they now share one withTargetSession helper.

Not included: reading DevToolsActivePort for the caller, a pipe transport (option 3), or anything that launches a browser. #2287 separately documents option 1.

Follow the contribution scope. The scope decision is pending in #2288.

Contract and boundary impact

  • Semantic owner and earliest changed stage: browserObservationEndpointSchema in src/domain/browserObservation.ts; transport selection in src/browser/CdpTargetSession.ts.
  • Contribution scope fit and linked maintainer decision: pending in #2288. Passive, attach-only; no new launch, execution or mutation authority.
  • CLI and MCP/tool-catalog contract: additive. The six tools accept a second cdp_endpoint form. The MCP description and CLI endpoint help name it. The advertised JSON Schema type is unchanged (string).
  • Provider, bridge, target-format, or platform compatibility: Chromium-family browsers exposing a loopback browser socket. With a socket, browser.revision is Browser.getVersion's value (@<hash>) instead of WebKit-Version (537.36 (@<hash>)). attached is a boolean where Chrome's /json/list omits it and HTTP discovery reports null. Both are documented.
  • Evidence, artifact, provenance, or reconstruction contract: parameters.cdp_endpoint is the redacted socket URL for socket calls; unchanged for HTTP calls.
  • Target selection, authority, upstream behavior, and cleanup details: same target authorization and origin scoping as HTTP discovery. REA never closes the browser or a page; it closes only its socket.
  • Generated metadata, package, or installation impact: none. No skill change.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

The attach is the existing passive CDP attach, over a different loopback transport.

Evidence and regression coverage

  • Tests added or updated:

    • src/domain/browserObservation.test.ts: accepted socket forms, recorded redaction, and rejected shapes (implicit port, localhost, wss:, credentials, query, fragment, empty or nested id, page socket).
    • tests/boundary/browser/cdpBrowserProvider.browserSocket.test.ts: socket discovery matches HTTP discovery; inspection uses one socket and makes no HTTP requests; the socket closes on a missing target, malformed Browser.getVersion, and cancellation; a refused socket is endpoint_unreachable without echoing the id.
    • tests/boundary/cli/browserCli.test.ts, tests/boundary/mcp/browserMcp.test.ts: public CLI/MCP calls with a socket record the redacted endpoint. MCP reconciliation accepts that Evidence, and the advertised description names the socket form.
    • scripts/lib/browser-socket-e2e.mjs, wired into npm run verify:browser. On real Chrome it checks that DevToolsActivePort names the same socket as /json/version, and that socket discovery matches HTTP discovery. It also checks that a public CLI inspection through the socket records redacted Evidence and compares unchanged for DOM structure and scripts against an HTTP-discovery inspection.
    • The fake CDP browser answers Browser.getVersion with Chrome's reply shape and counts opened sockets.
  • Issue success check (#2288, option 2), run manually on the notes-web demo (website/public/examples/notes-web/ served on 127.0.0.1). Chrome 138.0.7204.157 was started with an explicit --remote-debugging-port and a dedicated --user-data-dir. Only /json/version's webSocketDebuggerUrl was passed to the compiled CLI, and the result was compared with HTTP discovery:

    • list-browser-targets: the same target, title, URL and origin. The only difference is attached (null through HTTP, because Chrome's /json/list omits it; false through the socket).
    • inspect-web-page --include-script-sources --observation-ms 1000: identical apart from target.attached. Both returned the same three scripts (assets/main.js, assets/i18n.js, examples/notes-web/export.js) with identical source SHA-256 digests, 72 DOM nodes, an empty network.requests, and the same attach_limited_sections.
    • compare-web-captures (HTTP vs socket): dom_structure, scripts and resources are unchanged. network, metadata, webmcp, accessibility and storage are unknown, as for any two attach-window captures.
    • Recorded endpoints: http://127.0.0.1:<port> and ws://127.0.0.1:<port>/devtools/browser/[REDACTED]. The socket id appears in no CLI output.
  • Base reproduction: on upstream/main, rea list-browser-targets ws://127.0.0.1:PORT/devtools/browser/<id> fails input validation, because cdp_endpoint must be an explicit-port HTTP URL. Without HTTP discovery, no accepted endpoint exists.

  • User-visible CLI/MCP output: real Chrome 138, rea list-browser-targets ws://127.0.0.1:<port>/devtools/browser/<id> --allowed-origins http://127.0.0.1:<site> --json (trimmed):

    {
      "operation": "list_browser_targets",
      "parameters": {
        "cdp_endpoint": "ws://127.0.0.1:<port>/devtools/browser/[REDACTED]",
        "allowed_origins": ["http://127.0.0.1:<site>"]
      },
      "normalized_result": {
        "browser": {
          "product": "Chrome/138.0.7204.157",
          "protocol_version": "1.3",
          "revision": "@e533e98b1267baa1f1c46d666b120e64e5146aa9",
          "js_version": "13.8.258.26"
        },
        "targets": [
          {
            "type": "page",
            "title": "REA browser verifier",
            "url": "http://127.0.0.1:<site>/app",
            "origin": "http://127.0.0.1:<site>",
            "attached": false
          }
        ],
        "excluded": { "disallowed_origin": 0, "unsupported_url": 0, "non_page": 4 }
      }
    }
    

    The socket id does not appear anywhere in stdout.

  • Remaining proof gaps:

    • Not tested against the chrome://inspect toggle itself; the local Chrome is 138. The socket-only behavior and per-connection consent come from the third-party report above.
    • Other Chromium-family browsers (Brave, Edge) were not checked over the socket.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • Review fixes (head 616f8f84d): the browser-socket WebSocket handshake now runs inside the 10-second discovery deadline, and a reached deadline projects as provider_timeout rather than cancelled. New boundary tests cover a stalled discovery reply and a handshake that never completes. check:fast passes; tests/boundary/browser plus the browser CLI and MCP suites pass (45 files, 417 tests, 1 skipped).
  • Rebased on 4276aaf18 (head 4706bb9f4). The only conflict was with #951b095e1, which bounded HTTP discovery responses to 8 MiB and 10 seconds. Browser-socket discovery now shares that 10-second deadline (timeout reason, caller cancellation preserved, boundary test added). Each socket reply stays bounded by the 64 MiB protocol message limit. After the rebase: check:fast passes; all tests/boundary/browser files plus the browser/Electron CLI and MCP, Inspector and reconciliation suites pass (52 files, 467 tests, 1 skipped); the domain tests pass (6).
  • npm run check: typecheck, lint (0 errors), knip, metadata:check and architecture guards pass. format:check flagged only untracked local build output outside this diff; oxfmt --check on the 22 changed files passes.
  • npm run docs:check: passes.
  • npm run test:focused -- all tests/boundary/browser/*.test.ts, plus cli/browserCli, cli/electronCli, cli/browserRedirectShapeCompleteness, mcp/browserMcp, mcp/electronMcp, mcp/browserComparisonInput and inspector/javascriptRuntimeObservation: 48 files, 431 tests pass.
  • npm run test:focused -- the two JavaScript runtime reconciliation boundary suites: 13 tests pass.
  • npm run test:local -- 25 related browser, web, contract and Evidence source suites: 255 tests pass.
  • REA_BROWSER_EXECUTABLE=/usr/bin/google-chrome npm run verify:browser (Chrome 138.0.7204.157, headless, Linux): the new browser-socket step passes. The run then stops in the existing scenario launch-storage step (browser-scenario-storage-e2e.mjs: expected seeded storage values, got null). Unmodified upstream/main fails with the same assertion on this host, so the steps after it ran on neither revision. Run alone against the same Chrome, the browser-socket step returned {"targets":1,"revision":"@e533e98b1267baa1f1c46d666b120e64e5146aa9"}. Re-run after the capture-parity assertions were added: the step passes, and the lane stops at the same existing storage assertion.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Existing HTTP endpoints, results and Evidence are unchanged.
  • Real Hopper/Ghidra, browser, or OS coverage: real Google Chrome 138.0.7204.157 (headless) on Linux through npm run verify:browser.
  • Package or release metadata impact: none.
  • Agent and analysis cost: the MCP tools/list payload grows from 2,462,734 to 2,463,786 bytes (+1,052, about 0.04%), from the cdp_endpoint description on the six tools (14 schema occurrences). Tokens were not measured; at about 4 bytes per token that is roughly 260 tokens, an estimate. HTTP discovery calls run the same code path as before. Elapsed time, CPU and memory for the socket path were not benchmarked.
  • Security, privacy, process, or containment review: the socket id is treated as a transport credential and kept out of Evidence and errors. Loopback-only rules are unchanged. With the toggle, the user attaches to an existing profile, so the docs recommend --allowed-origins when listing targets. Chrome's own consent dialog still applies.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

Refs #2288


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/2346 **Author:** [@all-black-493](https://github.com/all-black-493) **Created:** 10/12/2026 **Status:** ✅ Merged **Merged:** 10/13/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `feat/browser-websocket-endpoint` --- ### 📝 Commits (3) - [`4efd6e4`](https://github.com/morluto/rea/commit/4efd6e48ba60bd5f2d37510ba0a65d9e06674989) feat(browser): attach passive tools to browsers without HTTP discovery - [`4706bb9`](https://github.com/morluto/rea/commit/4706bb9f4d452c2bc79362151d4651fc251029a4) test(browser): match browser-socket captures against HTTP discovery - [`616f8f8`](https://github.com/morluto/rea/commit/616f8f84de0419ec51bb5102fa4ea61a345be4a9) fix(browser): bound browser-socket handshake and report discovery timeouts ### 📊 Changes **22 files changed** (+960 additions, -179 deletions) <details> <summary>View changed files</summary> 📝 `docs/browser-observation.md` (+48 -3) ➕ `scripts/lib/browser-socket-e2e.mjs` (+100 -0) 📝 `scripts/verify-real-browser.mjs` (+9 -0) 📝 `src/application/BrowserEvidence.ts` (+1 -1) 📝 `src/browser/CdpBrowserProvider.ts` (+96 -132) 📝 `src/browser/CdpEndpoint.ts` (+103 -0) 📝 `src/browser/CdpTargetSession.ts` (+67 -0) 📝 `src/cli/browserAdvancedCommands.ts` (+6 -2) 📝 `src/cli/browserCommands.ts` (+12 -4) 📝 `src/domain/browserObservation.test.ts` (+54 -0) 📝 `src/domain/browserObservation.ts` (+103 -24) 📝 `src/domain/browserSession.ts` (+2 -2) 📝 `src/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.ts` (+11 -3) 📝 `src/domain/webMcpDiscovery.ts` (+2 -2) 📝 `src/domain/webScreenshot.ts` (+2 -2) ➕ `tests/boundary/browser/cdpBrowserProvider.browserSocket.test.ts` (+232 -0) 📝 `tests/boundary/browser/cdpBrowserProvider.targetInventory.test.ts` (+7 -4) 📝 `tests/boundary/cli/browserCli.test.ts` (+48 -0) 📝 `tests/boundary/mcp/browserMcp.test.ts` (+41 -0) 📝 `tests/fixtures/fakeCdpBrowser.ts` (+3 -0) _...and 2 more files_ </details> ### 📄 Description ## Summary Implements option 2 from #2288. The passive browser tools can now attach to a browser that serves a loopback browser WebSocket but no HTTP discovery. Before this change, every passive call read `/json/version` and `/json/list` first, so such a browser failed with `endpoint_unreachable`. The maintainer scope decision for #2288 is still pending. This PR is open for review, but per CONTRIBUTING it should not be merged until that decision covers it. The proposal and evidence are in [this comment](https://github.com/morluto/rea/issues/2288#issuecomment-6131623884). ## Problem and expected behavior Since Chrome 136, `--remote-debugging-port` is ignored for the default profile ([Chrome blog](https://developer.chrome.com/blog/remote-debugging-port)). Chrome 144+ can instead enable remote debugging on a running browser from `chrome://inspect/#remote-debugging` ([Chrome blog](https://developer.chrome.com/blog/chrome-devtools-mcp-debug-your-browser-session)). A third-party report ([trycua/cua#2916](https://github.com/trycua/cua/issues/2916), Chrome 151) says this mode writes the port and a `/devtools/browser/<id>` path to `DevToolsActivePort` and returns 404 for `/json/version`. Expected: a caller can pass `ws://127.0.0.1:PORT/devtools/browser/<id>` and get the same targets and inspection results as HTTP discovery. ## Change and scope - **Endpoint contract.** `cdp_endpoint` on the six passive tools also accepts `ws://127.0.0.1:PORT/devtools/browser/<id>` or `ws://[::1]:PORT/...`. The port must be explicit, the id one path segment, and credentials, query and fragment are rejected. The HTTP form is unchanged. `localhost`, LAN, `wss:` and `/devtools/page/` sockets stay invalid. The domain parses the endpoint once into `{ transport, url, recorded }`. - **Tools.** `list_browser_targets`, `inspect_web_page`, `analyze_web_bundle`, `observe_web_session`, `discover_webmcp_tools`, `capture_web_screenshot`. Electron, web runtime, scenario attach and V8 Inspector endpoints keep `browserEndpointSchema` and stay HTTP-only. - **One socket per call.** Socket discovery sends `Browser.getVersion` and `Target.getTargets`, then the target session adopts the same socket for `Target.attachToTarget` (flat). Consent is reportedly requested per WebSocket upgrade, so a second socket would prompt twice. Unadopted sockets are closed on failure and on cancellation. - **Evidence redaction.** Chrome refuses a browser-socket upgrade with the wrong id (HTTP 404, checked on Chrome 138), so the id gates access. Evidence records `ws://127.0.0.1:PORT/devtools/browser/[REDACTED]`. JavaScript runtime reconciliation accepts that recorded form for browser captures. HTTP-endpoint Evidence is unchanged. - **Refactor.** `CdpBrowserProvider` repeated the same discover → authorize → session → cleanup block in five operations. All five needed the new transport, so they now share one `withTargetSession` helper. Not included: reading `DevToolsActivePort` for the caller, a pipe transport (option 3), or anything that launches a browser. #2287 separately documents option 1. Follow the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope). The scope decision is pending in #2288. ## Contract and boundary impact - Semantic owner and earliest changed stage: `browserObservationEndpointSchema` in `src/domain/browserObservation.ts`; transport selection in `src/browser/CdpTargetSession.ts`. - Contribution scope fit and linked maintainer decision: pending in #2288. Passive, attach-only; no new launch, execution or mutation authority. - CLI and MCP/tool-catalog contract: additive. The six tools accept a second `cdp_endpoint` form. The MCP description and CLI `endpoint` help name it. The advertised JSON Schema type is unchanged (string). - Provider, bridge, target-format, or platform compatibility: Chromium-family browsers exposing a loopback browser socket. With a socket, `browser.revision` is `Browser.getVersion`'s value (`@<hash>`) instead of `WebKit-Version` (`537.36 (@<hash>)`). `attached` is a boolean where Chrome's `/json/list` omits it and HTTP discovery reports `null`. Both are documented. - Evidence, artifact, provenance, or reconstruction contract: `parameters.cdp_endpoint` is the redacted socket URL for socket calls; unchanged for HTTP calls. - Target selection, authority, upstream behavior, and cleanup details: same target authorization and origin scoping as HTTP discovery. REA never closes the browser or a page; it closes only its socket. - Generated metadata, package, or installation impact: none. No skill change. Expected effects: - [ ] Read existing files or captured data. - [x] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. The attach is the existing passive CDP attach, over a different loopback transport. ## Evidence and regression coverage - Tests added or updated: - `src/domain/browserObservation.test.ts`: accepted socket forms, recorded redaction, and rejected shapes (implicit port, `localhost`, `wss:`, credentials, query, fragment, empty or nested id, page socket). - `tests/boundary/browser/cdpBrowserProvider.browserSocket.test.ts`: socket discovery matches HTTP discovery; inspection uses one socket and makes no HTTP requests; the socket closes on a missing target, malformed `Browser.getVersion`, and cancellation; a refused socket is `endpoint_unreachable` without echoing the id. - `tests/boundary/cli/browserCli.test.ts`, `tests/boundary/mcp/browserMcp.test.ts`: public CLI/MCP calls with a socket record the redacted endpoint. MCP reconciliation accepts that Evidence, and the advertised description names the socket form. - `scripts/lib/browser-socket-e2e.mjs`, wired into `npm run verify:browser`. On real Chrome it checks that `DevToolsActivePort` names the same socket as `/json/version`, and that socket discovery matches HTTP discovery. It also checks that a public CLI inspection through the socket records redacted Evidence and compares `unchanged` for DOM structure and scripts against an HTTP-discovery inspection. - The fake CDP browser answers `Browser.getVersion` with Chrome's reply shape and counts opened sockets. - Issue success check (#2288, option 2), run manually on the notes-web demo (`website/public/examples/notes-web/` served on `127.0.0.1`). Chrome 138.0.7204.157 was started with an explicit `--remote-debugging-port` and a dedicated `--user-data-dir`. Only `/json/version`'s `webSocketDebuggerUrl` was passed to the compiled CLI, and the result was compared with HTTP discovery: - `list-browser-targets`: the same target, title, URL and origin. The only difference is `attached` (`null` through HTTP, because Chrome's `/json/list` omits it; `false` through the socket). - `inspect-web-page --include-script-sources --observation-ms 1000`: identical apart from `target.attached`. Both returned the same three scripts (`assets/main.js`, `assets/i18n.js`, `examples/notes-web/export.js`) with identical source SHA-256 digests, 72 DOM nodes, an empty `network.requests`, and the same `attach_limited_sections`. - `compare-web-captures` (HTTP vs socket): `dom_structure`, `scripts` and `resources` are `unchanged`. `network`, `metadata`, `webmcp`, `accessibility` and `storage` are `unknown`, as for any two attach-window captures. - Recorded endpoints: `http://127.0.0.1:<port>` and `ws://127.0.0.1:<port>/devtools/browser/[REDACTED]`. The socket id appears in no CLI output. - Base reproduction: on `upstream/main`, `rea list-browser-targets ws://127.0.0.1:PORT/devtools/browser/<id>` fails input validation, because `cdp_endpoint` must be an explicit-port HTTP URL. Without HTTP discovery, no accepted endpoint exists. - User-visible CLI/MCP output: real Chrome 138, `rea list-browser-targets ws://127.0.0.1:<port>/devtools/browser/<id> --allowed-origins http://127.0.0.1:<site> --json` (trimmed): ```json { "operation": "list_browser_targets", "parameters": { "cdp_endpoint": "ws://127.0.0.1:<port>/devtools/browser/[REDACTED]", "allowed_origins": ["http://127.0.0.1:<site>"] }, "normalized_result": { "browser": { "product": "Chrome/138.0.7204.157", "protocol_version": "1.3", "revision": "@e533e98b1267baa1f1c46d666b120e64e5146aa9", "js_version": "13.8.258.26" }, "targets": [ { "type": "page", "title": "REA browser verifier", "url": "http://127.0.0.1:<site>/app", "origin": "http://127.0.0.1:<site>", "attached": false } ], "excluded": { "disallowed_origin": 0, "unsupported_url": 0, "non_page": 4 } } } ``` The socket id does not appear anywhere in stdout. - Remaining proof gaps: - Not tested against the `chrome://inspect` toggle itself; the local Chrome is 138. The socket-only behavior and per-connection consent come from the third-party report above. - Other Chromium-family browsers (Brave, Edge) were not checked over the socket. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - Review fixes (head `616f8f84d`): the browser-socket WebSocket handshake now runs inside the 10-second discovery deadline, and a reached deadline projects as `provider_timeout` rather than `cancelled`. New boundary tests cover a stalled discovery reply and a handshake that never completes. `check:fast` passes; `tests/boundary/browser` plus the browser CLI and MCP suites pass (45 files, 417 tests, 1 skipped). - Rebased on `4276aaf18` (head `4706bb9f4`). The only conflict was with #951b095e1, which bounded HTTP discovery responses to 8 MiB and 10 seconds. Browser-socket discovery now shares that 10-second deadline (`timeout` reason, caller cancellation preserved, boundary test added). Each socket reply stays bounded by the 64 MiB protocol message limit. After the rebase: `check:fast` passes; all `tests/boundary/browser` files plus the browser/Electron CLI and MCP, Inspector and reconciliation suites pass (52 files, 467 tests, 1 skipped); the domain tests pass (6). - `npm run check`: typecheck, lint (0 errors), knip, `metadata:check` and architecture guards pass. `format:check` flagged only untracked local build output outside this diff; `oxfmt --check` on the 22 changed files passes. - `npm run docs:check`: passes. - `npm run test:focused --` all `tests/boundary/browser/*.test.ts`, plus `cli/browserCli`, `cli/electronCli`, `cli/browserRedirectShapeCompleteness`, `mcp/browserMcp`, `mcp/electronMcp`, `mcp/browserComparisonInput` and `inspector/javascriptRuntimeObservation`: 48 files, 431 tests pass. - `npm run test:focused --` the two JavaScript runtime reconciliation boundary suites: 13 tests pass. - `npm run test:local --` 25 related browser, web, contract and Evidence source suites: 255 tests pass. - `REA_BROWSER_EXECUTABLE=/usr/bin/google-chrome npm run verify:browser` (Chrome 138.0.7204.157, headless, Linux): the new browser-socket step passes. The run then stops in the existing scenario launch-storage step (`browser-scenario-storage-e2e.mjs`: expected seeded storage values, got `null`). Unmodified `upstream/main` fails with the same assertion on this host, so the steps after it ran on neither revision. Run alone against the same Chrome, the browser-socket step returned `{"targets":1,"revision":"@e533e98b1267baa1f1c46d666b120e64e5146aa9"}`. Re-run after the capture-parity assertions were added: the step passes, and the lane stops at the same existing storage assertion. ## Compatibility, safety, and release - Breaking changes or migration steps: none. Existing HTTP endpoints, results and Evidence are unchanged. - Real Hopper/Ghidra, browser, or OS coverage: real Google Chrome 138.0.7204.157 (headless) on Linux through `npm run verify:browser`. - Package or release metadata impact: none. - Agent and analysis cost: the MCP `tools/list` payload grows from 2,462,734 to 2,463,786 bytes (+1,052, about 0.04%), from the `cdp_endpoint` description on the six tools (14 schema occurrences). Tokens were not measured; at about 4 bytes per token that is roughly 260 tokens, an estimate. HTTP discovery calls run the same code path as before. Elapsed time, CPU and memory for the socket path were not benchmarked. - Security, privacy, process, or containment review: the socket id is treated as a transport credential and kept out of Evidence and errors. Loopback-only rules are unchanged. With the toggle, the user attaches to an existing profile, so the docs recommend `--allowed-origins` when listing targets. Chrome's own consent dialog still applies. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. Refs #2288 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:04:35 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#5179
No description provided.