[GH-ISSUE #2600] fix(browser): classify expanded SAZ input limits as input errors #918

Closed
opened 2026-10-15 18:29:33 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @coygeek on GitHub (Oct 13, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2600

Summary

Inspecting a small compressed SAZ file whose members exceed the documented 32 MiB expanded-content budget produces the classification for unreadable decoder output. Source establishes that callers receive execution_failure instead of invalid_input, although the selected producer archive is what exceeds the limit. The rejection remains safe and returns no partial capture.

Steps to reproduce

Use a checkout of the source baseline under Runtime or environment with Node.js and Python 3. Install its locked dependencies and prepare its compiled runtime with the commands below, then create a regular SAZ file containing a valid request member and a genuinely compressed 33 MiB non-session member with the following fixture command.

npm ci
npm run build:cached
python3 - <<'PYZIP'
import zipfile
with zipfile.ZipFile('expanded.saz', 'w', compression=zipfile.ZIP_DEFLATED) as archive:
    archive.writestr('raw/1_c.txt', b'GET / HTTP/1.1\r\nHost: example.test\r\n\r\n')
    archive.writestr('padding.bin', bytes(33 * 1024 * 1024))
PYZIP
node scripts/rea.mjs inspect-web-network-capture "$PWD/expanded.saz" saz --json

The build and CLI steps were not executed in this verification. A focused source test created the equivalent intact ZIP using the installed ZIP package, observed an archive size of 33973 bytes, and executed the SAZ decoder. The public classification below follows from the production reply and error mapping.

Expected behavior

An archive exceeding the expanded producer-input budget should return an input error that identifies the selected capture path and the expanded byte budget. Errors caused by the owned decoder's reply size should remain output errors. Neither case should return partial success.

Actual behavior

The focused decoder probe rejected the intact archive with reason limit and message "SAZ expanded members exceed the 32 MiB complete-evidence budget." Source establishes that the parent converts that reply into unreadable_output with category execution_failure. The resulting error does not identify the selected capture path. The end-to-end CLI classification was not reproduced at runtime.

Evidence

  • Expected source: docs/web-network-captures.md:113-114 documents the expanded-content budget; docs/web-network-captures.md:290-294 requires oversized captures to return input errors identifying capture_path and the byte budget.
  • Failure source: src/browser/history/SazCapture.ts:31-57 emits limit for expanded producer data; src/browser/history/NodeCaptureProcess.ts:46-62 preserves that reason; src/browser/history/HistoricalCaptureDecoder.ts:153-190 maps it to AnalysisOutputError, whose public classification is defined in src/domain/analysisErrorProjection.ts:194.
  • Evidence provenance: static
  • Local verification: static-proof
  • Reproduction completeness: complete

Runtime reproduction of the public classification was not run. The source path is reachable because the compressed regular file is below the acquisition limit, Node supplies the required heap bound, the valid ok:false reply permits the limit reason, and none of the format, input-limit, resource-limit, decoder, or unsupported cases matches. Successful process and private-root cleanup preserve the typed output error. The focused probe directly observed the decoder-side reason; the remaining production transitions are source evidence. The existing expanded-limit boundary case in tests/boundary/browser/sazWebCapture.test.ts:471-486 also expects unreadable_output, so that expectation conflicts with the documented input contract.

Restoration check

Inspect the same intact compressed archive and require invalid_input, an out-of-range input issue, and the selected path plus expanded-content byte limit. Confirm that no partial capture is returned. A genuine oversized decoder reply must still produce an output failure, and a capture file above the acquisition byte budget must retain its input-error classification.

Runtime or environment

Source baseline 8b181716ac. The focused probe used Node.js v26.10.0, npm 11.19.1, and the installed lockfile dependencies.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Expanded producer inputs receive the wrong machine-readable error category, so callers cannot use the documented input-error path for recovery or routing. The archive is still rejected without partial results; the defect is bounded to inputs above the expanded-content limit.
  • Workaround status: available
  • Workaround basis: The returned message states the expanded-content budget, and callers retain their selected path, so they can diagnose this case from the request and message while the error code is incorrect.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2600 ## Summary Inspecting a small compressed SAZ file whose members exceed the documented 32 MiB expanded-content budget produces the classification for unreadable decoder output. Source establishes that callers receive execution_failure instead of invalid_input, although the selected producer archive is what exceeds the limit. The rejection remains safe and returns no partial capture. ## Steps to reproduce Use a checkout of the source baseline under Runtime or environment with Node.js and Python 3. Install its locked dependencies and prepare its compiled runtime with the commands below, then create a regular SAZ file containing a valid request member and a genuinely compressed 33 MiB non-session member with the following fixture command. ```sh npm ci npm run build:cached python3 - <<'PYZIP' import zipfile with zipfile.ZipFile('expanded.saz', 'w', compression=zipfile.ZIP_DEFLATED) as archive: archive.writestr('raw/1_c.txt', b'GET / HTTP/1.1\r\nHost: example.test\r\n\r\n') archive.writestr('padding.bin', bytes(33 * 1024 * 1024)) PYZIP node scripts/rea.mjs inspect-web-network-capture "$PWD/expanded.saz" saz --json ``` The build and CLI steps were not executed in this verification. A focused source test created the equivalent intact ZIP using the installed ZIP package, observed an archive size of 33973 bytes, and executed the SAZ decoder. The public classification below follows from the production reply and error mapping. ## Expected behavior An archive exceeding the expanded producer-input budget should return an input error that identifies the selected capture path and the expanded byte budget. Errors caused by the owned decoder's reply size should remain output errors. Neither case should return partial success. ## Actual behavior The focused decoder probe rejected the intact archive with reason limit and message "SAZ expanded members exceed the 32 MiB complete-evidence budget." Source establishes that the parent converts that reply into unreadable_output with category execution_failure. The resulting error does not identify the selected capture path. The end-to-end CLI classification was not reproduced at runtime. ## Evidence - Expected source: docs/web-network-captures.md:113-114 documents the expanded-content budget; docs/web-network-captures.md:290-294 requires oversized captures to return input errors identifying capture_path and the byte budget. - Failure source: src/browser/history/SazCapture.ts:31-57 emits limit for expanded producer data; src/browser/history/NodeCaptureProcess.ts:46-62 preserves that reason; src/browser/history/HistoricalCaptureDecoder.ts:153-190 maps it to AnalysisOutputError, whose public classification is defined in src/domain/analysisErrorProjection.ts:194. - Evidence provenance: static - Local verification: static-proof - Reproduction completeness: complete Runtime reproduction of the public classification was not run. The source path is reachable because the compressed regular file is below the acquisition limit, Node supplies the required heap bound, the valid ok:false reply permits the limit reason, and none of the format, input-limit, resource-limit, decoder, or unsupported cases matches. Successful process and private-root cleanup preserve the typed output error. The focused probe directly observed the decoder-side reason; the remaining production transitions are source evidence. The existing expanded-limit boundary case in tests/boundary/browser/sazWebCapture.test.ts:471-486 also expects unreadable_output, so that expectation conflicts with the documented input contract. ## Restoration check Inspect the same intact compressed archive and require invalid_input, an out-of-range input issue, and the selected path plus expanded-content byte limit. Confirm that no partial capture is returned. A genuine oversized decoder reply must still produce an output failure, and a capture file above the acquisition byte budget must retain its input-error classification. ## Runtime or environment Source baseline 8b181716aca2cb467be499cba226abfb5ae19141. The focused probe used Node.js v26.10.0, npm 11.19.1, and the installed lockfile dependencies. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: Expanded producer inputs receive the wrong machine-readable error category, so callers cannot use the documented input-error path for recovery or routing. The archive is still rejected without partial results; the defect is bounded to inputs above the expanded-content limit. - Workaround status: available - Workaround basis: The returned message states the expanded-content budget, and callers retain their selected path, so they can diagnose this case from the request and message while the error code is incorrect.
bsakaguchi 2026-10-15 18:29:33 +00:00
Author
Owner

@morluto commented on GitHub (Oct 14, 2026):

Addressed on main in 29a2d13994708789fa3104437f1f2f93c6a34c36.

Expanded capture/decompression limits have a distinct tagged failure mapped to the input expansion budget, preserving decoder output-limit semantics.

Validation: Affected suites passed in the merged 65-file run (1169 passed, 2 explicit skips), with full static/architecture checks and documentation checks passing. Final installed-package verification is recorded separately in the audit.

Verification scope: Controlled source and production-boundary verification on macOS with pinned Node 24.18.0; real external engines and Windows hosts were not independently rerun. Closure covers the described source defect, not broader provider conformance or performance.

<!-- gh-comment-id:6159217573 --> @morluto commented on GitHub (Oct 14, 2026): Addressed on main in [29a2d13994708789fa3104437f1f2f93c6a34c36](https://github.com/morluto/rea/commit/29a2d13994708789fa3104437f1f2f93c6a34c36). Expanded capture/decompression limits have a distinct tagged failure mapped to the input expansion budget, preserving decoder output-limit semantics. Validation: Affected suites passed in the merged 65-file run (1169 passed, 2 explicit skips), with full static/architecture checks and documentation checks passing. Final installed-package verification is recorded separately in the audit. Verification scope: Controlled source and production-boundary verification on macOS with pinned Node 24.18.0; real external engines and Windows hosts were not independently rerun. Closure covers the described source defect, not broader provider conformance or performance.
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#918
No description provided.