From 283787a6e3b581a103e7650197a2ed774f9c2914 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:19:03 -0400 Subject: [PATCH 1/2] fix(pulumi-guard): retire the deleted personal-repo OIDC policy (contract v3) Epic #78 C4 deleted kyle-sexton/github-iac and reduced live Pulumi OIDC trust to the single organization rule, so the exact-match v2 contract now fails every production deploy before mutation. Contract v3 carries only the surviving melodic-software/github-iac policy; v2 is removed with the repository it described. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01JLfjHY8PY6ozhgZPiuHKik --- ...v2.json => kyle-sexton-github-iac-v3.json} | 22 ------------------- .../actions/pulumi-deploy-guard/guard.test.sh | 6 ++--- .github/scripts/pulumi-deploy-guard.test.cjs | 13 ++++------- 3 files changed, 7 insertions(+), 34 deletions(-) rename .github/actions/pulumi-deploy-guard/contracts/{kyle-sexton-github-iac-v2.json => kyle-sexton-github-iac-v3.json} (54%) diff --git a/.github/actions/pulumi-deploy-guard/contracts/kyle-sexton-github-iac-v2.json b/.github/actions/pulumi-deploy-guard/contracts/kyle-sexton-github-iac-v3.json similarity index 54% rename from .github/actions/pulumi-deploy-guard/contracts/kyle-sexton-github-iac-v2.json rename to .github/actions/pulumi-deploy-guard/contracts/kyle-sexton-github-iac-v3.json index 45b6d4c..053abf3 100644 --- a/.github/actions/pulumi-deploy-guard/contracts/kyle-sexton-github-iac-v2.json +++ b/.github/actions/pulumi-deploy-guard/contracts/kyle-sexton-github-iac-v3.json @@ -3,28 +3,6 @@ "organization": "kyle-sexton", "issuerUrl": "https://token.actions.githubusercontent.com", "personalAllowPolicies": [ - { - "decision": "allow", - "tokenType": "personal", - "userLogin": "kyle-sexton", - "authorizedPermissions": [], - "rules": { - "aud": "urn:pulumi:org:kyle-sexton", - "sub": "repo:kyle-sexton@153232337/github-iac@1277607417:environment:github-iac-production", - "repository": "kyle-sexton/github-iac", - "repository_id": "1277607417", - "repository_owner_id": "153232337", - "repository_visibility": "private", - "ref": "refs/heads/main", - "ref_type": "branch", - "environment": "github-iac-production", - "event_name": "workflow_dispatch", - "workflow": "github-iac-production-deploy-v1", - "runner_environment": "github-hosted", - "actor_id": "153232337", - "run_attempt": "1" - } - }, { "decision": "allow", "tokenType": "personal", diff --git a/.github/actions/pulumi-deploy-guard/guard.test.sh b/.github/actions/pulumi-deploy-guard/guard.test.sh index bc931fa..f7830dd 100755 --- a/.github/actions/pulumi-deploy-guard/guard.test.sh +++ b/.github/actions/pulumi-deploy-guard/guard.test.sh @@ -2,7 +2,7 @@ set -euo pipefail action_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -contract="$action_path/contracts/kyle-sexton-github-iac-v2.json" +contract="$action_path/contracts/kyle-sexton-github-iac-v3.json" temporary_directory="$(mktemp -d)" trap 'rm -rf -- "$temporary_directory"' EXIT @@ -71,7 +71,7 @@ run_guard() { MOCK_POLICY="$policy" \ MOCK_STATE="$state" \ OPERATIONAL_RESOURCE_URNS_JSON="$requested_urns" \ - POLICY_CONTRACT='kyle-sexton-github-iac-v2' \ + POLICY_CONTRACT='kyle-sexton-github-iac-v3' \ PULUMI_BIN="$mock_pulumi" \ STACK_NAME="${TEST_STACK_NAME:-kyle-sexton/project/production}" \ bash "$action_path/guard.sh" >"$stdout" 2>"$stderr" @@ -137,7 +137,7 @@ mkdir -p "$invalid_action_path/contracts" for operator in '*' '?' '.'; do jq --arg operator "$operator" \ '.personalAllowPolicies[0].rules.workflow += $operator' \ - "$contract" >"$invalid_action_path/contracts/kyle-sexton-github-iac-v2.json" + "$contract" >"$invalid_action_path/contracts/kyle-sexton-github-iac-v3.json" reset_valid_fixtures TEST_ACTION_PATH="$invalid_action_path" \ expect_failure "bundled contract rejects Pulumi '$operator' matcher semantics" diff --git a/.github/scripts/pulumi-deploy-guard.test.cjs b/.github/scripts/pulumi-deploy-guard.test.cjs index 3100de4..0f5118e 100644 --- a/.github/scripts/pulumi-deploy-guard.test.cjs +++ b/.github/scripts/pulumi-deploy-guard.test.cjs @@ -22,7 +22,7 @@ const contract = JSON.parse( "actions", "pulumi-deploy-guard", "contracts", - "kyle-sexton-github-iac-v2.json", + "kyle-sexton-github-iac-v3.json", ), "utf8", ), @@ -79,25 +79,21 @@ test("guard audits the complete personal allow set before exporting state", () = assert.doesNotMatch(guard, /set -x/u); }); -test("bundled OIDC contract is exact, wildcard-free, and covers both IaC repositories", () => { +test("bundled OIDC contract is exact, wildcard-free, and covers the organization IaC repository", () => { assert.equal(contract.schemaVersion, 2); assert.equal(contract.organization, "kyle-sexton"); assert.equal( contract.issuerUrl, "https://token.actions.githubusercontent.com", ); - assert.equal(contract.personalAllowPolicies.length, 2); + assert.equal(contract.personalAllowPolicies.length, 1); assert.deepEqual( contract.personalAllowPolicies .map((policy) => policy.rules.repository) .sort(), - ["kyle-sexton/github-iac", "melodic-software/github-iac"], + ["melodic-software/github-iac"], ); const identities = { - "kyle-sexton/github-iac": { - ownerId: "153232337", - repositoryId: "1277607417", - }, "melodic-software/github-iac": { ownerId: "58273638", repositoryId: "1277417810", @@ -137,7 +133,6 @@ test("bundled OIDC contract is exact, wildcard-free, and covers both IaC reposit ]), ), { - "kyle-sexton/github-iac": "1277607417", "melodic-software/github-iac": "1277417810", }, ); From 88eaf4cf509bf206737e8bd50e8f34e1c2755e3d Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:30:51 -0400 Subject: [PATCH 2/2] refactor(pulumi-guard): drop the version marker from the contract name The contract is a living exact-match document; its identity is the stack it guards, not a revision. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01JLfjHY8PY6ozhgZPiuHKik --- ...exton-github-iac-v3.json => kyle-sexton-github-iac.json} | 0 .github/actions/pulumi-deploy-guard/guard.test.sh | 6 +++--- .github/scripts/pulumi-deploy-guard.test.cjs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename .github/actions/pulumi-deploy-guard/contracts/{kyle-sexton-github-iac-v3.json => kyle-sexton-github-iac.json} (100%) diff --git a/.github/actions/pulumi-deploy-guard/contracts/kyle-sexton-github-iac-v3.json b/.github/actions/pulumi-deploy-guard/contracts/kyle-sexton-github-iac.json similarity index 100% rename from .github/actions/pulumi-deploy-guard/contracts/kyle-sexton-github-iac-v3.json rename to .github/actions/pulumi-deploy-guard/contracts/kyle-sexton-github-iac.json diff --git a/.github/actions/pulumi-deploy-guard/guard.test.sh b/.github/actions/pulumi-deploy-guard/guard.test.sh index f7830dd..365d61b 100755 --- a/.github/actions/pulumi-deploy-guard/guard.test.sh +++ b/.github/actions/pulumi-deploy-guard/guard.test.sh @@ -2,7 +2,7 @@ set -euo pipefail action_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -contract="$action_path/contracts/kyle-sexton-github-iac-v3.json" +contract="$action_path/contracts/kyle-sexton-github-iac.json" temporary_directory="$(mktemp -d)" trap 'rm -rf -- "$temporary_directory"' EXIT @@ -71,7 +71,7 @@ run_guard() { MOCK_POLICY="$policy" \ MOCK_STATE="$state" \ OPERATIONAL_RESOURCE_URNS_JSON="$requested_urns" \ - POLICY_CONTRACT='kyle-sexton-github-iac-v3' \ + POLICY_CONTRACT='kyle-sexton-github-iac' \ PULUMI_BIN="$mock_pulumi" \ STACK_NAME="${TEST_STACK_NAME:-kyle-sexton/project/production}" \ bash "$action_path/guard.sh" >"$stdout" 2>"$stderr" @@ -137,7 +137,7 @@ mkdir -p "$invalid_action_path/contracts" for operator in '*' '?' '.'; do jq --arg operator "$operator" \ '.personalAllowPolicies[0].rules.workflow += $operator' \ - "$contract" >"$invalid_action_path/contracts/kyle-sexton-github-iac-v3.json" + "$contract" >"$invalid_action_path/contracts/kyle-sexton-github-iac.json" reset_valid_fixtures TEST_ACTION_PATH="$invalid_action_path" \ expect_failure "bundled contract rejects Pulumi '$operator' matcher semantics" diff --git a/.github/scripts/pulumi-deploy-guard.test.cjs b/.github/scripts/pulumi-deploy-guard.test.cjs index 0f5118e..6004fdd 100644 --- a/.github/scripts/pulumi-deploy-guard.test.cjs +++ b/.github/scripts/pulumi-deploy-guard.test.cjs @@ -22,7 +22,7 @@ const contract = JSON.parse( "actions", "pulumi-deploy-guard", "contracts", - "kyle-sexton-github-iac-v3.json", + "kyle-sexton-github-iac.json", ), "utf8", ),