diff --git a/.github/workflows/originweave-mv3-evidence.yml b/.github/workflows/originweave-mv3-evidence.yml new file mode 100644 index 0000000000..6d9b83ed08 --- /dev/null +++ b/.github/workflows/originweave-mv3-evidence.yml @@ -0,0 +1,89 @@ +name: Reusable OriginWeave sandboxed MV3 evidence + +on: + workflow_call: + +permissions: + contents: read + +jobs: + chrome-for-testing: + name: Pinned Chrome for Testing MV3 fixture + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - name: Harden runner and block undeclared egress + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: block + disable-telemetry: true + allowed-endpoints: >- + api.github.com:443 + github.com:443 + codeload.github.com:443 + objects.githubusercontent.com:443 + release-assets.githubusercontent.com:443 + storage.googleapis.com:443 + *.actions.githubusercontent.com:443 + *.blob.core.windows.net:443 + results-receiver.actions.githubusercontent.com:443 + + - name: Verify OriginWeave caller + shell: bash + run: test "$GITHUB_REPOSITORY" = "ContextualWisdomLab/OriginWeave" + + - name: Checkout exact caller revision + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + persist-credentials: false + + - name: Download and verify exact Chrome for Testing pair + shell: bash + env: + CHROME_VERSION: "150.0.7871.129" + run: | + set -euo pipefail + base="https://storage.googleapis.com/chrome-for-testing-public/${CHROME_VERSION}/linux64" + curl --fail --location --proto '=https' --tlsv1.2 --retry 3 \ + --output chrome-linux64.zip "${base}/chrome-linux64.zip" + curl --fail --location --proto '=https' --tlsv1.2 --retry 3 \ + --output chromedriver-linux64.zip "${base}/chromedriver-linux64.zip" + printf '%s %s\n' \ + '3c8aa248aab79834862fcdc7593181b82b9079feb4a192d9ca1855c576e50060' \ + 'chrome-linux64.zip' \ + 'eb71d98fc5415d03f02949cad0bf7b2eba02715ade6fbeedefcb4d783f7695f3' \ + 'chromedriver-linux64.zip' \ + > mv3-download-sha256.txt + sha256sum --check mv3-download-sha256.txt + mkdir -p .mv3-browser + unzip -q chrome-linux64.zip -d .mv3-browser + unzip -q chromedriver-linux64.zip -d .mv3-browser + chmod 0755 \ + .mv3-browser/chrome-linux64/chrome \ + .mv3-browser/chromedriver-linux64/chromedriver + sudo chown root:root .mv3-browser/chrome-linux64/chrome_sandbox + sudo chmod 4755 .mv3-browser/chrome-linux64/chrome_sandbox + + - name: Execute OriginWeave browser evidence + shell: bash + env: + CHROME_BIN: ${{ github.workspace }}/.mv3-browser/chrome-linux64/chrome + CHROMEDRIVER_BIN: ${{ github.workspace }}/.mv3-browser/chromedriver-linux64/chromedriver + CHROME_DEVEL_SANDBOX: ${{ github.workspace }}/.mv3-browser/chrome-linux64/chrome_sandbox + run: | + set -euo pipefail + "$CHROME_BIN" --version + "$CHROMEDRIVER_BIN" --version + python3 scripts/ci/run_mv3_compatibility.py | tee mv3-compatibility.json + + - name: Upload bounded compatibility evidence + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: mv3-compatibility-${{ github.event.pull_request.head.sha || github.sha }} + path: | + mv3-download-sha256.txt + mv3-compatibility.json + if-no-files-found: warn + retention-days: 7 diff --git a/AGENTS.md b/AGENTS.md index e955f8b36a..42831ab988 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -188,6 +188,9 @@ them alone proves succession. or merge-base rather than `origin/main` once `main` has moved past it. If the failure reproduces on the baseline it is pre-existing: repair it as its own pull request and name the change that introduced it. +- When a host interpreter lacks `pytest`, use `uv run pytest` for the same + repository-local check. Do not add an `uv.lock` created solely by that + ad-hoc verification if this repository does not already track one. - When you change a workflow file or a `scripts/ci/` module, grep the whole `tests/` tree for every literal you touched — event-type strings, cron expressions, environment-variable names, tuple members, pinned digests — not only the obviously named sibling test. A change diff --git a/CHANGELOG.md b/CHANGELOG.md index bf192f6a9e..24a3fe9faa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,10 @@ - Raised `hourly-review-repair.yml`'s discovery ceiling from 50 to 200 while rotating deterministic 50-PR deep-inspection windows by hourly run number. The scheduler hydrates only the selected window and stops immediately after its single dispatch, preserving access to newer PRs without quadrupling expensive review/check/comment work. See `docs/doctoring/hourly-review-repair-single-file-consolidation.md`'s 2026-09-03 follow-up. ## [Unreleased] +- Add a reusable, read-only OriginWeave MV3 evidence workflow that verifies the + exact Chrome/ChromeDriver archives, configures Chromium's sandbox helper, + executes the product-owned runner at the caller head, and retains bounded + evidence without accepting secrets or caller-authored shell input. - Include merge-scheduler entrypoint, core, and regression-test changes in the existing runtime-quality workflow's trigger and suite selector. Scheduler workflow edits retain queue checks and also select the full review-repair diff --git a/CLAUDE.md b/CLAUDE.md index 30db1fc23b..aaf00921a7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -102,6 +102,10 @@ coverage run -m pytest tests && coverage report --show-missing interrogate ``` +If the host interpreter does not provide `pytest`, run the same repository-local +checks with `uv run pytest`; do not commit an `uv.lock` generated only for that +ad-hoc verification when this repository does not track one. + ## Hash-pinned requirements discipline CI installs Python tools only with `pip install --require-hashes` from the `*-hashes.txt` files. diff --git a/docs/doctoring/originweave-mv3-evidence.md b/docs/doctoring/originweave-mv3-evidence.md new file mode 100644 index 0000000000..e0ff9c95c2 --- /dev/null +++ b/docs/doctoring/originweave-mv3-evidence.md @@ -0,0 +1,36 @@ +# OriginWeave sandboxed browser evidence + +The reusable `originweave-mv3-evidence.yml` workflow owns the trusted runner, +Chrome for Testing supply-chain, sandbox-helper, and artifact mechanics for +OriginWeave's real-browser evidence. Product fixtures and interpretation remain +in OriginWeave; the central workflow executes its checked-out +`scripts/ci/run_mv3_compatibility.py` entry point at the exact caller revision. + +The workflow accepts only the OriginWeave repository, grants read-only contents +permission, downloads Chrome and ChromeDriver 150.0.7871.129 over declared +egress, verifies both archives against SHA-256 values recovered from successful +OriginWeave run 33866932365, and configures the archive's root-owned mode-4755 +`chrome_sandbox` through `CHROME_DEVEL_SANDBOX`. It receives no secrets and +does not contain product browser policy. + +An OriginWeave caller must pin this workflow file to the reviewed protected-main +commit that introduces it. A branch or tag reference is not accepted evidence. +Changing the browser build, checksums, sandbox mechanism, permissions, egress, +or artifact contract requires a new central review and fresh consumer execution. + +This owner workflow does not itself prove an OriginWeave feature. Acceptance +still requires an exact-head consumer run whose product-owned runner emits all +required trials and surfaces successfully. Runner unavailability, archive +verification failure, browser-session startup failure, product-contract +failure, and cancellation remain distinct from a successful run. + +## 2026-09-09 owner restack verification + +The owner branch was behind `main` at `6e356c3ad75bfd978e3dd9d3e20e5596c4df3aa6`. +It was non-force-restacked with `origin/main` as +`9c1417b6366d209a140b74bbd47cddf9597108c9`. The focused workflow contract +passed (`1 passed`), followed by the central suite (`2994 passed, 1 skipped, +21 subtests passed`). The local verifier generated an untracked `uv.lock`; it +is not part of the owner change. This is owner-source evidence only: it does +not establish a reviewed release, a protected-main pin, or a successful +OriginWeave consumer run. diff --git a/tests/test_originweave_mv3_workflow_contract.py b/tests/test_originweave_mv3_workflow_contract.py new file mode 100644 index 0000000000..36b4b740f7 --- /dev/null +++ b/tests/test_originweave_mv3_workflow_contract.py @@ -0,0 +1,27 @@ +"""Contract for the centrally owned OriginWeave browser-evidence workflow.""" + +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +WORKFLOW = ROOT / ".github" / "workflows" / "originweave-mv3-evidence.yml" + + +def test_originweave_mv3_workflow_is_pinned_sandboxed_and_least_privilege() -> None: + """The owner workflow must verify artifacts and preserve Chromium sandboxing.""" + + workflow = WORKFLOW.read_text(encoding="utf-8") + assert "workflow_call:" in workflow + assert "permissions:\n contents: read" in workflow + assert "ContextualWisdomLab/OriginWeave" in workflow + assert "150.0.7871.129" in workflow + assert "3c8aa248aab79834862fcdc7593181b82b9079feb4a192d9ca1855c576e50060" in workflow + assert "eb71d98fc5415d03f02949cad0bf7b2eba02715ade6fbeedefcb4d783f7695f3" in workflow + assert "sha256sum --check" in workflow + assert "sudo chown root:root" in workflow + assert "sudo chmod 4755" in workflow + assert "CHROME_DEVEL_SANDBOX" in workflow + assert "--no-sandbox" not in workflow + assert "scripts/ci/run_mv3_compatibility.py" in workflow + assert "secrets:" not in workflow + assert "persist-credentials: false" in workflow