Skip to content

feat(openai_responses): support aws_profile SigV4 auth for Bedrock OpenAI-wire#3463

Open
resrever wants to merge 6 commits into
tailcallhq:mainfrom
resrever:sigv4-openai-responses
Open

feat(openai_responses): support aws_profile SigV4 auth for Bedrock OpenAI-wire#3463
resrever wants to merge 6 commits into
tailcallhq:mainfrom
resrever:sigv4-openai-responses

Conversation

@resrever

@resrever resrever commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

What this enables

AWS Bedrock's OpenAI-compatible Responses endpoint (bedrock-mantle.<region>.api.aws/openai/v1/responses, which serves models like GPT-5.5 / GPT-5.4 over the OpenAI Responses wire) requires SigV4 request signing and rejects API keys. Forge's OpenAI-Responses path previously stubbed out AuthDetails::AwsProfile (emitted no auth header), so these requests failed with:

401 "Missing 'authorization' or 'x-api-key' header"

This PR SigV4-signs those requests using an AWS named profile and ships a built-in provider so it works out of the box. Because credentials resolve through the named profile and session tokens are forwarded (x-amz-security-token), temporary credentials work too — profiles backed by AWS SSO / IAM Identity Center, assume-role, or a credential_process broker.

What changed

  • SigV4 signing in the OpenAI-Responses path (repository.rs): new sigv4_headers() — when the credential is AuthDetails::AwsProfile, load the profile via aws_config (region from the AWS_REGION url-param, default us-east-1), SigV4-sign the request body for service bedrock, and inject Authorization / x-amz-date / x-amz-security-token. Wired into chat(); api_key / bearer / oauth paths are unchanged.
  • Preserve the endpoint path when it ends in /responses, so /openai/v1/responses isn't rewritten to /v1/responses.
  • Built-in provider entry (provider.json): bedrock_openai_responsesresponse_type: OpenAIResponses, URL templated on {{AWS_REGION}}, auth_methods: ["aws_profile"], models openai.gpt-5.5 / openai.gpt-5.4. This surfaces it in :provider (with the "AWS Profile" auth option) and forge list provider.
  • Adds aws-sigv4 1.4.4 (already in the lockfile via the AWS SDK).

Mirrors what #2831 did for BedrockProvider, applied to the OpenAI-Responses path.

Notes

  • auth_methods is intentionally ["aws_profile"] only: this endpoint rejects plain keys, and the OpenAI-Responses api_key path sends Authorization: Bearer, which isn't valid SigV4.
  • SigV4 is hand-rolled here (vs. BedrockProvider's SDK client) because the OpenAI-Responses path is plain HTTP via HttpInfra, not the AWS SDK.

Testing

  • New hermetic unit test asserts the Bedrock /openai/v1/responses path is preserved (not rewritten to /v1/responses). cargo test -p forge_repo passes.
  • Verified end-to-end against the live Bedrock endpoint: :providerbedrock_openai_responses with AWS profile auth → openai.gpt-5.5 / openai.gpt-5.4 are selectable and respond (SigV4 accepted, no 401).

…enAI-wire

The OpenAI Responses provider path previously stubbed out AuthDetails::AwsProfile
(no auth header emitted), so AWS Bedrock's OpenAI-compatible endpoint
(bedrock-mantle.<region>.api.aws/openai/v1/responses, which serves models like
gpt-5.5 / gpt-5.4 over the OpenAI Responses wire but requires SigV4) returned
401 "Missing 'authorization' or 'x-api-key' header".

This mirrors what PR tailcallhq#2831 did for BedrockProvider, but for the OpenAIResponses
path:

- Preserve the configured URL path when it ends in /responses (so
  /openai/v1/responses is not rewritten to /v1/responses).
- Add sigv4_headers(): when the credential is AwsProfile, load profile creds via
  aws_config, SigV4-sign the request body (service "bedrock", region from the
  AWS_REGION url param), and inject Authorization / x-amz-date /
  x-amz-security-token.
- Integrate into chat(); api_key / bearer / oauth behavior is unchanged.

Adds aws-sigv4 1.4.4 (already in the lockfile via the AWS SDK). All existing
tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the type: feature Brand new functionality, features, pages, workflows, endpoints, etc. label Jun 6, 2026
@resrever resrever marked this pull request as draft June 6, 2026 19:20
…ion test

Makes the new OpenAI-Responses SigV4 path usable end-to-end: registers a built-in provider (response_type OpenAIResponses, URL templated on AWS_REGION and ending in /openai/v1/responses so the path-preservation branch triggers, auth_methods [aws_profile]). api_key is intentionally omitted because the OpenAI-Responses api_key path sends Authorization: Bearer, which is not valid SigV4 for this endpoint. Model context_length values are placeholders pending confirmation against the live Mantle endpoint.

Adds a hermetic regression test asserting the Bedrock /openai/v1/responses path is preserved (not rewritten to /v1/responses). SigV4 header generation needs real AWS credentials, so it is not unit-tested here.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the type: provider Updates provider.json configuration. label Jun 6, 2026
resrever and others added 2 commits June 6, 2026 17:45
Live testing against the Bedrock OpenAI-wire endpoint shows the model ids must be prefixed with openai. (openai.gpt-5.5 / openai.gpt-5.4); the bare gpt-5.x ids were not accepted.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
GPT-5.5 / GPT-5.4 on the Bedrock OpenAI Responses (bedrock-mantle) endpoint expose a 1M-token context window per AWS and OpenAI docs; the 400k placeholder was the Codex-surface figure. Matches the repo other GPT-5.4 entries.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@resrever resrever marked this pull request as ready for review June 6, 2026 22:04
@github-actions

Copy link
Copy Markdown

Action required: PR inactive for 5 days.
Status update or closure in 10 days.

@github-actions github-actions Bot added the state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. label Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. type: feature Brand new functionality, features, pages, workflows, endpoints, etc. type: provider Updates provider.json configuration.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant