Summary
Extend the API token model with three related, internal capabilities. None of these change the public proto / service API.
1. Workflow scope on API tokens
API tokens can already be scoped to an organization and, optionally, a project. Today the apitoken row persists project_id and the minted JWT carries project_id/project_name claims.
Extend this one level deeper: a token may optionally be scoped to a single workflow within a project. The workflow scope is persisted on the row and embedded in the JWT as workflow_id/workflow_name claims, mirroring the project pattern. Expressed in biz through a new APITokenWithWorkflow(*Workflow) functional option on APITokenUseCase.Create, with validation that the workflow belongs to the requested project.
2. Attestation-process enforcement for workflow-scoped tokens
When an attestation call (AttestationService.Init, Store, Cancel, GetUploadCreds, GetContract, attestation state) is authenticated with a workflow-scoped API token, the workflow resolved from the request must equal the workflow encoded in the token. Mismatches are rejected.
Two layers of enforcement:
- Auth middleware verifies the JWT
workflow_id claim matches the row's workflow_id (mirrors the existing project mismatch check).
- A check in
findWorkflowFromTokenOrNameOrRunID — the single chokepoint every attestation endpoint goes through — rejects when the resolved workflow differs from the token's workflow.
FindOrCreateWorkflow additionally forbids workflow-scoped tokens from creating or looking up other workflows.
3. Internal "system" tokens hidden from the API
Add an immutable is_system flag on the apitoken row. System tokens are minted by internal code paths (a new APITokenAsSystem() biz option) and continue to mint and validate JWTs normally, but are hidden from the public API:
APITokenService/List excludes them by default; opt-in via a new biz-level WithIncludeSystemTokens() filter.
- Service-layer handlers that look up tokens by id/name (e.g.
Revoke) return NotFound when the row is a system token.
The mint path is not exposed in the proto; only internal callers can create system tokens.
Scope
All changes are internal: builders, persistence layer, auth middleware, and the attestation service chokepoint. No proto, no service-level API change.
Summary
Extend the API token model with three related, internal capabilities. None of these change the public proto / service API.
1. Workflow scope on API tokens
API tokens can already be scoped to an organization and, optionally, a project. Today the
apitokenrow persistsproject_idand the minted JWT carriesproject_id/project_nameclaims.Extend this one level deeper: a token may optionally be scoped to a single workflow within a project. The workflow scope is persisted on the row and embedded in the JWT as
workflow_id/workflow_nameclaims, mirroring the project pattern. Expressed in biz through a newAPITokenWithWorkflow(*Workflow)functional option onAPITokenUseCase.Create, with validation that the workflow belongs to the requested project.2. Attestation-process enforcement for workflow-scoped tokens
When an attestation call (
AttestationService.Init,Store,Cancel,GetUploadCreds,GetContract, attestation state) is authenticated with a workflow-scoped API token, the workflow resolved from the request must equal the workflow encoded in the token. Mismatches are rejected.Two layers of enforcement:
workflow_idclaim matches the row'sworkflow_id(mirrors the existing project mismatch check).findWorkflowFromTokenOrNameOrRunID— the single chokepoint every attestation endpoint goes through — rejects when the resolved workflow differs from the token's workflow.FindOrCreateWorkflowadditionally forbids workflow-scoped tokens from creating or looking up other workflows.3. Internal "system" tokens hidden from the API
Add an immutable
is_systemflag on theapitokenrow. System tokens are minted by internal code paths (a newAPITokenAsSystem()biz option) and continue to mint and validate JWTs normally, but are hidden from the public API:APITokenService/Listexcludes them by default; opt-in via a new biz-levelWithIncludeSystemTokens()filter.Revoke) returnNotFoundwhen the row is a system token.The mint path is not exposed in the proto; only internal callers can create system tokens.
Scope
All changes are internal: builders, persistence layer, auth middleware, and the attestation service chokepoint. No proto, no service-level API change.