feat(#2722): add reader role for self-minting tokens during harness loading - #2725
feat(#2722): add reader role for self-minting tokens during harness loading#2725fullsend-ai-coder[bot] wants to merge 4 commits into
Conversation
E2E tests did not runE2E tests run automatically for org/repo members and collaborators on pull requests. For other contributors, a maintainer must add the See E2E testing guide for details. |
1 similar comment
E2E tests did not runE2E tests run automatically for org/repo members and collaborators on pull requests. For other contributors, a maintainer must add the See E2E testing guide for details. |
Site previewPreview: https://b8ad0f74-site.fullsend-ai.workers.dev Commit: |
|
/fs-review |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
🤖 Finished Review · ❌ Failure · Started 7:38 PM UTC · Completed 7:55 PM UTC |
ReviewFindingsMedium
Labels: PR adds a new mint role and wires reader token minting into the harness loading flow. Previous runReviewFindingsMedium
Low
Info
|
|
/fs-fix resolve all the issues raised in #2725 (comment). |
|
🤖 Finished Fix · ✅ Success · Started 8:01 PM UTC · Completed 8:09 PM UTC |
🔧 Fix agent — iteration 1 (human-triggered)Addressed 4 of 5 review findings with code fixes. Disagreed with 1 (infrastructure-dependency) as it is an infrastructure prerequisite tracked in issue #2722, not a code issue. Key fix: reuse composeForgeClient in URL-skill resolution path so the minted loader token is used instead of independently calling resolveToken(). Fixed (4):
Disagreed (1):
Tests: passed Updated by fullsend fix agent |
- Reuse composeForgeClient in URL-skill resolution path so the already-minted loader token is used instead of independently calling resolveToken() (error-handling-gap finding) - Update github_token input description in action.yml to reflect its reduced scope after GH_TOKEN removal (documentation-contract-mismatch) - Add Repos field assertion to TestMintLoaderToken_Success for stronger coverage (test-adequacy) - Improve mintLoaderToken error message to name the required env vars (error-message-style) Addresses review feedback on #2725
|
/fs-fix fix any issues detailed in #2725 (comment) and also fix the code coverage CI test so that it has > 80% coverage. |
|
🤖 Finished Fix · ✅ Success · Started 10:23 PM UTC · Completed 10:31 PM UTC |
🔧 Fix agent — iteration 2 (human-triggered)Added 3 tests to achieve 100% coverage on mintLoaderToken (up from 80%), addressing the >80% patch coverage CI requirement. The remaining review findings were already addressed in the current PR or previous iteration, or are infrastructure concerns rather than code issues. Fixed (1):
Disagreed (4):
Tests: passed Updated by fullsend fix agent |
Add three additional test cases to achieve 100% coverage on mintLoaderToken, addressing the >80% patch coverage requirement: - TestMintLoaderToken_InvalidTokenPattern: covers the token validation error branch - TestMintLoaderToken_ResolveMintReposError: covers the resolveMintRepos failure path - TestMintLoaderToken_SuccessWithMasking: covers the GITHUB_ACTIONS ::add-mask:: workflow command path Addresses review feedback on #2725
|
/fs-fix rebase to get the latest sources, and also change from "loader" to "reader" role, updating all references as appropriate. Don't forget to change the PR title and description too. |
|
🤖 Finished Fix · ✅ Success · Started 11:47 PM UTC · Completed 11:55 PM UTC |
…oading The binary needs a GitHub token to create a ForgeClient for LoadWithBase() when fetching URL-based skill directories, but mintAgentToken() requires the harness role — which is only known after loading. PR #2720 worked around this by passing GH_TOKEN from action.yml, leaving an over-privileged ambient token. Add a dedicated "loader" mint role with minimal permissions (contents:read, metadata:read) and a mintLoaderToken() helper that runs before LoadWithBase. The binary now self-mints a short-lived loader token when OIDC is available, falling back to resolveToken() for local dev. The action.yml GH_TOKEN injection in the "Run fullsend" step is removed. Changes: - internal/mintcore/github.go: add "loader" role to canonicalRolePermissions - internal/cli/run.go: add hasOIDCEnv() and mintLoaderToken() helpers; move mintURL resolution before LoadWithBase; wire loader mint before resolveToken() fallback - action.yml: remove GH_TOKEN from "Run fullsend" step - Sync embedded copy per AGENTS.md rules Closes #2722
- Reuse composeForgeClient in URL-skill resolution path so the already-minted loader token is used instead of independently calling resolveToken() (error-handling-gap finding) - Update github_token input description in action.yml to reflect its reduced scope after GH_TOKEN removal (documentation-contract-mismatch) - Add Repos field assertion to TestMintLoaderToken_Success for stronger coverage (test-adequacy) - Improve mintLoaderToken error message to name the required env vars (error-message-style) Addresses review feedback on #2725
Add three additional test cases to achieve 100% coverage on mintLoaderToken, addressing the >80% patch coverage requirement: - TestMintLoaderToken_InvalidTokenPattern: covers the token validation error branch - TestMintLoaderToken_ResolveMintReposError: covers the resolveMintRepos failure path - TestMintLoaderToken_SuccessWithMasking: covers the GITHUB_ACTIONS ::add-mask:: workflow command path Addresses review feedback on #2725
Rename the mint role from "loader" to "reader" to better describe its purpose (read-only content access). Updates the role definition, mintReaderToken helper, all tests, action.yml description, and the embedded copy. Addresses review feedback on #2722
🔧 Fix agent — iteration 3 (human-triggered)Rebased onto latest main and renamed the mint role from loader to reader across all 6 changed files plus the PR title and description. All tests pass. Fixed (8):
Tests: passed Updated by fullsend fix agent |
908d4cd to
303f787
Compare
|
fs-fix fix all issues raised in #2725 (comment) |
|
/fs-fix fix all issues raised in #2725 (comment) |
|
🤖 Finished Fix · ✅ Success · Started 2:28 PM UTC · Completed 2:34 PM UTC |
🔧 Fix agent — iteration 4 (human-triggered)All 5 findings from the review comment have been verified against the current code (HEAD 303f787). All were already addressed by previous fix iterations (commits 997872a, 2434220, 303f787) that ran after the review was posted on SHA 19af916. The infrastructure-dependency finding is an operational prerequisite, not a code change. No new code changes are needed. Disagreed (5):
Tests: passed Updated by fullsend fix agent |
|
/fs-review |
|
🤖 Finished Review · ✅ Success · Started 2:50 PM UTC · Completed 3:05 PM UTC |
ragnar-howler
left a comment
There was a problem hiding this comment.
Code Review — feat(#2722): reader role for self-minting tokens
Decision: ✅ Approve
Summary
This is a clean security improvement. Removes the over-privileged ambient GH_TOKEN from the run step and replaces it with a minimal-permission OIDC-minted reader token (contents:read, metadata:read) specifically scoped for LoadWithBase. The fallback chain (mintReaderToken → resolveToken) preserves local dev ergonomics.
Positive
- Security uplift is real. Scoped reader token eliminates the ambient token attack surface during harness loading. Previously any URL-skill fetch carried full repo write permissions.
- Mint-before-load ordering is correct —
mintURLis now resolved beforeLoadWithBase, so the reader token is available at the right point in the call chain. - Token masking (
::add-mask::) is handled before the token touches any log output. - Test coverage is thorough. All branches covered: no OIDC env, no mint URL, mint error, invalid token pattern, repo resolution failure, and masking in GH Actions context.
- Embedded copy sync per AGENTS.md rules — no drift risk.
One Concern (non-blocking)
If mintReaderToken fails in CI (e.g., transient OIDC error), the fallback hits resolveToken(). Since GH_TOKEN is no longer injected into the run step env, resolveToken will also fail in CI. This means a mint failure → total forge client loss → URL-based skills silently unavailable.
This is probably acceptable (OIDC is reliable in practice), but worth a follow-up issue to add an explicit warning log when mint fails and fallback also fails, so operators aren't left debugging a silent empty forge client.
Verdict
Solid. The security benefit outweighs the edge-case risk above. ifireball already approved — this is ready to merge.
|
Closing as superseded by #2736. The chicken-and-egg token problem this solved (needing a ForgeClient token before the harness role was known) no longer exists — skill directory fetching now uses git sparse checkout instead of the GitHub Contents API, removing the pre-load token dependency entirely. |
|
🤖 Finished Retro · ✅ Success · Started 11:30 AM UTC · Completed 11:37 AM UTC |
Retro: PR #2725 — add reader role for self-minting tokens during harness loadingOutcome: Closed without merging — superseded by #2736, which eliminated the pre-load token dependency entirely by switching to git sparse checkout. Timeline: The code agent produced a technically sound implementation (new What went well:
What was wasteful:
Existing issues that cover the main improvement opportunities:
No new proposals filed — the systemic improvements are already tracked in existing issues. The PR being superseded was a normal engineering outcome (a simpler approach was discovered during parallel work) that is difficult to prevent through agent tooling. |
The binary needs a GitHub token to create a ForgeClient for LoadWithBase() when fetching URL-based skill directories, but mintAgentToken() requires the harness role — which is only known after loading. PR #2720 worked around this by passing GH_TOKEN from action.yml, leaving an over-privileged ambient token.
Add a dedicated "reader" mint role with minimal permissions (contents:read, metadata:read) and a mintReaderToken() helper that runs before LoadWithBase. The binary now self-mints a short-lived reader token when OIDC is available, falling back to resolveToken() for local dev. The action.yml GH_TOKEN injection in the "Run fullsend" step is removed.
Changes:
canonicalRolePermissions
helpers; move mintURL resolution before LoadWithBase; wire
reader mint before resolveToken() fallback
Closes #2722
Post-script verification
agent/2722-loader-role-self-mint)f73f2d21dde90e04fedc7dad2302649a434e2a43..HEAD)