Repository navigation
ci(review): use Anthropic workload identity federation, fall back to the stored key - #700
Merged
Merged
Conversation
…the stored key Signed-off-by: ajianaz <ajianaz@users.noreply.github.com>
This was referenced Oct 27, 2026
ajianaz
added a commit
that referenced
this pull request
Oct 27, 2026
## What - A 400 response that names `temperature` is retried once without that key, and the model is remembered for the rest of the process (no repeated failing request, and no extra cost on later chunks). Streaming and non-streaming share the same path. - Any other 400 (and every other status) is returned unchanged; providers that accept `temperature` keep the configured value (default `0.0`, deterministic). ## Why `claude-opus-5-5` answers HTTP 400 "`temperature` is deprecated for this model", so every review through the Anthropic workload identity federation path (#700) ended as "Review could not complete" while the check still turned green. Closes #701. ## Testing - Unit tests: request body without a `temperature` key, recognising the 400, per-model memory. - Two end-to-end tests against a local fake server: the first request carries `temperature`, the retry does not and succeeds; a different 400 is not retried (one request only). - fmt, clippy -D warnings and the full suite pass. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
ajianaz
added a commit
that referenced
this pull request
Oct 27, 2026
…the stored key (#700) ## What - The Cora Review job exchanges its GitHub OIDC token for a short-lived Anthropic access token when the four federation identifiers (`ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, `ANTHROPIC_WORKSPACE_ID`) are available as organization or repository secrets or variables. Model: `ANTHROPIC_MODEL`, default `claude-opus-5-5`. - With a federation token, API key, base URL and model switch together: the token is only ever sent to `https://api.anthropic.com/v1`, never to `CORA_BASE_URL`. - Without one (variables missing, or the exchange fails: it is only a warning) the job uses `CORA_API_KEY`, `CORA_BASE_URL` and `CORA_MODEL` as before, and the guard still fails with an error naming a missing secret. - `id-token: write` added to the job permissions; docs (`docs/examples.md`) and CHANGELOG updated. ## Why A stored API key can leak and does not expire; the exchanged token lives for one job. The exchange and a Bearer call to `/v1/chat/completions` (the way cora sends its key) were verified by the smoke test in the previous PR. ## Testing - The smoke workflow passed: token exchange HTTP 200, `/v1/chat/completions` with Bearer HTTP 200. - Not testable in this PR: the Cora Review job runs from the base branch for `pull_request_target`, so this change takes effect on the next PR after merge. The fallback keeps the required check working if the exchange fails there (the subject for `pull_request_target` may differ from `pull_request`). Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
ajianaz
added a commit
that referenced
this pull request
Oct 27, 2026
## What - A 400 response that names `temperature` is retried once without that key, and the model is remembered for the rest of the process (no repeated failing request, and no extra cost on later chunks). Streaming and non-streaming share the same path. - Any other 400 (and every other status) is returned unchanged; providers that accept `temperature` keep the configured value (default `0.0`, deterministic). ## Why `claude-opus-5-5` answers HTTP 400 "`temperature` is deprecated for this model", so every review through the Anthropic workload identity federation path (#700) ended as "Review could not complete" while the check still turned green. Closes #701. ## Testing - Unit tests: request body without a `temperature` key, recognising the 400, per-model memory. - Two end-to-end tests against a local fake server: the first request carries `temperature`, the retry does not and succeeds; a different 400 is not retried (one request only). - fmt, clippy -D warnings and the full suite pass. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
ajianaz
added a commit
to codecoradev/tole
that referenced
this pull request
Oct 28, 2026
…the stored key (#449) ## What The Cora Review job exchanges its GitHub OIDC token for a short-lived Anthropic access token (workload identity federation) when `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID` and `ANTHROPIC_WORKSPACE_ID` are available. Without them, or when the exchange fails, it uses the `CORA_*` secrets as before. Closes #448. Ported from codecoradev/cora-code#700. ## Why A stored API key can leak and does not expire; the exchanged token lives for one job. ## Changes - `.github/workflows/cora-review.yml`: `id-token: write`; an exchange step (`continue-on-error`, warning only) that keeps the OIDC token in its own shell and exports only the short-lived token; a guard that fails the job when neither federation nor the `CORA_*` secrets are available; with a federation token, key, base URL (`https://api.anthropic.com/v1`) and model (`ANTHROPIC_MODEL`, default `claude-opus-5-5`) switch together, so the token never goes to `CORA_BASE_URL`. - `.github/workflows/anthropic-wif-smoke.yml`: manual (`workflow_dispatch`) check of the exchange and a Bearer call to `/v1/chat/completions`; prints HTTP statuses only. - `CONTRIBUTING.md`: credential setup, including the numeric-id subject prefix gotcha. ## Testing - YAML parses; Cora agent review (prepare + finalize): 0 findings, `should_block: false`. - This repository's job runs on `pull_request`, so this PR's own Cora Review run exercises the new workflow: the federated path if the Anthropic federation rule allows `repo:codecoradev@<id>/tole@<id>:pull_request`, otherwise the fallback with a warning. --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
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.
What
ANTHROPIC_FEDERATION_RULE_ID,ANTHROPIC_ORGANIZATION_ID,ANTHROPIC_SERVICE_ACCOUNT_ID,ANTHROPIC_WORKSPACE_ID) are available as organization or repository secrets or variables. Model:ANTHROPIC_MODEL, defaultclaude-opus-5-5.https://api.anthropic.com/v1, never toCORA_BASE_URL.CORA_API_KEY,CORA_BASE_URLandCORA_MODELas before, and the guard still fails with an error naming a missing secret.id-token: writeadded to the job permissions; docs (docs/examples.md) and CHANGELOG updated.Why
A stored API key can leak and does not expire; the exchanged token lives for one job. The exchange and a Bearer call to
/v1/chat/completions(the way cora sends its key) were verified by the smoke test in the previous PR.Testing
/v1/chat/completionswith Bearer HTTP 200.pull_request_target, so this change takes effect on the next PR after merge. The fallback keeps the required check working if the exchange fails there (the subject forpull_request_targetmay differ frompull_request).