feat(controlplane): API token workflow scope, attestation enforcement, system flag#3116
Merged
migmartri merged 1 commit intoMay 14, 2026
Conversation
There was a problem hiding this comment.
5 issues found across 25 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/controlplane/internal/usercontext/apitoken_middleware_test.go">
<violation number="1" location="app/controlplane/internal/usercontext/apitoken_middleware_test.go:110">
P2: Set `orgExist: true` in this mismatch test so it specifically validates workflow-claim mismatch instead of potentially failing due to missing organization.</violation>
<violation number="2" location="app/controlplane/internal/usercontext/apitoken_middleware_test.go:119">
P2: Set `orgExist: true` in this test so it verifies the new `token.WorkflowID == nil` mismatch path instead of a generic organization lookup failure.</violation>
</file>
<file name="app/controlplane/pkg/jwt/apitoken/apitoken.go">
<violation number="1" location="app/controlplane/pkg/jwt/apitoken/apitoken.go:121">
P1: Guard `WorkflowName` before dereferencing when `WorkflowID` is set; current code can panic on nil pointer.</violation>
</file>
<file name="app/controlplane/pkg/biz/apitoken_integration_test.go">
<violation number="1" location="app/controlplane/pkg/biz/apitoken_integration_test.go:410">
P2: The new system-token visibility test only checks list length, not that the default-visible token is non-system. This can miss regressions where filtering returns the wrong token.
(Based on your team's feedback about adding or updating tests for new paths.) [FEEDBACK_USED]</violation>
</file>
<file name="app/controlplane/pkg/biz/apitoken.go">
<violation number="1" location="app/controlplane/pkg/biz/apitoken.go:232">
P1: `RegenerateJWT` does not set `ProjectID`/`ProjectName` or `WorkflowID`/`WorkflowName` on the JWT generation options, even though the token from `FindByID` carries these fields. A regenerated workflow-scoped (or project-scoped) token will produce a JWT missing those claims, causing the auth middleware's claim-vs-DB verification to reject it.</violation>
</file>
Tip: instead of fixing issues one by one fix them all with cubic
b352e74 to
a640f13
Compare
Contributor
AI Session Analysis
Session Detailsclaude-code 2.1.141 (claude-opus-4-7) — 🟢 84% — 17% AI —
|
| Criterion | Score | Findings |
|---|---|---|
| solution-quality | 🟢 88% |
|
| alignment | 🟢 87% | |
| user-trust-signal | 🟢 85% | |
| context-and-planning | 🟢 82% |
|
| verification | 🟢 82% |
|
| scope-discipline | 🟡 78% |
|
File Attribution
███░░░░░░░░░░░░░░░░░ 17% AI / 83% Human
Policies (4, 1 failing)
| Status | Policy | Material | Messages |
|---|---|---|---|
| ✅ Passed | ai-config-ai-agents-allowed |
ai-coding-session-ed7a91 |
- |
ai-config-no-dangerous-commands |
ai-coding-session-ed7a91 |
Forbidden bash pattern /git[^|]push[^|]--force/ matched command: git push --force-with-lease origin feat/apitoken-workflow-scope-system 2>&1 | tail -5 | |
| ✅ Passed | ai-config-no-secrets |
ai-coding-session-ed7a91 |
- |
| ✅ Passed | ai-config-mcp-servers-allowed |
ai-coding-session-ed7a91 |
- |
Powered by Chainloop and Chainloop Trace
…system flag to API tokens Closes chainloop-dev#3115 Extends the API token model with three internal capabilities: - Workflow scope: tokens may optionally be scoped to a workflow within a project. The workflow is persisted on the apitoken row and embedded as workflow_id/workflow_name JWT claims. Expressed in biz via a new APITokenWithWorkflow(*Workflow) functional option, with validation that the workflow belongs to the requested project. - Attestation enforcement: the auth middleware verifies the workflow_id JWT claim matches the row, and findWorkflowFromTokenOrNameOrRunID rejects when a workflow-scoped token operates on a different workflow. FindOrCreateWorkflow forbids workflow-scoped tokens from minting other workflows. - System tokens: an immutable is_system flag on the row. System tokens mint and validate JWTs normally but are hidden from APITokenService/List by default and return NotFound on Revoke. Opt-in via WithIncludeSystemTokens() in biz; mint via APITokenAsSystem(). No public proto API change. Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev> Chainloop-Trace-Sessions: ed7a9165-b8f5-46b7-8d6f-0daf35f75e0f
a640f13 to
18b28ae
Compare
Member
Author
|
Addressed CI + cubic review:
|
jiparis
approved these changes
May 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3115
Summary
Extends the API token model with three related internal capabilities. No public proto / service API surface changes.
Workflow scope. API tokens can already carry an org and optional project scope (
project_idcolumn + claim). This adds an analogous, optional workflow scope persisted on theapitokenrow and embedded in the JWT asworkflow_id/workflow_nameclaims. In biz it surfaces as a newAPITokenWithWorkflow(*Workflow)functional option onAPITokenUseCase.Create, validated against the requested project.Attestation enforcement. The auth middleware verifies the
workflow_idJWT claim matches the DB row (mirroring the existing project mismatch check). The single chokepointfindWorkflowFromTokenOrNameOrRunIDrejects when a workflow-scoped token operates on a different workflow; every attestation endpoint (Init,Store,Cancel,GetUploadCreds,GetContract, attestation state) inherits this.FindOrCreateWorkflowadditionally forbids workflow-scoped tokens from creating or looking up other workflows.System tokens. A new immutable
is_systemflag on the row. System tokens mint and validate JWTs normally but are hidden fromAPITokenService/Listby default, andRevokeagainst a system token returnsNotFound. List opt-in via bizWithIncludeSystemTokens(); mint viaAPITokenAsSystem(). Public proto does not exposeisSystem— internal code paths only.