Files
coder/aibridge/intercept
Garrett Delfosse b55f721f24 fix: apply user-supplied AWS Bedrock API keys instead of dropping them (#28724)
## Bug

Under `/agents/settings/api-keys`, a personal API key saved for a
Bedrock provider never took effect. AI Gateway forwarded the saved
value, but the Bedrock interceptors re-signed every request with the
deployment's AWS credentials (SigV4), overwriting the `Authorization`
header. The key was silently dropped, so users were unknowingly still
billed to the administrator's AWS account with no way to bring their own
credentials.

## Fix

Apply the user's Bedrock key instead of discarding it. AWS Bedrock API
keys are bearer tokens (`Authorization: Bearer <key>`), so when a
personal key is present AI Gateway now sends it as a bearer token and
skips SigV4 signing. This covers every Bedrock route:

- **InvokeModel** (`/v1/messages`): applies the same wire transform as
the signed path (`/model/{model}/invoke[-with-response-stream]`,
`anthropic_version`, `anthropic-beta` → body, `model`/`stream`
stripping) but sets a bearer `Authorization` header instead of signing.
- **Mantle** (`/v1/messages`, `/v1/responses`, `/v1/chat/completions`):
passthrough with a bearer `Authorization` header instead of signing.

The bearer paths resolve no deployment AWS credentials, so BYOK works
even where the deployment has none. Requests without a personal key keep
the existing SigV4 behavior.

This also reverts the earlier interim guard that hid the key field and
rejected Bedrock key upserts: the field is shown again and the API
accepts the keys, because they now work.

<details>
<summary>Implementation notes</summary>

**Gateway (`aibridge`)**
- `messages.newMessagesService` detects BYOK on a Bedrock interception
and routes it through bearer-token option builders instead of the SigV4
path.
- `withBedrockInvokeModelBYOKOptions` /
`bedrockInvokeModelBearerMiddleware` reimplement the Anthropic SDK's
`bedrock.WithConfig` wire transform without signing, because that helper
couples the transform with SigV4 and would resolve deployment
credentials a BYOK request must not depend on.
- `bedrocksig.BearerMiddleware` is shared by the Messages, Responses,
and chat-completions interceptors for the Mantle passthrough; each
installs it in place of `SignMiddleware` when the credential is BYOK.
- Streaming decoding is unchanged: the Bedrock event-stream decoder is
registered by the SDK package's `init` and selected by response
content-type, independent of `bedrock.WithConfig`.

**coderd / SDK / frontend / docs**
- Removed the interim guard and `supports_user_api_key` capability flag;
restored the API-key field for Bedrock providers.
- Docs describe the Bedrock personal key as an AWS Bedrock API key
forwarded as a bearer token for every model family Bedrock serves.

**Tests**
- Unit: bearer middleware transform + auth for InvokeModel; shared
bearer middleware; option-builder validation.
- Integration: end-to-end through the bridge for InvokeModel, Mantle
Messages, Mantle Responses, and Mantle chat completions, asserting
`Authorization: Bearer <key>`, no `X-Amz-*` headers, correct upstream
path/model, no `X-Api-Key` leak, and that InvokeModel streaming decodes
real AWS binary event-stream frames.
- coderd: Bedrock key upserts succeed.

</details>

Closes
[CODAGT-699](https://linear.app/codercom/issue/CODAGT-699/bedrock-provider-settings-for-byok-only-expose-one-api-key).

---

*This PR was generated by Coder Agents on behalf of @f0ssel.*
2026-09-25 18:15:47 -04:00
..