Skip to content

fix(security): enforce generated consumer signer pairs - #3611

Merged
devantler merged 6 commits into
mainfrom
codex/approved-signer-matchers-3569
Sep 5, 2026
Merged

devantler merged 6 commits into
mainfrom
codex/approved-signer-matchers-3569

Conversation

@devantler

Copy link
Copy Markdown
Contributor

🤖 Generated by the Agentic Engineer

Narrow each consumer’s accepted signing revisions to its approved deployed-signer/current-pin pair. Scheduled regeneration updates the matchers together with the approval data, and CI prevents broad matcher patterns from returning.

Implements #3569. Part of #3308. #3569 remains open for its post-deployment observation on the next consumer publication.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Validation at 0081916050f3d532b25183565a12634d9d8f0b9c:

  • RED: enforcing the approved set rejects broad matcher patterns; the original regeneration workflow fails the expanded output-path contract.
  • GREEN: writer regression cases, approved-set guard suite, 45 workflow mutation controls, and executed change-detection cases pass. The tests cover pin changes, no-op reruns, malformed or ambiguous input without partial writes, exact path fencing, and unchanged generic subjects.
  • ShellCheck and Actionlint pass. Both ksail workload validate and ksail --config ksail.prod.yaml workload validate pass, with 602 files validated each.
  • User exercise: ran the writer on the committed approved set, inspected the four resulting subjects, and reran it to observe zero changes. Fresh regeneration was byte-identical. Public-artifact cosign positive / wrong-signer / positive controls passed.

The scheduled-run prerequisite is satisfied by run 33950394952. Production observation on the next consumer publication remains tracked by #3569.

@coderabbitai review

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

The first CI run caught a ShellCheck portability warning in the writer’s file check. Replaced the compound expression with an explicit condition; ShellCheck and the complete writer regression suite pass. The generated manifests are unchanged from the validated implementation.

Please review b1a52002ef103cc2338f644327c2c7b063f38f74.

@coderabbitai review

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit request 5550980605 was posted at 09:46:54Z. At 09:50:21Z, the exact trigger was present with no reaction, acknowledgement, review, or provider check. The bounded three-minute no-reaction window has expired; advancing to the next provider.

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-05T10:17:10.486829Z 1f74211 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

revision='b1a52002ef103cc2338f644327c2c7b063f38f74'

printf '%s\n' '== Commit and changed files =='
git show --no-ext-diff --format=fuller --stat --summary "$revision"
git diff-tree --no-commit-id --name-status -r "$revision"

printf '%s\n' '== Patch =='
git show --no-ext-diff --format= --find-renames --find-copies "$revision"

printf '%s\n' '== Changed shell/workflow file outlines =='
while IFS= read -r file; do
  case "$file" in
    *.sh|*.bash|*.yml|*.yaml)
      printf '\n== %s ==\n' "$file"
      ast-grep outline "$file" --items all 2>/dev/null || true
      ;;
  esac
done < <(git diff-tree --no-commit-id --name-only -r "$revision")

Length of output: 2493


🏁 Script executed:

#!/bin/bash
set -euo pipefail

writer='scripts/write-publish-workflow-matchers.sh'

printf '%s\n' '== Writer outline =='
ast-grep outline "$writer" --items all || true

printf '%s\n' '== Writer source =='
cat -n "$writer"

printf '%s\n' '== Writer references and test candidates =='
rg -n -C 3 --glob '!**/.git/**' \
  '(write-publish-workflow-matchers\.sh|source manifest must be a writable regular file|approved.*signer|FIXED_REF_RE|EXPECTED_CONSUMERS)' .

printf '%s\n' '== Repository files with writer-related names =='
fd -t f 'write-publish-workflow-matchers|matcher|signer' . | sort

Length of output: 25020


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Writer regression test outline and source =='
ast-grep outline scripts/tests/test-write-publish-workflow-matchers.sh --items all || true
cat -n scripts/tests/test-write-publish-workflow-matchers.sh

printf '%s\n' '== Shared approved-revision library =='
cat -n scripts/publish-workflow-approved-revisions.lib.sh

printf '%s\n' '== Pull request change set from merge base =='
base="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"
printf 'merge base: %s\n' "$base"
git diff --no-ext-diff --stat "$base" HEAD
git diff --no-ext-diff --name-status "$base" HEAD

Length of output: 21607


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='1a8b8fd49097dbb516aa7460621c743d17394247'

printf '%s\n' '== CI and scheduled-regeneration changes =='
git diff --no-ext-diff --find-renames "$base" HEAD -- \
  .github/workflows/ci.yaml \
  .github/workflows/regenerate-publish-workflow-approved-revisions.yaml

printf '%s\n' '== Guard changes =='
git diff --no-ext-diff --find-renames "$base" HEAD -- \
  scripts/guard-publish-workflow-approved-revisions.sh \
  scripts/publish-workflow-approved-revisions.lib.sh

printf '%s\n' '== Generated subjects and approved rows =='
printf '%s\n' '-- approved set --'
cat scripts/publish-workflow-approved-revisions.tsv
printf '%s\n' '-- consumer subjects --'
rg -n -A 2 -B 2 --glob 'oci-repository.yaml' \
  'subject:\s' \
  k8s/bases/apps/ascoachingogvaner \
  k8s/bases/apps/github-config \
  k8s/bases/apps/wedding-app \
  k8s/providers/hetzner/apps/aws

printf '%s\n' '== Guard source =='
cat -n scripts/guard-publish-workflow-approved-revisions.sh

Length of output: 43341


@devantler Reviewed b1a52002ef103cc2338f644327c2c7b063f38f74.

I found no issues. The explicit file validation rejects symlinks, non-regular files, and non-writable manifests before any source manifest is changed. The staged writer, enforced guard, CI checks, and scheduled workflow path fence are consistent with the approved signer/current-pin pair requirement.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 18 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Team

Run ID: 6f0f71d8-66da-4fb4-a8d3-e740b4f312c9

📥 Commits

Reviewing files that changed from the base of the PR and between 1a8b8fd and b1a5200.

📒 Files selected for processing (12)
  • .github/workflows/ci.yaml
  • .github/workflows/regenerate-publish-workflow-approved-revisions.yaml
  • k8s/bases/apps/ascoachingogvaner/oci-repository.yaml
  • k8s/bases/apps/github-config/oci-repository.yaml
  • k8s/bases/apps/wedding-app/oci-repository.yaml
  • k8s/providers/hetzner/apps/aws/oci-repository.yaml
  • scripts/guard-publish-workflow-approved-revisions.sh
  • scripts/publish-workflow-approved-revisions.lib.sh
  • scripts/tests/test-publish-workflow-approved-revisions-guard.sh
  • scripts/tests/test-regenerate-publish-workflow-approved-revisions.sh
  • scripts/tests/test-write-publish-workflow-matchers.sh
  • scripts/write-publish-workflow-matchers.sh

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

revision='0081916050f3d532b25183565a12634d9d8f0b9c'
base="$(git merge-base "$revision" origin/main 2>/dev/null || git merge-base "$revision" main)"

printf '%s\n' '== Requested commit =='
git show --no-ext-diff --format=fuller --stat --summary "$revision"
git show --no-ext-diff --format= --find-renames --find-copies "$revision"

printf '%s\n' '== PR range changed files =='
printf 'merge-base: %s\n' "$base"
git diff --no-ext-diff --name-status "$base" "$revision"

printf '%s\n' '== Relevant source outlines =='
for file in \
  scripts/write-publish-workflow-matchers.sh \
  scripts/guard-publish-workflow-approved-revisions.sh \
  scripts/publish-workflow-approved-revisions.lib.sh \
  scripts/tests/test-write-publish-workflow-matchers.sh \
  scripts/tests/test-guard-publish-workflow-approved-revisions.sh \
  .github/workflows/ci.yaml \
  .github/workflows/regenerate-publish-workflow-approved-revisions.yaml
do
  if [ -f "$file" ]; then
    printf '\n== %s ==\n' "$file"
    ast-grep outline "$file" --items all 2>/dev/null || true
  fi
done

printf '%s\n' '== Relevant PR-range patch =='
git diff --no-ext-diff --find-renames "$base" "$revision" -- \
  scripts \
  .github/workflows/ci.yaml \
  .github/workflows/regenerate-publish-workflow-approved-revisions.yaml \
  k8s

printf '%s\n' '== Current approved revisions and generated subjects =='
if [ -f scripts/publish-workflow-approved-revisions.tsv ]; then
  cat -n scripts/publish-workflow-approved-revisions.tsv
fi
rg -n -A3 -B3 --glob 'oci-repository.yaml' 'subject:\s' k8s 2>/dev/null || true

printf '%s\n' '== References to approved revision controls =='
rg -n -C2 --glob '!**/.git/**' \
  '(write-publish-workflow-matchers\.sh|guard-publish-workflow-approved-revisions\.sh|publish-workflow-approved-revisions|FIXED_REF_RE|EXPECTED_CONSUMERS)' .

Length of output: 162827


@devantler Reviewed 0081916050f3d532b25183565a12634d9d8f0b9c.

I found no issues.

The writer derives each consumer subject from its approved deployed-signer/current-pin pair. It validates the complete staged result with enforcement enabled before it changes a manifest. CI enforces the guard. The scheduled workflow runs generator → writer → change detection → enforced guard before it opens or updates the draft pull request. Its path fence and add-paths list contain only the approved set and the four consumer manifests.

The committed matcher subjects match the approved revision rows for .github, ascoachingogvaner, aws, and wedding-app.

You are interacting with an AI system.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: b1a52002ef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

The authorization job exposed a second regeneration integration: its aggregate fingerprint includes consumer signer subjects. A one-off hash refresh would make the next scheduled rotation fail again. The projection now recognizes only exact signer subsets of the previously approved shared-workflow pattern for the four registered consumer artifacts. The approved-revisions guard still enforces exact generated membership; issuer, workflow, source, identity count and all other fields remain fingerprinted.

RED/GREEN: the complete authorization suite failed with the narrowed manifests before this change and now passes without changing the approved fingerprint. Added rotation, non-mutation, and 18 adversarial mutation cases; go test ./scripts/validate-eks-ci-role-policy and go vet pass. The prior manifest and workflow validation remains applicable because those files are unchanged.

@coderabbitai review

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit request 5551069697 was posted at 10:06:30Z. At 10:11:30Z it still had no reaction, acknowledgement, review, or current-head provider artifact. The bounded no-reaction window has expired.

@codex review for signer-set projection safety and scheduled regeneration behavior

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

revision='1f74211b3ff95bf3cf0e1cf6038e58dde77fba94'
base="$(git merge-base "$revision" origin/main 2>/dev/null || git merge-base "$revision" main)"

printf '%s\n' '== Commit and PR-range files =='
printf 'merge-base: %s\n' "$base"
git show --no-ext-diff --format=fuller --stat --summary "$revision"
git diff --no-ext-diff --name-status "$base" "$revision"
git diff --no-ext-diff --find-renames "$base" "$revision"

printf '%s\n' '== Authorization validator structure =='
ast-grep outline scripts/validate-eks-ci-role-policy --items all 2>/dev/null || true

printf '%s\n' '== Authorization validator files =='
fd -t f . scripts/validate-eks-ci-role-policy -x sh -c '
  printf "\n== %s ==\n" "$1"
  cat -n "$1"
' sh {} \;

printf '%s\n' '== Projection and fingerprint references =='
rg -n -C 5 --glob '!**/.git/**' \
  '(fingerprint|Fingerprint|signer|Signer|subject|Subject|approved.*revision|approved.*pattern|consumer)' \
  scripts/validate-eks-ci-role-policy scripts .github/workflows k8s 2>/dev/null || true

printf '%s\n' '== Consumer manifests and approval/guard controls =='
for file in \
  scripts/publish-workflow-approved-revisions.tsv \
  scripts/publish-workflow-approved-revisions.lib.sh \
  scripts/guard-publish-workflow-approved-revisions.sh \
  scripts/write-publish-workflow-matchers.sh \
  scripts/tests/test-guard-publish-workflow-approved-revisions.sh \
  .github/workflows/regenerate-publish-workflow-approved-revisions.yaml
do
  if [ -f "$file" ]; then
    printf '\n== %s ==\n' "$file"
    cat -n "$file"
  fi
done

Length of output: 201795


🏁 Script executed:

#!/bin/bash
set -euo pipefail

revision='1f74211b3ff95bf3cf0e1cf6038e58dde77fba94'
parent="${revision}^"

printf '%s\n' '== Files changed by target commit =='
git diff-tree --no-commit-id --name-status -r "$revision"

printf '%s\n' '== Target commit patch only =='
git diff --no-ext-diff --find-renames "$parent" "$revision" -- scripts/validate-eks-ci-role-policy

printf '%s\n' '== Validator Go file list =='
fd -t f -e go . scripts/validate-eks-ci-role-policy | sort

printf '%s\n' '== Validator package outline =='
ast-grep outline scripts/validate-eks-ci-role-policy --items all --type function,struct,interface,var,const 2>/dev/null || true

printf '%s\n' '== Validator source and tests =='
while IFS= read -r file; do
  printf '\n== %s ==\n' "$file"
  cat -n "$file"
done < <(fd -t f -e go . scripts/validate-eks-ci-role-policy | sort)

printf '%s\n' '== Fingerprint baseline and validator invocation references =='
rg -n -C 4 --glob '!**/.git/**' \
  '(validate-eks-ci-role-policy|authorization.*fingerprint|fingerprint.*authorization|EKS.*fingerprint)' \
  .github scripts README.md 2>/dev/null || true

Length of output: 11236


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Projection call path and commit matcher definition =='
rg -n -C 8 \
  '(exactGitCommit|authorizationSurfaceDocument|authorizationSurfaceEntry|canonicalFingerprint|func identityOf|type resourceIdentity)' \
  scripts/validate-eks-ci-role-policy/main.go \
  scripts/validate-eks-ci-role-policy/publish_matcher_projection.go

printf '%s\n' '== Authorization baseline, entry selection, and validation tests =='
rg -n -C 8 \
  '(authorizationSurface|authorization.*fingerprint|fingerprint.*authorization|expected.*fingerprint|baseline)' \
  scripts/validate-eks-ci-role-policy/main.go \
  scripts/validate-eks-ci-role-policy/main_test.go \
  scripts/validate-eks-ci-role-policy/coverage_test.go \
  scripts/validate-eks-ci-role-policy/kubescape_baseline_test.go

printf '%s\n' '== Exact source ranges needed for review =='
sed -n '1,180p' scripts/validate-eks-ci-role-policy/main.go
sed -n '2820,2985p' scripts/validate-eks-ci-role-policy/main.go
sed -n '1,180p' scripts/validate-eks-ci-role-policy/main_test.go
sed -n '1,220p' scripts/validate-eks-ci-role-policy/coverage_test.go
sed -n '1,220p' scripts/validate-eks-ci-role-policy/kubescape_baseline_test.go

printf '%s\n' '== Files that invoke the validator =='
rg -n -C 3 --glob '!**/.git/**' \
  '(go test \./scripts/validate-eks-ci-role-policy|validate-eks-ci-role-policy)' \
  .github scripts/tests scripts 2>/dev/null || true

Length of output: 110354


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Approved-revisions guard invocations =='
rg -n -C 8 \
  '(guard-publish-workflow-approved-revisions|APPROVED_REVISIONS_ENFORCE|write-publish-workflow-matchers)' \
  .github/workflows .github/actions scripts/tests \
  scripts/validate-eks-ci-role-policy 2>/dev/null || true

printf '%s\n' '== Authorization validator and matcher guard order in executable workflow steps =='
for file in .github/workflows/ci.yaml .github/workflows/cd.yaml .github/workflows/validate-main.yaml; do
  printf '\n== %s ==\n' "$file"
  rg -n -C 12 \
    '(Validate static production authorization controls|approved.revision|guard-publish|validate-eks-ci-role-policy|write-publish)' \
    "$file" || true
done

printf '%s\n' '== Guard test and workflow-contract coverage =='
fd -t f 'test-*publish*revision*|test-*matcher*' scripts/tests | sort
rg -n -C 6 \
  '(APPROVED_REVISIONS_ENFORCE|guard-publish-workflow-approved-revisions|regenerate-publish-workflow-approved-revisions|validate-eks-ci-role-policy)' \
  scripts/tests/test-guard-publish-workflow-approved-revisions.sh \
  scripts/tests/test-write-publish-workflow-matchers.sh \
  scripts/validate-eks-ci-role-policy/main_test.go 2>/dev/null || true

Length of output: 58384


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== CD workflow trigger, checkout, and deploy path =='
sed -n '1,180p' .github/workflows/cd.yaml
rg -n -C 8 \
  '(checkout|github\.ref|ref:|workflow_dispatch|deploy-prod|guard-publish-workflow-approved-revisions|APPROVED_REVISIONS_ENFORCE)' \
  .github/workflows/cd.yaml .github/actions/deploy-prod/action.yml 2>/dev/null || true

printf '%s\n' '== Main validation trigger and guard path =='
sed -n '1,120p' .github/workflows/validate-main.yaml
rg -n -C 8 \
  '(guard-publish-workflow-approved-revisions|APPROVED_REVISIONS_ENFORCE|deploy-prod)' \
  .github/workflows/validate-main.yaml .github/actions/deploy-prod/action.yml 2>/dev/null || true

printf '%s\n' '== All production deploy workflow references to the approved-revisions guard =='
rg -n -C 6 \
  '(guard-publish-workflow-approved-revisions|APPROVED_REVISIONS_ENFORCE)' \
  .github/workflows .github/actions 2>/dev/null || true

Length of output: 42821


@devantler I found one issue.

  • publishMatcherSurfaceDocument accepts any syntactically valid one- or two-SHA signer set for a registered consumer and projects it to the broad matcher. The approved-revisions guard restores membership validation only in ci.yaml and the regeneration workflow. However, cd.yaml deploys after validate-eks-authorization and validate-shared-publish-pin, but it does not run guard-publish-workflow-approved-revisions.sh with APPROVED_REVISIONS_ENFORCE=1. A direct push to main can therefore replace a consumer matcher with an unapproved, fixed SHA or SHA pair. The aggregate fingerprint now accepts the change, and the existing CD pin guard accepts it because the matcher remains fixed. Add the enforced approved-revisions guard as a hard prerequisite of deploy-prod in cd.yaml. Add the same check to validate-main.yaml for post-push detection.

You are interacting with an AI system.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: 1f74211b3f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Resolved the publication-route bypass reported in #3611 (comment) at e86c0f82dafd02e2bffdf2bfb60d40ceb08c921f. Approved signer membership is now an enforcing prerequisite in manual CD, post-push validation, and disaster recovery. The merge-group restore job also checks its own fresh main checkout before publishing; the speculative revision's guard cannot cover that checkout.

The parsed workflow regression failed before the wiring change and now passes for all five gate locations. Fifteen bypass mutations plus a publish-before-guard mutation are refused. The complete authorization and DR signing suites, existing RGD route contract, signer guard suite, ShellCheck, actionlint, and go vet pass. The authorization fingerprint remains unchanged.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

revision='e86c0f82dafd02e2bffdf2bfb60d40ceb08c921f'
parent="${revision}^"
base="$(git merge-base "$revision" origin/main 2>/dev/null || git merge-base "$revision" main)"

printf '%s\n' '== Target commit =='
git show --no-ext-diff --format=fuller --stat --summary "$revision"
git diff-tree --no-commit-id --name-status -r "$revision"
git diff --no-ext-diff --find-renames "$parent" "$revision"

printf '%s\n' '== Changed workflow and test outlines =='
git diff-tree --no-commit-id --name-only -r "$revision" |
while IFS= read -r file; do
  case "$file" in
    *.yml|*.yaml|*.sh)
      printf '\n== %s ==\n' "$file"
      ast-grep outline "$file" --items all 2>/dev/null || true
      ;;
  esac
done

printf '%s\n' '== Approval-guard and publication call sites =='
rg -n -C 10 --glob '!**/.git/**' \
  '(guard-publish-workflow-approved-revisions\.sh|APPROVED_REVISIONS_ENFORCE|deploy-prod|publish|restore|merge_group)' \
  .github/workflows .github/actions scripts/tests 2>/dev/null || true

printf '%s\n' '== Full changed workflow/test files =='
git diff-tree --no-commit-id --name-only -r "$revision" |
while IFS= read -r file; do
  case "$file" in
    .github/workflows/*|scripts/tests/*)
      printf '\n== %s ==\n' "$file"
      cat -n "$file"
      ;;
  esac
done

printf '%s\n' '== PR-range publication routes =='
git diff --no-ext-diff --name-status "$base" "$revision"

Length of output: 148975


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Exact target-commit workflow patch =='
git diff --no-ext-diff --find-renames e86c0f82dafd02e2bffdf2bfb60d40ceb08c921f^ e86c0f82dafd02e2bffdf2bfb60d40ceb08c921f -- \
  .github/workflows/cd.yaml \
  .github/workflows/ci.yaml \
  .github/workflows/dr-rebuild.yaml \
  .github/workflows/validate-main.yaml \
  scripts/tests/test-publish-workflow-approved-revisions-guard.sh

printf '%s\n' '== CD jobs: dependencies, checkout, guard, and deploy =='
rg -n -C 16 \
  '^(  (validate-eks-authorization|validate-shared-publish-pin|validate-publication-contract|deploy-prod):|      - name: (📑 Checkout|🔐 Enforce approved publication signers|🚀 Deploy)|        APPROVED_REVISIONS_ENFORCE:|        run: \./scripts/guard-publish-workflow-approved-revisions\.sh|    needs:|      \[|        validate-)' \
  .github/workflows/cd.yaml

printf '%s\n' '== CI merge-group jobs: dependencies, checkout, guard, and deploy =='
rg -n -C 16 \
  '^(  (validate-publication-contract|deploy-prod|heal-prod-on-failure):|      - name: (📑 Checkout|📑 Checkout main|🔐 Enforce approved publication signers|🚀 Deploy|🩹 Re-deploy)|        APPROVED_REVISIONS_ENFORCE:|        run: \./scripts/guard-publish-workflow-approved-revisions\.sh|    needs:|      \[|        validate-)' \
  .github/workflows/ci.yaml

printf '%s\n' '== Workflow wiring regression: route definitions and assertions =='
rg -n -C 12 \
  '(cd\.yaml|ci\.yaml|dr-rebuild\.yaml|validate-main\.yaml|guard-publish-workflow-approved-revisions|APPROVED_REVISIONS_ENFORCE|publish|deploy|rebuild|heal)' \
  scripts/tests/test-publish-workflow-approved-revisions-guard.sh

printf '%s\n' '== All production-publishing composite action call sites =='
rg -n -C 8 --glob '!**/.git/**' \
  'uses:\s*\./\.github/actions/deploy-prod|uses:\s*\./\.github/actions/deploy-prod/publish-platform-manifests' \
  .github/workflows

Length of output: 67890


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== CI guard-job definition =='
sed -n '55,155p' .github/workflows/ci.yaml

printf '%s\n' '== CI publication-contract and relevant job definitions =='
sed -n '455,515p' .github/workflows/ci.yaml
sed -n '620,705p' .github/workflows/ci.yaml
sed -n '1798,1862p' .github/workflows/ci.yaml

printf '%s\n' '== Job dependency graph for relevant CI jobs =='
python3 - <<'PY'
from pathlib import Path
import re
text = Path(".github/workflows/ci.yaml").read_text()
for job in ("validate-shared-publish-pin", "validate-publication-contract",
            "validate-eks-authorization", "deploy-prod"):
    match = re.search(rf"(?ms)^  {re.escape(job)}:\n(.*?)(?=^  [A-Za-z0-9_-]+:|\Z)", text)
    if not match:
        print(f"{job}: NOT FOUND")
        continue
    block = match.group(0)
    needs = re.search(r"(?m)^    needs:\s*(.*)$", block)
    print(f"{job}: {needs.group(1) if needs else 'no needs'}")
PY

printf '%s\n' '== Guard-related job names and needs in all production workflows =='
python3 - <<'PY'
from pathlib import Path
import re
for path in map(Path, [".github/workflows/ci.yaml", ".github/workflows/cd.yaml", ".github/workflows/dr-rebuild.yaml"]):
    text = path.read_text()
    print(f"\n{path}:")
    for m in re.finditer(r"(?ms)^  ([A-Za-z0-9_-]+):\n(.*?)(?=^  [A-Za-z0-9_-]+:|\Z)", text):
        if "guard-publish-workflow-approved-revisions.sh" in m.group(2):
            needs = re.search(r"(?m)^    needs:\s*(.*)$", m.group(2))
            print(f"  guard job={m.group(1)}; needs={needs.group(1) if needs else 'none'}")
PY

Length of output: 18549


@devantler I found no issues in e86c0f82dafd02e2bffdf2bfb60d40ceb08c921f.

The enforced guard now protects all publication routes:

  • Merge-group deployment requires the changes job, which runs the guard with APPROVED_REVISIONS_ENFORCE: '1'.
  • Manual CD deployment requires validate-eks-authorization, which runs the guard.
  • DR rebuild requires supersession-gate, which runs the guard before publication.
  • Post-push validation runs the guard on the pushed main revision.
  • The merge-group recovery job runs the guard after its fresh main checkout and before it republishes.

The recovery guard checks the actual main checkout. This closes the checkout-scope gap from the prior finding.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

You are interacting with an AI system.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

User evaluation for e86c0f82dafd02e2bffdf2bfb60d40ceb08c921f: in an isolated checkout, I extracted and ran the actual enforcing command and environment from all five workflow gate locations. The committed signer pair passed, a syntactically valid but unapproved fixed SHA was refused in every location, and restoring the approved pair passed again. No deployment or production mutation was performed by this exercise.

The rotation exercise ran the real generator, writer, enforced guard, authorization CLI with the checksum-verified pinned kubectl renderer, and the workflow's actual file detector. A synthetic pin change updated only the approval data and one consumer matcher; the second run was byte-identical. Those generator/writer/projection bytes are unchanged by the final route-wiring fix.

Fresh read-only live regeneration examined all four consumers and changed zero rows; its output is byte-identical to the committed approval set. Both KSail overlays validated 602 files. Direct signature positive/negative/positive checks passed for the two publicly accessible artifacts; the two private registry artifacts returned DENIED and are not claimed as independently verified by those direct checks.

CodeRabbit's current-head review reports no issues and explicitly confirms the earlier publication-route finding is resolved. #3569 remains open for the next real consumer publication after deployment.

@devantler
devantler marked this pull request as ready for review September 5, 2026 10:49
@devantler
devantler added this pull request to the merge queue Sep 5, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 5, 2026
@devantler
devantler marked this pull request as draft September 5, 2026 10:59
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

The signer-membership guard is now the first step of the checked-out deploy action, before tooling and credentials. The recovery workflow uses the action and signer policy from the same checkout. CI, manual CD, direct-main validation and DR retain their prerequisite guards.

At fedd576974402b6f967dc2f824bbd9abcc446bf3, the new placement regression and six recovery bypass mutations pass, along with the complete authorization and DR signing suites, the enforcing guard suite, actionlint, and go vet. The branch includes current main.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

revision='fedd576974402b6f967dc2f824bbd9abcc446bf3'
parent="${revision}^"
base="$(git merge-base "$revision" origin/main 2>/dev/null || git merge-base "$revision" main)"

printf '%s\n' '== Target commit and PR file list =='
git show --no-ext-diff --format=fuller --stat --summary "$revision"
git diff-tree --no-commit-id --name-status -r "$revision"
printf 'merge-base: %s\n' "$base"
git diff --no-ext-diff --name-status "$base" "$revision"

printf '%s\n' '== Target patch =='
git diff --no-ext-diff --find-renames "$parent" "$revision"

printf '%s\n' '== Changed source outlines =='
git diff-tree --no-commit-id --name-only -r "$revision" |
while IFS= read -r file; do
  case "$file" in
    *.yml|*.yaml|*.sh)
      printf '\n== %s ==\n' "$file"
      ast-grep outline "$file" --items all 2>/dev/null || true
      ;;
  esac
done

printf '%s\n' '== Deploy action, recovery workflow, and placement test =='
for file in \
  .github/actions/deploy-prod/action.yml \
  .github/workflows/ci.yaml \
  .github/workflows/cd.yaml \
  .github/workflows/dr-rebuild.yaml \
  .github/workflows/validate-main.yaml \
  scripts/tests/test-publish-workflow-approved-revisions-guard.sh \
  scripts/guard-publish-workflow-approved-revisions.sh
do
  if [ -f "$file" ]; then
    printf '\n== %s ==\n' "$file"
    cat -n "$file"
  fi
done

printf '%s\n' '== Every deploy action call site and approved-revisions guard call site =='
rg -n -C 10 --glob '!**/.git/**' \
  '(uses:\s*\./\.github/actions/deploy-prod|guard-publish-workflow-approved-revisions\.sh|APPROVED_REVISIONS_ENFORCE|checkout|publish-platform-manifests)' \
  .github/workflows .github/actions scripts/tests 2>/dev/null || true

Length of output: 200958


🏁 Script executed:

#!/bin/bash
set -euo pipefail

revision='fedd576974402b6f967dc2f824bbd9abcc446bf3'
parent="${revision}^"

printf '%s\n' '== Focused target patch =='
git diff --no-ext-diff --find-renames "$parent" "$revision" -- \
  .github/actions/deploy-prod/action.yml \
  .github/workflows/ci.yaml \
  .github/workflows/dr-rebuild.yaml \
  scripts/tests/test-publish-workflow-approved-revisions-guard.sh

printf '%s\n' '== Deploy action first steps =='
sed -n '45,105p' .github/actions/deploy-prod/action.yml

printf '%s\n' '== Guard-placement regression source =='
rg -n -C 12 \
  '(deploy-prod/action\.yml|dr-rebuild|heal-prod-on-failure|supersession-gate|first|guard-publish-workflow-approved-revisions|recovery|publish-platform-manifests)' \
  scripts/tests/test-publish-workflow-approved-revisions-guard.sh

printf '%s\n' '== Workflow structure relevant to direct publication =='
python3 - <<'PY'
from pathlib import Path
import yaml

for filename in ('.github/workflows/ci.yaml', '.github/workflows/cd.yaml', '.github/workflows/dr-rebuild.yaml'):
    data = yaml.safe_load(Path(filename).read_text())
    print(f'\n{filename}')
    for job_name, job in data['jobs'].items():
        steps = job.get('steps', [])
        publications = [
            s for s in steps
            if str(s.get('uses', '')).startswith('./.github/actions/deploy-prod')
        ]
        if publications:
            print(f'  {job_name}: needs={job.get("needs")}')
            for index, step in enumerate(steps):
                if step in publications:
                    print(f'    publication step {index}: {step.get("uses")}')
                    print(f'    preceding steps: {[s.get("name") for s in steps[:index]]}')
PY

Length of output: 22247


🏁 Script executed:

#!/bin/bash
set -euo pipefail

revision='fedd576974402b6f967dc2f824bbd9abcc446bf3'
base="$(git merge-base "$revision" origin/main 2>/dev/null || git merge-base "$revision" main)"

printf '%s\n' '== PR-range changes for relevant files =='
git diff --no-ext-diff --find-renames "$base" "$revision" -- \
  .github/actions/deploy-prod/action.yml \
  .github/workflows/ci.yaml \
  .github/workflows/cd.yaml \
  .github/workflows/dr-rebuild.yaml \
  .github/workflows/validate-main.yaml \
  scripts/tests

printf '%s\n' '== Commits that introduced relevant action and workflow lines =='
git blame -L 45,60 .github/actions/deploy-prod/action.yml
git blame -L 1905,1972 .github/workflows/ci.yaml
git blame -L 100,118 .github/workflows/dr-rebuild.yaml

printf '%s\n' '== Exact placement and bypass regression assertions =='
rg -n -C 8 --glob 'scripts/tests/*' \
  '(approved publication signers|APPROVED_REVISIONS_ENFORCE|deploy action|deploy-prod/action\.yml|supersession-gate|heal-prod-on-failure|recovery bypass|first step)' \
  scripts/tests

printf '%s\n' '== Direct publication invocations and local guard context =='
rg -n -C 14 --glob '*.yaml' --glob '*.yml' \
  'uses:\s*\./\.github/actions/deploy-prod(/publish-platform-manifests)?\s*$' \
  .github/workflows .github/actions

printf '%s\n' '== Action commits reachable from requested head =='
git log --oneline --decorate --ancestry-path "$base..$revision" -- \
  .github/actions/deploy-prod/action.yml \
  .github/workflows/ci.yaml \
  .github/workflows/dr-rebuild.yaml \
  scripts/tests/test-publish-workflow-approved-revisions-guard.sh

Length of output: 90288


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== DR signing validator structure and relevant source =='
ast-grep outline scripts/validate-dr-signing --items all 2>/dev/null || true
rg -n -C 12 \
  '(guard-publish-workflow-approved-revisions|APPROVED_REVISIONS_ENFORCE|deploy-prod/action\.yml|publish-platform-manifests|supersession-gate|heal-prod-on-failure|first step|first command|recovery)' \
  scripts/validate-dr-signing scripts/tests 2>/dev/null || true

printf '%s\n' '== Relevant CI wiring for the DR signing validator =='
rg -n -C 8 \
  '(validate-dr-signing|test-publish-workflow-approved-revisions-guard)' \
  .github/workflows/ci.yaml .github/workflows/cd.yaml .github/workflows/dr-rebuild.yaml

printf '%s\n' '== Provenance of validator changes in PR range =='
base="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"
git log --oneline "$base..HEAD" -- scripts/validate-dr-signing scripts/tests
git diff --no-ext-diff --find-renames "$base" HEAD -- scripts/validate-dr-signing scripts/tests | sed -n '1,1800p'

Length of output: 201291


@devantler Reviewed fedd576974402b6f967dc2f824bbd9abcc446bf3.

I found no issues.

The deploy action runs the enforced signer-membership guard as its first step. The guard runs before KSail setup, talosctl setup, and secret materialization.

The merge-group deploy, manual CD deploy, and merge-group recovery use the same deploy action. The recovery job checks out main before it invokes the action. The guard therefore reads the signer policy from the revision that recovery publishes.

DR rebuild still publishes through the nested publication action. Its rebuild job depends on supersession-gate, which runs the enforced guard on the checked-out workflow revision before publication.

You are interacting with an AI system.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

User evaluation at fedd576974402b6f967dc2f824bbd9abcc446bf3: I extracted and executed the guard command and environment from the four workflow prerequisites and the deploy action's first step in an isolated checkout. All five accepted the generated pair, refused a syntactically valid unapproved fixed SHA, and accepted the restored pair. This exercise did not invoke deployment actions.

The recovery regression verifies that main's checked-out action supplies its signer policy, including rejection of six ways to detach that policy from the checkout. CodeRabbit's current-head review found no issues.

@devantler
devantler marked this pull request as ready for review September 5, 2026 11:24
@devantler
devantler added this pull request to the merge queue Sep 5, 2026
Merged via the queue into main with commit fb2c613 Sep 5, 2026
27 checks passed
@devantler
devantler deleted the codex/approved-signer-matchers-3569 branch September 5, 2026 11:38
@github-project-automation github-project-automation Bot moved this from 🫴 Ready to ✅ Done in 🌊 Project Board Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

1 participant