[codex] expose Bedrock credential source in account/read (#27751)

## Why

`account/read` currently reports only `type: "amazonBedrock"`, so
clients cannot distinguish a Codex-managed Bedrock API key from
credentials supplied by AWS. The app UI needs that distinction to render
the appropriate account state without duplicating provider-auth logic.

Credential-source selection belongs to the Bedrock model provider
because it already owns the precedence between managed Bedrock auth and
the external AWS credential path. This builds on #27443 and #27689.

## What changed

- Added `AmazonBedrockCredentialSource` with `codexManaged` and
`awsManaged` values.
- Included the selected credential source in
`ProviderAccount::AmazonBedrock` and the app-server `Account` response.
- Made `AmazonBedrockModelProvider::account_state()` classify the source
from its managed-auth state.
- Regenerated the app-server JSON and TypeScript schemas.
- Updated app-server account documentation and downstream TUI matches.

`codexManaged` means the provider found a managed Bedrock API key.
`awsManaged` identifies the provider's external AWS credential path; it
does not assert that the AWS credential chain has been validated.

## Testing

- Added model-provider coverage for Codex-managed precedence and
AWS-managed fallback.
- Added app-server protocol serialization coverage for both wire values.
- Added app-server integration coverage for both `account/read`
responses.
- `just test -p codex-protocol -p codex-model-provider -p
codex-app-server-protocol` (497 tests passed).

After rebasing onto #27711, the `codex-app-server` test target compiled
past the image-generation `PathUri` migration. Local linking was then
interrupted by disk exhaustion (`No space left on device`).
This commit is contained in:
Celia Chen
2026-06-16 07:14:53 +00:00
committed by GitHub
parent 314fa3d25b
commit 12aaeb7bf8
15 changed files with 200 additions and 10 deletions
@@ -5847,6 +5847,14 @@
},
{
"properties": {
"credentialSource": {
"allOf": [
{
"$ref": "#/definitions/v2/AmazonBedrockCredentialSource"
}
],
"default": "awsManaged"
},
"type": {
"enum": [
"amazonBedrock"
@@ -6166,6 +6174,13 @@
"AgentPath": {
"type": "string"
},
"AmazonBedrockCredentialSource": {
"enum": [
"codexManaged",
"awsManaged"
],
"type": "string"
},
"AnalyticsConfig": {
"additionalProperties": true,
"properties": {
@@ -49,6 +49,14 @@
},
{
"properties": {
"credentialSource": {
"allOf": [
{
"$ref": "#/definitions/AmazonBedrockCredentialSource"
}
],
"default": "awsManaged"
},
"type": {
"enum": [
"amazonBedrock"
@@ -368,6 +376,13 @@
"AgentPath": {
"type": "string"
},
"AmazonBedrockCredentialSource": {
"enum": [
"codexManaged",
"awsManaged"
],
"type": "string"
},
"AnalyticsConfig": {
"additionalProperties": true,
"properties": {
@@ -45,6 +45,14 @@
},
{
"properties": {
"credentialSource": {
"allOf": [
{
"$ref": "#/definitions/AmazonBedrockCredentialSource"
}
],
"default": "awsManaged"
},
"type": {
"enum": [
"amazonBedrock"
@@ -61,6 +69,13 @@
}
]
},
"AmazonBedrockCredentialSource": {
"enum": [
"codexManaged",
"awsManaged"
],
"type": "string"
},
"PlanType": {
"enum": [
"free",
@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type AmazonBedrockCredentialSource = "codexManaged" | "awsManaged";
+1
View File
@@ -3,6 +3,7 @@
export type { AbsolutePathBuf } from "./AbsolutePathBuf";
export type { AgentMessageInputContent } from "./AgentMessageInputContent";
export type { AgentPath } from "./AgentPath";
export type { AmazonBedrockCredentialSource } from "./AmazonBedrockCredentialSource";
export type { ApiPathString } from "./ApiPathString";
export type { ApplyPatchApprovalParams } from "./ApplyPatchApprovalParams";
export type { ApplyPatchApprovalResponse } from "./ApplyPatchApprovalResponse";
@@ -1,6 +1,7 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AmazonBedrockCredentialSource } from "../AmazonBedrockCredentialSource";
import type { PlanType } from "../PlanType";
export type Account = { "type": "apiKey", } | { "type": "chatgpt", email: string, planType: PlanType, } | { "type": "amazonBedrock", };
export type Account = { "type": "apiKey", } | { "type": "chatgpt", email: string, planType: PlanType, } | { "type": "amazonBedrock", credentialSource: AmazonBedrockCredentialSource, };
@@ -1674,6 +1674,7 @@ mod tests {
use super::*;
use anyhow::Result;
use codex_protocol::ThreadId;
use codex_protocol::account::AmazonBedrockCredentialSource;
use codex_protocol::account::PlanType;
use codex_protocol::models::BUILT_IN_PERMISSION_PROFILE_READ_ONLY;
use codex_protocol::parse_command::ParsedCommand;
@@ -2777,6 +2778,41 @@ mod tests {
serde_json::to_value(&chatgpt)?,
);
let codex_managed_bedrock = v2::Account::AmazonBedrock {
credential_source: AmazonBedrockCredentialSource::CodexManaged,
};
assert_eq!(
json!({
"type": "amazonBedrock",
"credentialSource": "codexManaged",
}),
serde_json::to_value(&codex_managed_bedrock)?,
);
let aws_managed_bedrock = v2::Account::AmazonBedrock {
credential_source: AmazonBedrockCredentialSource::AwsManaged,
};
assert_eq!(
json!({
"type": "amazonBedrock",
"credentialSource": "awsManaged",
}),
serde_json::to_value(&aws_managed_bedrock)?,
);
Ok(())
}
#[test]
fn account_defaults_legacy_bedrock_credential_source() -> Result<()> {
assert_eq!(
v2::Account::AmazonBedrock {
credential_source: AmazonBedrockCredentialSource::AwsManaged,
},
serde_json::from_value(json!({
"type": "amazonBedrock",
}))?,
);
Ok(())
}
@@ -1,5 +1,6 @@
use crate::protocol::common::AuthMode;
use codex_experimental_api_macros::ExperimentalApi;
use codex_protocol::account::AmazonBedrockCredentialSource;
use codex_protocol::account::PlanType;
use codex_protocol::account::ProviderAccount;
use codex_protocol::protocol::CreditsSnapshot as CoreCreditsSnapshot;
@@ -28,7 +29,14 @@ pub enum Account {
#[serde(rename = "amazonBedrock", rename_all = "camelCase")]
#[ts(rename = "amazonBedrock", rename_all = "camelCase")]
AmazonBedrock {},
AmazonBedrock {
#[serde(default = "default_bedrock_credential_source")]
credential_source: AmazonBedrockCredentialSource,
},
}
fn default_bedrock_credential_source() -> AmazonBedrockCredentialSource {
AmazonBedrockCredentialSource::AwsManaged
}
impl From<ProviderAccount> for Account {
@@ -36,7 +44,9 @@ impl From<ProviderAccount> for Account {
match account {
ProviderAccount::ApiKey => Self::ApiKey {},
ProviderAccount::Chatgpt { email, plan_type } => Self::Chatgpt { email, plan_type },
ProviderAccount::AmazonBedrock => Self::AmazonBedrock {},
ProviderAccount::AmazonBedrock { credential_source } => {
Self::AmazonBedrock { credential_source }
}
}
}
}