From cd77bc3d9f148a7c7b80a5cf19e974ed5285c0e2 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Oct 2026 06:59:32 +0000 Subject: [PATCH] test: synchronize access browser navigation and shutdown --- .../access-browser-ci-20261020/acceptance.md | 68 +++++++ .../actual-access.log | 3 + .../access-browser-ci-20261020/cleanup.json | 17 ++ .../independent-review.json | 171 ++++++++++++++++++ .../independent-source-review.json | 75 ++++++++ .../original-failure-disposition.json | 113 ++++++++++++ .../original-failure-excerpt.log | 32 ++++ .../post-run-cleanup.json | 35 ++++ .../qualification.json | 114 ++++++++++++ .../access-browser-ci-20261020/receipt.json | 47 +++++ .../runner-receipt.json | 17 ++ .../schema-reservation.json | 7 + .../session-1280.jpg | Bin 0 -> 92512 bytes .../session-390.jpg | Bin 0 -> 46763 bytes tests/browser_access.cjs | 37 +++- tests/browser_access_session.cjs | 46 +++++ tests/test_browser_access_navigation.cjs | 61 +++++++ 17 files changed, 834 insertions(+), 9 deletions(-) create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/acceptance.md create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/actual-access.log create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/cleanup.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-review.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-source-review.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-disposition.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-excerpt.log create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/post-run-cleanup.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/qualification.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/receipt.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/runner-receipt.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/schema-reservation.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-1280.jpg create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-390.jpg create mode 100644 tests/browser_access_session.cjs create mode 100644 tests/test_browser_access_navigation.cjs diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/acceptance.md b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/acceptance.md new file mode 100644 index 00000000..709f8b4b --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/acceptance.md @@ -0,0 +1,68 @@ +# Access browser navigation and shutdown qualification + +The local repair descends from PR112 at +`0dedbc953902ac89389dca0693006aaa02a0a87c` on +`fix/access-browser-ci-qualification-20261020`. Root owns subsequent serial +integration. This branch is unpublished and retained for review; no remote PR, +workflow, branch or hosting state changed. + +The implementation changes three test files only. Both the initial workbench +navigation and scoped-agent reload capture the previous main frame/loader and +wait for a changed main loader with its matching load event before reading DOM. +The helper reuses the existing CDP session and load tracker. Request, connection +and document-load waits are bounded; failure context contains phase, method and +bounded frame/loader identities without command parameters. All 14 original +assertions remain, with one added assertion selecting the explicitly launched +blank page. No authentication or product behavior changes. + +Shutdown now awaits the existing supplied-child helper before bounded removal of +the exact test profile. Primary access failures and secondary cleanup failures +retain separate labels and a nonzero outcome. Main-handle termination does not +establish an unconditional Chromium-descendant shutdown guarantee. + +## Evidence + +- [Controlled regression](../../../../../tests/test_browser_access_navigation.cjs) + reproduces the old navigation/reload acknowledgement ordering with the exact + `-32000` error. The corrected sequence issues no DOM read before the changed + main loader's load; old-loader, subframe and DOMContentLoaded events cannot + release the gate. Target closure and request/load timeout cases remain failures. + This is a controlled protocol reproduction, not the original hosted trace. +- Three syntax checks, the new regression, the existing page-load regression, + owned-child delayed-write/ignored-TERM regression and diff check passed. +- The unchanged default command `node tests/browser_access.cjs` passed against + actual existing PostgreSQL17.6, Python3.12.14, Node24.19.0 and Chromium151 in + 8.605350 seconds. It includes the new regression before its real browser journey. + [Raw log](actual-access.log), [actual receipt](receipt.json), [runner](runner-receipt.json) + and desktop/narrow screenshots retain the result. +- The initial owner login still uses an actual one-time CLI code and interactive + browser form, not a preinstalled fixture cookie. Anonymous denials, HttpOnly/code + clearing, retained drafts, no mutation replay, deliberate commit and final + scoped-agent review denial all pass. The final scoped-agent switch installs its + separately issued real credential as in the original test. +- [Cleanup](post-run-cleanup.json) records the exact preregistered schema queried + absent after disposal, zero workspace Runs, terminal supplied app/browser + handles, absent exact profile and no matching task process at observation. + Only the disposable fixture was removed; no service or package was installed + or reconfigured. Reviewer inspected these receipts, not a second PG/browser run. +- [Independent review](independent-review.json) clears source, focused checks and + actual evidence. It rechecks all three tested source hashes. The actual receipt + records precommit HEAD0ded with dirty source; file hashes bind the tested repair + bytes and must match the eventual local commit. It does not claim 0ded already + contained the repair. + +## Original failure and remaining gates + +Original run39370107550/job118455819881 remains failed at access step41. +Its [excerpt](original-failure-excerpt.log), full decoded-log SHA and source +identity are retained in [qualification](qualification.json). The log provides +no failing command/phase trace, so exact navigation versus target closure/crash +remains unproven. Cleanup ENOTEMPTY followed the primary error and is separate. +The artifact ZIP was proxy403 blocked and its contents remain uninspected. + +The running sibling CI was untouched. No cancellation, rerun, source publication, +merge or branch/worktree cleanup occurred. This local access qualification is +not a passing full repaired-head lifecycle; fresh hosted gates and independent +integration review remain necessary when publication is authorized. PUB-1 original +diagnostic evidence and SCI-1 owned criterion/compatible real lab pair remain +missing. No training, scientific, CUDA or model-quality acceptance is inferred. diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/actual-access.log b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/actual-access.log new file mode 100644 index 00000000..0515b4c7 --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/actual-access.log @@ -0,0 +1,3 @@ +PASS access navigation/reload reproduction: old acknowledgement permits failing DOM read; changed main loader plus its load gates the original assertion +PASS access phase-specific timeout/target-close failures are bounded; diagnostics omit command parameters +PASS access browser /tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332 diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/cleanup.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/cleanup.json new file mode 100644 index 00000000..ddf102bc --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/cleanup.json @@ -0,0 +1,17 @@ +{ + "temporary": "/tmp/tuldok-access-browser-7VR9Z3", + "removed": true, + "children": [ + { + "pid": 119512, + "exit_code": null, + "signal": "SIGTERM" + }, + { + "pid": 119521, + "exit_code": 0, + "signal": null + } + ], + "scope": "Supplied test-owned main handles exited before bounded profile removal" +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-review.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-review.json new file mode 100644 index 00000000..e6112e9e --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-review.json @@ -0,0 +1,171 @@ +{ + "actual_qualification_review": { + "auth_scope": "Actual default entrypoint uses ordinary CLI one-time owner login, verifies replay denial, HttpOnly/code clearance, preserved unsaved drafts, no mutation replay and explicit successful retry. Existing final scoped-agent branch deliberately installs a real issued agent credential cookie and verifies human-review controls disabled; no fixture owner-cookie bootstrap is substituted.", + "checks": { + "actual_exit_zero": true, + "all3_original_auth_checks_complete": true, + "both_new_main_loads_recorded": true, + "exact_schema_absence_recorded": true, + "exact_schema_and_path_bound": true, + "exact_temporary_absence_and_no_matching_processes_recorded": true, + "three_source_hashes_exact_review_actual_and_current": true, + "two_supplied_main_handles_terminal_and_match": true, + "zero_workspace_runs": true + }, + "cleanup_limit": "Receipts support exact preregistered schema absent,0workspaceRuns, two supplied main handles terminal before rm, exact profile absent/no taskprocess matches at recorded observation. No blanket all-Chrome-descendant guarantee.", + "command": "node tests/browser_access.cjs", + "environment": "Root reports existing Python3.12.14, PostgreSQL17.6 and Chromium151; no installation/service/config change. Version commands not independently rerun by reviewer.", + "evidence": [ + { + "bytes": 763, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/runner-receipt.json", + "sha256": "b247a3d1147a47f0304649ae2a110969c2da7c1d6e4cd5a0abe8d82430753ef9" + }, + { + "bytes": 346, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/actual-access.log", + "sha256": "ae63a93687389ad38ed33d1ecbe7fe8916db65afff8222c4a9acfe8b07f4b2f4" + }, + { + "bytes": 1433, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/post-run-cleanup.json", + "sha256": "3fefda92278099fc5e93f1c05f363277b72469535a8dbd9cd83f5832023a6fc1" + }, + { + "bytes": 1693, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332/receipt.json", + "sha256": "57b652807e1ac0e89d9f422c0c551051e33782ec779a016f0046c3ed48c6268d" + }, + { + "bytes": 341, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332/cleanup.json", + "sha256": "06b2c257bca7797d663ad809335504a2a2d56a7b41eae4edf77b2049b110538e" + }, + { + "bytes": 92512, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332/session-1280.jpg", + "sha256": "ae5ecddb60cd751033a62eb24ee383daa4d56da85439115b080178b18b5c5580" + }, + { + "bytes": 46763, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332/session-390.jpg", + "sha256": "71f975c51592a0a92669c3d5213b21561acbc83cd4450a532b9e1a2cb7907519" + } + ], + "execution_owner": "Root executed actual PostgreSQL/HTTP/Chromium journey; this reviewer inspected retained bytes/receipts, did not repeat browser/server/PG.", + "exit": 0, + "finished_utc": "2026-10-20T06:56:00.320089+00:00", + "historical_failure_limit": "No new host event trace: controlled old-red/new-green and actual successful repair do not retroactively prove original failed-host cause.", + "loader_events": [ + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "C704421B4745793C1F166C7CC67C83F8" + }, + { + "event": "main-frame", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7534733FE54346FBED7374DBFE2EEB98" + }, + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7534733FE54346FBED7374DBFE2EEB98" + }, + { + "event": "main-frame", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7B0CA169AEB6A2150994309812BCD5B7" + }, + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7B0CA169AEB6A2150994309812BCD5B7" + } + ], + "reviewed_utc": "2026-10-20T06:57:54.185655+00:00", + "seconds": 8.60535, + "source_attribution": "Actual run used base0ded checkout with reviewed modified file bytes. Three file hashes agree in source-review/currentfiles/browserreceipt/postcleanup; do not claim base0ded includes repair or a later commit was literally executed.", + "source_dirty_at_execution": true, + "source_head_at_execution": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "started_utc": "2026-10-20T06:55:51.714739+00:00" + }, + "base": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "blocking_findings": [], + "cleanup_review": { + "limit": "Existing helper confirms supplied main child handles only, not an unconditional Chrome-descendant extinction guarantee; actual fixture run and final cleanup observation pending.", + "order": "Dispose session/socket; await existing stopOwnedChildren only on supplied children; bounded recursive removal maxRetries10/retryDelay100; write terminal-main-handle receipt.", + "primary_preservation": "Original failure printed as Primary access failure and recorded phase/protocol metadata; exitCode1 set before finally. Cleanup failure separately prints Secondary access cleanup failure and retains nonzero exit." + }, + "disposition": "CLEAR within reviewed three-file test-harness source plus actual default access qualification scope; external publication/CI acceptance remain parent-owned", + "historical_failure": { + "cause_limit": "Source race is demonstrated in controlled mock protocol scheduling; original hosted execution had no phase/pointer/context trace. Target closure/crash remains unexcluded. Original failed run is not reclassified.", + "head": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "job": 118455819881, + "primary": "Inspected target navigated or closed", + "run": 39370107550, + "secondary": "ENOTEMPTY after unawaited TERM/removal" + }, + "independent_tests": { + "command": "node --check tests/browser_access.cjs && node --check tests/browser_access_session.cjs && node --check tests/test_browser_access_navigation.cjs && node tests/test_browser_access_navigation.cjs && node tests/test_browser_page_load.cjs", + "exit": 0, + "not_run_by_reviewer": [ + "Actual browser/HTTP/PostgreSQL", + "Owned-child regression(no need duplicate existingroot pass)", + "Heavy suites/CI" + ], + "results": [ + "Controlled old navigation/reload ACK\u2192departing-DOM read produces -32000", + "New helper issues zero DOM reads until changed main loader matchingload; oldloader/subframe/DOMContentLoaded insufficient", + "Navigation load timeout and targetclose fail within configured bounds", + "Request timeout and snapshots omit MUST_NOT_APPEAR command token", + "Existing fresh-document helper regression passes" + ] + }, + "limits": [ + "No product/API/domain changes; exact source diff limited to three test files.", + "No remote mutation/CI polling/source edit or server/browser execution by reviewer.", + "PUB-1 and SCI-1 unchanged.", + "Actual evidence inspected, not independently rerun; no performance claim from8.605350s descriptive single-run wall time. Parent prohibits external publication, merging, branch cleanup or environment changes." + ], + "navigation_review": { + "both_transitions": [ + "Initial Page.navigate to workbench", + "Scoped-agent Page.reload after exact cookie replacement" + ], + "diagnostics": "Bounded last12main-frame/load identities plus phase and last method; command parameters absent. contextual errors preserve underlying code/cause.", + "exact_target": "Initial page target must type page and url about:blank; connection deadline10000ms.", + "failure_boundaries": "Default CDP requests15000ms; new-load wait20000ms with25ms polling; explicit errorText/target close/error refuse. No blanket navigation-error suppression or mutation retry.", + "fresh_dom_checks": "Original session dialog/identity/Collection-ready checks remain after fresh-document gate.", + "owner": "accessSession captures Page.getFrameTree previous main id+loader before command; pageLoadTracker observes Page.frameNavigated and lifecycle load. Only changed main loader with matching load releases DOM checks." + }, + "original_assertions": { + "all14_original_calls_present_verbatim": true, + "base_calls": 14, + "current_calls": 15, + "extra": "Explicitly launched about:blank target assertion", + "preserved_semantics": [ + "Anonymous legacy/current denied writes", + "One-time CLI login consumed/code cleared/HttpOnly cookie", + "Signout and rejected mutation preserve unsaved draft", + "Reauthentication never replays original mutation", + "Only deliberate retry changes revision", + "Real scoped agent cannot use owner human-review controls", + "No runtime exceptions or application stderr" + ] + }, + "reviewed_utc": "2026-10-20T06:54:04.651464+00:00", + "source_only_review_history": { + "old_disposition": "CLEAR within test-harness source/focused-test scope; actual default PostgreSQL/Chromium access qualification remains pending", + "path": "/tmp/tuldok-access-browser-ci-independent-review-source-only.json", + "sha256": "3b8d598bd31f575c0d8b20780a275abd9b0df10d7ee8a589b21a4968eccf56e3" + }, + "source_sha256": { + "tests/browser_access.cjs": "e3c1bcd19d73981a39a3adcc0d32d7e67029907e0cfd689e2739348efbf0e56f", + "tests/browser_access_session.cjs": "d61b7cf0c366134050d6bba3542fd209005c5ad22f10a3659afe0ca8f948e1a5", + "tests/test_browser_access_navigation.cjs": "56ae9b76f1aaa3803a90f03468129f243d0b37f6a50110bcf7c13840da18f80e" + }, + "source_state": "Uncommitted exact three test-file repair; root owns final commit/publication.", + "status_porcelain": " M tests/browser_access.cjs\n?? tests/browser_access_session.cjs\n?? tests/test_browser_access_navigation.cjs\n", + "worktree": "/workspace/Tuldok-access-browser-ci-repair-20261020" +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-source-review.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-source-review.json new file mode 100644 index 00000000..9aa653c4 --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-source-review.json @@ -0,0 +1,75 @@ +{ + "base": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "blocking_findings": [], + "cleanup_review": { + "limit": "Existing helper confirms supplied main child handles only, not an unconditional Chrome-descendant extinction guarantee; actual fixture run and final cleanup observation pending.", + "order": "Dispose session/socket; await existing stopOwnedChildren only on supplied children; bounded recursive removal maxRetries10/retryDelay100; write terminal-main-handle receipt.", + "primary_preservation": "Original failure printed as Primary access failure and recorded phase/protocol metadata; exitCode1 set before finally. Cleanup failure separately prints Secondary access cleanup failure and retains nonzero exit." + }, + "disposition": "CLEAR within test-harness source/focused-test scope; actual default PostgreSQL/Chromium access qualification remains pending", + "historical_failure": { + "cause_limit": "Source race is demonstrated in controlled mock protocol scheduling; original hosted execution had no phase/pointer/context trace. Target closure/crash remains unexcluded. Original failed run is not reclassified.", + "head": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "job": 118455819881, + "primary": "Inspected target navigated or closed", + "run": 39370107550, + "secondary": "ENOTEMPTY after unawaited TERM/removal" + }, + "independent_tests": { + "command": "node --check tests/browser_access.cjs && node --check tests/browser_access_session.cjs && node --check tests/test_browser_access_navigation.cjs && node tests/test_browser_access_navigation.cjs && node tests/test_browser_page_load.cjs", + "exit": 0, + "not_run_by_reviewer": [ + "Actual browser/HTTP/PostgreSQL", + "Owned-child regression(no need duplicate existingroot pass)", + "Heavy suites/CI" + ], + "results": [ + "Controlled old navigation/reload ACK\u2192departing-DOM read produces -32000", + "New helper issues zero DOM reads until changed main loader matchingload; oldloader/subframe/DOMContentLoaded insufficient", + "Navigation load timeout and targetclose fail within configured bounds", + "Request timeout and snapshots omit MUST_NOT_APPEAR command token", + "Existing fresh-document helper regression passes" + ] + }, + "limits": [ + "No product/API/domain changes; exact source diff limited to three test files.", + "Root must execute and retain actual default access journey against these exact source hashes before broader acceptance.", + "No remote mutation/CI polling/source edit or server/browser execution by reviewer.", + "PUB-1 and SCI-1 unchanged." + ], + "navigation_review": { + "both_transitions": [ + "Initial Page.navigate to workbench", + "Scoped-agent Page.reload after exact cookie replacement" + ], + "diagnostics": "Bounded last12main-frame/load identities plus phase and last method; command parameters absent. contextual errors preserve underlying code/cause.", + "exact_target": "Initial page target must type page and url about:blank; connection deadline10000ms.", + "failure_boundaries": "Default CDP requests15000ms; new-load wait20000ms with25ms polling; explicit errorText/target close/error refuse. No blanket navigation-error suppression or mutation retry.", + "fresh_dom_checks": "Original session dialog/identity/Collection-ready checks remain after fresh-document gate.", + "owner": "accessSession captures Page.getFrameTree previous main id+loader before command; pageLoadTracker observes Page.frameNavigated and lifecycle load. Only changed main loader with matching load releases DOM checks." + }, + "original_assertions": { + "all14_original_calls_present_verbatim": true, + "base_calls": 14, + "current_calls": 15, + "extra": "Explicitly launched about:blank target assertion", + "preserved_semantics": [ + "Anonymous legacy/current denied writes", + "One-time CLI login consumed/code cleared/HttpOnly cookie", + "Signout and rejected mutation preserve unsaved draft", + "Reauthentication never replays original mutation", + "Only deliberate retry changes revision", + "Real scoped agent cannot use owner human-review controls", + "No runtime exceptions or application stderr" + ] + }, + "reviewed_utc": "2026-10-20T06:54:04.651464+00:00", + "source_sha256": { + "tests/browser_access.cjs": "e3c1bcd19d73981a39a3adcc0d32d7e67029907e0cfd689e2739348efbf0e56f", + "tests/browser_access_session.cjs": "d61b7cf0c366134050d6bba3542fd209005c5ad22f10a3659afe0ca8f948e1a5", + "tests/test_browser_access_navigation.cjs": "56ae9b76f1aaa3803a90f03468129f243d0b37f6a50110bcf7c13840da18f80e" + }, + "source_state": "Uncommitted exact three test-file repair; root owns final commit/publication.", + "status_porcelain": " M tests/browser_access.cjs\n?? tests/browser_access_session.cjs\n?? tests/test_browser_access_navigation.cjs\n", + "worktree": "/workspace/Tuldok-access-browser-ci-repair-20261020" +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-disposition.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-disposition.json new file mode 100644 index 00000000..2858438f --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-disposition.json @@ -0,0 +1,113 @@ +{ + "observed_utc": "2026-10-20T06:41:53.697361+00:00", + "scope": "Read-only source/log diagnosis; local evidence files only. No browser/PG reproduction, tests, source edits or external mutations.", + "pr": 112, + "head": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "tested_checkout": "fb6c6c6c55b6ece1d6eab0eae20bef630b9fdf46", + "tested_source_attribution": "Hosted checkout merge message binds0ded into29011; remote comparison from0ded tofb6 has no changed files.", + "run": 39370107550, + "job": 118455819881, + "conclusion": "failure", + "successful_steps": 45, + "skipped_steps": 127, + "failed_steps": [ + { + "name": "Run node tests/browser_access.cjs", + "status": "completed", + "conclusion": "failure", + "number": 41 + } + ], + "prior_full_unittest": { + "tests": 1771, + "skips": 83, + "non_skipped": 1688, + "seconds": 2989.096, + "result": "OK" + }, + "log": { + "path": "/tmp/tuldok-pr112-0ded-access-failed-job-118455819881.log", + "bytes": 251955, + "sha256": "dce0386ccf600104e93c6129a28bbd4844ee5d73921b64567d3a2234a9748f6e" + }, + "source": { + "path": "tests/browser_access.cjs", + "git_blob": "bae9bae294fd3245d7f099e6185924308c7233bc", + "sha256": "b19ba3559cc8321c3a4d932f0c14a08c3763ca41ac8640fd965d346f95213159", + "exact_local_committed_bytes_match_remote": true + }, + "primary": { + "time": "2026-10-20T06:37:39.7616902Z", + "code": -32000, + "message": "Inspected target navigated or closed", + "command_and_phase": "Unknown: raw CDP error object has no method/phase/call stack.", + "source_findings": [ + "line31:Page.navigate acknowledgement immediately followed by Runtime.evaluate polling", + "line49:Page.reload acknowledgement immediately followed by Runtime.evaluate polling", + "No pageLoadTracker, no lifecycle subscription, no changed-main-loader barrier", + "line22 selects first page target without explicit about:blank identity", + "line23 rejects plain protocol object, losing method/phase/stack; requests have no timer or socket-close drainage" + ], + "causal_status": "The source has an exposed departing-document window compatible with the error. Exact hosted navigation versus target crash/closure and failing command remain unproven." + }, + "secondary": { + "time": "2026-10-20T06:37:39.7890264Z", + "error": "ENOTEMPTY", + "location": "browser_access.cjs53:141", + "path": "/tmp/tuldok-access-browser-aOJaTf", + "source_findings": [ + "finally sends SIGTERM to supplied ChildProcess handles and synchronously removes profile immediately", + "It does not await exit; a still-writing process can race removal", + "Thrown cleanup error obscures final primary diagnostic; no exited-process evidence is retained" + ], + "causal_status": "Missing shutdown-before-remove ordering is established in source; exact descendant write responsible for hosted ENOTEMPTY was not observed." + }, + "artifact": { + "id": 12245483273, + "metadata_digest": "sha256:0b60815d2c44a77b1b082d38280acd4d185907c6d11729a3735c0a175481cba6", + "metadata_bytes": 110805, + "reference_returned": true, + "contents_inspected": false, + "reason": "One local read failed: Tunnel connection failed:403 Forbidden. No retry or bypass. Screenshot/progress contents are unknown." + }, + "independent_reviewer": "/root/mcp_contract_ci_review", + "independent_findings": "Agrees navigation barrier absent and cleanup separate; exact hostcause unproven. No tests or changes.", + "proposed_smallest_repair": [ + "In access harness only: observe accepted pageLoadTracker events, enable Page lifecycle events, capture previous main frame/loader before both initial navigate and scoped-agent reload, and await changed MAIN loader plus matching load before DOM assertions. Keep every existing auth and mutation assertion.", + "Select explicitly launched about:blank page; reuse existing bounded cdpSession or equivalent method-tagged request timeouts/close drainage so target loss remains a finite failure. No blanket navigation-error catch/retry, no privileged-action replay.", + "Await existing stopOwnedChildren on supplied handles before bounded exact-owned-path removal. Retain directory when shutdown cannot be confirmed. Report primary and secondary failures separately, retaining exit1 and bounded phase/loader/method diagnostics without credentials." + ], + "verification_required_before_causal_claim": [ + "Existing pure page-load cases must continue refusing old-document, subframe, wrong-loader and DOMContentLoaded-only readiness.", + "Controlled delayed actual navigation/reload reproduction should demonstrate original failure and fixed absence of DOM reads until the exact new loader load; force target close to remain a bounded failure.", + "Owned-child delayed-final-write and ignored-TERM tests; ensure cleanup diagnostics cannot replace the recorded primary failure.", + "Once separately authorized for implementation/runtime execution: full unchanged access entrypoint on actual app/PostgreSQL/Chromium: real CLI one-time login, HttpOnly cookie, no mutation replay, preserved drafts, explicit commit, scoped-agent review denial,1280/390 captures, exact resource/schema cleanup.", + "Fresh exact repaired-head lifecycle and independent review; sibling success never erases this exact-head failure." + ], + "sibling_untouched": { + "run": 39370108074, + "job": 118455821471, + "status": "in_progress", + "active_steps": [ + { + "name": "Run python -m unittest discover -s tests", + "status": "in_progress", + "conclusion": null, + "number": 37 + } + ], + "cancelled_or_rerun": false, + "observed_utc": "2026-10-20 06:42:19 UTC", + "conclusion": null + }, + "PUB_1": "Original failed diagnostic bytes/path/profile/caps/receipt still missing", + "SCI_1": "Owned qualified criterion and compatible real lab pair still missing", + "external_mutations": [], + "system_integration_block": "Remains in force; no denied operation retried", + "same_as_predecessor_29011_sources": [ + "tests/browser_access.cjs", + "tests/browser_page_load.cjs", + "tests/browser_owned_cleanup.cjs", + "static/auth.js" + ] +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-excerpt.log b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-excerpt.log new file mode 100644 index 00000000..777038ac --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-excerpt.log @@ -0,0 +1,32 @@ +2026-10-20T06:37:15.2772080Z ##[group]Run node tests/browser_access.cjs +2026-10-20T06:37:15.2772426Z node tests/browser_access.cjs +2026-10-20T06:37:15.2825753Z shell: /usr/bin/bash -e {0} +2026-10-20T06:37:15.2826003Z env: +2026-10-20T06:37:15.2826392Z TULDOK_TRAINING_PYTHON: /home/runner/work/Tuldok/Tuldok/build/workspace-training/bin/python +2026-10-20T06:37:15.2827074Z TULDOK_NATIVE_READER_PYTHON: /home/runner/work/Tuldok/Tuldok/build/workspace-training/bin/python +2026-10-20T06:37:15.2827855Z TULDOK_DATABASE_URL: ***127.0.0.1:5432/tuldok_test +2026-10-20T06:37:15.2828258Z pythonLocation: /opt/hostedtoolcache/Python/3.12.15/x64 +2026-10-20T06:37:15.2828711Z PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.12.15/x64/lib/pkgconfig +2026-10-20T06:37:15.2829143Z Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.15/x64 +2026-10-20T06:37:15.2829525Z Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.15/x64 +2026-10-20T06:37:15.2829903Z Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.15/x64 +2026-10-20T06:37:15.2830328Z LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.12.15/x64/lib +2026-10-20T06:37:15.2830686Z BROWSER: /usr/bin/google-chrome +2026-10-20T06:37:15.2830939Z ##[endgroup] +2026-10-20T06:37:39.7616902Z { code: -32000, message: 'Inspected target navigated or closed' } +2026-10-20T06:37:39.7886304Z node:fs:1282 +2026-10-20T06:37:39.7887476Z return binding.rmSync(getValidatedPath(path), opts.maxRetries, opts.recursive, opts.retryDelay); +2026-10-20T06:37:39.7889224Z ^ +2026-10-20T06:37:39.7889560Z +2026-10-20T06:37:39.7890264Z Error: ENOTEMPTY, Directory not empty: '/tmp/tuldok-access-browser-aOJaTf' +2026-10-20T06:37:39.7891130Z at Object.rmSync (node:fs:1282:18) +2026-10-20T06:37:39.7892007Z at /home/runner/work/Tuldok/Tuldok/tests/browser_access.cjs:53:141 +2026-10-20T06:37:39.7894084Z at { +2026-10-20T06:37:39.7894665Z errno: 39, +2026-10-20T06:37:39.7895114Z code: 'ENOTEMPTY', +2026-10-20T06:37:39.7895754Z path: '/tmp/tuldok-access-browser-aOJaTf', +2026-10-20T06:37:39.7896347Z syscall: 'rm' +2026-10-20T06:37:39.7896775Z } +2026-10-20T06:37:39.7897797Z +2026-10-20T06:37:39.7898074Z Node.js v24.22.0 +2026-10-20T06:37:39.8035099Z ##[error]Process completed with exit code 1. diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/post-run-cleanup.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/post-run-cleanup.json new file mode 100644 index 00000000..00a8746d --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/post-run-cleanup.json @@ -0,0 +1,35 @@ +{ + "observed_utc": "2026-10-20T06:56:29.403793+00:00", + "schema": "catalog_82698c551bbd413a878d83de58438931", + "counts_before_disposal": { + "workspace_runs": 0 + }, + "schema_absent": true, + "temporary": "/tmp/tuldok-access-browser-7VR9Z3", + "temporary_absent": true, + "matching_task_processes": [], + "owned_main_handles": [ + { + "pid": 119512, + "exit_code": null, + "signal": "SIGTERM" + }, + { + "pid": 119521, + "exit_code": 0, + "signal": null + } + ], + "source_hashes": { + "tests/browser_access.cjs": "e3c1bcd19d73981a39a3adcc0d32d7e67029907e0cfd689e2739348efbf0e56f", + "tests/browser_access_session.cjs": "d61b7cf0c366134050d6bba3542fd209005c5ad22f10a3659afe0ca8f948e1a5", + "tests/test_browser_access_navigation.cjs": "56ae9b76f1aaa3803a90f03468129f243d0b37f6a50110bcf7c13840da18f80e" + }, + "checks": [ + "Anonymous legacy/current APIs denied; real one-time login consumed; cookie is HttpOnly and code cleared", + "Sign out and rejected mutation preserve draft; reauthentication does not replay mutation; deliberate retry commits", + "Real scoped agent identity cannot use owner human-review controls" + ], + "report": "/tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332", + "scope": "Exact preregistered test schema only; supplied main handles terminal and exact profile absent at post-exit observation; no blanket descendant shutdown guarantee." +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/qualification.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/qualification.json new file mode 100644 index 00000000..d371e0bd --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/qualification.json @@ -0,0 +1,114 @@ +{ + "base": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "branch": "fix/access-browser-ci-qualification-20261020", + "worktree": "/workspace/Tuldok-access-browser-ci-repair-20261020", + "retention": "retained-protected; unpublished local repair pending serial integration authority; no cleanup authorized", + "source_sha256": { + "tests/browser_access.cjs": "e3c1bcd19d73981a39a3adcc0d32d7e67029907e0cfd689e2739348efbf0e56f", + "tests/browser_access_session.cjs": "d61b7cf0c366134050d6bba3542fd209005c5ad22f10a3659afe0ca8f948e1a5", + "tests/test_browser_access_navigation.cjs": "56ae9b76f1aaa3803a90f03468129f243d0b37f6a50110bcf7c13840da18f80e" + }, + "companion_source_sha256": { + "tests/browser_cdp_session.cjs": "ecfac048e343e0be85a02d22d284ea2c731617ec80807762a0691276f2bec40f", + "tests/browser_page_load.cjs": "bb74bd6ad97e0ff7c4545c747df698d0466d143764b0ccb52ed26b2051a13318", + "tests/browser_owned_cleanup.cjs": "1cddb8bfe88999c89193b2c3f11f57ce842cb04e25dcdd99ba4f2f9ff28b3988" + }, + "actual_command": "node tests/browser_access.cjs", + "actual_exit": 0, + "actual_seconds": 8.60535, + "actual_attribution": "Precommit HEAD0ded plus three modified/new file hashes; actual receipt is not a literal repaired-commit execution.", + "original_failure": { + "run": 39370107550, + "job": 118455819881, + "decoded_log": "/tmp/tuldok-pr112-0ded-access-failed-job-118455819881.log", + "decoded_log_sha256": "dce0386ccf600104e93c6129a28bbd4844ee5d73921b64567d3a2234a9748f6e", + "primary": "Inspected target navigated or closed", + "secondary": "ENOTEMPTY", + "original_cause_proven": false, + "artifact_contents_inspected": false + }, + "focused_checks": { + "syntax": 3, + "new_controlled_navigation_reload_regression": "passed; mock CDP ordering only", + "existing_page_load_regression": "passed", + "owned_child_delayed_write_ignored_TERM_regression": "passed", + "diff_check": "passed" + }, + "preservation": { + "original_refs": 82, + "original_worktree_records": 96, + "unchanged": true, + "running_sibling_untouched": true + }, + "external_mutations": [], + "hosted_repaired_head_gate": "not run; publication outside current scope", + "PUB_1": "missing original evidence", + "SCI_1": "missing owned criterion and real lab pair", + "evidence": [ + { + "path": "acceptance.md", + "bytes": 4413, + "sha256": "ee8529aecfc71963e768cfc98c72a847680fe10de8b8930d21b4d9b394f85c74" + }, + { + "path": "actual-access.log", + "bytes": 346, + "sha256": "ae63a93687389ad38ed33d1ecbe7fe8916db65afff8222c4a9acfe8b07f4b2f4" + }, + { + "path": "cleanup.json", + "bytes": 341, + "sha256": "06b2c257bca7797d663ad809335504a2a2d56a7b41eae4edf77b2049b110538e" + }, + { + "path": "independent-review.json", + "bytes": 10086, + "sha256": "ce616c44d452ef18a96df683fd9ce6b524ac6eb97a40c497c91164ec480182c5" + }, + { + "path": "independent-source-review.json", + "bytes": 4965, + "sha256": "3b8d598bd31f575c0d8b20780a275abd9b0df10d7ee8a589b21a4968eccf56e3" + }, + { + "path": "original-failure-disposition.json", + "bytes": 6212, + "sha256": "3abe25f69e93b32459308ec15dae8e32e35c504447414faa0e657c1a0d9f5696" + }, + { + "path": "original-failure-excerpt.log", + "bytes": 2275, + "sha256": "7a92c80edc4a25e16424b63efcbad9b04cb2b53e45a9559733aa8d1724b72c87" + }, + { + "path": "post-run-cleanup.json", + "bytes": 1433, + "sha256": "3fefda92278099fc5e93f1c05f363277b72469535a8dbd9cd83f5832023a6fc1" + }, + { + "path": "receipt.json", + "bytes": 1693, + "sha256": "57b652807e1ac0e89d9f422c0c551051e33782ec779a016f0046c3ed48c6268d" + }, + { + "path": "runner-receipt.json", + "bytes": 763, + "sha256": "b247a3d1147a47f0304649ae2a110969c2da7c1d6e4cd5a0abe8d82430753ef9" + }, + { + "path": "schema-reservation.json", + "bytes": 234, + "sha256": "20bc035c94c464cfd13179a32bfdf069e49302f7d6f1369e8f7c2081ba15e5a5" + }, + { + "path": "session-1280.jpg", + "bytes": 92512, + "sha256": "ae5ecddb60cd751033a62eb24ee383daa4d56da85439115b080178b18b5c5580" + }, + { + "path": "session-390.jpg", + "bytes": 46763, + "sha256": "71f975c51592a0a92669c3d5213b21561acbc83cd4450a532b9e1a2cb7907519" + } + ] +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/receipt.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/receipt.json new file mode 100644 index 00000000..e2b89d92 --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/receipt.json @@ -0,0 +1,47 @@ +{ + "checks": [ + "Anonymous legacy/current APIs denied; real one-time login consumed; cookie is HttpOnly and code cleared", + "Sign out and rejected mutation preserve draft; reauthentication does not replay mutation; deliberate retry commits", + "Real scoped agent identity cannot use owner human-review controls" + ], + "anonymous_denied": true, + "real_cli_login": true, + "no_mutation_replay": true, + "source_commit": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "source_sha256": { + "tests/browser_access.cjs": "e3c1bcd19d73981a39a3adcc0d32d7e67029907e0cfd689e2739348efbf0e56f", + "tests/browser_access_session.cjs": "d61b7cf0c366134050d6bba3542fd209005c5ad22f10a3659afe0ca8f948e1a5", + "tests/test_browser_access_navigation.cjs": "56ae9b76f1aaa3803a90f03468129f243d0b37f6a50110bcf7c13840da18f80e" + }, + "navigation": { + "phase": "scoped-agent-reload", + "last_method": "Runtime.evaluate", + "events": [ + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "C704421B4745793C1F166C7CC67C83F8" + }, + { + "event": "main-frame", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7534733FE54346FBED7374DBFE2EEB98" + }, + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7534733FE54346FBED7374DBFE2EEB98" + }, + { + "event": "main-frame", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7B0CA169AEB6A2150994309812BCD5B7" + }, + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7B0CA169AEB6A2150994309812BCD5B7" + } + ] + } +} \ No newline at end of file diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/runner-receipt.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/runner-receipt.json new file mode 100644 index 00000000..08de421c --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/runner-receipt.json @@ -0,0 +1,17 @@ +{ + "command": "node tests/browser_access.cjs", + "exit_code": 0, + "started_utc": "2026-10-20T06:55:51.714739+00:00", + "finished_utc": "2026-10-20T06:56:00.320089+00:00", + "source_head_at_run": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "source_dirty_at_run": true, + "log": "/tmp/tuldok-access-browser-ci-repair-20261020/actual-access.log", + "schema_reservation": { + "dataset_id": "82698c551bbd413a878d83de58438931", + "schema": "catalog_82698c551bbd413a878d83de58438931", + "state": "created", + "owner": "access-browser-ci-20261020", + "catalog_path": "/tmp/tuldok-access-browser-7VR9Z3/data" + }, + "environment_changes": "None: existing runtime/Chromium/PG17 only; child environment and preregistered disposable fixture are task-scoped." +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/schema-reservation.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/schema-reservation.json new file mode 100644 index 00000000..98671362 --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/schema-reservation.json @@ -0,0 +1,7 @@ +{ + "dataset_id": "82698c551bbd413a878d83de58438931", + "schema": "catalog_82698c551bbd413a878d83de58438931", + "state": "created", + "owner": "access-browser-ci-20261020", + "catalog_path": "/tmp/tuldok-access-browser-7VR9Z3/data" +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-1280.jpg b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-1280.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2fb51729944307bef6890fa43bf4558d7bafab2a GIT binary patch literal 92512 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

F)HzmS<+gq)i_21rG4a2yER@PgPJWs$L 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 literal 0 HcmV?d00001 diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-390.jpg b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-390.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2e9d449cb275ab6b0774c83db85f01c217822750 GIT binary patch literal 46763 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 literal 0 HcmV?d00001 diff --git a/tests/browser_access.cjs b/tests/browser_access.cjs index bae9bae2..eba38f48 100644 --- a/tests/browser_access.cjs +++ b/tests/browser_access.cjs @@ -4,14 +4,19 @@ const assert=require('node:assert/strict'),fs=require('node:fs'),path=require('n const {spawn,execFileSync}=require('node:child_process'); const {authenticatedFixture}=require('./auth_helpers.cjs'); const {waitForDebugger}=require('./browser_startup.cjs'); +const {accessSession}=require('./browser_access_session.cjs'); +const {stopOwnedChildren}=require('./browser_owned_cleanup.cjs'); const {qaDirectory,screenshotOptions}=require('./qa_artifacts.cjs'); const root=path.resolve(__dirname,'..'),temporary=fs.mkdtempSync(path.join(os.tmpdir(),'tuldok-access-browser-')),data=path.join(temporary,'data'); const report=qaDirectory(root,'access'),children=[],errors=[],checks=[],fixture=authenticatedFixture(); -const pause=ms=>new Promise(resolve=>setTimeout(resolve,ms));let ws,send,evaluate; +const pause=ms=>new Promise(resolve=>setTimeout(resolve,ms));let ws,session,send,evaluate,phase='startup'; +function setPhase(value){phase=value;session?.setPhase(value);} async function until(fn){for(let n=0;n<200;n++){const value=await fn();if(value)return value;await pause(100);}throw Error('Access browser wait timed out');} function launch(command,args,options){const child=spawn(command,args,options);children.push(child);return child;} function code(){const file=path.join(temporary,'login-'+Date.now());execFileSync('python3',['access.py','login','--data',data,'--out',file],{cwd:root});const value=fs.readFileSync(file,'utf8').trim();fs.unlinkSync(file);return value;} (async()=>{ + await require('./test_browser_access_navigation.cjs').verifyAccessNavigation(); + setPhase('application-startup'); const server=launch('python3',['-u','app.py','--port','0','--data',data],{cwd:root,stdio:['ignore','pipe','pipe']});let output='',serverErrors='';server.stdout.on('data',chunk=>output+=chunk);server.stderr.on('data',chunk=>serverErrors+=chunk); const port=await until(()=>output.match(/127\.0\.0\.1:(\d+)/)?.[1]),base='http://127.0.0.1:'+port; assert.equal((await fetch(base+'/api/workbench/records')).status,401); @@ -19,19 +24,22 @@ function code(){const file=path.join(temporary,'login-'+Date.now());execFileSync await fixture.register(base,data,root); const response=await fixture.fetch(base+'/api/workbench/import',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({kind:'text',name:'Retained owner draft',text:'Original immutable source',groups:['auth-fixture'],rights:'Authored test fixture'})});assert.equal(response.status,201);const record=await response.json(); const browser=launch(process.env.BROWSER||'/usr/bin/chromium',['--headless','--no-sandbox','--disable-gpu','--no-first-run','--remote-debugging-port=0','--window-size=1280,900','--user-data-dir='+path.join(temporary,'browser'),'about:blank'],{stdio:'ignore'}); - const debug=await waitForDebugger(browser,path.join(temporary,'browser','DevToolsActivePort')),tabs=await(await fetch('http://127.0.0.1:'+debug+'/json')).json();ws=new WebSocket(tabs.find(tab=>tab.type==='page').webSocketDebuggerUrl);await new Promise((resolve,reject)=>{ws.onopen=resolve;ws.onerror=reject;}); - let counter=0;const pending=new Map();ws.onmessage=event=>{const value=JSON.parse(event.data);if(value.id){const task=pending.get(value.id);pending.delete(value.id);value.error?task.reject(value.error):task.resolve(value.result);}else if(value.method==='Runtime.exceptionThrown')errors.push(value.params.exceptionDetails.text);}; - send=(method,params={})=>new Promise((resolve,reject)=>{pending.set(++counter,{resolve,reject});ws.send(JSON.stringify({id:counter,method,params}));}); + const debug=await waitForDebugger(browser,path.join(temporary,'browser','DevToolsActivePort')),tabs=await(await fetch('http://127.0.0.1:'+debug+'/json')).json(); + const target=tabs.find(tab=>tab.type==='page'&&tab.url==='about:blank');assert.ok(target,'Expected the explicitly launched blank page'); + ws=new WebSocket(target.webSocketDebuggerUrl);await new Promise((resolve,reject)=>{const timer=setTimeout(()=>reject(Error('Access CDP connection timed out')),10000);ws.onopen=()=>{clearTimeout(timer);resolve();};ws.onerror=()=>{clearTimeout(timer);reject(Error('Access CDP connection failed'));};}); + session=accessSession(ws,{onEvent:value=>{if(value.method==='Runtime.exceptionThrown')errors.push(value.params.exceptionDetails.text);}});session.setPhase(phase);send=session.send; evaluate=async expression=>{const value=await send('Runtime.evaluate',{expression,awaitPromise:true,returnByValue:true});if(value.exceptionDetails)throw Error(JSON.stringify(value.exceptionDetails));return value.result.value;}; async function click(selector){const box=await evaluate(`(()=>{const el=document.querySelector(${JSON.stringify(selector)});el.scrollIntoView({block:'center'});const r=el.getBoundingClientRect();return {x:r.x+r.width/2,y:r.y+r.height/2}})()`);await send('Input.dispatchMouseEvent',{type:'mousePressed',button:'left',clickCount:1,...box});await send('Input.dispatchMouseEvent',{type:'mouseReleased',button:'left',clickCount:1,...box});} async function fill(selector,value){await click(selector);await evaluate(`document.querySelector(${JSON.stringify(selector)}).select()`);await send('Input.insertText',{text:value});} async function login(){const token=code();await fill('#session-token',token);await click('#session-submit');await until(()=>evaluate('!document.getElementById("session-dialog").open'));assert.equal(await evaluate('document.getElementById("session-token").value'),'');assert.equal(await evaluate('document.cookie.includes("tuldok_session")'),false);return token;} - await send('Page.enable');await send('Runtime.enable');await send('Network.enable'); + await send('Page.enable');await send('Page.setLifecycleEventsEnabled',{enabled:true});await send('Runtime.enable');await send('Network.enable'); // No fixture cookie is installed: this suite exercises actual interactive login. - await send('Page.navigate',{url:base+'/workbench'});await until(()=>evaluate('document.getElementById("session-dialog")?.open')); + setPhase('initial-navigation');await session.navigate('Page.navigate',{url:base+'/workbench'});await until(()=>evaluate('document.getElementById("session-dialog")?.open')); + setPhase('one-time-owner-login'); const oneTime=await login();await until(()=>evaluate('document.getElementById("notice").textContent==="Collection ready."')); assert.equal((await fetch(base+'/api/access/session',{method:'POST',headers:{Origin:base,'Content-Type':'application/json'},body:JSON.stringify({token:oneTime})})).status,401); checks.push('Anonymous legacy/current APIs denied; real one-time login consumed; cookie is HttpOnly and code cleared'); + setPhase('draft-and-reauthentication'); await click('#records .record button');await until(()=>evaluate('!document.getElementById("editor").hidden'));await fill('#label','retained-draft'); const before=(await(await fixture.fetch(base+'/api/workbench/records/'+record.id)).json()).revision; await click('#session-logout');await until(()=>evaluate('document.getElementById("session-dialog").open'));await click('#session-close'); @@ -42,12 +50,23 @@ function code(){const file=path.join(temporary,'login-'+Date.now());execFileSync assert.equal(await evaluate('document.getElementById("label").value'),'retained-draft'); await click('#save');await until(async()=>((await(await fixture.fetch(base+'/api/workbench/records/'+record.id)).json()).revision)>before); checks.push('Sign out and rejected mutation preserve draft; reauthentication does not replay mutation; deliberate retry commits'); + setPhase('session-layout-captures'); for(const [width,height] of [[1280,900],[390,844]]){await send('Emulation.setDeviceMetricsOverride',{width,height,deviceScaleFactor:1,mobile:false});await click('#session-open');await pause(100);const shot=await send('Page.captureScreenshot',screenshotOptions);fs.writeFileSync(path.join(report,'session-'+width+'.jpg'),Buffer.from(shot.data,'base64'));await click('#session-close');} const issued=await fixture.fetch(base+'/api/access/credentials',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({label:'Scoped browser agent',scopes:['inspect','edit']})});assert.equal(issued.status,201);const agent=await issued.json(); const cookies=await send('Network.getCookies',{urls:[base]});const sessionCookie=cookies.cookies.find(cookie=>cookie.httpOnly&&cookie.name==='tuldok_session');assert.ok(sessionCookie); await send('Network.setCookie',{name:sessionCookie.name,value:agent.token,url:base+'/',httpOnly:true,sameSite:'Strict',path:'/'}); - await send('Page.reload');await until(()=>evaluate('document.getElementById("session-identity")?.textContent.includes("Scoped browser agent")'));await until(()=>evaluate('document.getElementById("notice").textContent==="Collection ready."'));await click('#records .record button');await until(()=>evaluate('!document.getElementById("editor").hidden')); + setPhase('scoped-agent-reload');await session.navigate('Page.reload');await until(()=>evaluate('document.getElementById("session-identity")?.textContent.includes("Scoped browser agent")'));await until(()=>evaluate('document.getElementById("notice").textContent==="Collection ready."'));await click('#records .record button');await until(()=>evaluate('!document.getElementById("editor").hidden')); assert.equal(await evaluate('document.getElementById("record-review").disabled'),true); checks.push('Real scoped agent identity cannot use owner human-review controls'); - assert.deepEqual(errors,[]);assert.equal(serverErrors,'');fs.writeFileSync(path.join(report,'receipt.json'),JSON.stringify({checks,anonymous_denied:true,real_cli_login:true,no_mutation_replay:true},null,2));console.log('PASS access browser '+report); -})().catch(error=>{console.error(error);process.exitCode=1;}).finally(()=>{ws?.close();for(const child of children)child.kill('SIGTERM');fs.rmSync(temporary,{recursive:true,force:true});}); + assert.deepEqual(errors,[]);assert.equal(serverErrors,'');fs.writeFileSync(path.join(report,'receipt.json'),JSON.stringify({checks,anonymous_denied:true,real_cli_login:true,no_mutation_replay:true,source_commit:execFileSync('git',['rev-parse','HEAD'],{cwd:root,encoding:'utf8'}).trim(),source_sha256:Object.fromEntries(['tests/browser_access.cjs','tests/browser_access_session.cjs','tests/test_browser_access_navigation.cjs'].map(file=>[file,require('node:crypto').createHash('sha256').update(fs.readFileSync(path.join(root,file))).digest('hex')])),navigation:session.snapshot()},null,2));console.log('PASS access browser '+report); +})().catch(error=>{ + console.error('Primary access failure:',error);process.exitCode=1; + const failure={phase,protocol:session?.snapshot(),error:{name:error.name,message:error.message,code:error.code}}; + console.error('Access failure context:',JSON.stringify(failure)); + fs.writeFileSync(path.join(report,'failure.json'),JSON.stringify(failure,null,2)+'\n'); +}).finally(async()=>{ + if(session)session.close();else ws?.close(); + await stopOwnedChildren(children); + fs.rmSync(temporary,{recursive:true,force:true,maxRetries:10,retryDelay:100}); + fs.writeFileSync(path.join(report,'cleanup.json'),JSON.stringify({temporary,removed:!fs.existsSync(temporary),children:children.map(child=>({pid:child.pid,exit_code:child.exitCode,signal:child.signalCode})),scope:'Supplied test-owned main handles exited before bounded profile removal'},null,2)+'\n'); +}).catch(error=>{console.error('Secondary access cleanup failure:',error);process.exitCode=1;}); diff --git a/tests/browser_access_session.cjs b/tests/browser_access_session.cjs new file mode 100644 index 00000000..3c7bbaa2 --- /dev/null +++ b/tests/browser_access_session.cjs @@ -0,0 +1,46 @@ +'use strict'; +const {cdpSession}=require('./browser_cdp_session.cjs'); +const {pageLoadTracker}=require('./browser_page_load.cjs'); + +// Access-test diagnostics contain phase/method/loader identity, never command parameters. +function accessSession(socket,{timeoutMs=15000,loadTimeoutMs=20000,pollMs=25,onEvent=()=>{}}={}){ + const loads=pageLoadTracker(),events=[]; + let phase='startup',lastMethod=null,terminal=null; + const session=cdpSession(socket,{timeoutMs,onEvent:message=>{ + loads.observe(message); + if(message.method==='Page.frameNavigated'&&!message.params.frame.parentId){ + const {id,loaderId}=message.params.frame;events.push({event:'main-frame',frame:id,loader:loaderId}); + } + if(message.method==='Page.lifecycleEvent'&&message.params.name==='load'){ + events.push({event:'load',frame:message.params.frameId,loader:message.params.loaderId}); + } + if(events.length>12)events.splice(0,events.length-12); + onEvent(message); + }}); + socket.addEventListener('close',()=>{terminal='CDP socket closed';}); + socket.addEventListener('error',()=>{terminal='CDP socket failed';}); + function contextual(error,owner,method){ + return Object.assign(new Error(`Access browser [${owner}] ${method}: ${error.message}`,{cause:error}),{code:error.code}); + } + async function send(method,params={},budgetMs){ + const owner=phase;lastMethod=method; + try{return await session.send(method,params,budgetMs);} + catch(error){throw contextual(error,owner,method);} + } + async function navigate(method,params={}){ + if(!['Page.navigate','Page.reload'].includes(method))throw Error('Unsupported access navigation'); + const owner=phase,previous=(await send('Page.getFrameTree')).frameTree.frame; + if(!previous.id||!previous.loaderId)throw Error(`Access browser [${owner}] missing previous main loader`); + const result=await send(method,params); + if(result.errorText)throw Error(`Access browser [${owner}] ${method}: ${result.errorText}`); + const deadline=performance.now()+loadTimeoutMs; + // Navigation acknowledgement can precede document replacement. Never poll that old DOM. + while(!loads.reloaded(previous)){ + if(terminal)throw contextual(Error(terminal),owner,method); + if(performance.now()>=deadline)throw Error(`Access browser [${owner}] ${method}: new main document load timed out`); + await new Promise(resolve=>setTimeout(resolve,pollMs)); + } + } + return {send,navigate,setPhase(value){phase=value;},snapshot(){return {phase,last_method:lastMethod,events:[...events]};},close(){terminal='CDP session disposed';session.close();}}; +} +module.exports={accessSession}; diff --git a/tests/test_browser_access_navigation.cjs b/tests/test_browser_access_navigation.cjs new file mode 100644 index 00000000..a097d5bb --- /dev/null +++ b/tests/test_browser_access_navigation.cjs @@ -0,0 +1,61 @@ +'use strict'; +// Controlled CDP scheduling reproduces the departing-document window; not a hosted trace. +const assert=require('node:assert/strict'); +const {cdpSession}=require('./browser_cdp_session.cjs'); +const {accessSession}=require('./browser_access_session.cjs'); +const tick=()=>new Promise(resolve=>setImmediate(resolve)); +class Socket extends EventTarget{ + constructor(){super();this.reads=0;this.loaded=false;this.requested=new Promise(resolve=>{this.acknowledged=resolve;});} + receive(value){this.dispatchEvent(new MessageEvent('message',{data:JSON.stringify(value)}));} + send(raw){ + const {id,method}=JSON.parse(raw); + if(method==='Page.getFrameTree'){this.receive({id,result:{frameTree:{frame:{id:'main',loaderId:'old'}}}});return;} + if(method==='Page.navigate'||method==='Page.reload'){this.receive({id,result:{}});this.acknowledged();return;} + if(method==='Runtime.never')return; + if(method==='Runtime.evaluate'){ + this.reads++; + if(!this.loaded){this.receive({id,error:{code:-32000,message:'Inspected target navigated or closed'}});return;} + } + this.receive({id,result:{result:{value:true}}}); + } + frame(id,loaderId,parentId){this.receive({method:'Page.frameNavigated',params:{frame:{id,loaderId,parentId}}});} + load(frameId,loaderId,name='load'){this.receive({method:'Page.lifecycleEvent',params:{frameId,loaderId,name}});} + close(){this.dispatchEvent(new Event('close'));} +} +async function verifyAccessNavigation(){ + for(const method of ['Page.navigate','Page.reload']){ + const oldSocket=new Socket(),old=cdpSession(oldSocket); + try{ + await old.send(method); + await assert.rejects(old.send('Runtime.evaluate',{expression:'original access assertion'}),error=>error.code===-32000&&error.message==='Inspected target navigated or closed'); + }finally{old.close();} + const socket=new Socket(),current=accessSession(socket,{pollMs:1,loadTimeoutMs:1000}); + current.setPhase(method==='Page.reload'?'scoped-agent-reload':'initial-navigation'); + try{ + let finished=false; + const action=(async()=>{await current.navigate(method);await current.send('Runtime.evaluate',{expression:'original access assertion'});finished=true;})(); + await socket.requested;await tick();assert.equal(socket.reads,0);assert.equal(finished,false); + socket.frame('child','child-new','main');socket.load('child','child-new'); + socket.frame('main','new');socket.load('main','old');socket.load('main','new','DOMContentLoaded'); + await tick();assert.equal(socket.reads,0);assert.equal(finished,false,'Old/subframe/DOMContentLoaded events never permit access DOM reads'); + socket.loaded=true;socket.load('main','new');await action;assert.equal(socket.reads,1);assert.equal(finished,true); + }finally{current.close();} + } + console.log('PASS access navigation/reload reproduction: old acknowledgement permits failing DOM read; changed main loader plus its load gates the original assertion'); + for(const kind of ['timeout','close']){ + const socket=new Socket(),current=accessSession(socket,{pollMs:1,loadTimeoutMs:25});current.setPhase('scoped-agent-reload'); + try{ + const navigation=current.navigate('Page.reload'); + const rejected=assert.rejects(navigation,kind==='close'?/\[scoped-agent-reload\] Page.reload: CDP socket closed/:/\[scoped-agent-reload\] Page.reload: new main document load timed out/); + await socket.requested;if(kind==='close')socket.close();await rejected;assert.equal(socket.reads,0); + }finally{current.close();} + } + const socket=new Socket(),current=accessSession(socket,{timeoutMs:20});current.setPhase('private-operation'); + try{ + await assert.rejects(current.send('Runtime.never',{token:'MUST_NOT_APPEAR'}),error=>error.message==='Access browser [private-operation] Runtime.never: CDP timeout: Runtime.never'&&!error.message.includes('MUST_NOT_APPEAR')); + assert.ok(!JSON.stringify(current.snapshot()).includes('MUST_NOT_APPEAR')); + }finally{current.close();} + console.log('PASS access phase-specific timeout/target-close failures are bounded; diagnostics omit command parameters'); +} +module.exports={verifyAccessNavigation}; +if(require.main===module)verifyAccessNavigation().catch(error=>{console.error(error);process.exitCode=1;});