From aa212047a5ad5d017996089eff321bcdce922b46 Mon Sep 17 00:00:00 2001 From: vib-tools Date: Tue, 18 Aug 2026 12:44:23 -0700 Subject: [PATCH] fix(chrome): harden verified installer TLS transport v1.0.6.44 --- CHANGELOG.md | 10 ++ CITATION.cff | 2 +- COMPATIBILITY.md | 9 ++ DELTA_FILE_LIST.txt | 40 +++---- PATCH_MANIFEST.md | 84 +++++++------- PROJECT_STRUCTURE.md | 6 + README.md | 6 + ROADMAP.md | 6 + SHA256SUMS.txt | 74 +++++-------- UPDATE_LOG.md | 6 + VERSIONING.md | 6 + config/AppConfig/app.py | 2 +- ...0.6.44_final_release_chrome_tls_scope.json | 91 ++++++++++++++++ docs/docs.manifest.ygit | 6 +- docs/index.md | 6 + .../v1.0.6.44-final-release-chrome-tls.md | 13 +++ .../V1.0.6.44_FINAL_RELEASE_CHROME_TLS.md | 21 ++++ pyproject.toml | 2 +- scripts/verify_repository.py | 84 ++++++++++++-- src/vibrapilot/chrome_installer.py | 103 ++++++++++++++++-- tests/test_app_config.py | 2 +- .../test_v10638_portable_runtime_root_fix.py | 5 + tests/test_v10644_chrome_tls_transport.py | 95 ++++++++++++++++ vibproject.ygit | 4 +- 24 files changed, 542 insertions(+), 141 deletions(-) create mode 100644 config/verification/v1.0.6.44_final_release_chrome_tls_scope.json create mode 100644 docs/updates/v1.0.6.44-final-release-chrome-tls.md create mode 100644 docs/verification/V1.0.6.44_FINAL_RELEASE_CHROME_TLS.md create mode 100644 tests/test_v10644_chrome_tls_transport.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 21b038b..660a236 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## v1.0.6.44 — Final Release Chrome TLS Closure — 2026-08-18 + +- Final forensic verification of completed Phase-1 and Phase-2 behavior against the v1.0.6.43 baseline. +- Fixed Google Chrome prerequisite MSI download failures caused by the portable Python urllib/OpenSSL certificate-chain path. +- The approved Google MSI now downloads through the existing Requests runtime dependency with mandatory TLS verification, no automatic redirects, and validation of every redirect against the exact dl.google.com Stable x64 MSI policy. +- Preserved mandatory Windows Authenticode trust and Google LLC publisher verification before installer execution. +- No TLS bypass, HTTP fallback, Chromium fallback, Plugin API change, persistence schema change, licensing change, power change, workflow-lifecycle change or new UI page. + +--- + ## v1.0.6.43 — Phase 2 Forensic Closure — 2026-08-18 - Re-audited v1.0.6.42 workflow lifecycle and true multiworkflow implementation against the approved Phase-2 contract. diff --git a/CITATION.cff b/CITATION.cff index f899bea..ac0de96 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -2,7 +2,7 @@ cff-version: 1.2.0 title: "VibraPilot — Vib Tools Browser Automation Desktop" message: "If you reference this software, cite the Vib Tools project." type: software -version: 1.0.6.43 +version: 1.0.6.44 authors: - name: "Vib Tools" url: "https://vib.tools/" diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index d140f76..a82f155 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -1,3 +1,12 @@ +# v1.0.6.44 Final Release Compatibility + +- Baseline: v1.0.6.43. +- Plugin API remains 1; workspace/runtime schemas remain 2. +- Existing external workflows, per-Task multiworkflow identity, background runtime, power guard and browser profiles remain compatible. +- Chrome installer source/signature policy is unchanged; only the verified HTTPS transport is corrected for portable Windows certificate-chain reliability. + +--- + # v1.0.6.43 Phase 2 Forensic Closure Compatibility - External Workflow Plugin API remains version 1. diff --git a/DELTA_FILE_LIST.txt b/DELTA_FILE_LIST.txt index b8a1e4f..052fdc9 100644 --- a/DELTA_FILE_LIST.txt +++ b/DELTA_FILE_LIST.txt @@ -10,36 +10,22 @@ SHA256SUMS.txt UPDATE_LOG.md VERSIONING.md config/AppConfig/app.py -config/verification/v1.0.6.43_phase2_forensic_closure_scope.json +config/verification/v1.0.6.44_final_release_chrome_tls_scope.json docs/docs.manifest.ygit docs/index.md -docs/updates/v1.0.6.43-phase2-forensic-closure.md -docs/verification/V1.0.6.43_PHASE2_FORENSIC_CLOSURE.md -project/CURRENT_PROJECT_STATE.md -project/README.md -project/updates/v1.0.6.39-v1.0.6.40-production-readiness/03_PHASE_PROGRESS_COMPLETION_LEDGER.md -project/updates/v1.0.6.39-v1.0.6.40-production-readiness/04_ERROR_HANDLING_AUDIT_AND_PLAN.md -project/updates/v1.0.6.39-v1.0.6.40-production-readiness/05_ACTUAL_IMPLEMENTATION_STATUS.md -project/updates/v1.0.6.39-v1.0.6.40-production-readiness/07_ACCEPTANCE_TEST_MATRIX.md -project/updates/v1.0.6.39-v1.0.6.40-production-readiness/08_REQUIREMENTS_TRACEABILITY_MATRIX.md -project/updates/v1.0.6.42-phase2-workflow-lifecycle-multiworkflow/08_PHASE2_PROGRESS_LEDGER.md -project/updates/v1.0.6.42-phase2-workflow-lifecycle-multiworkflow/09_ACTUAL_IMPLEMENTATION_STATUS.md -project/updates/v1.0.6.42-phase2-workflow-lifecycle-multiworkflow/10_FINAL_VERIFICATION_REPORT.md -project/updates/v1.0.6.43-phase2-forensic-closure/00_SCOPE_LOCK.md -project/updates/v1.0.6.43-phase2-forensic-closure/01_FORENSIC_AUDIT_REPORT.md -project/updates/v1.0.6.43-phase2-forensic-closure/02_ROOT_CAUSE_AND_FIX_REPORT.md -project/updates/v1.0.6.43-phase2-forensic-closure/03_VERIFICATION_MATRIX.md -project/updates/v1.0.6.43-phase2-forensic-closure/04_ACTUAL_IMPLEMENTATION_STATUS.md +docs/updates/v1.0.6.44-final-release-chrome-tls.md +docs/verification/V1.0.6.44_FINAL_RELEASE_CHROME_TLS.md pyproject.toml scripts/verify_repository.py -src/vibrapilot/qt_app.py -src/vibrapilot/workflow/plugin_loader.py -src/vibrapilot/workspace_state.py +src/vibrapilot/chrome_installer.py tests/test_app_config.py -tests/test_v10623_pr06_workflow_state_atomic_switch.py -tests/test_v10624_pr07_workflow_showcase.py -tests/test_v10626_pr09_data_persistence_reporting_compatibility.py -tests/test_v10627_pr10_workflow_error_recovery.py -tests/test_v10642_workflow_lifecycle.py -tests/test_v10643_phase2_forensic_closure.py +tests/test_v10638_portable_runtime_root_fix.py +tests/test_v10644_chrome_tls_transport.py vibproject.ygit +project/CURRENT_PROJECT_STATE.md +project/README.md +project/updates/v1.0.6.44-final-release-chrome-tls/00_SCOPE_LOCK.md +project/updates/v1.0.6.44-final-release-chrome-tls/01_FORENSIC_AUDIT_REPORT.md +project/updates/v1.0.6.44-final-release-chrome-tls/02_ROOT_CAUSE_AND_FIX.md +project/updates/v1.0.6.44-final-release-chrome-tls/03_VERIFICATION_MATRIX.md +project/updates/v1.0.6.44-final-release-chrome-tls/04_ACTUAL_IMPLEMENTATION_STATUS.md diff --git a/PATCH_MANIFEST.md b/PATCH_MANIFEST.md index 5b2ea17..7d25b70 100644 --- a/PATCH_MANIFEST.md +++ b/PATCH_MANIFEST.md @@ -1,54 +1,46 @@ -# VibraPilot v1.0.6.43 — Phase 2 Forensic Closure Replace-Ready Patch +# VibraPilot v1.0.6.44 — Final Release Chrome TLS Closure Replace-Ready Patch ## Official baseline -- Input: `VibraPilot_Official_v1.0.6.42_Baseline(1).zip` -- Input SHA-256: `0713798e061b0eef15c1a1d4cb52e1347687f7498419b9ab1a79b3017f31dae1` -- Baseline version: `1.0.6.42` -- Baseline branch commit: `8c3e9a137ecf852aa152dba0590414e7f8f6209d` -- Baseline Git tree: `c61a9864e99659bf0a3d3cb229e1ad6e5e85cb69` -- Target version: `1.0.6.43` - -## Corrective scope - -- restart-free historical workflow-switch compatibility service; -- lifecycle transaction root/type and workflow-identity fail-closed validation; -- schema-v2 workspace Task-shell preservation when workflow identity is unresolved/unavailable; -- unresolved legacy unfinished-run package-mutation blocking; -- same-session live lifecycle transaction blocking for package mutation, Task creation and browser start; -- Default Workflow UI semantics replacing residual global `ACTIVE` wording; -- removal of one duplicated staging-directory setup statement. - -## Production source changes - -- `src/vibrapilot/qt_app.py` -- `src/vibrapilot/workflow/plugin_loader.py` -- `src/vibrapilot/workspace_state.py` - -Chrome prerequisite/runtime/installer/AuthentiCode, Plugin API 1, backend worker logic, runtime DB schema-v2 implementation, power, licensing, settings defaults, dependencies, CI and portable packaging are frozen from v1.0.6.42. - -## Verification evidence - -- v1.0.6.42 baseline: repository verifier PASS; pytest 541 passed / 6 skipped / 105 subtests; unittest 201 OK / 6 skipped; compileall PASS. -- tests-first v1.0.6.43 reproduction: 8 concrete failures reproduced / 1 guard already passing. -- corrected v1.0.6.43 closure tests: 9 PASS. -- targeted historical/current correction gate: 123 PASS. -- broader Phase-1/Phase-2/persistence/Chrome gate: 190 PASS. -- frozen SHA audit: PASS. -- metadata/current scope tests: 13 PASS; repository verifier PASS. -- final full pytest: 550 passed, 6 skipped, 105 subtests passed. -- final full unittest: 201 OK, 6 skipped. -- compileall: PASS. -- `git diff --check`: PASS. -- deleted files: 0. +- Input: `VibraPilot_Official_v1.0.6.43_Baseline(2).zip` +- Input SHA-256: `eb3d838d9fcdd1c1597883b820942b362123d3bb47190295a1f3565f37005002` +- Baseline version: `1.0.6.43` +- GitHub main merge: `8d76720740f9d822afb7ce5bc4f04f1e2407b5e9` +- Baseline source commit: `ab148f8137c1066e497136d6246ac6f84db54024` +- Baseline tree: `1fa6033f55e59d7abcdfa1fe62a781edb4024f36` +- Target version: `1.0.6.44` + +## Confirmed defect and correction + +The portable Windows Chrome prerequisite downloader used Python `urllib` and reproduced `CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate`. The default network transport now uses the existing Requests dependency with mandatory TLS verification. Automatic redirects are disabled; every redirect is validated against the exact approved `https://dl.google.com/dl/chrome/install/googlechromestandaloneenterprise64.msi` policy. Windows Authenticode trust and Google LLC publisher verification remain mandatory before execution. No insecure SSL or HTTP fallback is added. + +## Production source scope + +- `src/vibrapilot/chrome_installer.py` only. + +Phase-1, Phase-2, workflow lifecycle/multiworkflow, Plugin API 1, schemas, licensing, power, browser profiles, settings defaults, dependencies, CI and portable packaging architecture remain unchanged. + +## Verification + +- baseline repository verifier: PASS +- baseline pytest: 550 passed / 6 skipped / 105 subtests +- baseline unittest: 201 OK / 6 skipped +- tests-first Chrome TLS reproduction: 3 failures before fix +- targeted Chrome gate: 25 PASS +- final repository verifier: PASS +- final pytest: 553 passed / 6 skipped / 105 subtests +- final unittest: 201 OK / 6 skipped +- compileall: PASS +- git diff check: PASS +- deleted files: 0 ## Delta inventory -- Public changed/new files: 30 -- Private/local `project/` files: 15 -- Total Delta entries: 45 -- `project/**` is local/private only and must never be staged/pushed. +- Public changed/new files: 24 +- Private/local `project/` files: 7 +- Total Delta entries: 31 +- `project/**` is local/private only and must never be staged or pushed. -## External gates +## External release gates -Windows live acceptance and GitHub v1.0.6.43 CI remain PENDING and are not claimed PASS. +Real Windows portable Chrome download/install acceptance and GitHub v1.0.6.44 CI/portable build remain pending external evidence. diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md index 30bf882..b9a6ef7 100644 --- a/PROJECT_STRUCTURE.md +++ b/PROJECT_STRUCTURE.md @@ -1,3 +1,9 @@ +# Project Structure — v1.0.6.44 Final Release Closure + +`src/vibrapilot/chrome_installer.py` is the only production source modified. It retains exact Google-source validation and Windows Authenticode/Google LLC verification while using Requests verified TLS transport for the MSI download. + +--- + # Project Structure — v1.0.6.43 Phase 2 Forensic Closure ```text diff --git a/README.md b/README.md index 8fdda09..e98c7fd 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +# VibraPilot v1.0.6.44 — Final Release Candidate + +v1.0.6.44 seals the completed Phase-1/Phase-2 production work and fixes the Windows portable Chrome prerequisite download TLS failure. Chrome installation remains fail-closed: exact approved Google HTTPS source, verified TLS, redirect revalidation, Windows Authenticode trust and Google LLC publisher identity are required before execution. + +--- + # VibraPilot v1.0.6.43 — Phase 2 Forensic Closure v1.0.6.43 is a scope-locked corrective seal over v1.0.6.42. It preserves Workflow Update/Remove/Deactivate, restart-free lifecycle, immutable per-Task workflow identity and true simultaneous multiworkflow execution while closing concrete lifecycle-transaction, legacy-recovery, workspace-preservation and Default Workflow UI semantic gaps. Chrome prerequisite/secure-install, Plugin API 1, licensing, browser-profile, power, dependency, CI and packaging architecture remain unchanged. diff --git a/ROADMAP.md b/ROADMAP.md index d634421..eedd97f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,3 +1,9 @@ +# Current Roadmap — v1.0.6.44 Final Release Closure + +Phase 1: **COMPLETE**. Phase 2: **COMPLETE**. Phase-2 forensic closure: **COMPLETE**. v1.0.6.44 performs final release verification and fixes the reproduced Chrome prerequisite TLS transport failure. No new feature phase is introduced. + +--- + # Current Roadmap — v1.0.6.43 Phase 2 Forensic Closure ## Phase 2 status diff --git a/SHA256SUMS.txt b/SHA256SUMS.txt index 15147ad..eebf0a9 100644 --- a/SHA256SUMS.txt +++ b/SHA256SUMS.txt @@ -1,44 +1,30 @@ -3ca9efd2042d59e05ddf81905cc811c37bce42b23af042a6dc9e14fb38d642c3 CHANGELOG.md -55382d5dafbab1aba4eb0996690d609634536bd8939b23d4aa71e735fb848f42 CITATION.cff -e235132874f0227512d450b8381810b4fa06449050d5adc0d340feee55b46850 COMPATIBILITY.md -f091ee13ba2934dd04d045a2442085c44778ce6d44a003367300652190b9127f DELTA_FILE_LIST.txt -3cb32c4eaa173cbff68b07b04e6a5539d2fe3e6b172b0df28df79e707c1a6d02 PATCH_MANIFEST.md -71397439692a9ba350b1d8e644da373823bb0f314c40491c948885de94e4d812 PROJECT_STRUCTURE.md -fbb8f9040f3b54ed6ae4258dace8ef19e88272f7eff2f0c56c4943eff67356b6 README.md -8e74f72ac687d8382b3ccbe3ebea0b632151f036e3620a58226ddf2d13b37e52 ROADMAP.md -e1d2d87987b77eb6f918b0869752e8e6a33c646f03fb404b685e58117fd827c9 UPDATE_LOG.md -0661aa6b4fc0f4089832dab9d02dd835c236609eca468b38af7d03b057c779e0 VERSIONING.md -4d1e2490170d7757fadf29c08decd2c838ebd1fbcb04c63a7d55732759de6701 config/AppConfig/app.py -279bf322a267bd90c319af0d1a946ecc98f30f1237fb519a15cc2a8fee228b04 config/verification/v1.0.6.43_phase2_forensic_closure_scope.json -126d4fe3c24215edd2a86a8c725e5226d88508f7d760d1fb85c542e0d33d4022 docs/docs.manifest.ygit -6546113c1da8907713592217ecb200abedc9400eea0ed5059f250a12a526e51b docs/index.md -562264a0c3849e3a107d180dc69b6310cdfac8a808397dfd8e72d3f665882324 docs/updates/v1.0.6.43-phase2-forensic-closure.md -83d348427d10e73fb14f2d164a7c0e96572089161e9cbc6f9497fb4ffd79eb8e docs/verification/V1.0.6.43_PHASE2_FORENSIC_CLOSURE.md -47f0891fbab098ff73eec1437e3edc9aa9452a0e09171b595509129be0321909 project/CURRENT_PROJECT_STATE.md -7cacde2453c913fa2514b33961ff42ebfd7952e9ae809bd8457000ec034a39fd project/README.md -8d3c834769da7d236cafe8211ea85847f130a15de94cc6177b0287018f321c8c project/updates/v1.0.6.39-v1.0.6.40-production-readiness/03_PHASE_PROGRESS_COMPLETION_LEDGER.md -f15bc0d550722dc3ce65a62ab067cbc9164f9eba748f34c4e91985e4a9672437 project/updates/v1.0.6.39-v1.0.6.40-production-readiness/04_ERROR_HANDLING_AUDIT_AND_PLAN.md -714c116784765b6b2a4f8e5c1aaf5f3a6c4210cf0a9cfd48dc56e3be671511b2 project/updates/v1.0.6.39-v1.0.6.40-production-readiness/05_ACTUAL_IMPLEMENTATION_STATUS.md -3db19d7fced4da0d62e1cff7219c1ac6986c5990c277a26f2b68ab0ab0296b75 project/updates/v1.0.6.39-v1.0.6.40-production-readiness/07_ACCEPTANCE_TEST_MATRIX.md -48cd5e78ac5583507e1ad54b2f15547526e39e9286c36933e5152c09fec72644 project/updates/v1.0.6.39-v1.0.6.40-production-readiness/08_REQUIREMENTS_TRACEABILITY_MATRIX.md -7800d0bb2edd848946420e0f57cfce362f461ba7e13da63ad78d9bb9ed3d341a project/updates/v1.0.6.42-phase2-workflow-lifecycle-multiworkflow/08_PHASE2_PROGRESS_LEDGER.md -9fc8d56a71d7974c8eb29f481ef637c09ca80edabbd1027cc6361460ca9952fd project/updates/v1.0.6.42-phase2-workflow-lifecycle-multiworkflow/09_ACTUAL_IMPLEMENTATION_STATUS.md -04cbb70c9c31be346ee1a6aaa2c520ddf23f163f40ab3a9e8a99f1b0abe829b1 project/updates/v1.0.6.42-phase2-workflow-lifecycle-multiworkflow/10_FINAL_VERIFICATION_REPORT.md -fa3ee8efabd172f948d0cf916d4ff15125985855b4775835e8b59bae5ea9688b project/updates/v1.0.6.43-phase2-forensic-closure/00_SCOPE_LOCK.md -affa217a6e2f09b6f23e60d7f68ea6bc966b6a9ba32d2458464a9ad8c1dcc074 project/updates/v1.0.6.43-phase2-forensic-closure/01_FORENSIC_AUDIT_REPORT.md -b2ce52ba801b854ad73caab6883574ac75fb9097ea6d80cc9eb11cbdb6dde875 project/updates/v1.0.6.43-phase2-forensic-closure/02_ROOT_CAUSE_AND_FIX_REPORT.md -37759d13937d1598741c8a5bc88c7dafc1a115b2b4e58230b5b4428aa618987d project/updates/v1.0.6.43-phase2-forensic-closure/03_VERIFICATION_MATRIX.md -11c64a20aaa114a4df9558538a95a2b5b7c1a2aeb0eb353282bfe92b4e3bb50e project/updates/v1.0.6.43-phase2-forensic-closure/04_ACTUAL_IMPLEMENTATION_STATUS.md -895eca262c66c06978acba6abf9696ac657e4c6c3872f535239d3988605cd562 pyproject.toml -c58c6f8ca2e7f2de427fa3e559249f30a48754f5fea999214b3d481e24d8fb8b scripts/verify_repository.py -087ae992e95a7778944cfc2a41d692bd19df237b2714eaeeb2b30d7723e6d982 src/vibrapilot/qt_app.py -175b95801aad71d3e01b17f0521cc20eb2ac90384fa00031ff3c52705217746d src/vibrapilot/workflow/plugin_loader.py -b346b90e433f7b1c728887d497783428f6ef2099d82cfacba2e73c8ee4c54f7e src/vibrapilot/workspace_state.py -b043e4573d61da2e2aa441e73b8e86ff64d58aa1fd1e2dca1c5a936c505a3a70 tests/test_app_config.py -2a748ec89fe7ab0ef259279418cf4cc662e1f2ca14d36ffe0eeced790b5c6697 tests/test_v10623_pr06_workflow_state_atomic_switch.py -819040a94cd41a2b156d12f6ccb8baf4e2d99eb26def4c91065b1f699b918fdb tests/test_v10624_pr07_workflow_showcase.py -37110669b838914b656a09f0c4552f82f923b300bda0d7f8c5ab0b055b40d26f tests/test_v10626_pr09_data_persistence_reporting_compatibility.py -7b7e9452dce6ce1e319bfa4966cdeae07773f2baa83b5ab3037757c374914233 tests/test_v10627_pr10_workflow_error_recovery.py -a42c3ef5020d08a0b67cdbb36f6bdd604536dd5e825693056cacd0923d785fbb tests/test_v10642_workflow_lifecycle.py -591135843c74f322df6403f5509b28b5956ae288727836ec8d40bcb70f39adfe tests/test_v10643_phase2_forensic_closure.py -3b483474b389953c16abf8b4c2581704c0a1a8ee0c9bf924c2f7aa0570e7846f vibproject.ygit +ed6d4ae0424574cc2e70ded0842af3bdbd432a507f0afadac169190d38db01b0 CHANGELOG.md +40cff9a939b25a492b8ecb0bfbb7c64e99abe8993b3b0223121a79b322c5c379 CITATION.cff +02a013792fe38a53c3920145da4d23b3262758b374e670a9992e16d65e0260dd COMPATIBILITY.md +c30cf696fce20d3d9fb0f6b4b80414119a217d4d2f03f63e73f510b4ada5242c DELTA_FILE_LIST.txt +dca579355d191c4e6187a8246e1c3da963b9be0177d178c499c6291eb2be055e PATCH_MANIFEST.md +b3d2fe399cb87fa17cb53ad8332cc6a0065950ae3223345803c1dcaf38c888fe PROJECT_STRUCTURE.md +3023e922002373d59dc675dcf55db8552da89fa2b6b136b857da5695a9365b63 README.md +8c52d1d95605eaca1a13a6c2aaf3fa0081c071e39c695bd520bc08b33129e04f ROADMAP.md +ab7f5ac9d9b3fc20fe9fa39952ea751d17079b0dc1f06baaa2c2f7391bdaab6f UPDATE_LOG.md +bbbf6b4fe1b6d5195ad7d1312e4d3f9af154715ca0bfb3a3f1a4413cbc75b084 VERSIONING.md +019fabf5fc986da7132f58bba57495b7b7ef79963bf1a06472815088f879ef97 config/AppConfig/app.py +421c64791e66bd6004c01572ebe4e105c9fc2cf22d3d05efca7643fa97b66077 config/verification/v1.0.6.44_final_release_chrome_tls_scope.json +ac543917c510a49cfb5dcfc5f47f12b1426d49da89d0219ad5a6961f499f8942 docs/docs.manifest.ygit +1efaf8d10ad2f9d588a40895db15c2d20f6a65dbecbfc8c8087195cf4a2d1f94 docs/index.md +e0a019bcf6eddf0aeb787f0eea4870395cf76eda3aac342f31172ca6e5b0e935 docs/updates/v1.0.6.44-final-release-chrome-tls.md +d8861a76e59a2fc89b16942548970ad4a5578d2cd357417029a734d1637999be docs/verification/V1.0.6.44_FINAL_RELEASE_CHROME_TLS.md +cf8b992a3527df77318db2956162bbdcddbe24d60974bf33ffd15a49167166d1 pyproject.toml +a7e438ee0a5a90eef5219dc17fe62c2e6ac946e2ad5a205d8c533c6553d6f777 scripts/verify_repository.py +a80806577bbd65dc7d627800514f74717580fafd6e130bcff100deb33dc3a163 src/vibrapilot/chrome_installer.py +d9483f12960a14a414343dff1448d078232d42b6a9c49df510c09d1ad7778288 tests/test_app_config.py +6d83d38d91f79701bdaa821b5031eedc06671929b4c65a832071abac9c81d1b6 tests/test_v10638_portable_runtime_root_fix.py +5e3de87acec5ea5da43e23fa332decebad03ede2cb19d056ad12f95ddb529712 tests/test_v10644_chrome_tls_transport.py +a9ae4ffeee518b9ed26c248b53a04ef14e3823c20057a69749fbf36176217bb6 vibproject.ygit +3feb1ce17bba4c4bafc07a2c132f4f17149764d5bbc971de16ba11007c090a6f project/CURRENT_PROJECT_STATE.md +d2b124448ede408533c9ebc5ae05b6dfe1db7573fbd0ce6225ac7492bb834e72 project/README.md +eac734115e8b0839d1e37803c136c12d9858e20ac910d944ae84c27ea51a7d80 project/updates/v1.0.6.44-final-release-chrome-tls/00_SCOPE_LOCK.md +8f777c857839bb6b5c59498a726aa1c1e0f0d352f0c487adde1a93aa1063ee0b project/updates/v1.0.6.44-final-release-chrome-tls/01_FORENSIC_AUDIT_REPORT.md +b78de5432bb486051c2846b8067c2d81ddb386a9358bd3407a49738369cf5e30 project/updates/v1.0.6.44-final-release-chrome-tls/02_ROOT_CAUSE_AND_FIX.md +2d4819f8fab3bcfbcdab0265db5e19cbd2ac1eacec0ec54bfa51b6f453c0d5c9 project/updates/v1.0.6.44-final-release-chrome-tls/03_VERIFICATION_MATRIX.md +9f1644af2d589188b7a2c99099553faf4585452a9db93926634141f32fe538ac project/updates/v1.0.6.44-final-release-chrome-tls/04_ACTUAL_IMPLEMENTATION_STATUS.md diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 21e7980..d614a15 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,3 +1,9 @@ +# v1.0.6.44 — Final Release Chrome TLS Closure + +Replaced only the Chrome MSI network transport path with Requests verified-CA HTTPS transport while preserving the existing exact Google source/redirect policy and Authenticode/Google LLC execution gate. Phase-1, Phase-2, UI, persistence, workflow lifecycle and multiworkflow behavior remain unchanged. + +--- + # v1.0.6.43 — Phase 2 Forensic Closure Update Log — 2026-08-18 - Official baseline: v1.0.6.42 / `8c3e9a137ecf852aa152dba0590414e7f8f6209d` / tree `c61a9864e99659bf0a3d3cb229e1ad6e5e85cb69`. diff --git a/VERSIONING.md b/VERSIONING.md index 82afd3d..aa9c0e2 100644 --- a/VERSIONING.md +++ b/VERSIONING.md @@ -1,3 +1,9 @@ +# v1.0.6.44 + +Final-release corrective version over v1.0.6.43. Production code scope is limited to `src/vibrapilot/chrome_installer.py`; completed Phase-1 and Phase-2 architecture remains frozen. + +--- + # v1.0.6.43 Version Boundary - Official input: v1.0.6.42. diff --git a/config/AppConfig/app.py b/config/AppConfig/app.py index 3f5c259..8f4d241 100644 --- a/config/AppConfig/app.py +++ b/config/AppConfig/app.py @@ -12,7 +12,7 @@ DESCRIPTION = "VibraPilot browser automation desktop application by Vib Tools." TAGLINE = "Authorized browser automation desktop application." -VERSION = "1.0.6.43" +VERSION = "1.0.6.44" CREATED_DATE = "2026-08-07" RELEASE_DATE = "2026-08-18" UPDATED_DATE = "2026-08-18" diff --git a/config/verification/v1.0.6.44_final_release_chrome_tls_scope.json b/config/verification/v1.0.6.44_final_release_chrome_tls_scope.json new file mode 100644 index 0000000..eef4207 --- /dev/null +++ b/config/verification/v1.0.6.44_final_release_chrome_tls_scope.json @@ -0,0 +1,91 @@ +{ + "plan_id": "VP-V10644-FINAL-RELEASE-CHROME-TLS-001", + "classification": "Final release forensic closure / Windows Chrome prerequisite verified TLS transport fix only", + "baseline_version": "1.0.6.43", + "target_version": "1.0.6.44", + "baseline_main_commit": "8d76720740f9d822afb7ce5bc4f04f1e2407b5e9", + "baseline_source_commit": "ab148f8137c1066e497136d6246ac6f84db54024", + "baseline_tree": "1fa6033f55e59d7abcdfa1fe62a781edb4024f36", + "baseline_zip": "VibraPilot_Official_v1.0.6.43_Baseline(2).zip", + "baseline_zip_sha256": "eb3d838d9fcdd1c1597883b820942b362123d3bb47190295a1f3565f37005002", + "scope": "Preserve completed Phase-1/Phase-2/forensic-closure behavior and correct the reproduced portable Windows Google Chrome MSI TLS certificate-chain download failure without weakening source, TLS, redirect, Authenticode or publisher policy.", + "allowed_production_source_changes": [ + "src/vibrapilot/chrome_installer.py" + ], + "allowed_runtime_config_changes": [], + "plugin_api_version": 1, + "database_schema": { + "from": 2, + "to": 2, + "changes": 0 + }, + "workspace_schema": { + "from": 2, + "to": 2, + "changes": 0 + }, + "new_top_level_ui_pages": false, + "required_contracts": { + "requests_verified_ca_transport": true, + "tls_verification_mandatory": true, + "automatic_redirects_disabled": true, + "every_redirect_revalidated": true, + "official_google_exact_source_preserved": true, + "authenticode_required": true, + "google_llc_publisher_required": true, + "no_tls_bypass": true, + "no_http_fallback": true, + "no_chromium_fallback": true, + "phase1_phase2_behavior_preserved": true + }, + "frozen_file_sha256": { + "src/vibrapilot/backend.py": "a3badec5f9473aea559ead1f891fa561a6f90c764f76900d87c380c3de7733af", + "src/vibrapilot/qt_app.py": "087ae992e95a7778944cfc2a41d692bd19df237b2714eaeeb2b30d7723e6d982", + "src/vibrapilot/chrome_runtime.py": "f13a64271af900ddb4aaba7af348bed0607be772f5ca4e993bd9cd54173e9fcd", + "src/vibrapilot/windows_authenticode.py": "6f03731087c2eaff23a4b92d25ea9a365c0e7ddef2cecd984824040f4771c6a0", + "src/vibrapilot/power_management.py": "69a8e54bafc825e45492a8e662acf0223adbbbb6617dd08991d16c8077eff6d2", + "src/vibrapilot/task_runtime_store.py": "a5fd334d54d2a512f75f5c2f491727cf475673154a4583c70cada366b486e03a", + "src/vibrapilot/workspace_state.py": "b346b90e433f7b1c728887d497783428f6ef2099d82cfacba2e73c8ee4c54f7e", + "src/vibrapilot/workflow/plugin_loader.py": "175b95801aad71d3e01b17f0521cc20eb2ac90384fa00031ff3c52705217746d", + "src/vibrapilot/workflow/state.py": "e89f94635020db073f00a12c7dc536f2e8a564fc36aae1b1d1d9f5e8dd71099f", + "src/vibrapilot/workflow/manager.py": "d502314d9c17132b3d436b1bdbd73569e618a0f091c1e383cca58914de15bc49", + "src/vibrapilot/workflow/contracts.py": "5c3210746e7e79c905075a887d2fba2a1a9446e4f22bd127e763bd5a18490b2c", + "src/vibrapilot/workflow/schemas.py": "a2b5e48af9530e00206fd21c9e9adf16c7302aa2e0dce7ae0c6b74754458d1a1", + "src/vibrapilot/licensing_v2.py": "36435d05593785b7ec02310dcf2d031342524e95d5be6212591a09277699a91b", + "config/settings.defaults.json": "f0ed6cd3f24d6f18fd0445eaafd75136d128d52dcaca28f5fe438b71f95943ad", + "requirements.txt": "92890827d0d19fe07168cf801d15c96cf48b846813d7f687a04531e40ed2b083", + "requirements-portable.txt": "4c84508a5399ce66ed3d7393e672fa5658d6a55bb6f86ac386dce9ce27f4f861", + "requirements-build.txt": "39d98aacb5781de72933397e6c431b83a4b62aa1177798600db1907c8def53eb", + ".github/workflows/ci.yml": "a722955f9860315f77abdeb8b75cd1bfc269db24e8d46d437dd678917ba258a3", + ".github/workflows/portable-release.yml": "342bd815df0fa4e34170eaaecc5c47abc2619a9d600718b7f7ac564fa4586a62" + }, + "private_project_docs": { + "path": "project/updates/v1.0.6.44-final-release-chrome-tls/", + "github_public": false + }, + "authorized_nonproduction_files": [ + "config/AppConfig/app.py", + "pyproject.toml", + "CITATION.cff", + "vibproject.ygit", + "scripts/verify_repository.py", + "config/verification/v1.0.6.44_final_release_chrome_tls_scope.json", + "CHANGELOG.md", + "README.md", + "UPDATE_LOG.md", + "VERSIONING.md", + "ROADMAP.md", + "COMPATIBILITY.md", + "PROJECT_STRUCTURE.md", + "PATCH_MANIFEST.md", + "DELTA_FILE_LIST.txt", + "SHA256SUMS.txt", + "docs/index.md", + "docs/docs.manifest.ygit", + "docs/updates/v1.0.6.44-final-release-chrome-tls.md", + "docs/verification/V1.0.6.44_FINAL_RELEASE_CHROME_TLS.md", + "tests/test_app_config.py", + "tests/test_v10644_chrome_tls_transport.py", + "tests/test_v10638_portable_runtime_root_fix.py" + ] +} diff --git a/docs/docs.manifest.ygit b/docs/docs.manifest.ygit index 65d1711..6ae651e 100644 --- a/docs/docs.manifest.ygit +++ b/docs/docs.manifest.ygit @@ -3,12 +3,12 @@ "documentation": { "id": "vibrapilot", "title": "VibraPilot Documentation", - "description": "Documentation for VibraPilot v1.0.6.43 Phase 2 Forensic Closure.", - "version": "1.0.6.43", + "description": "Documentation for VibraPilot v1.0.6.44 final release Chrome TLS closure.", + "version": "1.0.6.44", "root": "docs", "home": "index.md" }, "product": { - "description": "v1.0.6.43 closes proven Phase-2 lifecycle transaction, restart-free switch compatibility, workspace preservation and Default Workflow UI semantic gaps without changing the frozen Chrome secure-install implementation." + "description": "v1.0.6.44 seals completed Phase-1/Phase-2 behavior and fixes the portable Windows Chrome prerequisite verified TLS download path without weakening installer trust policy." } } diff --git a/docs/index.md b/docs/index.md index 553ffb7..f09b60e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,3 +1,9 @@ +# VibraPilot v1.0.6.44 + +Final release forensic closure: Phase-1 and Phase-2 remain complete; the Chrome prerequisite MSI download now uses verified Requests CA transport while exact Google source, redirect, Authenticode and Google LLC policies remain enforced. + +--- + # VibraPilot Documentation — v1.0.6.43 Phase 2 Forensic Closure - Update: `docs/updates/v1.0.6.43-phase2-forensic-closure.md` diff --git a/docs/updates/v1.0.6.44-final-release-chrome-tls.md b/docs/updates/v1.0.6.44-final-release-chrome-tls.md new file mode 100644 index 0000000..d9ac53f --- /dev/null +++ b/docs/updates/v1.0.6.44-final-release-chrome-tls.md @@ -0,0 +1,13 @@ +# v1.0.6.44 — Final Release Chrome TLS Closure + +## Baseline + +v1.0.6.43, GitHub main merge `8d76720740f9d822afb7ce5bc4f04f1e2407b5e9`, tree `1fa6033f55e59d7abcdfa1fe62a781edb4024f36`. + +## Fix + +The Chrome prerequisite downloader no longer depends on the portable `urllib`/OpenSSL default certificate path. It uses the already-required Requests stack with TLS verification explicitly enabled. Redirect following is manual and every target must pass the existing exact `dl.google.com` Stable x64 MSI policy. Authenticode and Google LLC signer verification remain mandatory before execution. + +## Frozen + +Phase-1/Phase-2 runtime architecture, Plugin API 1, schemas, licensing, power, browser profiles, settings, dependencies, CI and portable packaging architecture are unchanged. diff --git a/docs/verification/V1.0.6.44_FINAL_RELEASE_CHROME_TLS.md b/docs/verification/V1.0.6.44_FINAL_RELEASE_CHROME_TLS.md new file mode 100644 index 0000000..09e5079 --- /dev/null +++ b/docs/verification/V1.0.6.44_FINAL_RELEASE_CHROME_TLS.md @@ -0,0 +1,21 @@ +# v1.0.6.44 Final Release Chrome TLS Verification + +Required contracts: + +- official Google HTTPS MSI source only; +- Requests TLS verification enabled; +- automatic redirects disabled; every redirect revalidated; +- no `verify=False`, unverified SSL context, HTTP fallback or Chromium fallback; +- Windows Authenticode trust and Google LLC publisher verification remain mandatory; +- Phase-1 and Phase-2 regression suites remain green. + +## Automated result + +- repository verifier: PASS +- pytest: 553 passed, 6 skipped, 105 subtests passed +- unittest: 201 OK, 6 skipped +- compileall: PASS +- git diff check: PASS +- production source delta: `src/vibrapilot/chrome_installer.py` only + +Real Windows portable download/install acceptance remains an external release gate. diff --git a/pyproject.toml b/pyproject.toml index 59f7728..8b068cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "vibrapilot" -version = "1.0.6.43" +version = "1.0.6.44" description = "VibraPilot browser automation desktop application by Vib Tools." requires-python = ">=3.12,<3.13" license = {text = "GPL-3.0-only"} diff --git a/scripts/verify_repository.py b/scripts/verify_repository.py index a9287eb..4060c1a 100644 --- a/scripts/verify_repository.py +++ b/scripts/verify_repository.py @@ -62,6 +62,7 @@ V10641_PHASE1_ACTIVE_PAGE_ORIGIN_CLOSURE_SCOPE_CONTRACT = ROOT / "config" / "verification" / "v1.0.6.41_phase1_active_page_origin_closure_scope.json" V10642_PHASE2_WORKFLOW_LIFECYCLE_MULTIWORKFLOW_SCOPE_CONTRACT = ROOT / "config" / "verification" / "v1.0.6.42_phase2_workflow_lifecycle_multiworkflow_scope.json" V10643_PHASE2_FORENSIC_CLOSURE_SCOPE_CONTRACT = ROOT / "config" / "verification" / "v1.0.6.43_phase2_forensic_closure_scope.json" +V10644_FINAL_RELEASE_CHROME_TLS_SCOPE_CONTRACT = ROOT / "config" / "verification" / "v1.0.6.44_final_release_chrome_tls_scope.json" APP_CONFIG_ROOT = ROOT / "config" / "AppConfig" APP_CONFIG_APP = APP_CONFIG_ROOT / "app.py" @@ -467,11 +468,29 @@ def ast_contract_sha(node: ast.AST) -> str: ) v10643_worker_methods = set(v10643_scope.get("authorized_automationworker_method_changes", [])) +# v1.0.6.44 is the final-release forensic seal. It may change only the +# reproduced Chrome prerequisite TLS download transport surface. +if not V10644_FINAL_RELEASE_CHROME_TLS_SCOPE_CONTRACT.is_file(): + fail("v1.0.6.44 final release Chrome TLS scope contract is missing") +try: + v10644_scope = json.loads( + V10644_FINAL_RELEASE_CHROME_TLS_SCOPE_CONTRACT.read_text(encoding="utf-8") + ) +except Exception as exc: + fail(f"v1.0.6.44 Chrome TLS scope contract is invalid: {exc}") +v10644_production_allowed = set(v10644_scope.get("allowed_production_source_changes", [])) +v10644_allowed_files = ( + v10644_production_allowed + | set(v10644_scope.get("allowed_runtime_config_changes", [])) + | set(v10644_scope.get("authorized_nonproduction_files", [])) +) +v10644_worker_methods = set() + current_worker_methods = ( - v10630_worker_methods | v10631_worker_methods | v10632_worker_methods | v10633_worker_methods | v10635_worker_methods | v10636_worker_methods | v10639_worker_methods | v10640_worker_methods | v10641_worker_methods | v10642_worker_methods | v10643_worker_methods + v10630_worker_methods | v10631_worker_methods | v10632_worker_methods | v10633_worker_methods | v10635_worker_methods | v10636_worker_methods | v10639_worker_methods | v10640_worker_methods | v10641_worker_methods | v10642_worker_methods | v10643_worker_methods | v10644_worker_methods ) current_allowed_files = ( - v10630_allowed_files | v10631_allowed_files | v10632_allowed_files | v10633_allowed_files | v10634_allowed_files | v10635_allowed_files | v10636_allowed_files | v10637_allowed_files | v10638_allowed_files | v10639_allowed_files | v10640_allowed_files | v10641_allowed_files | v10642_allowed_files | v10643_allowed_files + v10630_allowed_files | v10631_allowed_files | v10632_allowed_files | v10633_allowed_files | v10634_allowed_files | v10635_allowed_files | v10636_allowed_files | v10637_allowed_files | v10638_allowed_files | v10639_allowed_files | v10640_allowed_files | v10641_allowed_files | v10642_allowed_files | v10643_allowed_files | v10644_allowed_files ) if pr08_allowed_files != { "src/vibrapilot/workflow_inputs.py", @@ -2727,7 +2746,7 @@ def ast_contract_sha(node: ast.AST) -> str: if set(v10639_scope.get("allowed_runtime_config_changes", [])) != {"config/settings.defaults.json"}: fail("v1.0.6.39 Phase 1 runtime config scope mismatch") for relative, expected_sha in v10639_scope.get("frozen_file_sha256", {}).items(): - if relative in v10642_production_allowed: + if relative in v10642_production_allowed or relative in v10644_production_allowed: continue path = ROOT / relative if not path.is_file() or sha256(path) != expected_sha: @@ -2774,7 +2793,7 @@ def ast_contract_sha(node: ast.AST) -> str: if v10640_scope.get("allowed_runtime_config_changes", []) != []: fail("v1.0.6.40 must not alter the v1.0.6.39 runtime settings policy") for relative, expected_sha in v10640_scope.get("frozen_file_sha256", {}).items(): - if relative in v10642_production_allowed: + if relative in v10642_production_allowed or relative in v10644_production_allowed: continue path = ROOT / relative if not path.is_file() or sha256(path) != expected_sha: @@ -2821,7 +2840,7 @@ def ast_contract_sha(node: ast.AST) -> str: if v10641_scope.get("allowed_runtime_config_changes", []) != []: fail("v1.0.6.41 must not alter runtime settings") for relative, expected_sha in v10641_scope.get("frozen_file_sha256", {}).items(): - if relative in v10642_production_allowed: + if relative in v10642_production_allowed or relative in v10644_production_allowed: continue path = ROOT / relative if not path.is_file() or sha256(path) != expected_sha: @@ -2867,6 +2886,8 @@ def ast_contract_sha(node: ast.AST) -> str: if v10642_scope.get("chrome_implementation_changes") != 0: fail("v1.0.6.42 Chrome implementation must remain frozen unless a proven defect exists") for relative, expected_sha in v10642_scope.get("frozen_file_sha256", {}).items(): + if relative in v10644_production_allowed: + continue path = ROOT / relative if not path.is_file() or sha256(path) != expected_sha: fail(f"v1.0.6.42 frozen surface drift detected: {relative}") @@ -2953,6 +2974,8 @@ def ast_contract_sha(node: ast.AST) -> str: if v10643_scope.get("chrome_implementation_changes") != 0: fail("v1.0.6.43 Chrome implementation must remain frozen") for relative, expected_sha in v10643_scope.get("frozen_file_sha256", {}).items(): + if relative == "src/vibrapilot/chrome_installer.py" and literal_assignment(APP_CONFIG_APP, "VERSION") == "1.0.6.44": + continue path = ROOT / relative if not path.is_file() or sha256(path) != expected_sha: fail(f"v1.0.6.43 frozen surface drift detected: {relative}") @@ -3004,6 +3027,49 @@ def ast_contract_sha(node: ast.AST) -> str: if 'launch_args["channel"] = "chromium"' in backend_text: fail("v1.0.6.43 must not reintroduce Chromium fallback") +# v1.0.6.44 final-release Chrome TLS exact scope. +if v10644_scope.get("plan_id") != "VP-V10644-FINAL-RELEASE-CHROME-TLS-001": + fail("v1.0.6.44 final release plan identifier mismatch") +if v10644_scope.get("baseline_version") != "1.0.6.43" or v10644_scope.get("target_version") != "1.0.6.44": + fail("v1.0.6.44 version boundary mismatch") +if v10644_scope.get("baseline_main_commit") != "8d76720740f9d822afb7ce5bc4f04f1e2407b5e9": + fail("v1.0.6.44 baseline main commit mismatch") +if v10644_scope.get("baseline_source_commit") != "ab148f8137c1066e497136d6246ac6f84db54024": + fail("v1.0.6.44 baseline source commit mismatch") +if v10644_scope.get("baseline_tree") != "1fa6033f55e59d7abcdfa1fe62a781edb4024f36": + fail("v1.0.6.44 baseline tree mismatch") +if v10644_scope.get("baseline_zip_sha256") != "eb3d838d9fcdd1c1597883b820942b362123d3bb47190295a1f3565f37005002": + fail("v1.0.6.44 baseline ZIP hash mismatch") +if v10644_production_allowed != {"src/vibrapilot/chrome_installer.py"}: + fail("v1.0.6.44 production source scope mismatch") +if v10644_scope.get("allowed_runtime_config_changes", []) != []: + fail("v1.0.6.44 must not change runtime settings defaults") +if v10644_scope.get("plugin_api_version") != 1: + fail("v1.0.6.44 must preserve external Workflow Plugin API 1") +if v10644_scope.get("new_top_level_ui_pages") is not False: + fail("v1.0.6.44 must not add a top-level navigation page") +for relative, expected_sha in v10644_scope.get("frozen_file_sha256", {}).items(): + path = ROOT / relative + if not path.is_file() or sha256(path) != expected_sha: + fail(f"v1.0.6.44 frozen surface drift detected: {relative}") +chrome_v10644 = (SRC / "chrome_installer.py").read_text(encoding="utf-8") +for required_marker in ( + "import requests", + "class _RequestsDownloadResponse", + "verify=True", + "allow_redirects=False", + "validate_download_url(redirected)", + 'GOOGLE_CHROME_EXPECTED_PUBLISHER = "Google LLC"', + "verify_google_chrome_installer", +): + if required_marker not in chrome_v10644: + fail(f"v1.0.6.44 Chrome TLS marker missing: {required_marker}") +for insecure_marker in ("verify=False", "_create_unverified_context", "CERT_NONE", 'http://dl.google.com'): + if insecure_marker in chrome_v10644: + fail(f"v1.0.6.44 insecure Chrome TLS marker detected: {insecure_marker}") +if 'launch_args["channel"] = "chromium"' in backend_text: + fail("v1.0.6.44 must not reintroduce Chromium fallback") + app_version = literal_assignment(APP_CONFIG_APP, "VERSION") app_id = literal_assignment(APP_CONFIG_APP, "APP_ID") app_name = literal_assignment(APP_CONFIG_APP, "APP_NAME") @@ -3013,8 +3079,8 @@ def ast_contract_sha(node: ast.AST) -> str: license_identifier = literal_assignment(APP_CONFIG_APP, "LICENSE_IDENTIFIER") homepage_url = literal_assignment(APP_CONFIG_APP, "HOMEPAGE_URL") repository_url = literal_assignment(APP_CONFIG_APP, "REPOSITORY_URL") -if app_version != "1.0.6.43": - fail("AppConfig VERSION must be 1.0.6.43 for the Phase 2 forensic closure candidate") +if app_version != "1.0.6.44": + fail("AppConfig VERSION must be 1.0.6.44 for the final release Chrome TLS closure candidate") for name, value in { "APP_ID": app_id, "APP_NAME": app_name, @@ -3784,6 +3850,7 @@ def ast_contract_sha(node: ast.AST) -> str: "config/verification/v1.0.6.41_phase1_active_page_origin_closure_scope.json", "config/verification/v1.0.6.42_phase2_workflow_lifecycle_multiworkflow_scope.json", "config/verification/v1.0.6.43_phase2_forensic_closure_scope.json", + "config/verification/v1.0.6.44_final_release_chrome_tls_scope.json", "src/vibrapilot/power_management.py", "src/vibrapilot/chrome_runtime.py", "src/vibrapilot/chrome_installer.py", @@ -3796,6 +3863,7 @@ def ast_contract_sha(node: ast.AST) -> str: "tests/test_v10642_multiworkflow_persistence.py", "tests/test_v10642_chrome_final_acceptance_contract.py", "tests/test_v10643_phase2_forensic_closure.py", + "tests/test_v10644_chrome_tls_transport.py", "src/vibrapilot/workflow/plugin_loader.py", "src/vibrapilot/workflow/schemas.py", "src/vibrapilot/workflow/settings_state.py", "src/vibrapilot/workflow/task_state.py", "config/verification/backend_v1.0.6_contract.json", "docs/index.md", "docs/updates/v1.0.6.31-chrome-only-runtime-foundation.md", @@ -3826,6 +3894,8 @@ def ast_contract_sha(node: ast.AST) -> str: "docs/verification/V1.0.6.42_PHASE2_WORKFLOW_LIFECYCLE_MULTIWORKFLOW.md", "docs/updates/v1.0.6.43-phase2-forensic-closure.md", "docs/verification/V1.0.6.43_PHASE2_FORENSIC_CLOSURE.md", + "docs/updates/v1.0.6.44-final-release-chrome-tls.md", + "docs/verification/V1.0.6.44_FINAL_RELEASE_CHROME_TLS.md", "scripts/diagnostics/verify_v10633_browser_forensic_closure.py", "scripts/diagnostics/verify_v10634_ui_compact_polish.py", "scripts/diagnostics/verify_v10635_workflow_scoped_test_safety.py", diff --git a/src/vibrapilot/chrome_installer.py b/src/vibrapilot/chrome_installer.py index 74eaad9..1089d9c 100644 --- a/src/vibrapilot/chrome_installer.py +++ b/src/vibrapilot/chrome_installer.py @@ -17,6 +17,8 @@ import urllib.error import urllib.parse import urllib.request + +import requests from ctypes import wintypes from dataclasses import dataclass from pathlib import Path @@ -117,14 +119,99 @@ def redirect_request(self, req, fp, code, msg, headers, newurl): # noqa: ANN001 return super().redirect_request(req, fp, code, msg, headers, newurl) +class _RequestsDownloadResponse: + """File-like HTTPS response backed by Requests' verified CA transport.""" + + def __init__(self, session: requests.Session, response: requests.Response, final_url: str) -> None: + self._session = session + self._response = response + self._final_url = final_url + self.headers = response.headers + self._response.raw.decode_content = True + + def read(self, size: int) -> bytes: + return self._response.raw.read(size) + + def geturl(self) -> str: + return self._final_url + + def close(self) -> None: + try: + self._response.close() + finally: + self._session.close() + + def __enter__(self): + return self + + def __exit__(self, *_args) -> bool: + self.close() + return False + + def _default_open(url: str, *, timeout: float): - opener = urllib.request.build_opener(_PolicyRedirectHandler()) - request = urllib.request.Request( - validate_download_url(url), - headers={"User-Agent": "VibraPilot Chrome Prerequisite Installer"}, - method="GET", - ) - return opener.open(request, timeout=timeout) + """Open the approved Google MSI with verified TLS and redirect policy. + + Requests is already a runtime dependency and carries a bundled CA set, which + avoids relying on the frozen executable's OpenSSL default-cert path. TLS + verification stays mandatory and every redirect is revalidated against the + exact Google host/path policy before another request is sent. + """ + current_url = validate_download_url(url) + session = requests.Session() + headers = { + "User-Agent": "VibraPilot Chrome Prerequisite Installer", + "Accept-Encoding": "identity", + } + try: + for _hop in range(6): + response = session.get( + current_url, + headers=headers, + stream=True, + allow_redirects=False, + timeout=timeout, + verify=True, + ) + if 300 <= int(response.status_code) < 400: + location = str(response.headers.get("Location", "") or "").strip() + response.close() + if not location: + raise ChromeInstallError( + "download_redirect_rejected", + "Google Chrome installer download returned an invalid redirect.", + detail="Redirect response did not include a Location header.", + ) + redirected = urllib.parse.urljoin(current_url, location) + try: + current_url = validate_download_url(redirected) + except ValueError as exc: + raise ChromeInstallError( + "download_redirect_rejected", + "Google Chrome installer download redirected outside the approved Google source.", + detail=str(exc), + ) from exc + continue + response.raise_for_status() + final_url = validate_download_url(str(response.url or current_url)) + return _RequestsDownloadResponse(session, response, final_url) + raise ChromeInstallError( + "download_redirect_rejected", + "Google Chrome installer download exceeded the allowed redirect limit.", + ) + except ChromeInstallError: + session.close() + raise + except requests.RequestException as exc: + session.close() + raise ChromeInstallError( + "download_failed", + "Google Chrome installer could not be downloaded from the official Google source.", + detail=str(exc), + ) from exc + except Exception: + session.close() + raise def _emit( @@ -206,7 +293,7 @@ def download_google_chrome_msi( partial_path.unlink(missing_ok=True) final_path.unlink(missing_ok=True) raise - except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, OSError) as exc: + except (urllib.error.URLError, urllib.error.HTTPError, requests.RequestException, TimeoutError, OSError) as exc: partial_path.unlink(missing_ok=True) final_path.unlink(missing_ok=True) raise ChromeInstallError( diff --git a/tests/test_app_config.py b/tests/test_app_config.py index 995434c..aca16dc 100644 --- a/tests/test_app_config.py +++ b/tests/test_app_config.py @@ -24,7 +24,7 @@ def test_authoritative_identity(self): self.assertEqual(APP.app_id, "vibrapilot") self.assertEqual(APP.app_name, "VibraPilot") self.assertEqual(APP.display_name, "VibraPilot") - self.assertEqual(APP.version, "1.0.6.43") + self.assertEqual(APP.version, "1.0.6.44") self.assertEqual(APP.owner_name, "Vib Tools") self.assertEqual(APP.license_identifier, "GPL-3.0-only") self.assertEqual(APP.updated_date, "2026-08-18") diff --git a/tests/test_v10638_portable_runtime_root_fix.py b/tests/test_v10638_portable_runtime_root_fix.py index ef9f3af..0bfbace 100644 --- a/tests/test_v10638_portable_runtime_root_fix.py +++ b/tests/test_v10638_portable_runtime_root_fix.py @@ -16,6 +16,7 @@ SCOPE = ROOT / "config/verification/v1.0.6.38_portable_runtime_root_fix_scope.json" V10639_SCOPE = ROOT / "config/verification/v1.0.6.39_runtime_reliability_session_policy_scope.json" V10642_SCOPE = ROOT / "config/verification/v1.0.6.42_phase2_workflow_lifecycle_multiworkflow_scope.json" +V10644_SCOPE = ROOT / "config/verification/v1.0.6.44_final_release_chrome_tls_scope.json" def _sha256(path: Path) -> str: @@ -94,6 +95,10 @@ def test_v10638_freezes_runtime_and_build_surfaces_outside_root_helper(): phase2 = json.loads(V10642_SCOPE.read_text(encoding="utf-8")) later_allowed.update(phase2.get("allowed_production_source_changes", [])) later_allowed.update(phase2.get("allowed_runtime_config_changes", [])) + if V10644_SCOPE.is_file(): + final_release = json.loads(V10644_SCOPE.read_text(encoding="utf-8")) + later_allowed.update(final_release.get("allowed_production_source_changes", [])) + later_allowed.update(final_release.get("allowed_runtime_config_changes", [])) for relative, expected in scope["frozen_file_sha256"].items(): if relative in later_allowed: continue diff --git a/tests/test_v10644_chrome_tls_transport.py b/tests/test_v10644_chrome_tls_transport.py new file mode 100644 index 0000000..a0bf0b3 --- /dev/null +++ b/tests/test_v10644_chrome_tls_transport.py @@ -0,0 +1,95 @@ +from __future__ import annotations + +from pathlib import Path + +import pytest + + +APPROVED = "https://dl.google.com/dl/chrome/install/googlechromestandaloneenterprise64.msi" + + +def test_v10644_default_transport_uses_requests_with_tls_verification_and_no_auto_redirect(monkeypatch): + from src.vibrapilot import chrome_installer + + calls = [] + + class Raw: + decode_content = False + def read(self, _size): + return b"" + + class Response: + status_code = 200 + headers = {"Content-Length": "0"} + raw = Raw() + url = APPROVED + def raise_for_status(self): + return None + def close(self): + pass + + class Session: + def get(self, url, **kwargs): + calls.append((url, kwargs)) + return Response() + def close(self): + pass + + monkeypatch.setattr(chrome_installer.requests, "Session", Session) + with chrome_installer._default_open(APPROVED, timeout=12.5) as response: + assert response.geturl() == APPROVED + + assert calls == [ + ( + APPROVED, + { + "headers": { + "User-Agent": "VibraPilot Chrome Prerequisite Installer", + "Accept-Encoding": "identity", + }, + "stream": True, + "allow_redirects": False, + "timeout": 12.5, + "verify": True, + }, + ) + ] + + +def test_v10644_requests_transport_revalidates_every_redirect(monkeypatch): + from src.vibrapilot import chrome_installer + + class Raw: + decode_content = False + def read(self, _size): + return b"" + + class Redirect: + status_code = 302 + headers = {"Location": "https://evil.example/chrome.msi"} + raw = Raw() + url = APPROVED + def close(self): + pass + + class Session: + def get(self, *_args, **_kwargs): + return Redirect() + def close(self): + pass + + monkeypatch.setattr(chrome_installer.requests, "Session", Session) + with pytest.raises(chrome_installer.ChromeInstallError) as exc: + chrome_installer._default_open(APPROVED, timeout=10) + assert exc.value.code == "download_redirect_rejected" + + +def test_v10644_tls_transport_keeps_authenticode_execution_gate_and_no_insecure_bypass(): + source = Path("src/vibrapilot/chrome_installer.py").read_text(encoding="utf-8") + assert "verify=True" in source + assert "allow_redirects=False" in source + assert "verify=False" not in source + assert "_create_unverified_context" not in source + assert "CERT_NONE" not in source + assert "verify_google_chrome_installer" in source + assert "GOOGLE_CHROME_EXPECTED_PUBLISHER = \"Google LLC\"" in source diff --git a/vibproject.ygit b/vibproject.ygit index 57bae08..d736091 100644 --- a/vibproject.ygit +++ b/vibproject.ygit @@ -8,8 +8,8 @@ "slug": "vibrapilot", "displayName": "VibraPilot", "description": "VibraPilot browser automation desktop application by Vib Tools.", - "summary": "VibraPilot v1.0.6.43 closes concrete Phase-2 workflow lifecycle safety and default-workflow semantic gaps while preserving the v1.0.6.42 multiworkflow architecture and all frozen Chrome, licensing, power, dependency, CI and packaging surfaces.", - "version": "1.0.6.43", + "summary": "VibraPilot v1.0.6.44 final-release forensic seal fixes the Windows portable Chrome installer TLS download path while preserving exact Google-source, verified HTTPS, Authenticode/Google LLC execution gates and all completed Phase-1/Phase-2 behavior.", + "version": "1.0.6.44", "status": "production", "visibility": "private", "category": "desktop-application",