[PR #986] [MERGED] fix(browser): preserve authorized redirect hops #2556

Closed
opened 2026-10-17 21:07:32 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/986
Author: @morluto
Created: 10/7/2026
Status: ✅ Merged
Merged: 10/7/2026
Merged by: @morluto

Base: main ← Head: codex/browser-redirect-hops-pr


📝 Commits (10+)

  • 54c0465 fix(browser): preserve authorized redirect hops
  • 5c605a5 fix(browser): compare redirect semantics without event times
  • 4879fbd fix(browser): classify missing redirect predecessors
  • ee89eb8 fix(browser): distinguish malformed redirect URLs
  • 3ab21e9 Merge commit '98b2b027af' into codex/browser-redirect-hops-publish
  • 64236b6 fix(browser): preserve evidence on malformed redirect envelopes
  • 5c43252 fix(browser): freeze evidence after malformed redirect
  • 4e5950a Merge remote-tracking branch 'origin/main' into codex/browser-redirect-hops-publish
  • 2458965 docs: regenerate catalogs after main integration
  • de6a6a5 fix(browser): account for skipped redirect body shapes

📊 Changes

16 files changed (+798 additions, -12 deletions)

View changed files

📝 docs/browser-observation.md (+1 -1)
📝 docs/product-catalog.json (+2 -2)
📝 docs/verification/managed-conformance-manifest.json (+2 -2)
📝 skills/reverse-engineer-anything/SKILL.md (+1 -1)
📝 src/browser/CdpCaptureEventHandlers.ts (+102 -2)
📝 src/browser/CdpCaptureEventState.ts (+2 -0)
📝 src/browser/CdpCaptureEvents.ts (+9 -0)
📝 src/domain/browserObservationSchemas.ts (+15 -0)
📝 src/domain/webCaptureDiff.ts (+7 -0)
📝 tests/boundary/browser/cdpBrowserProvider.network.test.ts (+91 -0)
➕ tests/boundary/browser/cdpBrowserProvider.redirectBodyShapeLedger.test.ts (+66 -0)
➕ tests/boundary/browser/cdpBrowserProvider.redirectErrors.test.ts (+150 -0)
📝 tests/boundary/browser/webCaptureDiff.test.ts (+78 -1)
➕ tests/boundary/cli/browserRedirectShapeCompleteness.test.ts (+113 -0)
📝 tests/fixtures/fakeCdpBrowserEvents.ts (+153 -3)
📝 tests/fixtures/fakeCdpBrowserTypes.ts (+6 -0)

📄 Description

inspect_web_page previously replaced a CDP request record when Network.requestWillBeSent reported a redirect with the same request ID, dropping the earlier URL and redirect response. It now exposes authorized hops as an additive optional network.requests[].redirects array while leaving the final request fields unchanged and preserving one record per CDP request ID.

A hop includes the prior request URL and CDP response URL, method and resource type, response status/MIME/encoded length, the prior request timestamp, and the timestamp of the following requestWillBeSent event. That last timestamp marks when CDP reports redirectResponse; it is not a response duration. Hops and their metadata are retained only when their URLs pass the configured origin authorization. Cross-origin request chains are excluded, including redirect metadata for an excluded prior hop. Redirect response headers and bodies are never retained.

Example (abbreviated):

{
  "request_id": "CDP_REQUEST_ID",
  "url": "http://127.0.0.1:PORT/landing",
  "status": 200,
  "redirects": [
    {
      "url": "http://127.0.0.1:PORT/start",
      "response_url": "http://127.0.0.1:PORT/start",
      "method": "GET",
      "resource_type": "Fetch",
      "status": 302,
      "mime_type": "text/plain",
      "encoded_data_length": 176,
      "request_timestamp": 123.45,
      "redirect_event_timestamp": 123.46
    }
  ]
}

Capture comparison ignores the two CDP event timestamps while comparing hop order, URLs, methods, resource types, statuses, MIME types, and encoded lengths. Thus timing-only changes do not alter the network comparison, while changed redirect behavior remains visible. Captured inspections still retain the timestamps.

Redirect predecessor diagnostics distinguish policy-filtered URLs from malformed protocol data: an excluded origin is reported as filtered without retaining its URL, while missing or unparsable redirect URLs are reported as invalid protocol values and valid unsupported schemes as unsupported URLs. When a present redirect envelope is not an object, REA marks network evidence unavailable and preserves the previously observed authorized request for that CDP ID. Later response, loading, or response-body events for that ID cannot overwrite it.

Validation:

  • Focused browser network, redirect error, capture diff, CLI parity, and MCP parity tests: 23 passed, including ordered redirects, cross-origin filtering, excluded-origin return, malformed/missing/unsupported URL classification, malformed null/array/scalar envelope handling, late same-ID response/loading events, and comparison semantics.
  • npm run build:cached, npm run check:fast, npm run format:check, and npm run docs:check passed after integration with current main (504737300632d8644fbd6c658d2c97e38bb54c3b).
  • Real Chrome 154 verification used owned loopback HTTP fixtures only: same-origin 302→200 redirects retained the prior hop on each final request; a redirect to a different loopback origin produced no redirect-chain request data. This verifies the redirect behavior in that fixture, not general browser runtime behavior.
  • The generated MCP tool catalog, product catalog, conformance manifest, and skill catalog digest were regenerated from the source contract.

🔄 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/986 **Author:** [@morluto](https://github.com/morluto) **Created:** 10/7/2026 **Status:** ✅ Merged **Merged:** 10/7/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `codex/browser-redirect-hops-pr` --- ### 📝 Commits (10+) - [`54c0465`](https://github.com/morluto/rea/commit/54c046583e7ce2def36d6312f2fe13c0e985a0fd) fix(browser): preserve authorized redirect hops - [`5c605a5`](https://github.com/morluto/rea/commit/5c605a508f5fe113bae51770ee8aad3e51f827e0) fix(browser): compare redirect semantics without event times - [`4879fbd`](https://github.com/morluto/rea/commit/4879fbdfe654fcd0ba1785d5f9eee4fd090e9d87) fix(browser): classify missing redirect predecessors - [`ee89eb8`](https://github.com/morluto/rea/commit/ee89eb86e1c2f5f3d07984ff093eddae44f7b945) fix(browser): distinguish malformed redirect URLs - [`3ab21e9`](https://github.com/morluto/rea/commit/3ab21e9d428738da47e17c27b39682a805e2c0c3) Merge commit '98b2b027afd8c80b68e9daaf97bdaa4d942105cc' into codex/browser-redirect-hops-publish - [`64236b6`](https://github.com/morluto/rea/commit/64236b681cb5b99ed42dc83e5d6563506eeb5db9) fix(browser): preserve evidence on malformed redirect envelopes - [`5c43252`](https://github.com/morluto/rea/commit/5c432523f41e70866107c2e2297bb9ba36882b6c) fix(browser): freeze evidence after malformed redirect - [`4e5950a`](https://github.com/morluto/rea/commit/4e5950adb803785e93a6d575df33f36e3710cece) Merge remote-tracking branch 'origin/main' into codex/browser-redirect-hops-publish - [`2458965`](https://github.com/morluto/rea/commit/2458965aa0c97b01a0ff54852526cb2222d84ce0) docs: regenerate catalogs after main integration - [`de6a6a5`](https://github.com/morluto/rea/commit/de6a6a532ac5a205ac7a1d5384d2d85e8bd903f3) fix(browser): account for skipped redirect body shapes ### 📊 Changes **16 files changed** (+798 additions, -12 deletions) <details> <summary>View changed files</summary> 📝 `docs/browser-observation.md` (+1 -1) 📝 `docs/product-catalog.json` (+2 -2) 📝 `docs/verification/managed-conformance-manifest.json` (+2 -2) 📝 `skills/reverse-engineer-anything/SKILL.md` (+1 -1) 📝 `src/browser/CdpCaptureEventHandlers.ts` (+102 -2) 📝 `src/browser/CdpCaptureEventState.ts` (+2 -0) 📝 `src/browser/CdpCaptureEvents.ts` (+9 -0) 📝 `src/domain/browserObservationSchemas.ts` (+15 -0) 📝 `src/domain/webCaptureDiff.ts` (+7 -0) 📝 `tests/boundary/browser/cdpBrowserProvider.network.test.ts` (+91 -0) ➕ `tests/boundary/browser/cdpBrowserProvider.redirectBodyShapeLedger.test.ts` (+66 -0) ➕ `tests/boundary/browser/cdpBrowserProvider.redirectErrors.test.ts` (+150 -0) 📝 `tests/boundary/browser/webCaptureDiff.test.ts` (+78 -1) ➕ `tests/boundary/cli/browserRedirectShapeCompleteness.test.ts` (+113 -0) 📝 `tests/fixtures/fakeCdpBrowserEvents.ts` (+153 -3) 📝 `tests/fixtures/fakeCdpBrowserTypes.ts` (+6 -0) </details> ### 📄 Description `inspect_web_page` previously replaced a CDP request record when `Network.requestWillBeSent` reported a redirect with the same request ID, dropping the earlier URL and redirect response. It now exposes authorized hops as an additive optional `network.requests[].redirects` array while leaving the final request fields unchanged and preserving one record per CDP request ID. A hop includes the prior request URL and CDP response URL, method and resource type, response status/MIME/encoded length, the prior request timestamp, and the timestamp of the following `requestWillBeSent` event. That last timestamp marks when CDP reports `redirectResponse`; it is not a response duration. Hops and their metadata are retained only when their URLs pass the configured origin authorization. Cross-origin request chains are excluded, including redirect metadata for an excluded prior hop. Redirect response headers and bodies are never retained. Example (abbreviated): ```json { "request_id": "CDP_REQUEST_ID", "url": "http://127.0.0.1:PORT/landing", "status": 200, "redirects": [ { "url": "http://127.0.0.1:PORT/start", "response_url": "http://127.0.0.1:PORT/start", "method": "GET", "resource_type": "Fetch", "status": 302, "mime_type": "text/plain", "encoded_data_length": 176, "request_timestamp": 123.45, "redirect_event_timestamp": 123.46 } ] } ``` Capture comparison ignores the two CDP event timestamps while comparing hop order, URLs, methods, resource types, statuses, MIME types, and encoded lengths. Thus timing-only changes do not alter the network comparison, while changed redirect behavior remains visible. Captured inspections still retain the timestamps. Redirect predecessor diagnostics distinguish policy-filtered URLs from malformed protocol data: an excluded origin is reported as filtered without retaining its URL, while missing or unparsable redirect URLs are reported as invalid protocol values and valid unsupported schemes as unsupported URLs. When a present redirect envelope is not an object, REA marks network evidence unavailable and preserves the previously observed authorized request for that CDP ID. Later response, loading, or response-body events for that ID cannot overwrite it. Validation: - Focused browser network, redirect error, capture diff, CLI parity, and MCP parity tests: 23 passed, including ordered redirects, cross-origin filtering, excluded-origin return, malformed/missing/unsupported URL classification, malformed null/array/scalar envelope handling, late same-ID response/loading events, and comparison semantics. - `npm run build:cached`, `npm run check:fast`, `npm run format:check`, and `npm run docs:check` passed after integration with current `main` (`504737300632d8644fbd6c658d2c97e38bb54c3b`). - Real Chrome 154 verification used owned loopback HTTP fixtures only: same-origin 302→200 redirects retained the prior hop on each final request; a redirect to a different loopback origin produced no redirect-chain request data. This verifies the redirect behavior in that fixture, not general browser runtime behavior. - The generated MCP tool catalog, product catalog, conformance manifest, and skill catalog digest were regenerated from the source contract. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:07:32 +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#2556
No description provided.