Skip to content

[codex] Support multiple forced ChatGPT workspaces#18161

Merged
rreichel3-oai merged 21 commits into
mainfrom
rreichel3/forced-chatgpt-workspace-id-list
May 14, 2026
Merged

[codex] Support multiple forced ChatGPT workspaces#18161
rreichel3-oai merged 21 commits into
mainfrom
rreichel3/forced-chatgpt-workspace-id-list

Conversation

@rreichel3-oai
Copy link
Copy Markdown
Contributor

@rreichel3-oai rreichel3-oai commented Apr 16, 2026

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
rreichel3-oai added a commit that referenced this pull request Apr 16, 2026
rreichel3-oai added a commit that referenced this pull request Apr 16, 2026
rreichel3-oai added a commit that referenced this pull request Apr 16, 2026
@rreichel3-oai rreichel3-oai force-pushed the rreichel3/forced-chatgpt-workspace-id-list branch from 6efb453 to 8b4867b Compare April 16, 2026 23:56
rreichel3-oai added a commit that referenced this pull request Apr 16, 2026
rreichel3-oai added a commit that referenced this pull request Apr 21, 2026
rreichel3-oai added a commit that referenced this pull request Apr 21, 2026
@rreichel3-oai rreichel3-oai force-pushed the rreichel3/forced-chatgpt-workspace-id-list branch from 9545da1 to d189b55 Compare April 21, 2026 15:06
rreichel3-oai added a commit that referenced this pull request Apr 22, 2026
rreichel3-oai added a commit that referenced this pull request Apr 22, 2026
@rreichel3-oai rreichel3-oai force-pushed the rreichel3/forced-chatgpt-workspace-id-list branch from de2e639 to fd71d7c Compare April 22, 2026 19:49
rreichel3-oai added a commit that referenced this pull request Apr 22, 2026
rreichel3-oai added a commit that referenced this pull request Apr 22, 2026
@rreichel3-oai rreichel3-oai force-pushed the rreichel3/forced-chatgpt-workspace-id-list branch from fd71d7c to e12d9db Compare April 22, 2026 19:50
rreichel3-oai added a commit that referenced this pull request May 4, 2026
rreichel3-oai added a commit that referenced this pull request May 4, 2026
@rreichel3-oai rreichel3-oai force-pushed the rreichel3/forced-chatgpt-workspace-id-list branch from e12d9db to 7c19791 Compare May 4, 2026 15:10
rreichel3-oai added a commit that referenced this pull request May 4, 2026
rreichel3-oai added a commit that referenced this pull request May 4, 2026
@rreichel3-oai rreichel3-oai force-pushed the rreichel3/forced-chatgpt-workspace-id-list branch from 5ae4cef to a2d466d Compare May 4, 2026 17:18
rreichel3-oai added a commit that referenced this pull request May 6, 2026
@rreichel3-oai rreichel3-oai force-pushed the rreichel3/forced-chatgpt-workspace-id-list branch from a2d466d to 12f6b43 Compare May 6, 2026 00:12
rreichel3-oai added a commit that referenced this pull request May 6, 2026
rreichel3-oai added a commit that referenced this pull request May 6, 2026
rreichel3-oai added a commit that referenced this pull request May 6, 2026
@rreichel3-oai rreichel3-oai force-pushed the rreichel3/forced-chatgpt-workspace-id-list branch 2 times, most recently from cd69a02 to 949782b Compare May 8, 2026 20:39
rreichel3-oai added a commit that referenced this pull request May 8, 2026
rreichel3-oai added a commit that referenced this pull request May 8, 2026
@owenlin0
Copy link
Copy Markdown
Collaborator

owenlin0 commented May 12, 2026

codex flagged this, mind taking a look? the rest looks good! nice catch on the agent identity thing

Potential regression: config/read looks like it can fail for existing configs that still use the legacy single-string shape.

Scenario:

  1. A user has forced_chatgpt_workspace_id = "ws_123" in config.toml. This branch still accepts that as ForcedChatgptWorkspaceIds::Single, so normal config loading works.
  2. ConfigManagerService::read loads the effective config into ConfigToml, then serializes it with serde_json::to_value(&effective_config_toml) and deserializes it into the v2 API Config.
  3. The untagged enum serializes the single form as JSON string: { "forced_chatgpt_workspace_id": "ws_123" }.
  4. The v2 API type now expects Option<Vec<String>>, so it expects { "forced_chatgpt_workspace_id": ["ws_123"] }.

That means config/read can return a deserialization error for an existing valid single-string config. The fix should normalize this field before the API round-trip, or use a compatibility conversion/type for the API config response.

@rreichel3-oai rreichel3-oai marked this pull request as ready for review May 12, 2026 21:39
@rreichel3-oai rreichel3-oai requested a review from a team as a code owner May 12, 2026 21:39
codex-rs/core/src/config/mod.rs: honor a debug-only CODEX_DISABLE_MANAGED_CONFIG env var in the main config loader so local interactive testing can ignore managed config and managed preferences outside app-server flows.
codex-rs/config/src/config_toml.rs: restore the backward-compatible ForcedChatgptWorkspaceIds enum that the rebased branch still references when parsing forced_chatgpt_workspace_id.
codex-rs/login/src/auth/auth_tests.rs: drop a stale auth-manager watcher test that no longer matches the main-branch API.

codex-rs/login/tests/suite/device_code_login.rs: pass the current ServerOptions::new streamlined-login argument.
codex-rs/login/tests/suite/login_server_e2e.rs: pass the current ServerOptions::new streamlined-login argument in the fallback-port test.
codex-rs/login/tests/suite/device_code_login.rs: keep ServerOptions::new aligned with the current four-argument constructor.
codex-rs/login/tests/suite/login_server_e2e.rs: add the streamlined-login field to the multi-workspace server options literal and remove a stale extra constructor argument.
codex-rs/login/src/server.rs: join forced ChatGPT workspace IDs into one comma-separated allowed_workspace_id query parameter for authapi compatibility.

codex-rs/login/tests/suite/login_server_e2e.rs: update the multi-workspace login-server regression test to assert exactly one allowed_workspace_id value.
codex-rs/config/src/config_toml.rs: add a custom forced_chatgpt_workspace_id deserializer that keeps single-string and list forms but rejects comma-separated strings with guidance to use a TOML list, plus focused parser tests.

codex-rs/core/config.schema.json: refresh the generated config schema description for the workspace allowlist shape.
Add app-server coverage for ChatGPT login URLs when config contains multiple forced workspaces.

Assert the interactive account/login/start response carries one comma-separated allowed_workspace_id query parameter, matching authapi's allowlist contract.
sdk/python/src/openai_codex/generated/v2_all.py: regenerate the v2 app-server client model after rebasing so forced_chatgpt_workspace_id matches the current schema.
Update enforced ChatGPT workspace checks so AgentIdentity credentials are compared against the configured workspace allowlist instead of skipping workspace enforcement.

Add a regression test for AgentIdentity credentials that belong to a disallowed workspace and verify the auth file is removed.
Normalize legacy single-string forced_chatgpt_workspace_id values before converting ConfigToml into the app-server v2 Config response.

Add config/read coverage for existing configs that still use the legacy single workspace string shape.
Update workspace allowlist and ChatGPT account test fixtures to use UUID-shaped IDs instead of org/ws/acct placeholders.

Refresh config TOML examples and app-server/login assertions to match the same ID shape.
Keep the PR rebased on current main without carrying the removed commit_attribution field from the old merge side of the conflict.
@rreichel3-oai rreichel3-oai force-pushed the rreichel3/forced-chatgpt-workspace-id-list branch from e2503f3 to d14a17b Compare May 13, 2026 21:06
Allow app-server config payloads to represent forced ChatGPT workspace IDs as either a single string or a string list.

Preserve legacy config/read string responses while accepting list configs, refresh generated app-server schemas, and cover both config shapes in tests.
Add runtime config coverage showing unset, empty string, whitespace string, empty list, and blank-only lists disable forced workspace restriction, while mixed lists keep trimmed valid workspace IDs.
@rreichel3-oai rreichel3-oai merged commit 02a7205 into main May 14, 2026
31 checks passed
@rreichel3-oai rreichel3-oai deleted the rreichel3/forced-chatgpt-workspace-id-list branch May 14, 2026 21:11
@github-actions github-actions Bot locked and limited conversation to collaborators May 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

2 participants