Skip to content

feat(auth): treat pg- delegated grants as project-bound - #476

Open
tkkhq wants to merge 12 commits into
mainfrom
feat/grant-project-bound
Open

tkkhq wants to merge 12 commits into
mainfrom
feat/grant-project-bound

Conversation

@tkkhq

@tkkhq tkkhq commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Tracking

Why

  • A Builder worker runs this CLI with VOLCANO_TOKEN=pg-…, a delegated grant bound to one customer project. The CLI does not know the pg- prefix, so it treats the grant as an account token: it makes account calls the grant can't make, and the detached telemetry flush posts the grant to /cli/telemetry.
  • The worker must tell a spent mutation budget (429 grant_budget_exhausted) apart from other failures, because the fix is a new grant and a retry.

Summary

Kept to what Hosting's refusals require ("the CLI carries minimal changes; things are controlled server-side"). Hosting decides what a grant may do and words every refusal; the CLI adds no hints of its own.

  • add config.DelegatedGrantPrefix (pg-), IsDelegatedGrant, and IsProjectBound (pt- or pg-)
  • use IsProjectBound where IsProjectToken was: RequireAccountToken, RequireProject, connect project handling, feedback, durable approvals, LavaFlow, so a grant is refused where a pt- token is, with the same exit codes. volcano login is unchanged for grants (decided 2026-11-13)
  • add ErrAccountTokenRequiredForGrant and ErrNoProjectSelectedForGrant: the account-command and no-project refusals, and the feedback status line, name a delegated grant (pg-) instead of a project access token. Both match the pt- errors with errors.Is, so exit codes stay the same
  • name delegated grants next to project access tokens in the LavaFlow and durable-approval refusals, and their --help
  • redact pg- grants and vgt_ model-gateway run tokens in telemetry error text, resources and feedback, the same pattern Hosting uses
  • telemetry Flush sends no bearer when the token is a grant. pt- behaviour is unchanged. This one can't be left to Hosting: it ignores the grant there, but only the client can stop sending it
  • exit code 6 for 429 grant_budget_exhausted only (internal/api/grant_errors.go); C4's 429 rate_limit_exceeded stays exit 1
  • docs, now in docs(cli): document delegated grants, exit code 6 and VOLCANO_TOKEN_FD volcano-docs#190 (content/cli): exit code 6 in scripting.md; a short "Delegated grants" section in authentication.md that says a grant is meant for VOLCANO_TOKEN and what volcano login --token pg-… does with one: Hosting refuses a grant on GET /projects, so login fails without --project or with a project name; with the grant's own project ID it can pass and save the grant
  • worker env contract checked, nothing missing: VOLCANO_TOKEN (or K4's VOLCANO_TOKEN_FD), VOLCANO_API_URL, the link file .volcano/project.json (or --project <uuid>), VOLCANO_TELEMETRY_DISABLED=1, VOLCANO_NONINTERACTIVE=1. VOLCANO_PROJECT_ID works but prints a deprecation warning on every run, so the worker should use the link file
  • removed in review as not required by Hosting: CLI hints for each grant refusal, and the grant wording of the wrong-project hint

Verification

  • go build ./...
  • make check (openapi-generated-check, release-workflow-check, lint with 0 issues, test)
  • cmd/volcano/grant_test.go runs the real command tree with the worker's environment against a recording server. On every run it asserts the grant is never in stdout or stderr and no request goes to /service-keys or /user. It covers the exit code of each grant refusal, and account commands refused before any request
  • TestFlush_DelegatedGrantSendsNoAuthorization carries the telemetry guarantee. The harness check on /cli/telemetry proves little, since telemetry is a no-op in tests
  • TestIsDelegatedGrantAndIsProjectBound, TestRequireAccountTokenAndProjectRefuseADelegatedGrant (grant wording, same errors.Is matches), TestRunMapsErrorsToStableExitCodes (grant rows), TestFeedback_ProjectTokenSendsNothing (pt- and pg-), TestCanSendFeedbackRefusesProjectBoundTokens, TestRedact (pg-, vgt_), TestRunStartWithAProjectTokenNeedsTheOwnersSession and TestApprovalsDecideRefusesAProjectTokenBeforeAnyRequest (pt- and pg-)
  • merged main at 96438255: docs: move published docs to volcano-docs #489 moved docs/ to Kong/volcano-docs, so this PR's docs edits moved to docs(cli): document delegated grants, exit code 6 and VOLCANO_TOKEN_FD volcano-docs#190

@tkkhq
tkkhq marked this pull request as ready for review November 13, 2026 12:23
@tkkhq
tkkhq requested a review from a team as a code owner November 13, 2026 12:23
Copilot AI balanced review requested due to automatic review settings November 13, 2026 12:23
@github-actions

github-actions Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

AI review: no P0-P2 findings

Reviewed 33e2f79. Run log

Treats pg- delegated grants as credentials bound to one project. Account-only commands, LavaFlow changes and approval decisions now refuse a grant before sending any request. Their errors name the grant but still match the pt- errors, so exit codes stay the same. The detached telemetry flush no longer sends a grant as its bearer, telemetry and feedback text now remove pg- and vgt_ tokens, and a 429 grant_budget_exhausted exits with code 6. The code matches what the earlier rounds checked, and all their findings are still fixed. Merging main removed this PR's edits under docs/, which now have to go to Kong/volcano-docs. Risk is moderate because credential handling and the public exit-code contract change.

⚪ P3

  • cmd/volcano/main.go:42 Docs for exit code 6 and delegated grants were dropped in the merge, and no volcano-docs PR is linked (also reported as: Link the required companion documentation PR)
  • internal/cmd/lavaflow/enable.go:42 volcano lavaflow enable --help now has a short line ending in "The"

Not checked: The AI review read the diff, the code, and the PR's text; it ran no tests or builds and read nothing outside this repository.

  • Whether Hosting's 429 for a spent grant sends code as the JSON string grant_budget_exhausted, which the CLI needs to exit 6 (Kong/volcano-hosting#3313).
  • Whether a Kong/volcano-docs PR exists that documents exit code 6 and delegated grants under content/cli.
  • Whether Hosting's server-side telemetry redaction also covers the pg- and vgt_ prefixes added to keyPattern.
  • Whether the Builder worker treats exit code 6 as the signal to get a new grant and retry (Kong/volcano-builder#518, #523).
  • Whether the worker's other commands (deploy, storage, env, migrations) reach only routes in Hosting's grant table; the e2e test covers only cloud functions list.

Human review: needed

  • Should the CLI refuse pg- grants before any request on account, LavaFlow-change and approval commands (internal/config/config.go, internal/lavaflow, internal/durable), or leave that to Hosting?
  • Is exit code 6, used only for a 429 grant_budget_exhausted, the public scripting contract the Builder worker should rely on (cmd/volcano/main.go)?
  • Should volcano login --token pg-… --project <id> keep saving a short-lived grant to ~/.volcano/config.json, as it does unchanged here, or refuse it?
  • Should telemetry Flush send no bearer for a grant while still sending pt- tokens (internal/telemetry/send.go)?
  • Are the delegated-grant restrictions in internal/config/config.go, internal/durable/durable.go, and internal/lavaflow/ the intended credential policy?

The AI review found no P0-P2 problems at 33e2f79, so the code needs no second review for bugs. Decide the points above: approve to accept them, or request changes.

Suggested reviewer: swkeever (most commits to the LavaFlow and config code whose pt- checks this extends). Any collaborator with write access other than the author can approve.

@github-actions
github-actions Bot requested a review from subnetmarco November 13, 2026 12:29
Comment thread docs/authentication.md Resolved
Comment thread internal/telemetry/send.go Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Grant credentials can still leak through telemetry bodies because redaction omits the pg prefix, requiring a pattern fix and regression tests for error redaction and resource filtering.

1 open issue
What changed in this PR

This PR adds delegated-grant (pg-) support to the CLI’s existing project-bound authentication flow, while leaving permission enforcement to Hosting.

Changes:

  • Treat grants as project-bound credentials and refuse to save them through login.
  • Omit grants from telemetry authorization and return exit code 6 for exhausted mutation budgets.
  • Document grant behavior and add authentication, telemetry, and command-level tests.
File Description
internal/​telemetry/​telemetry.go Disallow feedback with delegated grants.
internal/​telemetry/​telemetry_test.go Test grant authorization omission and feedback restrictions.
internal/​telemetry/​send.go Omit grant bearer tokens from telemetry requests.
internal/​lavaflow/​start.go Reject grants for person-only run starts.
internal/​lavaflow/​lavaflow.go Reject grants for person-only settings updates.
internal/​durable/​durable.go Require personal credentials for approvals.
internal/​config/​config.go Define grants and shared project-bound checks.
internal/​config/​config_test.go Test credential classification and restrictions.
internal/​cmd/​feedback/​feedback.go Apply project-bound feedback status handling.
internal/​cmd/​connect/​connect.go Skip account validation for grants.
internal/​cmd/​auth/​auth_test.go Verify login rejects grants without requests or writes.
internal/​auth/​auth.go Reject grant persistence and use project-bound checks.
internal/​api/​grant_errors.go Identify grant-budget exhaustion responses.
docs/​scripting.md Document exit code 6.
docs/​authentication.md Explain delegated-grant usage and restrictions.
cmd/​volcano/​main.go Map grant-budget exhaustion to exit code 6.
cmd/​volcano/​grant_test.go Test worker authentication, refusals, and exit codes.

Review effort: Balanced

Comment thread internal/telemetry/send.go Resolved
Comment thread internal/telemetry/telemetry.go Resolved
@tkkhq

tkkhq commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

AI review findings (d1ab0df):

  • P2 internal/telemetry/send.go:82 grant payload redaction: fixed in b2efdbc (pg- added to keyPattern, with tests).
  • P3 docs/authentication.md:107 logout under the grants subsection: fixed in d5f9208.
  • P3 internal/telemetry/fields.go:180 pg- not redacted: fixed in b2efdbc.

Comment thread docs/authentication.md Resolved
Comment thread docs/authentication.md Resolved
Comment thread internal/config/config.go Resolved
@tkkhq

tkkhq commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

Verdict findings on ea51c75, fixed in 726c499:

  • docs/authentication.md:64: docs now say a grant is meant for VOLCANO_TOKEN and state what volcano login --token pg-… does, without claiming login refuses it.
  • internal/config/config.go:639: grant refusals now name a delegated grant (pg-); they still match the pt- errors, so exit codes are unchanged.

Comment thread internal/telemetry/telemetry.go Resolved
@tkkhq

tkkhq commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

P3 findings on 726c499, fixed in 55e9a0e:

  • docs/feedback.md:140: the feedback, LavaFlow, approvals, domains and git docs and the matching --help now name delegated grants with project access tokens; the LavaFlow refusals say "a project access token or a delegated grant can't".
  • internal/durable/durable.go:501: the durable, LavaFlow and connect comments now name grants too.

Comment thread cmd/volcano/main.go
exitPermissionDenied = 5
// exitGrantBudgetExhausted is the API's 429 grant_budget_exhausted: a
// delegated grant used all of its mutations, and a new grant is the fix.
exitGrantBudgetExhausted = 6

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ P3: Docs for exit code 6 and delegated grants were dropped in the merge, and no volcano-docs PR is linked

After the merge of main (#489 moved published docs to Kong/volcano-docs), this diff no longer touches docs/scripting.md, docs/authentication.md, docs/feedback.md, docs/lavaflow.md, docs/durable-functions.md, docs/domains.md or docs/git.md. The PR description still lists them under Summary, and its Tracking section links no Kong/volcano-docs PR. AGENTS.md says a change to user-facing behavior needs a companion PR in Kong/volcano-docs that updates content/cli, and that the two PRs must be linked. Without one, the published scripting page will not list exit code 6, which the Builder worker relies on. The authentication, feedback, LavaFlow and approvals pages also won't mention delegated grants. Fix: move those edits into a Kong/volcano-docs PR under content/cli, following its spec/markdown-format.md, link it here, and update the description's docs bullet.

Found by claude-opus-5-5

and asks you to confirm; --yes skips the question. Only the project's owner
can turn it on, from their own session: a project access token is refused. The
can turn it on, from their own session: a project access token or a delegated
grant is refused. The

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ P3: volcano lavaflow enable --help now has a short line ending in "The"

The edit added "or a delegated grant" without rewrapping the paragraph, so line 42 reads grant is refused. The and the sentence continues on the next line. Cobra prints Long as written, so the help output shows this broken line. Rewrap lines 40–44 so each line is about the same length as the rest of the paragraph.

Found by claude-opus-5-5

Comment thread cmd/volcano/main.go
exitPermissionDenied = 5
// exitGrantBudgetExhausted is the API's 429 grant_budget_exhausted: a
// delegated grant used all of its mutations, and a new grant is the fix.
exitGrantBudgetExhausted = 6

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ P3: Link the required companion documentation PR

AGENTS.md requires a cross-linked Kong/volcano-docs PR for user-facing changes. The supplied description and comments contain no companion link and still cite removed local docs, including docs/scripting.md. Open or link the companion PR updating content/cli for grant handling and exit code 6.

Found by gpt-6.1-sol

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants