feat(roles): add workflows:write to builder reference role (lr-8681)#10
Conversation
clagentic-builder GitHub App now holds the workflows permission so build agents can push .github/workflows/* changes. Gatekeeper narrows minted tokens to the per-role permission set, so without this the App grant is necessary but not sufficient -- minted builder tokens would still strip workflow access. Widens builder only; reviewer/merger/security untouched.
There was a problem hiding this comment.
PEACHES — clean (1 observation)
- internal/mint/mint_test.go — peaches.nit.observation — Diff output truncated by peaches-github-review; unable to verify builder assertion update in TestMintSuccess. Local code inspection confirms roles.go, docs/ROLES.md, and roles_test.go correctly include workflows:write for builder. Verify mint_test.go line ~96 want map assertion in TestMintSuccess contains "workflows": "write" before merge.
Builder role widening (lr-8681) approved: workflows:write added to builder reference set only; reviewer/merger/security untouched; negative assertions (no administration, no merge) preserved; docs/ROLES.md row added with clear rationale.
Note: PR body migration record not visible in metadata fetch; confirm it documents the permission widening per contents/CLAUDE.md §migrations before merge.
There was a problem hiding this comment.
PEACHES — Follow-up Verification Pass (lr-8681)
Verification status:
✓ Item 3 (mint_test.go in diff): ABSENT — confirmed correct (test uses dynamic role.GitHubPermissions() lookup, no hardcoded map modification needed)
⚠ Item 1 (comment_id readback): Cannot verify — peaches-github-review read does not output PR comments section
⚠ Item 2 (HEAD SHA): Cannot verify — no tool available within PEACHES allowlist to fetch commit SHA (cannot exec git; cannot call GitHub API directly)
⚠ Item 4 (PR body migration record): Cannot verify — peaches-github-review read outputs only diff, not PR description/body
Code changes verified correct:
- docs/ROLES.md: added workflows | write row with rationale
- internal/roles/roles.go: added "workflows": Write to builder reference map
- internal/roles/roles_test.go: updated builder test expectation to include "workflows": "write"
Items 1-2 are mandatory per lr-e305. Escalating tooling limitation to project lead.
There was a problem hiding this comment.
BOBBIE — clean
Scope: PR #10 widens the builder GitHub App reference role to add workflows: write (docs/ROLES.md, internal/roles/roles.go, internal/roles/roles_test.go). No other role touched.
Findings:
- PRAISE: internal/roles/roles.go:37 — only the
builderentry inreferencegained"workflows": Write;reviewer,merger, andsecuritymaps are byte-identical to pre-PR state. No widening ofadministration, no merge-capability change, no new role introduced. bobbie.bleed.scope-minimal - PRAISE: docs/ROLES.md builder table — the added
workflows/writerow documents the grant is scoped to feature branches and is justified as aligning the reference model with an App permission already held, not an independent capability expansion. bobbie.bleed.least-privilege-doc - NIT: docs/ROLES.md — the new
workflowsrow does not restate the merge-separation guarantee (merger token exclusivity) in the same paragraph as the workflows grant, though the guarantee is stated two lines below unchanged. Low value, doc-clarity only. bobbie.bleed.doc-clarity - NIT (tooling gap, not a code finding): BOBBIE's
bobbie-github-security readdoes not surface the PR body/description field (only title/state/base/head/author/URL/diff), so I could not directly confirm or deny whether the PR body records a permission-widening migration entry. This is a BOBBIE tooling limitation (lr-e41b scanner/tooling wiring), not a statement about the PR author's compliance. Flagging for AMoS/operator follow-up rather than asserting absence.
No secrets, no SAST hits: gitleaks and semgrep both ran clean against the three changed files. go.mod/go.sum untouched by this PR — dependency scan not applicable (osv-scanner has no lockfile diff to evaluate).
Privilege-escalation assessment: this PR grants builder tokens workflows: write, meaning a builder-authored branch/PR could modify .github/workflows/ci.yml (e.g. weaken build/test gates). However, the existing two-layer merge control is untouched by this PR: the merger role (contents:write + pull_requests:write, including the merge action) remains a separate GitHub App identity, and the default-branch ruleset (per docs/ROLES.md, unchanged) still restricts pushes/merges to the merger identity. A builder PR that rewrites CI still requires a separate reviewer approval and a separate merger action to land — this PR does not remove or weaken either gate. The change aligns the reference role with an App permission already granted (per the added doc note) rather than opening a new escalation path on its own.
scanners_run: gitleaks(clean), semgrep(clean, community ruleset, 131 rules/1 file), osv-scanner(not applicable — no dependency-manifest change in diff)
audit_scope.head_sha: 36a7e9a
- docs/ROLES.md:17 — bobbie.bleed.least-privilege-doc — workflows:write documented as scoped to feature branches, App-permission-aligned
- internal/roles/roles.go:37 — bobbie.bleed.scope-minimal — only builder map changed; reviewer/merger/security untouched
- internal/roles/roles_test.go:210 — bobbie.bleed.scope-minimal — test assertion updated in lockstep, negative cases preserved per PEACHES
There was a problem hiding this comment.
BOBBIE -- clean
Audit scope: PR #10, head_sha bc98771.
Change: adds workflows: write to the builder reference role only (internal/roles/roles.go:37), documents it in docs/ROLES.md, and updates the regression-guard test (roles_test.go:210). Confirmed reviewer, merger, and security role maps are byte-identical to pre-PR (roles.go:38-39; roles_test.go:213-223) -- no widening of administration, no merge-capability change. docs/ROLES.md:18-20 ("Builder must not be able to merge... two-layer enforcement") is unmodified by this diff.
Privilege-escalation assessment: this PR does not by itself create the workflows:write capability -- the underlying clagentic-builder GitHub App must already hold that App-level permission (commit message bc98771 states this explicitly), and Gatekeeper's renderer only narrows a token to the declared role map, never widens beyond the App's own grant (roles.go:134-140, RenderPermissions). The diff aligns the reference role with an already-granted App permission rather than opening a new path. Residual acceptance risk (a builder-minted token can now edit .github/workflows/* on feature branches, which is a self-modifying-CI surface if a required-check ruleset does not also cover workflow files) is a design/policy question for holden, not a defect introduced by this diff -- I have no RULEBOOK.md rule_id that fits (no bobbie.secret/bleed/dep/sast rule covers CI-permission-widening as such), so no citable finding is raised for it per the no-invented-rules rule.
Secrets: gitleaks (source, no-git mode) -- no leaks found. No credential/token literal in the 3-file diff.
SAST: semgrep --config auto on internal/roles/roles.go -- 0 findings (131 rules, 1 file).
Dependencies: osv-scanner flagged 43 pre-existing stdlib advisories tied to the go.mod Go toolchain directive (1.22.99). go.mod is NOT touched by this diff (file list: docs/ROLES.md, internal/roles/roles.go, internal/roles/roles_test.go only) -- not introduced by this PR, out of scope per bobbie.dep criteria (no new dependency here).
PR body / migrations record: bobbie-github-security read has no flag/field exposing the PR description text (title/state/base/head/author/URL/diff only) -- I cannot confirm or deny a CLAUDE.md section-migrations record in the PR body with tooling in my allowlist. This is a tooling gap, not a security finding. Separately: this repo (clagentic-gatekeeper) has no section-migrations convention in its own docs (README.md, docs/ROLES.md) -- the commit message (bc98771) does narrate the widening rationale in prose, which is the closest available record. Flag as nit for AMoS/holden to confirm PR body compliance directly; not a security block.
Findings: none blocking, none citable against RULEBOOK.md for the privilege-widening design question (no rule_id fits). One process nit below.
- (process, not security) PR body migration record unverifiable by BOBBIE tooling (bobbie-github-security has no body-read capability) -- recommend AMoS/holden confirm the section-migrations entry exists in the PR description directly.
scanners_run: gitleaks(no leaks), semgrep(0 findings, 131 rules/1 file), osv-scanner(43 pre-existing stdlib advisories, unrelated to diff, go.mod unchanged)
{"reviewer": "bobbie", "review_status": "clean", "head_sha": "bc9877137508545379144ac76494b9e8bd2f7856", "pr_number": 10}
clagentic gate-note — authorized
Authorize rationale: authorize: PEACHES clean, BOBBIE clean (privilege-escalation assessed — builder workflows:write does not open self-merge path), operator-approved permission-widening migration lr-8681, holden + andy 2026-07-04 |
PERMISSION-WIDENING migration (operator-approved). Adds workflows write to the builder reference role because the clagentic-builder GitHub App now holds the workflows permission; Gatekeeper narrows minted tokens to the per-role set so the App grant alone was not enough. Security implication: a builder token can now modify .github/workflows/* on feature branches (approved by andy). No merge capability added -- builder still cannot merge. Scope: internal/roles/roles.go builder entry gains workflows write; docs/ROLES.md builder table gains a workflows write row; internal/roles/roles_test.go exact-map assertion for builder updated to include workflows write. reviewer/merger/security untouched. Reviewed internal/mint/mint_test.go builder assertions -- none pin an exact literal needing a change. Tests: make test -- go test ./... all packages pass (cmd/gatekeeper, internal/broker, internal/config, internal/githubapp, internal/mint, internal/roles). Task lr-8681. No merge requested, leaving for NAOMI gate.