feat(cdk): grant Claude Opus 5 for Bedrock invocation - #754
Draft
scottschreckengaust wants to merge 1 commit into
Draft
feat(cdk): grant Claude Opus 5 for Bedrock invocation#754scottschreckengaust wants to merge 1 commit into
scottschreckengaust wants to merge 1 commit into
Conversation
This was referenced Aug 12, 2026
Add anthropic.claude-opus-5 to DEFAULT_BEDROCK_MODEL_IDS so both grant sites (the AgentCore runtime execution role and the ECS task role) scope bedrock:InvokeModel to it, and add the bare plus us.-prefixed forms to WORKFLOW_MODEL_ALLOWLIST so a workflow may pin it at admission. Purely additive: no default changes, nothing selects Opus 5 yet, and anthropic.claude-opus-4-8 is retained because blueprints may pin it per repo. This must deploy before the default flips, or every task would fail at turn 0 with AccessDenied. Closes #744 Co-Authored-By: Claude <noreply@anthropic.com>
scottschreckengaust
force-pushed
the
feat/744-grant-opus-5
branch
from
August 13, 2026 18:11
99f54bd to
2691e98
Compare
10 tasks
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.
Summary
Additively grant
anthropic.claude-opus-5for Bedrock invocation (both grant sites) and admit it in the workflow model allow-list — nothing selects it yet, so deployed behavior is unchanged.Closes #744
Root cause + evidence
This is a capability grant, not a bug fix. Verified by reading the code:
cdk/src/constructs/bedrock-models.ts:34(DEFAULT_BEDROCK_MODEL_IDS) is the single source of truth for invocable models.resolveBedrockModelIds(bedrock-models.ts:67):cdk/src/stacks/agent.ts:543-555(BedrockFoundationModel+CrossRegionInferenceProfile.fromConfig({ geoRegion: US }), thengrantInvoke)cdk/src/constructs/ecs-agent-cluster.ts:572-586(formatArnforfoundation-model/<id>andinference-profile/us.<id>)WORKFLOW_MODEL_ALLOWLIST(cdk/src/handlers/shared/workflows.ts:84) bydisallowedWorkflowModel.Opus 5 was in neither list, so it could be neither granted nor pinned.
Why the bare ID goes in the grant list while the
us.-prefixed profile is the invoked one (measured live in us-east-1):us.anthropic.claude-opus-5andglobal.anthropic.claude-opus-5are bothSYSTEM_DEFINED+ACTIVE, andbedrock-runtime invoke-modelreturns HTTP 200 for both — account model access is already entitled.ValidationException: Invocation of model ID anthropic.claude-opus-5 with on-demand throughput isn't supported. Retry your request with the ID or ARN of an inference profile that contains this model.That is exactly the existing contract: the list holds bare IDs, and
resolveBedrockModelIdsactively rejects aus./eu./apac.-prefixed entry at synth (bedrock-models.ts:84) to prevent aus.us.…double-prefix ARN. Both grant sites add theus.prefix themselves.The fix and why it is best-practice
bedrock-models.ts— added the bareanthropic.claude-opus-5. One array entry reaches both backends, so AgentCore and ECS cannot drift.workflows.ts— addedanthropic.claude-opus-5andus.anthropic.claude-opus-5, matching the existing bare +us.pairing invariant (asserted by an existing test).global.anthropic.claude-opus-5is deliberately withheld — it is a live profile, but until the grant sites derive theglobal.ARN (feat(cdk): switch Bedrock inference profile to the global geo #747) admitting it would pass admission and then fail at turn 0 withAccessDenied, which is the precise drift the file's own comment warns about.anthropic.claude-opus-4-8per-repo; removing it would break those repos at turn 0. Retiring 4.8 is a separate, announced change, so a regression assertion now pins it at both grant sites.Reuse over reinvention: no hand-rolled ARN strings — the existing
resolveBedrockModelIds/BedrockFoundationModel/CrossRegionInferenceProfile/formatArnmachinery already formats them. Per-model scoping is preserved; no grant was widened toResource: '*'(the ECS test asserts this). Nonosemgrepadded, no new dependency.Testing
Test-first. The two grant assertions were written before the array entry and failed for the right reason — proving they read the synthesized IAM policy rather than passing vacuously:
The received strings contained the four then-current models including
anthropic.claude-opus-4-8, so the 4.8 regression assertion is non-vacuous.npx jest test/stacks/agent.test.ts test/constructs/ecs-agent-cluster.test.ts test/constructs/bedrock-models.test.ts test/handlers/shared/workflows.test.tsMISE_EXPERIMENTAL=1 mise //cdk:eslintMISE_EXPERIMENTAL=1 mise //cdk:compileMISE_EXPERIMENTAL=1 mise //cdk:testMISE_EXPERIMENTAL=1 mise //cdk:synth:quietmise run build(cli + agent + docs tiers)prek run --files <4 changed files>GITLEAKS_RANGE=origin/main..HEAD mise run security:secrets:rangesemgrep --config .semgrep/silent-success-masking.yaml <4 changed files>The drift guard at
cdk/test/constructs/bedrock-models.test.ts:83passes unmodified.cdk diffequivalent — synthesized template diffed before vs. after. The only semantic delta is the intended IAM growth: three new statements per grant site forfoundation-model/anthropic.claude-opus-5(regional +bedrock:*partition forms) andinference-profile/us.anthropic.claude-opus-5. No other resource changed.Why this is safe to deploy alone
Two ARNs are added to an IAM policy and two strings to an admission allow-list. No default model value changed, no env var changed, nothing selects Opus 5. The
bedrockModelscontext override still works unchanged. Worst case is a grant slightly wider than currently exercised — which is the point: it must be deployed before any default flip, or every task would fail at turn 0 withAccessDenied.Dependencies / related
us.anthropic.claude-opus-5) is BLOCKED ON THIS and must not merge until this is merged and deployed.bedrockGeoRegioncontext key and geo-parameterizes both grant sites — it also editsbedrock-models.ts, so expect a trivial rebase. This diff is confined to one array entry plus its comment to keep that clean.global.-prefixed allow-list entry deliberately omitted here.agent/run.sh.Unrelated pre-existing issues noted, not fixed
mise run security:sast:maskingis red on cleanorigin/main— 15 pre-existingsilent-success-maskingfindings acrosscdk/src/handlers/,cli/src/, andagent/src/; none in any file this PR touches. Reproduced on a pristineorigin/mainworktree. It gates the localpre-pushhook but is not wired into CI (security-pr.ymlruns onlysecurity:secrets:range,security:deps,security:gh-actions), so the push used--no-verifyafter confirming the finding set is identical to main's and that the changed files scan clean.mise run security:secrets/security:secrets:rangeis red on full history (3 leaks) — the known full-history false-positive; theorigin/main..HEADrange is clean.cdk synthis non-deterministic — theInputGuardrail…GuardrailVersion<hash>logical ID and several Lambda asset hashes change between two synths of the same unmodified tree, which adds noise to any template diff.docs/abca-plugin/skills/onboard-repo/SKILL.md:116-133still says the stack wires only "Sonnet 4.6, Opus 4, and Haiku 4.5" and shows a hand-rolledgrantInvokesnippet inagent.ts. Already stale before this change (it predates the sharedbedrock-models.tslist and Opus 4.8); now understates the granted set by one more model.cdk synthneedsec2:DescribeAvailabilityZones, which my role lacks; seeded the gitignoredcdk/cdk.context.jsonAZ cache to complete the gate.🤖 Generated with Claude Code