Skip to content

bug(ci): the authorization gate's moved-entry diagnostics never run on a real mismatch #3879

Description

@devantler

🤖 Generated by the Agentic Engineer

Evidence

#3836 added moved-entry diagnostics to the authorization gate: on an unapproved
aggregate, run() calls surfaceMismatchReport, which renders the approval base and
names the surface entries that differ. describeSurfaceDelta is covered by
surface_delta_test.go and works.

It has never run on a real mismatch. The CI step invokes two commands in order:

run: |
  set -euo pipefail
  go test ./scripts/validate-eks-ci-role-policy
  base_root="$RUNNER_TEMP/approval-base-tree"
  if git worktree add --detach "$base_root" HEAD^1; then
    go run ./scripts/validate-eks-ci-role-policy . "$base_root"

TestValidateAuthorizationAcceptsCommittedPolicy (main_test.go:1609) calls
validateAuthorization() and t.Fatalfs with the bare error. It fails on exactly the
condition the diagnostics exist to explain, and under set -e that aborts the step — so
go run, the only caller of surfaceMismatchReport, never executes. The
cd.yaml copy of the step has the same ordering.

Measured live on #3878, CI run 35257229458, job 105324573289:

observation value
approval base checkout succeeded (EKS CI role authorization approval base passed, 18:13:32Z)
go test verdict FAIL, 18:13:44Z
aggregate reported a4781e58…
moved-entry lines emitted 0

The entry that moved was a single HelmRelease, and identifying it took a
purpose-written conservation render — precisely the cost #3836 set out to remove.

Affected audience and impact

Whoever next moves the aggregate. Every such PR pays a manual conservation render to
learn what the gate already knows, and the re-approval is reviewed without the one fact
that makes it checkable. That is the desensitisation risk #2803 names: re-approval
becomes a rubber stamp when nothing states what actually moved.

Four re-approvals on 2026-09-17 alone (#3873, #3874, #3875, #3876) each paid this cost.

Expected behaviour

A run that fails the aggregate check emits the moved-entry diagnostics, and still fails.

Smallest useful change

Run both commands and fail if either failed, rather than short-circuiting on the first:
the go test verdict and the diagnostics are independent outputs, and the step needs
both. Apply to ci.yaml and cd.yaml.

Acceptance criteria

  • A run whose aggregate does not match emits the moved-entry lines and exits non-zero.
  • A negative control proves the step still fails when go test fails for a reason
    unrelated to the aggregate.
  • The cd.yaml copy of the step gets the same treatment.

Size

Small.

Follow-up to #3836. Unblocks #2803's third acceptance criterion.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions