mirror of
https://github.com/openai/codex.git
synced 2026-11-02 16:20:35 +00:00
[codex] Support multiple forced ChatGPT workspaces (#18161)
## Summary This change lets `forced_chatgpt_workspace_id` accept multiple workspace IDs instead of a single value. It keeps the existing config key name, adds backward-compatible parsing for a single string in `config.toml`, and normalizes the setting into an allowed workspace list across login enforcement, app-server config surfaces, and local ChatGPT auth helpers. ## Why Workspace-restricted deployments may need to allow more than one ChatGPT workspace without dropping the guardrail entirely. ## Server-side impact Codex's local server and app-server protocol needed changes because they previously assumed a single workspace ID. The local login flow now matches the auth backend interface by sending the allowed workspace list as a single comma-separated `allowed_workspace_id` query parameter. ## Validation This was tested with: - A single workspace config - With multi-workspace configs - With multiple workspaces in the config - The user only being a part of a subset of them All were successful. Automated coverage: - `cargo test -p codex-login` - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-tui local_chatgpt_auth` - `cargo test --locked -p codex-app-server login_account_chatgpt_includes_forced_workspace_allowlist_query_param`
This commit is contained in:
1 parent
32b45a43e2
commit
02a7205250
22 files changed
+673
-117
No files matched your search
@@ -16,7 +16,7 @@ pub(crate) struct LocalChatgptAuth {
|
||||
pub(crate) fn load_local_chatgpt_auth(
|
||||
codex_home: &Path,
|
||||
auth_credentials_store_mode: AuthCredentialsStoreMode,
|
||||
forced_chatgpt_workspace_id: Option<&str>,
|
||||
forced_chatgpt_workspace_id: Option<&[String]>,
|
||||
) -> Result<LocalChatgptAuth, String> {
|
||||
let auth = load_auth_dot_json(codex_home, auth_credentials_store_mode)
|
||||
.map_err(|err| format!("failed to load local auth: {err}"))?
|
||||
@@ -33,11 +33,11 @@ pub(crate) fn load_local_chatgpt_auth(
|
||||
.account_id
|
||||
.or(tokens.id_token.chatgpt_account_id.clone())
|
||||
.ok_or_else(|| "local ChatGPT auth is missing chatgpt account id".to_string())?;
|
||||
if let Some(expected_workspace) = forced_chatgpt_workspace_id
|
||||
&& chatgpt_account_id != expected_workspace
|
||||
if let Some(expected_workspaces) = forced_chatgpt_workspace_id
|
||||
&& !expected_workspaces.contains(&chatgpt_account_id)
|
||||
{
|
||||
return Err(format!(
|
||||
"local ChatGPT auth must use workspace {expected_workspace}, but found {chatgpt_account_id:?}"
|
||||
"local ChatGPT auth must use one of workspace(s) {expected_workspaces:?}, but found {chatgpt_account_id:?}",
|
||||
));
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ mod tests {
|
||||
let auth = load_local_chatgpt_auth(
|
||||
codex_home.path(),
|
||||
AuthCredentialsStoreMode::File,
|
||||
Some("workspace-1"),
|
||||
Some(&["workspace-1".to_string()]),
|
||||
)
|
||||
.expect("chatgpt auth should load");
|
||||
|
||||
@@ -186,7 +186,7 @@ mod tests {
|
||||
let auth = load_local_chatgpt_auth(
|
||||
codex_home.path(),
|
||||
AuthCredentialsStoreMode::File,
|
||||
Some("workspace-1"),
|
||||
Some(&["workspace-1".to_string(), "workspace-2".to_string()]),
|
||||
)
|
||||
.expect("managed auth should win");
|
||||
|
||||
@@ -202,7 +202,7 @@ mod tests {
|
||||
let auth = load_local_chatgpt_auth(
|
||||
codex_home.path(),
|
||||
AuthCredentialsStoreMode::File,
|
||||
Some("workspace-1"),
|
||||
Some(&["workspace-1".to_string()]),
|
||||
)
|
||||
.expect("chatgpt auth should load");
|
||||
|
||||
|
||||
Reference in new issue
Block a user