From effc805e04d61b91f094636738f69063a92c7159 Mon Sep 17 00:00:00 2001 From: Sam Gbafa Date: Sat, 17 Oct 2026 10:02:08 +0000 Subject: [PATCH 1/3] ci(TC-887): resolve the w5 workspace with --locked using a policy-engine deploy key A w5-lockfile job resolves test/w5-policy-runtime-node-e2e with --locked once a read-only deploy key for TinyCloudLabs/policy-engine is in the POLICY_ENGINE_DEPLOY_KEY secret; without it the job skips with a notice. The key lives in an ssh-agent for the cargo step only, checkout keeps no credentials, GitHub's host key is pinned and only that repository's URL is rewritten. The email-claim verifier fixture becomes its own workspace, so cargo loads it standalone; a root exclude cannot reach it under the tinycloud-node-server member. --- .github/workflows/rust.yml | 44 +++++++++++++++++++ .../fixtures/email-claim-v1/rust/Cargo.toml | 4 ++ 2 files changed, 48 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 108d0cc0..bce869c2 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -304,3 +304,47 @@ jobs: if [ -f "$TC887_STATE" ]; then bash scripts/at-rest-harness/harness.sh down --purge "$TC887_STATE" fi + + # TC-887: test/w5-policy-runtime-node-e2e depends on the private + # TinyCloudLabs/policy-engine repository by git, so the workflow token cannot + # resolve it. With a read-only deploy key for that one repository in the + # POLICY_ENGINE_DEPLOY_KEY secret, this job resolves w5 with --locked like + # the other workspaces. Without the secret (fork PRs, or before the key + # exists) it skips with a notice. The key is loaded into an ssh-agent for the + # cargo step only; checkout keeps no credentials. + w5-lockfile: + name: w5 workspace lockfile (private dependency) + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + env: + HAS_DEPLOY_KEY: ${{ secrets.POLICY_ENGINE_DEPLOY_KEY != '' }} + steps: + - name: Skip without the policy-engine deploy key + if: env.HAS_DEPLOY_KEY != 'true' + run: echo "::notice title=w5 lockfile not checked::POLICY_ENGINE_DEPLOY_KEY is not available (fork PR, or the key is not added yet); the w5 --locked resolve was skipped." + - name: Checkout TinyCloud repository + if: env.HAS_DEPLOY_KEY == 'true' + uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: dtolnay/rust-toolchain@1.97.1 + if: env.HAS_DEPLOY_KEY == 'true' + - name: Resolve w5 with --locked + if: env.HAS_DEPLOY_KEY == 'true' + env: + POLICY_ENGINE_DEPLOY_KEY: ${{ secrets.POLICY_ENGINE_DEPLOY_KEY }} + CARGO_NET_GIT_FETCH_WITH_CLI: "true" + run: | + set -euo pipefail + eval "$(ssh-agent -s)" > /dev/null + trap 'ssh-agent -k > /dev/null' EXIT + ssh-add - <<< "$POLICY_ENGINE_DEPLOY_KEY" 2> /dev/null + # GitHub's published ED25519 host key: + # https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints + mkdir -p ~/.ssh + echo "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl" >> ~/.ssh/known_hosts + # Only this repository's URL is rewritten to SSH; the lockfile keeps the https source. + git config --global url."ssh://git@github.com/TinyCloudLabs/policy-engine".insteadOf "https://github.com/TinyCloudLabs/policy-engine" + cargo metadata --locked --format-version 1 --manifest-path test/w5-policy-runtime-node-e2e/Cargo.toml > /dev/null diff --git a/tinycloud-node-server/tests/fixtures/email-claim-v1/rust/Cargo.toml b/tinycloud-node-server/tests/fixtures/email-claim-v1/rust/Cargo.toml index c09453e9..a5e465d0 100644 --- a/tinycloud-node-server/tests/fixtures/email-claim-v1/rust/Cargo.toml +++ b/tinycloud-node-server/tests/fixtures/email-claim-v1/rust/Cargo.toml @@ -4,6 +4,10 @@ version = "0.1.0" edition = "2021" publish = false +# Its own workspace (with its own Cargo.lock). A root `workspace.exclude` +# entry cannot reach it: it sits under the `tinycloud-node-server` member. +[workspace] + [dependencies] base64 = "0.22.1" ed25519-dalek = "2.2.0" From f8cfc3c197a318d9bcf79567ebd8bfeb93afd049 Mon Sep 17 00:00:00 2001 From: Sam Gbafa Date: Sat, 17 Oct 2026 10:07:24 +0000 Subject: [PATCH 2/3] ci(TC-887): harden the w5 lockfile job Unset the deploy key after ssh-add (cargo can run an in-tree rustc wrapper), let ssh-add report a malformed key, drop the unpinned toolchain action (rustup installs the rust-toolchain.toml pin), scope the SSH rewrite to the cargo process and anchor it: every lockfile source under the policy-engine prefix must be exactly that repository. Document when the missing-secret skip should become a failure. --- .github/workflows/rust.yml | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bce869c2..cadff5b5 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -309,9 +309,13 @@ jobs: # TinyCloudLabs/policy-engine repository by git, so the workflow token cannot # resolve it. With a read-only deploy key for that one repository in the # POLICY_ENGINE_DEPLOY_KEY secret, this job resolves w5 with --locked like - # the other workspaces. Without the secret (fork PRs, or before the key - # exists) it skips with a notice. The key is loaded into an ssh-agent for the - # cargo step only; checkout keeps no credentials. + # the other workspaces. The key is loaded into an ssh-agent for the cargo + # step only and removed from the environment before cargo runs; checkout + # keeps no credentials. + # Without the secret the job skips with a notice. That is intended for fork + # PRs, which never receive secrets, and for the period before the deploy key + # exists. Once the key is added, pushes and same-repository PRs are meant to + # fail when the secret is missing; only fork PRs keep the notice skip. w5-lockfile: name: w5 workspace lockfile (private dependency) runs-on: ubuntu-latest @@ -329,8 +333,8 @@ jobs: uses: actions/checkout@v4 with: persist-credentials: false - - uses: dtolnay/rust-toolchain@1.97.1 - if: env.HAS_DEPLOY_KEY == 'true' + # No toolchain action: rustup on the runner installs the toolchain pinned + # in rust-toolchain.toml when cargo first runs. - name: Resolve w5 with --locked if: env.HAS_DEPLOY_KEY == 'true' env: @@ -338,13 +342,26 @@ jobs: CARGO_NET_GIT_FETCH_WITH_CLI: "true" run: | set -euo pipefail + lock=test/w5-policy-runtime-node-e2e/Cargo.lock + repo=https://github.com/TinyCloudLabs/policy-engine + # The rewrite below is a git prefix match. Anchor it: every lockfile + # source under that prefix must be exactly this repository (followed + # by its ?query or #revision), so no other URL can be rewritten. + if grep -E "^source = \"git\+${repo}[^?#\"]" "$lock"; then + echo "::error::$lock has a git source that shares the ${repo} prefix but is a different URL" + exit 1 + fi eval "$(ssh-agent -s)" > /dev/null trap 'ssh-agent -k > /dev/null' EXIT - ssh-add - <<< "$POLICY_ENGINE_DEPLOY_KEY" 2> /dev/null + ssh-add - <<< "$POLICY_ENGINE_DEPLOY_KEY" + unset POLICY_ENGINE_DEPLOY_KEY # GitHub's published ED25519 host key: # https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints mkdir -p ~/.ssh echo "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl" >> ~/.ssh/known_hosts - # Only this repository's URL is rewritten to SSH; the lockfile keeps the https source. - git config --global url."ssh://git@github.com/TinyCloudLabs/policy-engine".insteadOf "https://github.com/TinyCloudLabs/policy-engine" - cargo metadata --locked --format-version 1 --manifest-path test/w5-policy-runtime-node-e2e/Cargo.toml > /dev/null + # Rewrite only this repository to SSH, for the cargo process only; the + # lockfile keeps the https source. + GIT_CONFIG_COUNT=1 \ + GIT_CONFIG_KEY_0="url.ssh://git@github.com/TinyCloudLabs/policy-engine.insteadOf" \ + GIT_CONFIG_VALUE_0="$repo" \ + cargo metadata --locked --format-version 1 --manifest-path test/w5-policy-runtime-node-e2e/Cargo.toml > /dev/null From d47e956ec3254f27c384918e37c59d7ffe9149e2 Mon Sep 17 00:00:00 2001 From: Sam Gbafa Date: Sat, 17 Oct 2026 10:29:07 +0000 Subject: [PATCH 3/3] revert(TC-887): leave the frozen email-claim fixture manifest unchanged The fixture is pinned by hash (pinned_email_claim_manifest_runs_all_negative_rows); nothing needs it to load standalone. --- .../tests/fixtures/email-claim-v1/rust/Cargo.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tinycloud-node-server/tests/fixtures/email-claim-v1/rust/Cargo.toml b/tinycloud-node-server/tests/fixtures/email-claim-v1/rust/Cargo.toml index a5e465d0..c09453e9 100644 --- a/tinycloud-node-server/tests/fixtures/email-claim-v1/rust/Cargo.toml +++ b/tinycloud-node-server/tests/fixtures/email-claim-v1/rust/Cargo.toml @@ -4,10 +4,6 @@ version = "0.1.0" edition = "2021" publish = false -# Its own workspace (with its own Cargo.lock). A root `workspace.exclude` -# entry cannot reach it: it sits under the `tinycloud-node-server` member. -[workspace] - [dependencies] base64 = "0.22.1" ed25519-dalek = "2.2.0"