feat: add managed Bedrock login API (#31327)

## Why

App-server clients can report whether Amazon Bedrock is using
AWS-managed credentials or a Codex-managed API key, but they do not have
a matching API for creating the managed login. This PR defines that
experimental wire contract independently from its implementation.

Managed Bedrock API keys are already a primary `CodexAuth` mode. The API
therefore describes a normal Codex login that replaces the current
stored auth rather than introducing provider-scoped credential storage.

## What changed

- Add the experimental `amazonBedrock` variant to `account/login/start`.
- Accept an API key and AWS region and return a matching discriminated
response.
- Gate the request behind the app-server `experimentalApi` capability.
- Regenerate the JSON and TypeScript protocol schemas.
- Document the login contract, notifications, primary-auth replacement
semantics, restart boundary, and non-transactional durable writes.

## Impact

This PR defines the API shape but does not implement login behavior. The
next PR adds validation, persistence through the existing Codex auth
lifecycle, provider selection, and notifications.

## Validation

- `just test -p codex-app-server-protocol`

## Stack

1. **#31327 Managed Bedrock experimental API** — base: `main`
2. #31326 Managed Bedrock login — base: `codex/managed-bedrock-api`
3. #31325 Managed Bedrock logout — base:
`codex/managed-bedrock-login-v2`
This commit is contained in:
Celia Chen
2026-07-09 17:05:37 -07:00
committed by GitHub
parent ac3da4fb1a
commit b45fef0774
11 changed files with 216 additions and 4 deletions
@@ -2722,6 +2722,34 @@ mod tests {
Ok(())
}
#[test]
fn serialize_account_login_amazon_bedrock() -> Result<()> {
let request = ClientRequest::LoginAccount {
request_id: RequestId::Integer(2),
params: v2::LoginAccountParams::AmazonBedrock {
api_key: "secret".to_string(),
region: "us-west-2".to_string(),
},
};
assert_eq!(
json!({
"method": "account/login/start",
"id": 2,
"params": {
"type": "amazonBedrock",
"apiKey": "secret",
"region": "us-west-2"
}
}),
serde_json::to_value(&request)?,
);
assert_eq!(
json!({"type": "amazonBedrock"}),
serde_json::to_value(v2::LoginAccountResponse::AmazonBedrock {})?,
);
Ok(())
}
#[test]
fn serialize_account_login_chatgpt() -> Result<()> {
let request = ClientRequest::LoginAccount {
@@ -105,6 +105,11 @@ pub enum LoginAccountParams {
#[ts(optional = nullable)]
chatgpt_plan_type: Option<String>,
},
/// [UNSTABLE] Managed Amazon Bedrock login is experimental.
#[experimental("account/login/start.amazonBedrock")]
#[serde(rename = "amazonBedrock", rename_all = "camelCase")]
#[ts(rename = "amazonBedrock", rename_all = "camelCase")]
AmazonBedrock { api_key: String, region: String },
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
@@ -148,6 +153,9 @@ pub enum LoginAccountResponse {
#[serde(rename = "chatgptAuthTokens", rename_all = "camelCase")]
#[ts(rename = "chatgptAuthTokens", rename_all = "camelCase")]
ChatgptAuthTokens {},
#[serde(rename = "amazonBedrock", rename_all = "camelCase")]
#[ts(rename = "amazonBedrock", rename_all = "camelCase")]
AmazonBedrock {},
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]