mirror of
https://github.com/openai/codex.git
synced 2026-10-18 17:18:52 +00:00
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:
@@ -1543,6 +1543,31 @@
|
||||
],
|
||||
"title": "ChatgptAuthTokensLoginAccountParams",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "[UNSTABLE] Managed Amazon Bedrock login is experimental.",
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"region": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockLoginAccountParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"apiKey",
|
||||
"region",
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockLoginAccountParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+41
@@ -11591,6 +11591,31 @@
|
||||
],
|
||||
"title": "ChatgptAuthTokensv2::LoginAccountParams",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "[UNSTABLE] Managed Amazon Bedrock login is experimental.",
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"region": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"apiKey",
|
||||
"region",
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountParams",
|
||||
"type": "object"
|
||||
}
|
||||
],
|
||||
"title": "LoginAccountParams"
|
||||
@@ -11684,6 +11709,22 @@
|
||||
],
|
||||
"title": "ChatgptAuthTokensv2::LoginAccountResponse",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountResponseType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountResponse",
|
||||
"type": "object"
|
||||
}
|
||||
],
|
||||
"title": "LoginAccountResponse"
|
||||
|
||||
+41
@@ -7995,6 +7995,31 @@
|
||||
],
|
||||
"title": "ChatgptAuthTokensv2::LoginAccountParams",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "[UNSTABLE] Managed Amazon Bedrock login is experimental.",
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"region": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"apiKey",
|
||||
"region",
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountParams",
|
||||
"type": "object"
|
||||
}
|
||||
],
|
||||
"title": "LoginAccountParams"
|
||||
@@ -8088,6 +8113,22 @@
|
||||
],
|
||||
"title": "ChatgptAuthTokensv2::LoginAccountResponse",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountResponseType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountResponse",
|
||||
"type": "object"
|
||||
}
|
||||
],
|
||||
"title": "LoginAccountResponse"
|
||||
|
||||
@@ -112,6 +112,31 @@
|
||||
],
|
||||
"title": "ChatgptAuthTokensv2::LoginAccountParams",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "[UNSTABLE] Managed Amazon Bedrock login is experimental.",
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"region": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"apiKey",
|
||||
"region",
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountParams",
|
||||
"type": "object"
|
||||
}
|
||||
],
|
||||
"title": "LoginAccountParams"
|
||||
|
||||
@@ -87,6 +87,22 @@
|
||||
],
|
||||
"title": "ChatgptAuthTokensv2::LoginAccountResponse",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountResponseType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockv2::LoginAccountResponse",
|
||||
"type": "object"
|
||||
}
|
||||
],
|
||||
"title": "LoginAccountResponse"
|
||||
|
||||
@@ -19,4 +19,4 @@ chatgptAccountId: string,
|
||||
* When `null`, Codex attempts to derive the plan type from access-token
|
||||
* claims. If unavailable, the plan defaults to `unknown`.
|
||||
*/
|
||||
chatgptPlanType?: string | null, };
|
||||
chatgptPlanType?: string | null, } | { "type": "amazonBedrock", apiKey: string, region: string, };
|
||||
|
||||
@@ -14,4 +14,4 @@ verificationUrl: string,
|
||||
/**
|
||||
* One-time code the user must enter after signing in.
|
||||
*/
|
||||
userCode: string, } | { "type": "chatgptAuthTokens", };
|
||||
userCode: string, } | { "type": "chatgptAuthTokens", } | { "type": "amazonBedrock", };
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -1921,16 +1921,17 @@ Codex supports these authentication modes. The current mode is surfaced in `acco
|
||||
|
||||
- **API key (`apiKey`)**: Caller supplies an OpenAI API key via `account/login/start` with `type: "apiKey"`. The API key is saved and used for API requests.
|
||||
- **ChatGPT managed (`chatgpt`)** (recommended): Codex owns the ChatGPT OAuth flow and refresh tokens. Start via `account/login/start` with `type: "chatgpt"` for the browser flow or `type: "chatgptDeviceCode"` for device code; Codex persists tokens to disk and refreshes them automatically.
|
||||
- **Codex managed Amazon Bedrock auth (`amazonBedrock`, experimental)**: Caller supplies an Amazon Bedrock API key and region via `account/login/start` with `type: "amazonBedrock"`. The client must enable the `experimentalApi` initialization capability for Codex-managed Amazon Bedrock login. Codex replaces the current primary auth with the Bedrock credential and writes `model_provider = "amazon-bedrock"` to the user config.
|
||||
- **Personal access token (`personalAccessToken`)**: Codex uses a ChatGPT-backed personal access token loaded outside the app-server login RPCs, such as with `codex login --with-access-token` or `CODEX_ACCESS_TOKEN`.
|
||||
|
||||
### API Overview
|
||||
|
||||
- `account/read` — fetch current account info; optionally refresh tokens.
|
||||
- `account/login/start` — begin login (`apiKey`, `chatgpt`, `chatgptDeviceCode`).
|
||||
- `account/login/start` — begin login (`apiKey`, `chatgpt`, `chatgptDeviceCode`, `amazonBedrock`).
|
||||
- `account/login/completed` (notify) — emitted when a login attempt finishes (success or error).
|
||||
- `account/login/cancel` — cancel a pending managed ChatGPT login by `loginId`.
|
||||
- `account/logout` — sign out; triggers `account/updated`.
|
||||
- `account/updated` (notify) — emitted whenever auth mode changes (`authMode`: `apikey`, `chatgpt`, `personalAccessToken`, or `null`) and includes the current ChatGPT `planType` when available.
|
||||
- `account/updated` (notify) — emitted whenever auth mode changes (`authMode`: `apikey`, `bedrockApiKey`, `chatgpt`, `personalAccessToken`, or `null`) and includes the current ChatGPT `planType` when available.
|
||||
- `account/rateLimits/read` — fetch ChatGPT rate limits, an optional effective monthly credit limit, and the earned rate-limit resets currently available, including expiry details when provided by the backend. Rate-limit updates arrive via `account/rateLimits/updated` (notify); reset-credit data is snapshot-only.
|
||||
- `account/rateLimitResetCredit/consume` — consume one earned reset using a caller-provided idempotency key, optionally selecting a reset-credit ID returned by `account/rateLimits/read`.
|
||||
- `account/usage/read` — fetch ChatGPT account token-activity summary and daily buckets.
|
||||
@@ -2006,6 +2007,30 @@ Field notes:
|
||||
{ "method": "account/updated", "params": { "authMode": "chatgpt", "planType": "plus" } }
|
||||
```
|
||||
|
||||
### 3) Log in with an Amazon Bedrock API key
|
||||
|
||||
This experimental flow requires the client to initialize with `experimentalApi: true`.
|
||||
|
||||
1. Send:
|
||||
```json
|
||||
{
|
||||
"method": "account/login/start",
|
||||
"id": 3,
|
||||
"params": { "type": "amazonBedrock", "apiKey": "…", "region": "us-west-2" }
|
||||
}
|
||||
```
|
||||
2. Expect:
|
||||
```json
|
||||
{ "id": 3, "result": { "type": "amazonBedrock" } }
|
||||
```
|
||||
3. Notifications:
|
||||
```json
|
||||
{ "method": "account/login/completed", "params": { "loginId": null, "success": true, "error": null } }
|
||||
{ "method": "account/updated", "params": { "authMode": "bedrockApiKey", "planType": null } }
|
||||
```
|
||||
|
||||
Codex stores the key and region as the primary Codex auth, replacing any previously stored login, and writes `model_provider = "amazon-bedrock"` to the active user config. Existing loaded sessions keep their current provider selection, so clients should restart the app-server before sending more model requests. This limitation will be addressed in a follow-up.
|
||||
|
||||
### 4) Log in with ChatGPT (device code flow)
|
||||
|
||||
1. Start:
|
||||
|
||||
@@ -293,6 +293,9 @@ impl AccountRequestProcessor {
|
||||
)
|
||||
.await;
|
||||
}
|
||||
LoginAccountParams::AmazonBedrock { .. } => {
|
||||
return Err(invalid_request("Amazon Bedrock login is not implemented"));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user