Skip to content

feat(auth): label-gated workflow-change elevation#2548

Closed
ifireball wants to merge 14 commits into
fullsend-ai:mainfrom
ifireball:cursor/c4c62cea
Closed

feat(auth): label-gated workflow-change elevation#2548
ifireball wants to merge 14 commits into
fullsend-ai:mainfrom
ifireball:cursor/c4c62cea

Conversation

@ifireball

@ifireball ifireball commented Jun 23, 2026

Copy link
Copy Markdown
Member

Closes #470

Summary

  • Add a reusable authorization gate framework (ADR 0054) for elevated agent permissions, starting with workflow-change-needed / workflow-change-allowed.
  • Verify labels via fullsend auth check in workflows and agent pre/post scripts; mint mechanically merges elevations (e.g. workflows: write) only when the CLI approves.
  • Triage defers ready-to-code when workflow edits are anticipated; code and fix agents are gated at pre-run and pre-push.

Test plan

  • make go-test (authorization, cli, forge, mintcore, appsetup, dispatch embed sync)
  • bash internal/scaffold/fullsend-repo/scripts/post-triage-test.sh
  • bash internal/scaffold/fullsend-repo/scripts/pre-code-auth-test.sh
  • bash internal/scaffold/fullsend-repo/scripts/post-code-auth-test.sh
  • Manual: triage sets workflow-change-needed without ready-to-code
  • Manual: add workflow-change-allowed, /fs-code, verify mint elevation and successful workflow push
  • Manual: non-collaborator comment after authorization invalidates label on next run

Implement ADR 0054 so collaborators can authorize workflow file edits via
labels, with fullsend auth check enforcing gates and mint granting
workflows:write only through requested elevations.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

Site preview

Preview: https://725afbf1-site.fullsend-ai.workers.dev

Commit: eca6b73fddbb1c31794bba93276c416cfe803015

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 23, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 10:24 AM UTC · Ended 10:39 AM UTC
Commit: 4e21a60 · View workflow run →

@ifireball ifireball self-assigned this Jun 23, 2026
The mint-token action used jq's empty filter in object construction,
which produced no JSON body when elevations were omitted and broke all
agent token mints (including triage e2e). Also apply gofmt and fix
shellcheck issues in auth harness tests.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 23, 2026

Copy link
Copy Markdown

🤖 Finished Review · ❌ Failure · Started 10:44 AM UTC · Completed 11:00 AM UTC
Commit: 1a3ce9e · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review

Findings

Medium

  • [documentation-code-mismatch] docs/guides/dev/cli-internals.md:374 — The CLI tree documents the labels copy flags as --from-number <int> and --to-number <int>, but the actual implementation in internal/cli/labels.go registers them as --from and --to. Users following the documentation will get "unknown flag" errors.
    Remediation: Update the documentation to use --from <int> and --to <int>, or rename the flags in labels.go to --from-number and --to-number to match the docs.

  • [exit-code-convention] internal/cli/exitcode.go:21 — New exit code constant AuthExitBlocked = 10 collides with the existing StaleHeadExitCode = 10 in internal/cli/postreview.go. Both types (exitError and staleHeadError) implement the exitCoder interface consumed by cmd/fullsend/main.go. While these are used by different subcommands (auth check vs post-review), sharing the same numeric value could cause confusion in CI log analysis or wrapper scripts that inspect process exit codes without knowing which subcommand ran.
    Remediation: Use a distinct value for AuthExitBlocked (e.g., 20) or extract all exit codes into a shared constant block with non-overlapping ranges per subcommand.

  • [protected-path] .github/actions/mint-token/action.yml, .github/workflows/reusable-code.yml, .github/workflows/reusable-fix.yml — Three files under .github/ are modified to add workflow-change authorization checks and elevation passthrough to the mint-token action. The PR links to issue Missing github app permissions for updating workflows #470 and ADR 0055 explains the rationale. Human approval is always required for protected-path changes.

Previous run

Review

Findings

Medium

  • [documentation-code-mismatch] docs/guides/dev/cli-internals.md — The CLI tree documents the labels copy flags as --from-number <int> and --to-number <int>, but the actual implementation in internal/cli/labels.go registers them as --from and --to. Users following the documentation will get "unknown flag" errors.
    Remediation: Update the documentation to use --from <int> and --to <int>, or rename the flags in labels.go to --from-number and --to-number to match the docs.

  • [exit-code-convention] internal/cli/exitcode.go — New exit code constant AuthExitBlocked = 10 collides with the existing StaleHeadExitCode = 10 in internal/cli/postreview.go. While these are used by different subcommands (auth check vs post-review), sharing the same numeric value could cause confusion in CI log analysis or wrapper scripts that inspect process exit codes without knowing which subcommand ran.
    Remediation: Use non-overlapping exit codes across the CLI package, or document the per-subcommand exit code semantics in a central location.

  • [permission-expansion] internal/forge/github/types.go:98 — The coder GitHub App manifest now declares workflows: write as a permanent ceiling permission. This is intentional per ADR 0055 and issue Missing github app permissions for updating workflows #470. Mint grants it only via the workflow-change authorization gate; default coder tokens remain without workflows: write. A cross-validation test (TestAgentAppConfig_Coder_CoversMintcoreElevation) asserts the manifest covers mintcore elevation requirements.

  • [architectural-coherence] internal/authorization/registry.go and internal/mintcore/elevations.go — Gate definitions are duplicated between authorization/registry.go (CLI) and mintcore/elevations.go / elevations.go.embed (mint). The two registries must stay aligned but have no compile-time enforcement. The cross-validation test in types_test.go checks manifest permission coverage but not semantic equivalence of gate names and permission maps across the two registries.
    Remediation: Add an integration test that directly verifies authorization.Gates() and mintcore.elevationGates stay aligned on gate names and permission maps.

  • [breaking-api-change] internal/forge/forge.go:307 — The forge.Client interface adds 5 new required methods (GetIssue, AddIssueLabels, RemoveIssueLabel, GetLabelAppliedAt, GetCommentAuthorAssociation). Both LiveClient and FakeClient are updated in this PR. The package is under internal/, preventing external Go imports.

  • [breaking-function-signature] internal/mintcore/github.go:207CreateInstallationToken adds a new elevations []string parameter. All call sites within this PR (including the embedded GCF copy) are updated. The mintcore package is under internal/, preventing external imports.

  • [protected-path] .github/actions/mint-token/action.yml, .github/workflows/reusable-code.yml, .github/workflows/reusable-fix.yml — Three files under .github/ are modified to add workflow-change authorization checks and elevation passthrough to the mint-token action. The PR links to issue Missing github app permissions for updating workflows #470 and ADR 0055 explains the rationale. Human approval is always required for protected-path changes.


Labels: PR modifies mint token service, authorization gates, CLI commands, and agent workflow/script infrastructure for code/fix/triage workflows.


Labels: PR modifies dispatch workflows and GCF provisioner embed files alongside mint and authorization components.

Previous run (2)

Review

Findings

Medium

  • [logic-error] internal/forge/github/github.go:1700GetLabelAppliedAt returns on the first page containing a matching "labeled" event, but timeline events are chronological (oldest first). If the label was applied, removed, then re-applied and the two application events span different pages, the function returns the older timestamp instead of the most recent one. The stale check then uses an overly-old allowedAt value, causing valid authorizations to be incorrectly flagged as stale (false-positive blocking).
    Remediation: Track the latest timestamp across all pages instead of returning early when !latest.IsZero().

  • [architectural-coherence] internal/mintcore/elevations.go — Gate definitions are duplicated between authorization/registry.go (CLI) and mintcore/elevations.go / elevations.go.embed (mint). The two registries must stay aligned but have no compile-time enforcement. The cross-validation test in types_test.go checks manifest permission coverage but not semantic equivalence of gate names and permission maps across the two registries.

  • [protected-path] .github/actions/mint-token/action.yml, .github/workflows/reusable-code.yml, .github/workflows/reusable-fix.yml — Three files under .github/ are modified. The PR links to issue Missing github app permissions for updating workflows #470 and ADR 0054 explains the rationale for adding workflow-level authorization checks. Human approval is always required for protected-path changes.


Labels: PR modifies mint token service, authorization gates, and agent scripts for code/fix/triage workflows

Previous run (3)

Review

Findings

Medium

  • [logic-error] internal/forge/github/github.go:1700GetLabelAppliedAt returns on the first page containing a matching "labeled" event, but timeline events are chronological (oldest first). If the label was applied, removed, then re-applied and the two application events span different pages, the function returns the older timestamp instead of the most recent one. The stale check then uses an overly-old allowedAt value, causing valid authorizations to be incorrectly flagged as stale (false-positive blocking).
    Remediation: Track the latest timestamp across all pages instead of returning early when !latest.IsZero().

  • [architectural-coherence] internal/mintcore/elevations.go — Gate definitions are duplicated between authorization/registry.go (CLI) and mintcore/elevations.go / elevations.go.embed (mint). The two registries must stay aligned but have no compile-time enforcement. The cross-validation test in types_test.go checks manifest permission coverage but not semantic equivalence of gate names and permission maps across the two registries.

  • [protected-path] .github/actions/mint-token/action.yml, .github/workflows/reusable-code.yml, .github/workflows/reusable-fix.yml — Three files under .github/ are modified. The PR links to issue Missing github app permissions for updating workflows #470 and ADR 0054 explains the rationale for adding workflow-level authorization checks. Human approval is always required for protected-path changes.


Labels: PR modifies mint token service, authorization gates, and agent scripts for code/fix/triage workflows

Previous run (4)

Review

Findings

High

  • [protected-path] .github/actions/mint-token/action.yml, .github/workflows/reusable-code.yml, .github/workflows/reusable-fix.yml — Three files under .github/ are modified. This PR has no linked issue justifying changes to governance/infrastructure files. Human approval is always required for protected-path changes.
    Remediation: Link an authorizing issue to this PR that explains why .github/ workflow and action files need modification.

Medium

  • [logic-error] internal/mintcore/handler.go:225 — After minting with elevations, the grant-logging code compares granted permissions against RolePermissionsFor(req.Role) (base permissions only). When elevations are active (e.g. workflows: write), the granted permission will not appear in the base set, producing a spurious WARNING: extra permission granted: workflows=write (not requested) log entry. Same issue in the .embed copy.
    Remediation: Use MergeRoleElevations(req.Role, req.Elevations) instead of RolePermissionsFor(req.Role) for the logging comparison, falling back to base permissions if merge returns an error.

  • [permission-expansion] internal/forge/github/types.go:97 — Coder GitHub App manifest ceiling now includes Workflows: "write". Existing orgs must manually approve this permission change in GitHub org settings. Until approved, mint cannot grant workflows:write even when elevated. The PR adds a stale-permission detection test and documents the upgrade path in ADR 0054, but the change requires coordinated rollout communication.

  • [api-shape] internal/cli/auth.go:940 — Token resolution uses only --token flag and GITHUB_TOKEN env var. The established pattern in admin.go:resolveToken() uses a 3-tier fallback (GH_TOKEN, GITHUB_TOKEN, gh auth token). This inconsistency means developers running fullsend auth check locally may get unexpected token-not-found errors.
    Remediation: Use the shared resolveToken() helper from admin.go, or document why auth check intentionally uses a simpler resolution path.

  • [missing-doc] docs/guides/dev/cli-internals.md:5 — The CLI command tree is missing the new fullsend auth (with subcommand check) and fullsend labels (with subcommands ensure and copy) commands introduced in this PR.
    Remediation: Add the new commands to the CLI command tree documentation.

Low

  • [error-handling-gap] internal/authorization/check.go:105 — The default case in Evaluate phase switch silently returns StatusOK for unrecognized phases. The CLI validates phases before calling, but a future internal caller could get silent success without an auth check (fail-open).
  • [test-inadequate] internal/authorization/check_test.go — Missing test coverage: no test for PhasePrePush with hasAllowed=true, no test for stale-label path via Evaluate, no tests for ApplyMutations.
  • [pattern-violation] internal/cli/exitcode.go:19AuthExitBlocked=10 collides with StaleHeadExitCode=10 in postreview.go. Different subcommands, but sharing values is fragile.
  • [api-contract] internal/forge/github/github.go:1649GetLabelAppliedAt uses deprecated mockingbird-preview Accept header. The timeline API was graduated; standard header works.
  • [missing-authorization] docs/ADRs/0054-label-gated-elevated-agent-permissions.md — Non-trivial change (47 files, 1820 additions) has no linked GitHub issue. ADR 0054 references #470 as motivation.
  • [architectural-coherence] internal/mintcore/elevations.go:8 — Gate definitions duplicated between authorization/registry.go (CLI) and mintcore/elevations.go (mint). Cross-validation test exists in types_test.go but only checks manifest coverage, not semantic equivalence.
  • [stale-doc] docs/glossary.md:117 — "Ready to Code" entry does not mention workflow-change authorization deferral.
  • [incomplete-doc] docs/guides/user/bugfix-workflow.md:40 — Labels table missing workflow-change-needed and workflow-change-allowed.

Labels: PR introduces authorization gate framework for elevated agent permissions, modifies mint service and GitHub App manifests

ifireball and others added 2 commits June 24, 2026 14:42
Signed-off-by: Barak Korren <bkorren@redhat.com>
Merge upstream main, fix gofmt on appsetup_test.go, use
MergeRoleElevations for mint grant logging, adopt resolveToken() in
auth/labels CLI commands, and document new commands in cli-internals.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@ifireball ifireball marked this pull request as ready for review June 24, 2026 11:43
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

feat(auth): label-gated workflow-change elevation
✨ Enhancement 🐞 Bug fix 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

Description

• Add label-gated authorization framework to grant elevated agent permissions (ADR 0054).
• Gate workflow file edits via fullsend auth check and mint workflows:write only when
 authorized.
• Defer ready-to-code when workflow edits are expected; enforce pre-run and pre-push checks.
Diagram

graph TD
  W["Reusable agent workflows"] --> C["fullsend auth check"] --> GH{{"GitHub API"}}
  C --> M["Mint service"] --> T["Scoped app token"] --> A["Code/Fix agents"]
  A --> S["Pre/Post scripts"] --> C
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Enforce label policy inside mint
  • ➕ Single enforcement point; callers can’t forget to run checks
  • ➖ Mint would need to read GitHub issues/labels, expanding its trust and attack surface
  • ➖ Harder to keep mint purely mechanical/downscoping-focused as intended by ADR 0054
2. Use GitHub protected paths / CODEOWNERS only
  • ➕ No custom authorization logic
  • ➕ Leverages native GitHub controls
  • ➖ Doesn’t solve agent token scope (still needs workflows:write to push changes)
  • ➖ May block legitimate automated workflow edits without a structured re-authorization flow
3. Separate “workflow editor” GitHub App/role
  • ➕ Clear blast-radius separation; no dynamic elevation path
  • ➖ More app sprawl and operational overhead (installations, secrets, rotations)
  • ➖ Harder UX: switching roles/tokens mid-pipeline, more workflow wiring

Recommendation: The PR’s approach (workflow/runner-side label verification + mint-side mechanical permission merging) is the best balance of security and operability: mint remains a minimal downscoping service, while the policy and stale-detection logic stays closer to the workflow context that can safely talk to GitHub and post guidance back to users.

Files changed (48) +1851 / -37

Enhancement (23) +1093 / -25
check.goImplement multi-phase gate evaluation + label mutations helpers +187/-0

Implement multi-phase gate evaluation + label mutations helpers

• Introduces core authorization evaluation for pre-run, mint, and pre-push phases, including workflow file matching and mutation hooks for stale/unauthorized outcomes.

internal/authorization/check.go

comment.goGenerate sticky comment marker + user-facing failure messages +58/-0

Generate sticky comment marker + user-facing failure messages

• Adds helpers to format consistent sticky comments for blocked/stale/unauthorized outcomes across phases.

internal/authorization/comment.go

gate.goDefine Gate model for label-gated permission elevation +11/-0

Define Gate model for label-gated permission elevation

• Adds the 'Gate' struct tying gate name, needed/allowed labels, file patterns, and mint elevation permissions.

internal/authorization/gate.go

patterns.goWorkflow file glob patterns and matching utilities +43/-0

Workflow file glob patterns and matching utilities

• Adds workflow file patterns ('.github/workflows/**') and matching logic supporting '**' recursive patterns.

internal/authorization/patterns.go

registry.goGate registry with initial workflow-change gate +29/-0

Gate registry with initial workflow-change gate

• Registers 'workflow-change' gate mapping labels to 'workflows: write' mint elevation and provides lookup by name.

internal/authorization/registry.go

stale.goStale authorization detection via comment association + command detection +58/-0

Stale authorization detection via comment association + command detection

• Implements stale invalidation by scanning comments after label application and checking '/fs-' influence plus non-collaborator associations (NONE/READ).

internal/authorization/stale.go

auth.goAdd 'fullsend auth check' command with JSON output + apply mode +160/-0

Add 'fullsend auth check' command with JSON output + apply mode

• Adds CLI command to evaluate authorization gates for a repo/issue/PR across phases, optionally applying label mutations and posting sticky comments. Returns distinct exit codes for blocked vs stale/unauthorized outcomes.

internal/cli/auth.go

exitcode.goIntroduce structured exit error + auth-specific exit codes +23/-0

Introduce structured exit error + auth-specific exit codes

• Adds 'exitError' with exit code plumbing and constants for auth outcomes (10 blocked, 11 stale/unauthorized).

internal/cli/exitcode.go

labels.goAdd 'fullsend labels ensure' and 'labels copy' helpers +159/-0

Add 'fullsend labels ensure' and 'labels copy' helpers

• Implements label mutation helpers for workflows/scripts (add/remove a label; copy labels by prefix from issue to PR). Uses token resolution and basic label validation.

internal/cli/labels.go

root.goRegister new auth and labels subcommands +2/-0

Register new auth and labels subcommands

• Wires 'fullsend auth' and 'fullsend labels' into the CLI root command.

internal/cli/root.go

elevations.go.embedEmbed mintcore elevation gate merging logic (GCF source) +47/-0

Embed mintcore elevation gate merging logic (GCF source)

• Adds embedded 'MergeRoleElevations' and elevation gate registry for the deployed mint function source bundle.

internal/dispatch/gcf/mintsrc/mintcore/elevations.go.embed

github.go.embedMint embedded GitHub token creation now merges role elevations +4/-4

Mint embedded GitHub token creation now merges role elevations

• Updates embedded mintcore to accept 'elevations' and use 'MergeRoleElevations' when requesting installation tokens.

internal/dispatch/gcf/mintsrc/mintcore/github.go.embed

handler.go.embedMint embedded handler accepts elevations and validates them +17/-6

Mint embedded handler accepts elevations and validates them

• Extends the mint request schema with 'elevations', validates requested elevations, and logs granted permissions relative to merged requested permissions.

internal/dispatch/gcf/mintsrc/mintcore/handler.go.embed

forge.goExpand forge.Client interface for issue/label operations and timestamps +6/-0

Expand forge.Client interface for issue/label operations and timestamps

• Adds 'GetIssue', label mutation APIs, label-applied timestamp lookup, and comment author association lookup to support auth gate evaluation.

internal/forge/forge.go

github.goImplement new issue/label APIs and timeline-based label timestamps +117/-2

Implement new issue/label APIs and timeline-based label timestamps

• Adds live GitHub implementations for fetching issues, adding/removing labels, retrieving last-labeled timestamp via issue timeline API, and fetching comment author association. Also refactors request helper to support custom Accept headers.

internal/forge/github/github.go

elevations.goAdd elevation gate merging to mintcore library +47/-0

Add elevation gate merging to mintcore library

• Introduces elevation gate registry and 'MergeRoleElevations' to merge role baseline permissions with validated, role-allowed elevations.

internal/mintcore/elevations.go

github.goUse merged permissions (role + elevations) when minting installation tokens +4/-4

Use merged permissions (role + elevations) when minting installation tokens

• Extends token minting to accept 'elevations' and compute the permission request via 'MergeRoleElevations'.

internal/mintcore/github.go

handler.goMint API accepts elevations and validates/uses them in token minting +17/-6

Mint API accepts elevations and validates/uses them in token minting

• Extends mint request schema, validates elevation lists, passes elevations into token minting, and updates permission-grant logging to compare against merged requested permissions.

internal/mintcore/handler.go

post-code.shEnforce pre-push workflow-change gate and copy labels to PR +28/-0

Enforce pre-push workflow-change gate and copy labels to PR

• Adds a pre-push auth check using changed files on stdin to block unauthorized workflow file pushes. Copies workflow-change labels from issue to existing/new PRs after pushing/creating PRs.

internal/scaffold/fullsend-repo/scripts/post-code.sh

post-fix.shEnforce pre-push workflow-change gate for fix pushes +20/-0

Enforce pre-push workflow-change gate for fix pushes

• Adds a pre-push auth check using changed files to block fix-agent pushes that modify workflow files without authorization.

internal/scaffold/fullsend-repo/scripts/post-fix.sh

post-triage.shApply workflow-change-needed and defer ready-to-code based on triage output +17/-3

Apply workflow-change-needed and defer ready-to-code based on triage output

• Treats workflow-change labels as control labels, reads 'authorizations_required', applies 'workflow-change-needed', and skips auto-promotion to 'ready-to-code' until authorized.

internal/scaffold/fullsend-repo/scripts/post-triage.sh

pre-code.shEnforce pre-run workflow-change gate for code agent +20/-0

Enforce pre-run workflow-change gate for code agent

• Runs 'fullsend auth check' in pre-run phase; if blocked, posts notice and skips the code agent by writing 'skipped=true'.

internal/scaffold/fullsend-repo/scripts/pre-code.sh

pre-fix.shEnforce pre-run workflow-change gate for fix agent +19/-0

Enforce pre-run workflow-change gate for fix agent

• Runs 'fullsend auth check' in pre-run phase against the PR; if blocked, errors out to prevent running fix agent without authorization.

internal/scaffold/fullsend-repo/scripts/pre-fix.sh

Bug fix (1) +9 / -2
action.ymlSupport optional elevations in mint-token action request body +9/-2

Support optional elevations in mint-token action request body

• Adds an 'elevations' input and includes it in the mint request JSON only when non-empty. Fixes jq object construction so token minting works when elevations are omitted.

.github/actions/mint-token/action.yml

Tests (9) +403 / -2
appsetup_test.goTest stale-permission detection for coder missing workflows:write +32/-0

Test stale-permission detection for coder missing workflows:write

• Adds a dedicated test to ensure setup surfaces stale permission errors when the coder app installation lacks 'workflows' permission.

internal/appsetup/appsetup_test.go

check_test.goUnit tests for gate evaluation, workflow matching, and stale detection +80/-0

Unit tests for gate evaluation, workflow matching, and stale detection

• Covers workflow glob patterns, phase-specific evaluation outcomes, and stale invalidation on non-collaborator agent-influencing comments.

internal/authorization/check_test.go

auth_test.goCLI tests for auth check exit codes and JSON elevations output +109/-0

CLI tests for auth check exit codes and JSON elevations output

• Verifies blocked exit code mapping and mint-phase JSON output includes 'elevations' when authorized.

internal/cli/auth_test.go

types_test.goTest coder manifest includes workflows and covers elevation requirements +15/-0

Test coder manifest includes workflows and covers elevation requirements

• Asserts coder app permissions include 'workflows: write' and adds a compatibility test ensuring manifest ceilings cover mintcore’s elevated permission set.

internal/forge/github/types_test.go

elevations_test.goUnit tests for mintcore elevation merging behavior +32/-0

Unit tests for mintcore elevation merging behavior

• Covers workflow-change elevation merge, unknown gate errors, disallowed role errors, and baseline behavior with no elevations.

internal/mintcore/elevations_test.go

github_test.goUpdate mintcore GitHub token tests for new elevations parameter +2/-2

Update mintcore GitHub token tests for new elevations parameter

• Updates existing tests to pass the new 'elevations' argument and preserves unknown-role coverage.

internal/mintcore/github_test.go

post-code-auth-test.shAdd harness test to ensure post-code blocks unauthorized workflow push +62/-0

Add harness test to ensure post-code blocks unauthorized workflow push

• Creates a local git repo with workflow changes and asserts post-code fails when 'fullsend auth' returns unauthorized (exit 11).

internal/scaffold/fullsend-repo/scripts/post-code-auth-test.sh

post-triage-test.shTest triage defers ready-to-code when workflow-change authorization is required +31/-0

Test triage defers ready-to-code when workflow-change authorization is required

• Adds tests asserting 'workflow-change-needed' is applied and 'ready-to-code' is not applied when triage output requests workflow-change authorization.

internal/scaffold/fullsend-repo/scripts/post-triage-test.sh

pre-code-auth-test.shAdd harness test to ensure pre-code skips agent when blocked +40/-0

Add harness test to ensure pre-code skips agent when blocked

• Mocks 'fullsend auth' returning blocked (exit 10) and asserts pre-code sets 'skipped=true' and exits successfully.

internal/scaffold/fullsend-repo/scripts/pre-code-auth-test.sh

Documentation (9) +101 / -6
0007-per-role-github-apps.mdDocument coder workflows elevation as ceiling + gated grant +1/-0

Document coder workflows elevation as ceiling + gated grant

• Clarifies that coder app includes 'workflows: write' only as a ceiling permission, and mint grants it solely via the 'workflow-change' gate per ADR 0054.

docs/ADRs/0007-per-role-github-apps.md

0054-label-gated-elevated-agent-permissions.mdAdd ADR 0054 defining label-gated elevated permissions model +55/-0

Add ADR 0054 defining label-gated elevated permissions model

• Introduces the decision record describing gate registry, phases (mint/pre-run/pre-push), stale invalidation rules, and mint’s mechanical merging of elevations.

docs/ADRs/0054-label-gated-elevated-agent-permissions.md

code.mdDocument workflow-change gating for code agent pipeline and labels +5/-3

Document workflow-change gating for code agent pipeline and labels

• Updates the code agent pipeline description to include pre-run and pre-push authorization checks. Documents 'workflow-change-needed/allowed' behavior and how it affects 'ready-to-code'.

docs/agents/code.md

fix.mdDocument workflow-change gating for fix agent +2/-2

Document workflow-change gating for fix agent

• Updates fix agent docs to describe pre-run authorization checks against the PR and pre-push enforcement in post-script.

docs/agents/fix.md

triage.mdDocument new triage outcomes for workflow-change authorization +2/-0

Document new triage outcomes for workflow-change authorization

• Adds label meanings for 'workflow-change-needed' and 'workflow-change-allowed' as triage outcomes that defer coding until authorized.

docs/agents/triage.md

architecture.mdAdd architecture note for authorization gates + mint elevation merging +6/-0

Add architecture note for authorization gates + mint elevation merging

• Documents the new authorization gates concept and links ADR 0054, clarifying that label policy is enforced outside mint.

docs/architecture.md

cli-internals.mdDocument new 'fullsend auth' and 'fullsend labels' CLI commands +20/-0

Document new 'fullsend auth' and 'fullsend labels' CLI commands

• Adds CLI internals documentation for 'auth check' flags and 'labels ensure/copy' helpers used by workflows and scripts.

docs/guides/dev/cli-internals.md

infrastructure-reference.mdMark coder workflows permission as gated grant +3/-1

Mark coder workflows permission as gated grant

• Updates permission table to include 'workflows: write*' for coder and explains that mint grants it only when elevations include 'workflow-change' after auth checks.

docs/guides/infrastructure/infrastructure-reference.md

triage.mdTeach triage output schema about required authorizations +7/-0

Teach triage output schema about required authorizations

• Adds 'authorizations_required: ["workflow-change"]' guidance and instructions for maintainers messaging when workflow edits require authorization.

internal/scaffold/fullsend-repo/agents/triage.md

Other (6) +245 / -2
reusable-code.ymlRun workflow-change auth check before minting coder token +30/-0

Run workflow-change auth check before minting coder token

• Adds a mint-phase authorization check that outputs a comma-separated 'elevations' list. Passes elevations into the mint-token action and wires GH token + trigger comment ID into pre/post scripts for stale detection.

.github/workflows/reusable-code.yml

reusable-fix.ymlGate fix workflow token mint and scripts on workflow-change authorization +47/-0

Gate fix workflow token mint and scripts on workflow-change authorization

• Extracts a PR number reliably for auth checks, runs mint-phase auth check to compute elevations, and passes GH token/trigger comment ID into pre/post scripts to enforce pre-run and pre-push gates.

.github/workflows/reusable-fix.yml

provisioner.goInclude elevations.go in embedded mint source provisioning +2/-1

Include elevations.go in embedded mint source provisioning

• Adds the new embedded file to the provisioner’s go:embed set and filename mapping.

internal/dispatch/gcf/provisioner.go

fake.goExtend FakeClient with issue/label/timeline primitives for auth tests +157/-1

Extend FakeClient with issue/label/timeline primitives for auth tests

• Adds in-memory issue storage, label application timestamps, comment author association mapping, and label add/remove operations used by authorization and CLI tests.

internal/forge/fake.go

types.goRaise coder app manifest ceiling to include workflows:write +1/-0

Raise coder app manifest ceiling to include workflows:write

• Adds 'Workflows: write' to the coder GitHub App manifest permissions so gated elevation can be granted by mint when authorized.

internal/forge/github/types.go

triage-result.schema.jsonAdd authorizations_required field to triage result schema +8/-0

Add authorizations_required field to triage result schema

• Extends the triage JSON schema to allow an 'authorizations_required' array with 'workflow-change' enum.

internal/scaffold/fullsend-repo/schemas/triage-result.schema.json

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 11:46 AM UTC · Ended 11:47 AM UTC
Commit: 6bd5f3a · View workflow run →

Update TestBundleEmbeddedMintSource count after adding
mintcore/elevations.go to the embedded mint source.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 11:50 AM UTC · Ended 11:57 AM UTC
Commit: 6bd5f3a · View workflow run →

@qodo-code-review

qodo-code-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 58 rules

Grey Divider


Action required

1. Null trigger comment ID ✓ Resolved 🐞 Bug ☼ Reliability
Description
The scripts append --trigger-comment-id "${TRIGGER_COMMENT_ID}" whenever the env var is non-empty,
but the workflows already acknowledge this value can be the literal string null; passing null
into an int-typed Cobra flag can make fullsend auth check fail and incorrectly skip agents or
block pushes.
Code

internal/scaffold/fullsend-repo/scripts/pre-code.sh[R64-66]

+  if [[ -n "${TRIGGER_COMMENT_ID:-}" ]]; then
+    AUTH_ARGS+=(--trigger-comment-id "${TRIGGER_COMMENT_ID}")
+  fi
Relevance

⭐⭐⭐ High

Repo often guards against literal "null"/missing values in scripts/workflows; hardening likely
accepted.

PR-#603
PR-#729

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The reusable workflows already special-case TRIGGER_COMMENT_ID != 'null' in one place, but the
scripts do not, and the CLI defines --trigger-comment-id as an int flag; this combination can
break authorization checks when the env var is null.

.github/workflows/reusable-code.yml[115-138]
internal/scaffold/fullsend-repo/scripts/pre-code.sh[54-71]
internal/scaffold/fullsend-repo/scripts/post-code.sh[225-243]
internal/scaffold/fullsend-repo/scripts/post-fix.sh[247-265]
internal/cli/auth.go[134-143]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Several scripts treat `TRIGGER_COMMENT_ID` as present if it is non-empty, but GitHub Actions expressions can yield the literal string `null`. When this happens, the scripts pass `--trigger-comment-id null` into `fullsend auth check`, whose flag is declared as an integer, causing parsing failure and breaking the gate.

## Issue Context
The reusable workflows’ mint-phase auth-check step already guards against `"null"`, which implies this value is expected in some event payload shapes.

## Fix Focus Areas
- internal/scaffold/fullsend-repo/scripts/pre-code.sh[54-71]
- internal/scaffold/fullsend-repo/scripts/pre-fix.sh[89-106]
- internal/scaffold/fullsend-repo/scripts/post-code.sh[225-243]
- internal/scaffold/fullsend-repo/scripts/post-fix.sh[247-265]
- .github/workflows/reusable-code.yml[115-167]
- .github/workflows/reusable-fix.yml[143-167]
- internal/cli/auth.go[134-143]

## Suggested fix
- In every place that appends `--trigger-comment-id`, require a numeric value, e.g.:
 - `if [[ "${TRIGGER_COMMENT_ID:-}" =~ ^[0-9]+$ && "${TRIGGER_COMMENT_ID}" -gt 0 ]]; then ... fi`
 - Otherwise, do not pass the flag.
- Optionally also normalize at the workflow level by setting the env var to empty when null (or by using the same `!= 'null'` guard pattern used in the mint auth-check step).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Fix pre-run fails job ✓ Resolved 🐞 Bug ≡ Correctness
Description
When the pre-run workflow-change gate blocks, scripts/pre-fix.sh exits 1, failing the whole fix
workflow instead of “agent skipped” behavior described by ADR 0054 and already implemented for the
code workflow.
Code

internal/scaffold/fullsend-repo/scripts/pre-fix.sh[R92-105]

+if [[ -n "${GH_TOKEN:-}" ]]; then
+  AUTH_ARGS=(auth check --gate workflow-change
+    --repo "${REPO_FULL_NAME}"
+    --number "${PR_NUMBER}"
+    --phase pre-run
+    --apply
+    --token "${GH_TOKEN}")
+  if [[ -n "${TRIGGER_COMMENT_ID:-}" ]]; then
+    AUTH_ARGS+=(--trigger-comment-id "${TRIGGER_COMMENT_ID}")
+  fi
+  if ! fullsend "${AUTH_ARGS[@]}"; then
+    echo "::error::Workflow-change authorization blocked — skipping fix agent"
+    exit 1
+  fi
Relevance

⭐⭐⭐ High

Repo treats non-zero pre-script exits as fatal; prefers skip-with-exit0 patterns (PR #286, #603).

PR-#286
PR-#603

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
ADR 0054 explicitly defines pre-run blocked outcome as “Agent skipped,” and the code agent
implements skipping via skipped=true + exit 0, but the fix agent pre-script exits 1 and the fix
workflow has no skip gating on later steps.

docs/ADRs/0054-label-gated-elevated-agent-permissions.md[37-44]
internal/scaffold/fullsend-repo/scripts/pre-fix.sh[89-106]
internal/scaffold/fullsend-repo/scripts/pre-code.sh[54-72]
.github/workflows/reusable-fix.yml[381-427]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`pre-fix.sh` treats a blocked pre-run gate as a hard error (`exit 1`). ADR 0054 specifies that the pre-run phase should skip the agent, and the code workflow already uses `skipped=true` + exit 0 to implement that.

## Issue Context
If you want “blocked == skipped,” the workflow must also stop subsequent steps from running (setup, agent execution) based on an output.

## Fix Focus Areas
- internal/scaffold/fullsend-repo/scripts/pre-fix.sh[89-106]
- .github/workflows/reusable-fix.yml[381-427]
- docs/ADRs/0054-label-gated-elevated-agent-permissions.md[37-44]

## Suggested fix
- Update `pre-fix.sh` to mirror `pre-code.sh`:
 - On blocked/stale, write `skipped=true` to `${GITHUB_OUTPUT}` and `exit 0`.
- In `reusable-fix.yml`:
 - Add `id: validate` to the “Validate inputs” step.
 - Gate downstream steps (`setup-gcp`, `setup-agent-env`, `Run fix agent`, etc.) with `if: steps.validate.outputs.skipped != 'true'` (same pattern as `reusable-code.yml`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Stale check misclassifies users ✓ Resolved 🐞 Bug ⛨ Security
Description
authorization.IsNonCollaboratorAssociation only treats author_association values NONE/READ
as non-collaborator, so many non-collaborator comments will not invalidate
workflow-change-allowed, weakening the stale-invalidation guarantee and enabling elevation after
untrusted /fs-* comments.
Code

internal/authorization/stale.go[R49-57]

+// IsNonCollaboratorAssociation reports whether assoc indicates the author lacks
+// write access (NONE or READ on GitHub).
+func IsNonCollaboratorAssociation(assoc string) bool {
+	switch strings.ToUpper(strings.TrimSpace(assoc)) {
+	case "NONE", "READ":
+		return true
+	default:
+		return false
+	}
Relevance

⭐⭐ Medium

No historical evidence for new internal/authorization logic; only general author_association
patterns in PRs #279/#2106.

PR-#279
PR-#2106

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
ADR 0054 requires invalidation on any non-collaborator agent-influencing comment, but the
implementation only treats NONE/READ as non-collaborator while sourcing the value from GitHub’s
author_association field, so the stale check can fail to invalidate for other non-collaborator
associations.

docs/ADRs/0054-label-gated-elevated-agent-permissions.md[37-46]
internal/authorization/stale.go[11-58]
internal/forge/github/github.go[1776-1792]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`IsNonCollaboratorAssociation` is intended to detect commenters who lack write access, but it currently only flags `NONE` and `READ`. Since `GetCommentAuthorAssociation` returns GitHub’s `author_association` string, the stale check will incorrectly treat many non-collaborator associations as “collaborator,” preventing invalidation of `workflow-change-allowed` after untrusted agent-triggering comments.

## Issue Context
ADR 0054 states that a subsequent non-collaborator agent-influencing comment invalidates the label. The current association classifier is too narrow.

## Fix Focus Areas
- internal/authorization/stale.go[44-58]
- internal/authorization/check_test.go[60-75]

## Suggested fix
- Replace the current `NONE/READ => non-collaborator` check with an allowlist of trusted associations (e.g. return **false** only for `OWNER`, `MEMBER`, `COLLABORATOR`; return **true** for everything else, including empty/unknown).
- Add/adjust tests to cover at least one additional non-collaborator association string (and ensure it invalidates).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread internal/authorization/stale.go
Comment thread internal/scaffold/fullsend-repo/scripts/pre-code.sh Outdated
Comment thread internal/scaffold/fullsend-repo/scripts/pre-fix.sh
Update validate-output-schema harness after adding authorizations_required
to triage-result.schema.json.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 12:00 PM UTC · Ended 12:08 PM UTC
Commit: 6bd5f3a · View workflow run →

pre-code.sh now runs auth check when GH_TOKEN is set; stub fullsend
to pass authorization so PR-search tests keep exercising their path.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 12:12 PM UTC · Ended 12:23 PM UTC
Commit: 6bd5f3a · View workflow run →

@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Add tests for registry, comment templates, ApplyMutations, pre-push
allowed path, and auth exit codes to improve patch coverage.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 12:26 PM UTC · Ended 12:33 PM UTC
Commit: 6bd5f3a · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 9:11 PM UTC · Ended 9:14 PM UTC
Commit: ff8ec85 · View workflow run →

Cover apply/sticky posting, mint text output, pre-push denial, stale
evaluation paths, and multi-page label timeline lookup.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 9:17 PM UTC · Ended 9:24 PM UTC
Commit: ff8ec85 · View workflow run →

Add pattern matching, stale-check edge case, fake client label, CLI apply,
and mint elevation handler tests to improve codecov patch coverage.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:27 PM UTC · Completed 9:43 PM UTC
Commit: 229c98d · View workflow run →

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Squad Report — 6-agent review (round 2)

Agents: 2x claude-coder, 2x claude-researcher, 1x gemini-code-review, 1x cursor-code-review
Models: Claude, Gemini, Codex

3 unique MEDIUM findings posted inline (not covered by prior 10-agent review). See inline comments.

Contents: "write",
PullRequests: "write",
Checks: "read",
Workflows: "write",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] blast-radius (1/6 agents flagged)

Adding Workflows: "write" to the coder app manifest means every org's GitHub App installation for the coder role now has workflows: write as a ceiling permission. While mint only requests this at token-mint time when elevations are passed, the app installation itself has the capability at the org level.

Impact:

  1. Increases blast radius of a coder app PEM key compromise — attacker gains workflows: write for all token mints, not just elevated ones
  2. Existing orgs must re-approve the coder app installation in GitHub org settings after this change

Suggested fix: No code change needed — this is inherent to how GitHub App permissions work (manifest = ceiling, token = scoped). Recommend:

  • Document in ADR 0055 that this increases PEM compromise blast radius
  • Add to enrollment/upgrade docs that orgs must re-approve the coder app after this rollout
  • Consider an admin CLI warning when installed app permissions don't match the manifest

// New creates a new GitHub client with the given personal access token.
func New(token string) *LiveClient {
baseURL := "https://api.github.com"
if override := strings.TrimSpace(os.Getenv("GITHUB_API_URL")); override != "" {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] scope-creep (1/6 agents flagged)

New() now reads GITHUB_API_URL from the environment, overriding the base URL for all ~20 production call sites that use New(). The existing WithBaseURL() was the opt-in mechanism for custom URLs.

If a CI environment sets GITHUB_API_URL for other tools (e.g., GitHub CLI, actions/github-script), all forge API calls silently redirect to that URL. This is a behavioral change with no explicit opt-in at each call site.

Suggested fix: Limit the env override to the call sites that need it (the new auth.go and labels.go CLI commands):

client := gh.New(token)
if u := os.Getenv("GITHUB_API_URL"); u != "" {
    client = client.WithBaseURL(u)
}

Or, if this is an intentional global knob, add a code comment documenting that it affects all New() callers.

Comment thread internal/cli/labels.go
cmd.Flags().StringVar(&repo, "repo", "", "repository in owner/repo format (required)")
cmd.Flags().IntVar(&fromNumber, "from", 0, "source issue or PR number (required)")
cmd.Flags().IntVar(&toNumber, "to", 0, "destination issue or PR number (required)")
cmd.Flags().StringVar(&prefix, "prefix", "workflow-change-", "copy labels with this prefix")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] auth-scope (2/6 agents flagged)

labels copy defaults to prefix workflow-change-, copying both workflow-change-needed AND workflow-change-allowed from the source issue to the destination PR. The copy is mechanical — no staleness check, no collaborator verification on the destination.

This means the PR's fix agent inherits the authorization without separate collaborator approval on the PR itself. If this is intentional (collaborator approved on issue → applies to PR), the scope expansion should be documented.

Additionally, post-code.sh lines 419-423 and 493-496 use || true, silently swallowing copy failures.

Suggested fix:

  • If authorization should be issue-scoped only, filter to copy only workflow-change-needed (not allowed)
  • If cross-scope is intentional, document this in ADR 0055 under "Authorization Scope"
  • Replace || true with explicit error handling that at least logs failures

@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment component/dispatch Workflow dispatch and triggers and removed requires-manual-review Review requires human judgment labels Jun 24, 2026
Signed-off-by: Barak Korren <bkorren@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 25, 2026

Copy link
Copy Markdown

🤖 Finished Review · ❌ Failure · Started 6:09 AM UTC · Completed 6:22 AM UTC
Commit: eca6b73 · View workflow run →

@ifireball

Copy link
Copy Markdown
Member Author

Since PR #2389 moved token minting into the binary, the approach in this PR needs to change so drastically to the point where the code here is irrelevant. We also tried to do too many things here in the same PR which resulted in messy code with many issues that were flagged by the reviewers.

Here is a phased plan for fixing #470:

  1. Introduce elevated/reduced permissions token minting - so we can apply the least privileges principle to minted tokens - generalize the Elevations concept introduced here (Probably via the
  2. Provide the means to use different tokens for different agent phases - e.g. a token that can only read for the LLM v.s. one that can also write for the post script - and a means to specify that in the harness.
  3. Provide means to specify (in the harness) that tokens with higher privileges may be granted to certain phases when a certain label exists as well as that such privileges are indicated to be required when another label exists - this will allow fullsend run to manage both the process of acquiring elevated privileges as well as alerting the user when they are needed.

@ifireball ifireball closed this Jun 25, 2026
@fullsend-ai-retro

fullsend-ai-retro Bot commented Jun 25, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 7:17 AM UTC · Completed 7:25 AM UTC
Commit: eca6b73 · View workflow run →

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #2548 — label-gated workflow-change elevation

Outcome: Closed without merging. The author (ifireball) abandoned the PR after recognizing that upstream changes in PR #2389 (moving token minting into the binary) made the approach obsolete, and that the PR tried to do too many things at once.

Timeline:

  • Jun 23: PR opened (59 files, +3026/-40). First fullsend-ai-review failed, then succeeded with 3 findings (documentation-code mismatch, exit-code collision, protected-path changes).
  • Jun 24 AM: qodo-code-review posted 3 action-required findings (stale check misclassification, null trigger comment ID, fix pre-run behavior). fullsend-ai-review had 5 cancellations before succeeding with 2 medium findings (pagination logic error, gate definition duplication).
  • Jun 24 PM: Human reviewer (waynesun09) posted two rounds via Review Squad — 10 inline findings total including 3 HIGH severity (shell safety with set +euo pipefail, TOCTOU race between auth-check and mint, auth-bypass via agent-scoped CHANGED_FILES).
  • Jun 25: Final review failed. Author closed PR, proposing a 3-phase decomposition plan.

What went well:

  • Review quality was strong across all three review sources. Both automated and human reviewers found real, actionable security issues.
  • The author made a good architectural decision to close and decompose rather than patch forward.
  • waynesun09's Review Squad caught critical security findings (TOCTOU race, auth-bypass) that automated reviewers missed.

Existing issues already cover most improvement opportunities:

One proposal filed for the security review gap between automated and human reviewers.

Proposals filed

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

Labels

agent/code Code agent component/dispatch Workflow dispatch and triggers component/mint Token mint and cross-boundary credentials requires-manual-review Review requires human judgment security Security threat model and related concerns

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing github app permissions for updating workflows

2 participants