# Bedrock workload identity

The `bedrock` connection profile uses AWS SigV4 and temporary AssumeRole credentials.
It supports **regional Anthropic Claude Messages through InvokeModel and
InvokeModelWithResponseStream**, exposed through both existing buyer surfaces. It is not
a universal Converse adapter. `count_tokens` is not supported for this profile.

Only direct `anthropic.claude-...-vN:N` model IDs are accepted. Cross-region/global inference
profiles, profile ARNs, provisioned-throughput ARNs and arbitrary endpoints are rejected.
The public model-to-Bedrock model mapping and AWS region are immutable connection config.
Availability and account model access must be checked for the exact chosen region.

## Operator setup

The gateway's AWS credentials come from its instance role, through IMDSv2; the application
does not use an ambient AWS static-key credential chain.
Grant this role `sts:AssumeRole` on the customer's exact role ARN. The customer role trust
policy must name the source role and require `sts:ExternalId` equal to `tm:<org UUID>`.
Its permissions should allow `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream`
only on approved regional foundation-model ARNs.

Both processes require an operator-controlled grant map, e.g.:

```sh
TM_BEDROCK_ROLE_GRANTS='{"ORG_UUID":["arn:aws:iam::123456789012:role/tm-customer"]}'
```

An org cannot register or use another org's role without an explicit operator grant.
Updating the map requires restarting the affected processes. It does not replace AWS IAM
authorization. Keep trust grants least-privilege and use a distinct external ID per org.
The console offers the Bedrock profile only to an organization with a grant.

## Create and validate

Using the same session/Origin headers as other connection management calls:

```json
{
  "profile": "bedrock",
  "models": ["your-public-model-id"],
  "endpoint_config": {
    "region": "us-east-1",
    "deployments": {
      "your-public-model-id": "anthropic.claude-3-haiku-20240307-v1:0"
    }
  },
  "workload_role": {
    "role_arn": "arn:aws:iam::123456789012:role/tm-customer"
  }
}
```

POST this to `/api/connections`; replace the example model with a regional model your
account can invoke. The role reference is write-only and envelope-encrypted using the
existing environment wrapping-key ring. Do not supply `api_key`, AWS access keys, an
external ID override, a bearer token or a request-time credential.

`POST /api/connections/<id>/validate` checks the AssumeRole path without generating a
billable completion. An active result proves role assumption, **not model entitlement,
capacity, private connectivity, processing residency or ZDR**. Declare and bind a
`provider:"bedrock"` quota pool, then bind the connection or policy to a virtual key.
Run a real minimal inference to qualify model permissions and streaming.

Rotation uses `/rotate` with `{workload_role:{role_arn:"..."}}`, revokes the old connection
version and returns it to pending. It preserves account-pool identity. Disabling or deleting
the connection uses the existing fenced revocation path.

## Runtime behavior

STS uses the configured regional endpoint, 15-minute sessions and an org-bound external
ID. Temporary credentials live only in bounded process memory (256 sessions, 64 concurrent
refreshes), refresh at least a minute before expiry and never enter SQL, Redis, journals
or telemetry. Both AWS clients use one attempt; the gateway remains the retry authority.
The HTTP/1.1 handler is set explicitly. SDK-internal retries and endpoint-environment
overrides are disabled.

The durable intent precedes role resolution and inference. The existing final authority
and admission checks still precede the signed inference call. A credential failure before
inference is accounted as never dispatched. Inference transport uncertainty retains the
normal conservative usage reservation. AWS binary events are decoded into the existing
Anthropic stream pipeline; once output commits, errors are terminal, with no silent retry.
AWS exception text is not relayed because it can echo sensitive input.

Free BYOK economics are unchanged: platform debit and provider payable are zero; external
inference cost remains unknown unless independently priced. A regional endpoint is not a
ZDR attestation. Privacy/residency route filters still require operator evidence.

References: [AWS Claude request format](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages-request-response.html),
[stream operation](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModelWithResponseStream.html),
[Bedrock PrivateLink](https://docs.aws.amazon.com/bedrock/latest/userguide/vpc-interface-endpoints.html).
