feat: route Bedrock via Cloudflare AI Gateway BYOK (drop client-side SigV4)#47
feat: route Bedrock via Cloudflare AI Gateway BYOK (drop client-side SigV4)#47jphein wants to merge 2 commits into
Conversation
…SigV4) When AI_GATEWAY_BASE and AI_GATEWAY_AUTH_TOKEN are both set, the chat backend now sends UNSIGNED Bedrock requests with a `cf-aig-authorization: Bearer <token>` header and lets the Cloudflare AI Gateway perform SigV4 on its own infrastructure. This eliminates the per-request 4×HMAC-SHA256 + 2×SHA256 that was pushing the chat hot path toward the Workers CPU cap (~10ms -> ~1ms), structurally killing the 1102 errors (issue #18). SigV4 signing is kept as a fallback for direct Bedrock calls or an unauthenticated gateway pass-through when no BYOK token is configured, so AWS keys remain a belt-and-suspenders option. - bedrock.ts: add AI_GATEWAY_AUTH_TOKEN to BedrockEnv; branch on BYOK vs SigV4; AWS keys now optional (only required for the SigV4 path) - chat.ts: read AI_GATEWAY_AUTH_TOKEN, relax misconfigured check to accept BYOK OR AWS keys - .env.example: document the two Bedrock auth modes + chat env vars Closes #18 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds a BYOK authentication mode to Bedrock calls routed through the Cloudflare AI Gateway. ChangesBedrock BYOK Auth via Cloudflare AI Gateway
Sequence Diagram(s)sequenceDiagram
participant Client
participant ChatAPI as pages/api/chat.ts
participant invokeBedrock as lib/chat-server/bedrock.ts
participant AIGateway as Cloudflare AI Gateway
participant Bedrock as AWS Bedrock
Client->>ChatAPI: POST /api/chat
ChatAPI->>ChatAPI: Validate SESSION_SIGN_SECRET + (BYOK creds OR SigV4 keys)
ChatAPI->>invokeBedrock: invokeBedrock(bedrockEnv with AI_GATEWAY_AUTH_TOKEN)
alt BYOK mode (AI_GATEWAY_BASE + AI_GATEWAY_AUTH_TOKEN set)
invokeBedrock->>AIGateway: fetch with cf-aig-authorization header (no SigV4)
AIGateway->>Bedrock: SigV4-signed request (Cloudflare signs)
Bedrock-->>AIGateway: Streaming response
AIGateway-->>invokeBedrock: Streaming response
else SigV4 fallback (AWS keys set)
invokeBedrock->>Bedrock: fetch with SigV4 Authorization header
Bedrock-->>invokeBedrock: Streaming response
end
invokeBedrock-->>ChatAPI: InvokeResult
ChatAPI-->>Client: Streamed reply
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces a "Bring Your Own Key" (BYOK) authentication mode for AWS Bedrock via Cloudflare AI Gateway, which offloads SigV4 signing to the gateway to reduce Worker CPU usage, while retaining local SigV4 signing as a fallback. Feedback on these changes suggests trimming environment variables in pages/api/chat.ts to handle whitespace-only values robustly, and automatically prepending https:// to AI_GATEWAY_BASE in lib/chat-server/bedrock.ts if the protocol is omitted.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const hasByok = !!aiGatewayBase && !!aiGatewayAuthToken | ||
| const hasAwsKeys = !!awsAccessKeyId && !!awsSecretAccessKey |
There was a problem hiding this comment.
To prevent issues with whitespace-only environment variables or secrets (which can happen during copy-pasting), it is safer to trim the values before checking if they are present.
| const hasByok = !!aiGatewayBase && !!aiGatewayAuthToken | |
| const hasAwsKeys = !!awsAccessKeyId && !!awsSecretAccessKey | |
| const hasByok = !!aiGatewayBase.trim() && !!aiGatewayAuthToken.trim() | |
| const hasAwsKeys = !!awsAccessKeyId.trim() && !!awsSecretAccessKey.trim() |
| const gatewayBase = (env.AI_GATEWAY_BASE ?? '').trim() | ||
| const authToken = (env.AI_GATEWAY_AUTH_TOKEN ?? '').trim() | ||
| // BYOK is active only when we have both a gateway to route through AND a | ||
| // token to authenticate to it. Either one alone falls back to SigV4. | ||
| const useByok = gatewayBase !== '' && authToken !== '' |
There was a problem hiding this comment.
If AI_GATEWAY_BASE is configured without a protocol (e.g., gateway.ai.cloudflare.com/...), the subsequent fetch call will fail. Automatically prepending https:// if the protocol is missing makes the configuration more robust and user-friendly.
let gatewayBase = (env.AI_GATEWAY_BASE ?? '').trim()
if (gatewayBase && !/^https?:\/\//i.test(gatewayBase)) {
gatewayBase = `https://${gatewayBase}`
}
const authToken = (env.AI_GATEWAY_AUTH_TOKEN ?? '').trim()
// BYOK is active only when we have both a gateway to route through AND a
// token to authenticate to it. Either one alone falls back to SigV4.
const useByok = gatewayBase !== '' && authToken !== ''There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
pages/api/chat.ts (1)
141-157:⚠️ Potential issue | 🟠 Major | ⚡ Quick winNormalize env values before auth-mode checks.
hasByok/hasAwsKeysare computed from untrimmed values here, butinvokeBedrocktrims gateway values again before choosing BYOK. A whitespace-only secret can pass this guard and then fail later at runtime instead of returning early as misconfigured.Suggested fix
- const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID ?? '' - const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY ?? '' + const awsAccessKeyId = (process.env.AWS_ACCESS_KEY_ID ?? '').trim() + const awsSecretAccessKey = (process.env.AWS_SECRET_ACCESS_KEY ?? '').trim() const awsRegion = process.env.AWS_REGION ?? 'us-west-2' - const aiGatewayBase = process.env.AI_GATEWAY_BASE ?? '' - const aiGatewayAuthToken = process.env.AI_GATEWAY_AUTH_TOKEN ?? '' + const aiGatewayBase = (process.env.AI_GATEWAY_BASE ?? '').trim() + const aiGatewayAuthToken = (process.env.AI_GATEWAY_AUTH_TOKEN ?? '').trim()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pages/api/chat.ts` around lines 141 - 157, The environment variables are being checked for truthiness without trimming whitespace, but invokeBedrock trims these values later. This allows whitespace-only secrets to pass the early validation guard and fail at runtime instead. Trim the aiGatewayBase and aiGatewayAuthToken values (and similarly for awsAccessKeyId and awsSecretAccessKey if needed) before computing the hasByok and hasAwsKeys boolean checks to ensure that whitespace-only values are properly treated as empty and rejected early with the misconfiguration check at the if statement.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@pages/api/chat.ts`:
- Around line 141-157: The environment variables are being checked for
truthiness without trimming whitespace, but invokeBedrock trims these values
later. This allows whitespace-only secrets to pass the early validation guard
and fail at runtime instead. Trim the aiGatewayBase and aiGatewayAuthToken
values (and similarly for awsAccessKeyId and awsSecretAccessKey if needed)
before computing the hasByok and hasAwsKeys boolean checks to ensure that
whitespace-only values are properly treated as empty and rejected early with the
misconfiguration check at the if statement.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: fcab0d55-6f7a-4951-9d3c-fe90487ab835
📒 Files selected for processing (3)
.env.examplelib/chat-server/bedrock.tspages/api/chat.ts
Addresses the two medium findings from the gemini-code-assist review on PR #47 (coderabbit found 0 actionable items): - bedrock.ts: auto-prepend `https://` to AI_GATEWAY_BASE when it is configured without a scheme — fetch() requires an absolute URL, so a scheme-less value would throw at deploy time and take chat down. - chat.ts: trim the Bedrock-auth env vars (AWS keys + gateway base/token) at the source. Whitespace-only values (copy-paste mishap) would otherwise pass the `!!` presence guards while being effectively empty; bedrock.ts already trims the gateway values when choosing BYOK vs SigV4, so trimming here keeps the guard and the consumer in agreement. No behavior change for correctly-configured environments. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks for the reviews 🙏 CodeRabbit: 0 actionable comments, 5/5 pre-merge checks passed. Gemini — both medium findings addressed in 735d03e:
Reminder for reviewers: this is not mergeable until the Cloudflare-side BYOK setup is done (AI Gateway provider key + |
Closes #18.
What this does
Migrates the chat backend's Bedrock auth from in-worker AWS SigV4 signing to Cloudflare AI Gateway BYOK (Bring Your Own Keys).
When
AI_GATEWAY_BASEandAI_GATEWAY_AUTH_TOKENare both present,invokeBedrocknow:cf-aig-authorization: Bearer <token>,Authorizationheader entirely — the gateway holds the AWS credentials and performs SigV4 on its own infra before forwarding to Bedrock.This removes the per-request
4×HMAC-SHA256 + 2×SHA256from the chat hot path (~10ms → ~1ms CPU/request), which is what was pushing requests toward the Workers CPU cap and surfacing as 1102 errors.SigV4 signing is retained as a fallback (direct Bedrock, or unauthenticated gateway pass-through) for when no BYOK token is configured — so AWS keys remain a belt-and-suspenders option rather than being deleted outright.
Changes
lib/chat-server/bedrock.ts— addAI_GATEWAY_AUTH_TOKENtoBedrockEnv; branch BYOK vs SigV4; AWS keys are now optional (required only for the SigV4 path, with a clear thrown error if neither auth mode is configured).pages/api/chat.ts— readAI_GATEWAY_AUTH_TOKEN; relax themisconfiguredguard to accept BYOK OR AWS keys (session secret still always required)..env.example— document the two Bedrock auth modes and the chat env vars (previously undocumented).The Haiku topic classifier (
classify.ts) inherits the new path automatically — it calls the sameinvokeBedrock.This PR is code-only and must NOT be auto-merged. The following must be done on the Cloudflare side first, or chat will fall back to SigV4 (or fail if AWS keys are later removed):
techempower-chatgateway → Provider Keys → Add → AWS Bedrock. Paste the AWS access key + secret and set regionus-west-2(must matchAWS_REGION).pnpm exec wrangler secret put AI_GATEWAY_AUTH_TOKENAI_GATEWAY_BASEis set (Worker secret/var) to the base up to but not including/aws-bedrock, i.e.https://gateway.ai.cloudflare.com/v1/<account_id>/<gateway_id>.AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYWorker secrets can optionally be removed — code no longer needs them in BYOK mode. Recommend keeping them initially as a direct-Bedrock fallback, then dropping once BYOK is proven stable.Validation
pnpm install✅npx tsc --noEmit✅pnpm test(eslint + prettier) ✅No unit-test framework in this repo, so no tests added.
Summary by CodeRabbit
.env.examplewith a new, documented configuration section for the chat assistant authentication, including optional bot-defense settings