diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 04c3525d2e..71ea5952a1 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -6666,6 +6666,13 @@ "AgentPath": { "type": "string" }, + "AllowDenyRequirement": { + "enum": [ + "allow", + "deny" + ], + "type": "string" + }, "AnalyticsConfig": { "additionalProperties": true, "properties": { @@ -7555,13 +7562,122 @@ }, "type": "object" }, + "BrowserUseAccessApprovalLifetime": { + "enum": [ + "turn", + "thread" + ], + "type": "string" + }, + "BrowserUseOriginPolicy": { + "properties": { + "access": { + "anyOf": [ + { + "$ref": "#/definitions/v2/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "accessApprovalLifetime": { + "anyOf": [ + { + "$ref": "#/definitions/v2/BrowserUseAccessApprovalLifetime" + }, + { + "type": "null" + } + ] + }, + "autoReview": { + "anyOf": [ + { + "$ref": "#/definitions/v2/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "downloads": { + "anyOf": [ + { + "$ref": "#/definitions/v2/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "fullCdpAccess": { + "anyOf": [ + { + "$ref": "#/definitions/v2/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "persistentApproval": { + "type": [ + "boolean", + "null" + ] + }, + "uploads": { + "anyOf": [ + { + "$ref": "#/definitions/v2/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, "BrowserUseRequirements": { "properties": { + "allowGlobalPersistentApproval": { + "type": [ + "boolean", + "null" + ] + }, + "allowHistoryAccess": { + "type": [ + "boolean", + "null" + ] + }, + "defaultOriginPolicy": { + "anyOf": [ + { + "$ref": "#/definitions/v2/BrowserUseOriginPolicy" + }, + { + "type": "null" + } + ] + }, "disableAutoReview": { "type": [ "boolean", "null" ] + }, + "origins": { + "additionalProperties": { + "$ref": "#/definitions/v2/BrowserUseOriginPolicy" + }, + "type": [ + "object", + "null" + ] } }, "type": "object" @@ -8365,6 +8481,20 @@ ], "type": "object" }, + "ComputerUseMacosRequirements": { + "properties": { + "bundleIds": { + "additionalProperties": { + "$ref": "#/definitions/v2/AllowDenyRequirement" + }, + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + }, "ComputerUseRequirements": { "properties": { "allowLockedComputerUse": { @@ -8372,6 +8502,90 @@ "boolean", "null" ] + }, + "allowPersistentApproval": { + "type": [ + "boolean", + "null" + ] + }, + "defaultAppAccess": { + "anyOf": [ + { + "$ref": "#/definitions/v2/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "macos": { + "anyOf": [ + { + "$ref": "#/definitions/v2/ComputerUseMacosRequirements" + }, + { + "type": "null" + } + ] + }, + "windows": { + "anyOf": [ + { + "$ref": "#/definitions/v2/ComputerUseWindowsRequirements" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + "ComputerUseWindowsExeRequirement": { + "properties": { + "access": { + "$ref": "#/definitions/v2/AllowDenyRequirement" + }, + "binaryName": { + "type": [ + "string", + "null" + ] + }, + "productName": { + "type": "string" + }, + "publisherName": { + "type": "string" + } + }, + "required": [ + "access", + "productName", + "publisherName" + ], + "type": "object" + }, + "ComputerUseWindowsRequirements": { + "properties": { + "aumids": { + "additionalProperties": { + "$ref": "#/definitions/v2/AllowDenyRequirement" + }, + "type": [ + "object", + "null" + ] + }, + "exes": { + "items": { + "$ref": "#/definitions/v2/ComputerUseWindowsExeRequirement" + }, + "type": [ + "array", + "null" + ] } }, "type": "object" @@ -8940,6 +9154,12 @@ "null" ] }, + "allowBrowserAndComputerUse": { + "type": [ + "boolean", + "null" + ] + }, "allowLoginShell": { "type": [ "boolean", diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index 6542337a86..08a4feba99 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -391,6 +391,13 @@ "AgentPath": { "type": "string" }, + "AllowDenyRequirement": { + "enum": [ + "allow", + "deny" + ], + "type": "string" + }, "AnalyticsConfig": { "additionalProperties": true, "properties": { @@ -1280,13 +1287,122 @@ }, "type": "object" }, + "BrowserUseAccessApprovalLifetime": { + "enum": [ + "turn", + "thread" + ], + "type": "string" + }, + "BrowserUseOriginPolicy": { + "properties": { + "access": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "accessApprovalLifetime": { + "anyOf": [ + { + "$ref": "#/definitions/BrowserUseAccessApprovalLifetime" + }, + { + "type": "null" + } + ] + }, + "autoReview": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "downloads": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "fullCdpAccess": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "persistentApproval": { + "type": [ + "boolean", + "null" + ] + }, + "uploads": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, "BrowserUseRequirements": { "properties": { + "allowGlobalPersistentApproval": { + "type": [ + "boolean", + "null" + ] + }, + "allowHistoryAccess": { + "type": [ + "boolean", + "null" + ] + }, + "defaultOriginPolicy": { + "anyOf": [ + { + "$ref": "#/definitions/BrowserUseOriginPolicy" + }, + { + "type": "null" + } + ] + }, "disableAutoReview": { "type": [ "boolean", "null" ] + }, + "origins": { + "additionalProperties": { + "$ref": "#/definitions/BrowserUseOriginPolicy" + }, + "type": [ + "object", + "null" + ] } }, "type": "object" @@ -4403,6 +4519,20 @@ ], "type": "object" }, + "ComputerUseMacosRequirements": { + "properties": { + "bundleIds": { + "additionalProperties": { + "$ref": "#/definitions/AllowDenyRequirement" + }, + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + }, "ComputerUseRequirements": { "properties": { "allowLockedComputerUse": { @@ -4410,6 +4540,90 @@ "boolean", "null" ] + }, + "allowPersistentApproval": { + "type": [ + "boolean", + "null" + ] + }, + "defaultAppAccess": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "macos": { + "anyOf": [ + { + "$ref": "#/definitions/ComputerUseMacosRequirements" + }, + { + "type": "null" + } + ] + }, + "windows": { + "anyOf": [ + { + "$ref": "#/definitions/ComputerUseWindowsRequirements" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + "ComputerUseWindowsExeRequirement": { + "properties": { + "access": { + "$ref": "#/definitions/AllowDenyRequirement" + }, + "binaryName": { + "type": [ + "string", + "null" + ] + }, + "productName": { + "type": "string" + }, + "publisherName": { + "type": "string" + } + }, + "required": [ + "access", + "productName", + "publisherName" + ], + "type": "object" + }, + "ComputerUseWindowsRequirements": { + "properties": { + "aumids": { + "additionalProperties": { + "$ref": "#/definitions/AllowDenyRequirement" + }, + "type": [ + "object", + "null" + ] + }, + "exes": { + "items": { + "$ref": "#/definitions/ComputerUseWindowsExeRequirement" + }, + "type": [ + "array", + "null" + ] } }, "type": "object" @@ -4978,6 +5192,12 @@ "null" ] }, + "allowBrowserAndComputerUse": { + "type": [ + "boolean", + "null" + ] + }, "allowLoginShell": { "type": [ "boolean", diff --git a/codex-rs/app-server-protocol/schema/json/v2/ConfigRequirementsReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ConfigRequirementsReadResponse.json index aef399e799..b19e72c0db 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ConfigRequirementsReadResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ConfigRequirementsReadResponse.json @@ -1,6 +1,13 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { + "AllowDenyRequirement": { + "enum": [ + "allow", + "deny" + ], + "type": "string" + }, "ApprovalsReviewer": { "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ @@ -82,13 +89,122 @@ }, "type": "object" }, + "BrowserUseAccessApprovalLifetime": { + "enum": [ + "turn", + "thread" + ], + "type": "string" + }, + "BrowserUseOriginPolicy": { + "properties": { + "access": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "accessApprovalLifetime": { + "anyOf": [ + { + "$ref": "#/definitions/BrowserUseAccessApprovalLifetime" + }, + { + "type": "null" + } + ] + }, + "autoReview": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "downloads": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "fullCdpAccess": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "persistentApproval": { + "type": [ + "boolean", + "null" + ] + }, + "uploads": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, "BrowserUseRequirements": { "properties": { + "allowGlobalPersistentApproval": { + "type": [ + "boolean", + "null" + ] + }, + "allowHistoryAccess": { + "type": [ + "boolean", + "null" + ] + }, + "defaultOriginPolicy": { + "anyOf": [ + { + "$ref": "#/definitions/BrowserUseOriginPolicy" + }, + { + "type": "null" + } + ] + }, "disableAutoReview": { "type": [ "boolean", "null" ] + }, + "origins": { + "additionalProperties": { + "$ref": "#/definitions/BrowserUseOriginPolicy" + }, + "type": [ + "object", + "null" + ] } }, "type": "object" @@ -102,6 +218,20 @@ ], "type": "string" }, + "ComputerUseMacosRequirements": { + "properties": { + "bundleIds": { + "additionalProperties": { + "$ref": "#/definitions/AllowDenyRequirement" + }, + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + }, "ComputerUseRequirements": { "properties": { "allowLockedComputerUse": { @@ -109,6 +239,90 @@ "boolean", "null" ] + }, + "allowPersistentApproval": { + "type": [ + "boolean", + "null" + ] + }, + "defaultAppAccess": { + "anyOf": [ + { + "$ref": "#/definitions/AllowDenyRequirement" + }, + { + "type": "null" + } + ] + }, + "macos": { + "anyOf": [ + { + "$ref": "#/definitions/ComputerUseMacosRequirements" + }, + { + "type": "null" + } + ] + }, + "windows": { + "anyOf": [ + { + "$ref": "#/definitions/ComputerUseWindowsRequirements" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + "ComputerUseWindowsExeRequirement": { + "properties": { + "access": { + "$ref": "#/definitions/AllowDenyRequirement" + }, + "binaryName": { + "type": [ + "string", + "null" + ] + }, + "productName": { + "type": "string" + }, + "publisherName": { + "type": "string" + } + }, + "required": [ + "access", + "productName", + "publisherName" + ], + "type": "object" + }, + "ComputerUseWindowsRequirements": { + "properties": { + "aumids": { + "additionalProperties": { + "$ref": "#/definitions/AllowDenyRequirement" + }, + "type": [ + "object", + "null" + ] + }, + "exes": { + "items": { + "$ref": "#/definitions/ComputerUseWindowsExeRequirement" + }, + "type": [ + "array", + "null" + ] } }, "type": "object" @@ -127,6 +341,12 @@ "null" ] }, + "allowBrowserAndComputerUse": { + "type": [ + "boolean", + "null" + ] + }, "allowLoginShell": { "type": [ "boolean", diff --git a/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-experimental.json.zst b/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-experimental.json.zst index a845b52144..f51d0612a2 100644 Binary files a/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-experimental.json.zst and b/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-experimental.json.zst differ diff --git a/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-stable.json.zst b/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-stable.json.zst index 9e20374641..97e4418b46 100644 Binary files a/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-stable.json.zst and b/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-stable.json.zst differ diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/AllowDenyRequirement.ts b/codex-rs/app-server-protocol/schema/typescript/v2/AllowDenyRequirement.ts new file mode 100644 index 0000000000..ec13796831 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/AllowDenyRequirement.ts @@ -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 AllowDenyRequirement = "allow" | "deny"; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/BrowserUseAccessApprovalLifetime.ts b/codex-rs/app-server-protocol/schema/typescript/v2/BrowserUseAccessApprovalLifetime.ts new file mode 100644 index 0000000000..f86b59ef29 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/BrowserUseAccessApprovalLifetime.ts @@ -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 BrowserUseAccessApprovalLifetime = "turn" | "thread"; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/BrowserUseOriginPolicy.ts b/codex-rs/app-server-protocol/schema/typescript/v2/BrowserUseOriginPolicy.ts new file mode 100644 index 0000000000..117330d05c --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/BrowserUseOriginPolicy.ts @@ -0,0 +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 { AllowDenyRequirement } from "./AllowDenyRequirement"; +import type { BrowserUseAccessApprovalLifetime } from "./BrowserUseAccessApprovalLifetime"; + +export type BrowserUseOriginPolicy = { access: AllowDenyRequirement | null, downloads: AllowDenyRequirement | null, uploads: AllowDenyRequirement | null, fullCdpAccess: AllowDenyRequirement | null, autoReview: AllowDenyRequirement | null, persistentApproval: boolean | null, accessApprovalLifetime: BrowserUseAccessApprovalLifetime | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/BrowserUseRequirements.ts b/codex-rs/app-server-protocol/schema/typescript/v2/BrowserUseRequirements.ts index 397532d61e..894caa95ce 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/BrowserUseRequirements.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/BrowserUseRequirements.ts @@ -1,5 +1,6 @@ // 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 { BrowserUseOriginPolicy } from "./BrowserUseOriginPolicy"; -export type BrowserUseRequirements = { disableAutoReview: boolean | null, }; +export type BrowserUseRequirements = { allowHistoryAccess: boolean | null, disableAutoReview: boolean | null, allowGlobalPersistentApproval: boolean | null, defaultOriginPolicy: BrowserUseOriginPolicy | null, origins: { [key in string]?: BrowserUseOriginPolicy } | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseMacosRequirements.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseMacosRequirements.ts new file mode 100644 index 0000000000..e5577ae07b --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseMacosRequirements.ts @@ -0,0 +1,6 @@ +// 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 { AllowDenyRequirement } from "./AllowDenyRequirement"; + +export type ComputerUseMacosRequirements = { bundleIds: { [key in string]?: AllowDenyRequirement } | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseRequirements.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseRequirements.ts index 7a82e7aec8..f0894b1d70 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseRequirements.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseRequirements.ts @@ -1,5 +1,8 @@ // 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 { AllowDenyRequirement } from "./AllowDenyRequirement"; +import type { ComputerUseMacosRequirements } from "./ComputerUseMacosRequirements"; +import type { ComputerUseWindowsRequirements } from "./ComputerUseWindowsRequirements"; -export type ComputerUseRequirements = { allowLockedComputerUse: boolean | null, }; +export type ComputerUseRequirements = { allowLockedComputerUse: boolean | null, allowPersistentApproval: boolean | null, defaultAppAccess: AllowDenyRequirement | null, macos: ComputerUseMacosRequirements | null, windows: ComputerUseWindowsRequirements | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseWindowsExeRequirement.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseWindowsExeRequirement.ts new file mode 100644 index 0000000000..e7fa076023 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseWindowsExeRequirement.ts @@ -0,0 +1,6 @@ +// 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 { AllowDenyRequirement } from "./AllowDenyRequirement"; + +export type ComputerUseWindowsExeRequirement = { publisherName: string, productName: string, binaryName: string | null, access: AllowDenyRequirement, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseWindowsRequirements.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseWindowsRequirements.ts new file mode 100644 index 0000000000..1f9f42e34f --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ComputerUseWindowsRequirements.ts @@ -0,0 +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 { AllowDenyRequirement } from "./AllowDenyRequirement"; +import type { ComputerUseWindowsExeRequirement } from "./ComputerUseWindowsExeRequirement"; + +export type ComputerUseWindowsRequirements = { aumids: { [key in string]?: AllowDenyRequirement } | null, exes: Array | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ConfigRequirements.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ConfigRequirements.ts index badb7db303..12be715d1f 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ConfigRequirements.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ConfigRequirements.ts @@ -15,4 +15,4 @@ import type { ResidencyRequirement } from "./ResidencyRequirement"; import type { SandboxMode } from "./SandboxMode"; import type { WindowsSandboxSetupMode } from "./WindowsSandboxSetupMode"; -export type ConfigRequirements = {cliAuthCredentialsStore: CliAuthCredentialsStoreMode | null, chatgptBaseUrl: string | null, additionalDeveloperInstructions: string | null, allowedApprovalPolicies: Array | null, allowedSandboxModes: Array | null, allowedWindowsSandboxImplementations: Array | null, allowedPermissionProfiles: { [key in string]?: boolean } | null, defaultPermissions: string | null, allowedWebSearchModes: Array | null, allowManagedHooksOnly: boolean | null, allowAppshots: boolean | null, allowRemoteControl: boolean | null, computerUse: ComputerUseRequirements | null, browserUse: BrowserUseRequirements | null, inAppBrowser: InAppBrowserRequirements | null, featureRequirements: { [key in string]?: boolean } | null, enforceResidency: ResidencyRequirement | null, autoReview: AutoReviewRequirements | null, models: ModelsRequirements | null, sqliteHome: PathUri | null, logDir: PathUri | null, modelCatalogJson: PathUri | null, checkForUpdateOnStartup: boolean | null, allowLoginShell: boolean | null, feedback: FeedbackRequirements | null, windowsSandboxPrivateDesktop: boolean | null}; +export type ConfigRequirements = {cliAuthCredentialsStore: CliAuthCredentialsStoreMode | null, chatgptBaseUrl: string | null, additionalDeveloperInstructions: string | null, allowedApprovalPolicies: Array | null, allowedSandboxModes: Array | null, allowedWindowsSandboxImplementations: Array | null, allowedPermissionProfiles: { [key in string]?: boolean } | null, defaultPermissions: string | null, allowedWebSearchModes: Array | null, allowManagedHooksOnly: boolean | null, allowBrowserAndComputerUse: boolean | null, allowAppshots: boolean | null, allowRemoteControl: boolean | null, computerUse: ComputerUseRequirements | null, browserUse: BrowserUseRequirements | null, inAppBrowser: InAppBrowserRequirements | null, featureRequirements: { [key in string]?: boolean } | null, enforceResidency: ResidencyRequirement | null, autoReview: AutoReviewRequirements | null, models: ModelsRequirements | null, sqliteHome: PathUri | null, logDir: PathUri | null, modelCatalogJson: PathUri | null, checkForUpdateOnStartup: boolean | null, allowLoginShell: boolean | null, feedback: FeedbackRequirements | null, windowsSandboxPrivateDesktop: boolean | null}; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/index.ts b/codex-rs/app-server-protocol/schema/typescript/v2/index.ts index 3013132f43..171d661412 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/index.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/index.ts @@ -16,6 +16,7 @@ export type { AdditionalNetworkPermissions } from "./AdditionalNetworkPermission export type { AdditionalPermissionProfile } from "./AdditionalPermissionProfile"; export type { AgentMessageDelivery } from "./AgentMessageDelivery"; export type { AgentMessageDeltaNotification } from "./AgentMessageDeltaNotification"; +export type { AllowDenyRequirement } from "./AllowDenyRequirement"; export type { AnalyticsConfig } from "./AnalyticsConfig"; export type { AppBranding } from "./AppBranding"; export type { AppInfo } from "./AppInfo"; @@ -43,6 +44,8 @@ export type { AttestationGenerateParams } from "./AttestationGenerateParams"; export type { AttestationGenerateResponse } from "./AttestationGenerateResponse"; export type { AutoReviewDecisionSource } from "./AutoReviewDecisionSource"; export type { AutoReviewRequirements } from "./AutoReviewRequirements"; +export type { BrowserUseAccessApprovalLifetime } from "./BrowserUseAccessApprovalLifetime"; +export type { BrowserUseOriginPolicy } from "./BrowserUseOriginPolicy"; export type { BrowserUseRequirements } from "./BrowserUseRequirements"; export type { ByteRange } from "./ByteRange"; export type { CancelLoginAccountParams } from "./CancelLoginAccountParams"; @@ -78,7 +81,10 @@ export type { CommandExecutionRequestApprovalResponse } from "./CommandExecution export type { CommandExecutionSource } from "./CommandExecutionSource"; export type { CommandExecutionStatus } from "./CommandExecutionStatus"; export type { CommandMigration } from "./CommandMigration"; +export type { ComputerUseMacosRequirements } from "./ComputerUseMacosRequirements"; export type { ComputerUseRequirements } from "./ComputerUseRequirements"; +export type { ComputerUseWindowsExeRequirement } from "./ComputerUseWindowsExeRequirement"; +export type { ComputerUseWindowsRequirements } from "./ComputerUseWindowsRequirements"; export type { Config } from "./Config"; export type { ConfigBatchWriteParams } from "./ConfigBatchWriteParams"; export type { ConfigEdit } from "./ConfigEdit"; diff --git a/codex-rs/app-server-protocol/src/protocol/v2/config.rs b/codex-rs/app-server-protocol/src/protocol/v2/config.rs index f6c1777627..9c4b45774e 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/config.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/config.rs @@ -396,6 +396,7 @@ pub struct ConfigRequirements { pub default_permissions: Option, pub allowed_web_search_modes: Option>, pub allow_managed_hooks_only: Option, + pub allow_browser_and_computer_use: Option, pub allow_appshots: Option, pub allow_remote_control: Option, pub computer_use: Option, @@ -467,13 +468,75 @@ pub struct FeedbackRequirements { #[ts(export_to = "v2/")] pub struct ComputerUseRequirements { pub allow_locked_computer_use: Option, + pub allow_persistent_approval: Option, + pub default_app_access: Option, + pub macos: Option, + pub windows: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct BrowserUseRequirements { + pub allow_history_access: Option, pub disable_auto_review: Option, + pub allow_global_persistent_approval: Option, + pub default_origin_policy: Option, + pub origins: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct BrowserUseOriginPolicy { + pub access: Option, + pub downloads: Option, + pub uploads: Option, + pub full_cdp_access: Option, + pub auto_review: Option, + pub persistent_approval: Option, + pub access_approval_lifetime: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "lowercase")] +#[ts(rename_all = "lowercase", export_to = "v2/")] +pub enum AllowDenyRequirement { + Allow, + Deny, +} + +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "lowercase")] +#[ts(rename_all = "lowercase", export_to = "v2/")] +pub enum BrowserUseAccessApprovalLifetime { + Turn, + Thread, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct ComputerUseMacosRequirements { + pub bundle_ids: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct ComputerUseWindowsRequirements { + pub aumids: Option>, + pub exes: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct ComputerUseWindowsExeRequirement { + pub publisher_name: String, + pub product_name: String, + pub binary_name: Option, + pub access: AllowDenyRequirement, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] diff --git a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs index 2db87b4fef..c71f65cbc2 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs @@ -2057,6 +2057,7 @@ fn config_requirements_granular_allowed_approval_policy_is_marked_experimental() default_permissions: None, allowed_web_search_modes: None, allow_managed_hooks_only: None, + allow_browser_and_computer_use: None, allow_appshots: None, allow_remote_control: None, computer_use: None, diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md index 92e83d1309..f8cfbf1cc0 100644 --- a/codex-rs/app-server/README.md +++ b/codex-rs/app-server/README.md @@ -290,7 +290,7 @@ Example with notification opt-out: - `externalAgentConfig/import/readHistories` — read completed import histories and connector candidates detected from successfully imported session histories. Successful session entries include the original imported title when one was available. Connector candidates include a normalized display `name`, the number of imported sessions that used the connector, and the source metadata field used for detection. - `config/value/write` — write a single config key/value to the user's config.toml on disk; dotted paths such as `desktop.someKey` use the same generic write surface. Writes that overlap a managed requirement are rejected with `configRequirementReadonly`. - `config/batchWrite` — apply multiple config edits atomically to the user's config.toml on disk, with optional `reloadUserConfig: true` to hot-reload loaded threads, including multiple `desktop.*` edits. Session-static model, reasoning-effort, Plan-mode reasoning-effort, service-tier, and personality defaults do not reload existing threads. -- `configRequirements/read` — fetch loaded requirements constraints from `requirements.toml` and/or MDM (or `null` if none are configured), including exact managed values (`cliAuthCredentialsStore`, `chatgptBaseUrl`, `sqliteHome`, `logDir`, `modelCatalogJson`, `checkForUpdateOnStartup`, `allowLoginShell`, `feedback.enabled`, and `windowsSandboxPrivateDesktop`), requirements-only developer instructions (`additionalDeveloperInstructions`, supplied independently of ordinary developer instructions), allow-lists (`allowedApprovalPolicies`, `allowedSandboxModes`, `allowedWebSearchModes`), the layered permission-profile allow map (`allowedPermissionProfiles`), the managed permission-profile default (`defaultPermissions`), lifecycle hook lockdown (`allowManagedHooksOnly`), remote-control policy (`allowRemoteControl`; `false` force-disables remote control while `true` or `null` preserves existing behavior), computer use policy (`computerUse`), Browser Use policy (`browserUse.disableAutoReview`), interactive browser import policy (`inAppBrowser.allowExternalBrowserSettingsImport`), pinned feature values (`featureRequirements`, including the default-allowed `in_app_updates` policy that administrators can set to `false`), managed lifecycle hooks (`hooks`, including command handlers with optional `additionalContextLimit` and `mcp_tool` handlers with `server`, `tool`, `input`, `timeoutSec`, and `statusMessage`), `enforceResidency`, managed automatic review (`autoReview.requiredOnModels` and `autoReview.ignoreRules`), model defaults (`models.newThread.model`, `models.newThread.modelReasoningEffort`, and `models.newThread.serviceTier`), and `network` constraints such as canonical domain/socket permissions plus `managedAllowedDomainsOnly` and `dangerFullAccessDenylistOnly`. +- `configRequirements/read` — fetch loaded requirements constraints from `requirements.toml` and/or MDM (or `null` if none are configured), including exact managed values (`cliAuthCredentialsStore`, `chatgptBaseUrl`, `sqliteHome`, `logDir`, `modelCatalogJson`, `checkForUpdateOnStartup`, `allowLoginShell`, `feedback.enabled`, and `windowsSandboxPrivateDesktop`), requirements-only developer instructions (`additionalDeveloperInstructions`, supplied independently of ordinary developer instructions), allow-lists (`allowedApprovalPolicies`, `allowedSandboxModes`, `allowedWebSearchModes`), the layered permission-profile allow map (`allowedPermissionProfiles`), the managed permission-profile default (`defaultPermissions`), lifecycle hook lockdown (`allowManagedHooksOnly`), remote-control policy (`allowRemoteControl`; `false` force-disables remote control while `true` or `null` preserves existing behavior), the Browser/Computer Use umbrella policy (`allowBrowserAndComputerUse`), computer use policy (`computerUse`, including persistent approval, default application access, and per-platform application rules), Browser Use policy (`browserUse`, including history access, origin rules, auto-review, and approval controls), interactive browser import policy (`inAppBrowser.allowExternalBrowserSettingsImport`), pinned feature values (`featureRequirements`, including the default-allowed `in_app_updates` policy that administrators can set to `false`), managed lifecycle hooks (`hooks`, including command handlers with optional `additionalContextLimit` and `mcp_tool` handlers with `server`, `tool`, `input`, `timeoutSec`, and `statusMessage`), `enforceResidency`, managed automatic review (`autoReview.requiredOnModels` and `autoReview.ignoreRules`), model defaults (`models.newThread.model`, `models.newThread.modelReasoningEffort`, and `models.newThread.serviceTier`), and `network` constraints such as canonical domain/socket permissions plus `managedAllowedDomainsOnly` and `dangerFullAccessDenylistOnly`. ### Example: Start or resume a thread diff --git a/codex-rs/app-server/src/request_processors/config_processor.rs b/codex-rs/app-server/src/request_processors/config_processor.rs index 25e730e064..88b0ce098f 100644 --- a/codex-rs/app-server/src/request_processors/config_processor.rs +++ b/codex-rs/app-server/src/request_processors/config_processor.rs @@ -7,11 +7,17 @@ use crate::error_code::invalid_request; use crate::outgoing_message::ConnectionRequestId; use crate::outgoing_message::OutgoingMessageSender; use codex_analytics::AnalyticsEventsClient; +use codex_app_server_protocol::AllowDenyRequirement; use codex_app_server_protocol::AutoReviewRequirements; +use codex_app_server_protocol::BrowserUseAccessApprovalLifetime; +use codex_app_server_protocol::BrowserUseOriginPolicy; use codex_app_server_protocol::BrowserUseRequirements; use codex_app_server_protocol::CliAuthCredentialsStoreMode; use codex_app_server_protocol::ClientResponsePayload; +use codex_app_server_protocol::ComputerUseMacosRequirements; use codex_app_server_protocol::ComputerUseRequirements; +use codex_app_server_protocol::ComputerUseWindowsExeRequirement; +use codex_app_server_protocol::ComputerUseWindowsRequirements; use codex_app_server_protocol::ConfigBatchWriteParams; use codex_app_server_protocol::ConfigReadParams; use codex_app_server_protocol::ConfigReadResponse; @@ -420,6 +426,7 @@ fn map_requirements_toml_to_api(requirements: ConfigRequirementsToml) -> ConfigR normalized }), allow_managed_hooks_only: requirements.allow_managed_hooks_only, + allow_browser_and_computer_use: requirements.allow_browser_and_computer_use, allow_appshots: requirements.allow_appshots, allow_remote_control: requirements.allow_remote_control, computer_use: requirements @@ -472,6 +479,44 @@ fn map_computer_use_requirements_to_api( ) -> ComputerUseRequirements { ComputerUseRequirements { allow_locked_computer_use: computer_use.allow_locked_computer_use, + allow_persistent_approval: computer_use.allow_persistent_approval, + default_app_access: computer_use + .default_app_access + .map(map_allow_deny_requirement_to_api), + macos: computer_use + .macos + .map(|macos| ComputerUseMacosRequirements { + bundle_ids: macos.bundle_ids.map(|bundle_ids| { + bundle_ids + .into_iter() + .map(|(bundle_id, requirement)| { + (bundle_id, map_allow_deny_requirement_to_api(requirement)) + }) + .collect() + }), + }), + windows: computer_use + .windows + .map(|windows| ComputerUseWindowsRequirements { + aumids: windows.aumids.map(|aumids| { + aumids + .into_iter() + .map(|(aumid, requirement)| { + (aumid, map_allow_deny_requirement_to_api(requirement)) + }) + .collect() + }), + exes: windows.exes.map(|exes| { + exes.into_iter() + .map(|exe| ComputerUseWindowsExeRequirement { + publisher_name: exe.publisher_name, + product_name: exe.product_name, + binary_name: exe.binary_name, + access: map_allow_deny_requirement_to_api(exe.access), + }) + .collect() + }), + }), } } @@ -479,7 +524,58 @@ fn map_browser_use_requirements_to_api( browser_use: codex_config::BrowserUseRequirementsToml, ) -> BrowserUseRequirements { BrowserUseRequirements { + allow_history_access: browser_use.allow_history_access, disable_auto_review: browser_use.disable_auto_review, + allow_global_persistent_approval: browser_use.allow_global_persistent_approval, + default_origin_policy: browser_use + .default_origin_policy + .map(map_browser_use_origin_policy_to_api), + origins: browser_use.origins.map(|origins| { + origins + .into_iter() + .map(|(pattern, policy)| (pattern, map_browser_use_origin_policy_to_api(policy))) + .collect() + }), + } +} + +fn map_browser_use_origin_policy_to_api( + policy: codex_config::BrowserUseOriginPolicyToml, +) -> BrowserUseOriginPolicy { + BrowserUseOriginPolicy { + access: policy.access.map(map_allow_deny_requirement_to_api), + downloads: policy.downloads.map(map_allow_deny_requirement_to_api), + uploads: policy.uploads.map(map_allow_deny_requirement_to_api), + full_cdp_access: policy + .full_cdp_access + .map(map_allow_deny_requirement_to_api), + auto_review: policy.auto_review.map(map_allow_deny_requirement_to_api), + persistent_approval: policy.persistent_approval, + access_approval_lifetime: policy + .access_approval_lifetime + .map(map_browser_use_access_approval_lifetime_to_api), + } +} + +fn map_allow_deny_requirement_to_api( + requirement: codex_config::AllowDenyRequirementToml, +) -> AllowDenyRequirement { + match requirement { + codex_config::AllowDenyRequirementToml::Allow => AllowDenyRequirement::Allow, + codex_config::AllowDenyRequirementToml::Deny => AllowDenyRequirement::Deny, + } +} + +fn map_browser_use_access_approval_lifetime_to_api( + lifetime: codex_config::BrowserUseAccessApprovalLifetimeToml, +) -> BrowserUseAccessApprovalLifetime { + match lifetime { + codex_config::BrowserUseAccessApprovalLifetimeToml::Turn => { + BrowserUseAccessApprovalLifetime::Turn + } + codex_config::BrowserUseAccessApprovalLifetimeToml::Thread => { + BrowserUseAccessApprovalLifetime::Thread + } } } @@ -679,11 +775,26 @@ fn config_write_error(code: ConfigWriteErrorCode, message: impl Into) -> #[cfg(test)] mod tests { use super::map_requirements_toml_to_api; + use codex_app_server_protocol::AllowDenyRequirement; use codex_app_server_protocol::AutoReviewRequirements; + use codex_app_server_protocol::BrowserUseAccessApprovalLifetime; + use codex_app_server_protocol::BrowserUseOriginPolicy; + use codex_app_server_protocol::BrowserUseRequirements; + use codex_app_server_protocol::ComputerUseMacosRequirements; + use codex_app_server_protocol::ComputerUseRequirements; + use codex_app_server_protocol::ComputerUseWindowsExeRequirement; + use codex_app_server_protocol::ComputerUseWindowsRequirements; use codex_app_server_protocol::FeedbackRequirements; use codex_app_server_protocol::WindowsSandboxSetupMode; + use codex_config::AllowDenyRequirementToml; use codex_config::AutoReviewRequirementsToml; + use codex_config::BrowserUseAccessApprovalLifetimeToml; + use codex_config::BrowserUseOriginPolicyToml; + use codex_config::BrowserUseRequirementsToml; + use codex_config::ComputerUseMacosRequirementsToml; use codex_config::ComputerUseRequirementsToml; + use codex_config::ComputerUseWindowsExeRequirementToml; + use codex_config::ComputerUseWindowsRequirementsToml; use codex_config::ConfigRequirementsToml; use codex_config::ModelsRequirementsToml; use codex_config::NewThreadModelDefaultsToml; @@ -786,20 +897,118 @@ mod tests { } #[test] - fn requirements_api_includes_computer_use_requirements() { + fn requirements_api_includes_browser_and_computer_use_requirements() { let mapped = map_requirements_toml_to_api(ConfigRequirementsToml { + allow_browser_and_computer_use: Some(false), + browser_use: Some(BrowserUseRequirementsToml { + allow_history_access: Some(false), + disable_auto_review: Some(true), + allow_global_persistent_approval: Some(false), + default_origin_policy: Some(BrowserUseOriginPolicyToml { + access: Some(AllowDenyRequirementToml::Deny), + downloads: Some(AllowDenyRequirementToml::Allow), + uploads: Some(AllowDenyRequirementToml::Deny), + full_cdp_access: Some(AllowDenyRequirementToml::Allow), + auto_review: Some(AllowDenyRequirementToml::Deny), + persistent_approval: Some(false), + access_approval_lifetime: Some(BrowserUseAccessApprovalLifetimeToml::Turn), + }), + origins: Some(BTreeMap::from([( + "https://example.com".to_string(), + BrowserUseOriginPolicyToml { + access: Some(AllowDenyRequirementToml::Allow), + downloads: Some(AllowDenyRequirementToml::Deny), + uploads: Some(AllowDenyRequirementToml::Allow), + full_cdp_access: Some(AllowDenyRequirementToml::Deny), + auto_review: Some(AllowDenyRequirementToml::Deny), + persistent_approval: Some(true), + access_approval_lifetime: Some( + BrowserUseAccessApprovalLifetimeToml::Thread, + ), + }, + )])), + }), computer_use: Some(ComputerUseRequirementsToml { allow_locked_computer_use: Some(false), - ..ComputerUseRequirementsToml::default() + allow_persistent_approval: Some(false), + default_app_access: Some(AllowDenyRequirementToml::Deny), + macos: Some(ComputerUseMacosRequirementsToml { + bundle_ids: Some(BTreeMap::from([( + "com.apple.Safari".to_string(), + AllowDenyRequirementToml::Allow, + )])), + }), + windows: Some(ComputerUseWindowsRequirementsToml { + aumids: Some(BTreeMap::from([( + "Microsoft.Paint_8wekyb3d8bbwe!App".to_string(), + AllowDenyRequirementToml::Allow, + )])), + exes: Some(vec![ComputerUseWindowsExeRequirementToml { + publisher_name: "CN=Google LLC".to_string(), + product_name: "Google Chrome".to_string(), + binary_name: Some("chrome.exe".to_string()), + access: AllowDenyRequirementToml::Deny, + }]), + }), }), ..ConfigRequirementsToml::default() }); + assert_eq!(mapped.allow_browser_and_computer_use, Some(false)); assert_eq!( - mapped - .computer_use - .and_then(|requirements| requirements.allow_locked_computer_use), - Some(false) + mapped.browser_use, + Some(BrowserUseRequirements { + allow_history_access: Some(false), + disable_auto_review: Some(true), + allow_global_persistent_approval: Some(false), + default_origin_policy: Some(BrowserUseOriginPolicy { + access: Some(AllowDenyRequirement::Deny), + downloads: Some(AllowDenyRequirement::Allow), + uploads: Some(AllowDenyRequirement::Deny), + full_cdp_access: Some(AllowDenyRequirement::Allow), + auto_review: Some(AllowDenyRequirement::Deny), + persistent_approval: Some(false), + access_approval_lifetime: Some(BrowserUseAccessApprovalLifetime::Turn), + }), + origins: Some(BTreeMap::from([( + "https://example.com".to_string(), + BrowserUseOriginPolicy { + access: Some(AllowDenyRequirement::Allow), + downloads: Some(AllowDenyRequirement::Deny), + uploads: Some(AllowDenyRequirement::Allow), + full_cdp_access: Some(AllowDenyRequirement::Deny), + auto_review: Some(AllowDenyRequirement::Deny), + persistent_approval: Some(true), + access_approval_lifetime: Some(BrowserUseAccessApprovalLifetime::Thread), + }, + )])), + }) + ); + assert_eq!( + mapped.computer_use, + Some(ComputerUseRequirements { + allow_locked_computer_use: Some(false), + allow_persistent_approval: Some(false), + default_app_access: Some(AllowDenyRequirement::Deny), + macos: Some(ComputerUseMacosRequirements { + bundle_ids: Some(BTreeMap::from([( + "com.apple.Safari".to_string(), + AllowDenyRequirement::Allow, + )])), + }), + windows: Some(ComputerUseWindowsRequirements { + aumids: Some(BTreeMap::from([( + "Microsoft.Paint_8wekyb3d8bbwe!App".to_string(), + AllowDenyRequirement::Allow, + )])), + exes: Some(vec![ComputerUseWindowsExeRequirement { + publisher_name: "CN=Google LLC".to_string(), + product_name: "Google Chrome".to_string(), + binary_name: Some("chrome.exe".to_string()), + access: AllowDenyRequirement::Deny, + }]), + }), + }) ); } diff --git a/codex-rs/app-server/tests/suite/v2/config_requirements_in_app_browser.rs b/codex-rs/app-server/tests/suite/v2/config_requirements_in_app_browser.rs index e1d49d7db6..6cdc14d455 100644 --- a/codex-rs/app-server/tests/suite/v2/config_requirements_in_app_browser.rs +++ b/codex-rs/app-server/tests/suite/v2/config_requirements_in_app_browser.rs @@ -106,7 +106,11 @@ async fn import_policy_is_separate_from_browser_feature_and_agent_policy() -> Re allow_external_browser_settings_import: Some(false), }), Some(BrowserUseRequirements { + allow_history_access: None, disable_auto_review: Some(true), + allow_global_persistent_approval: None, + default_origin_policy: None, + origins: None, }), Some(BTreeMap::from([ ("browser_use".to_string(), false), diff --git a/codex-rs/app-server/tests/suite/v2/config_rpc.rs b/codex-rs/app-server/tests/suite/v2/config_rpc.rs index 3eefad5308..ac95494782 100644 --- a/codex-rs/app-server/tests/suite/v2/config_rpc.rs +++ b/codex-rs/app-server/tests/suite/v2/config_rpc.rs @@ -2,13 +2,21 @@ use anyhow::Result; use app_test_support::TestAppServer; use app_test_support::test_path_buf_with_windows; use app_test_support::test_tmp_path_buf; +use codex_app_server_protocol::AllowDenyRequirement; use codex_app_server_protocol::AppConfig; use codex_app_server_protocol::AppToolApproval; use codex_app_server_protocol::ApprovalsReviewer; use codex_app_server_protocol::AppsConfig; use codex_app_server_protocol::AppsDefaultConfig; use codex_app_server_protocol::AskForApproval; +use codex_app_server_protocol::BrowserUseAccessApprovalLifetime; +use codex_app_server_protocol::BrowserUseOriginPolicy; +use codex_app_server_protocol::BrowserUseRequirements; use codex_app_server_protocol::CliAuthCredentialsStoreMode; +use codex_app_server_protocol::ComputerUseMacosRequirements; +use codex_app_server_protocol::ComputerUseRequirements; +use codex_app_server_protocol::ComputerUseWindowsExeRequirement; +use codex_app_server_protocol::ComputerUseWindowsRequirements; use codex_app_server_protocol::ConfigBatchWriteParams; use codex_app_server_protocol::ConfigEdit; use codex_app_server_protocol::ConfigLayerSource; @@ -34,6 +42,7 @@ use codex_protocol::openai_models::ReasoningEffort; use codex_utils_absolute_path::AbsolutePathBuf; use pretty_assertions::assert_eq; use serde_json::json; +use std::collections::BTreeMap; use tempfile::TempDir; use tokio::time::timeout; @@ -215,13 +224,52 @@ statusMessage = "Scanning file" } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn config_requirements_read_includes_browser_use_auto_review_setting() -> Result<()> { +async fn config_requirements_read_includes_browser_and_computer_use_schema() -> Result<()> { let codex_home = TempDir::new()?; std::fs::write( codex_home.path().join("requirements.toml"), r#" +allow_browser_and_computer_use = false + [browser_use] +allow_history_access = false disable_auto_review = true +allow_global_persistent_approval = false + +[browser_use.default_origin_policy] +access = "deny" +downloads = "allow" +uploads = "deny" +full_cdp_access = "allow" +auto_review = "deny" +persistent_approval = false +access_approval_lifetime = "turn" + +[browser_use.origins."https://example.com"] +access = "allow" +downloads = "deny" +uploads = "allow" +full_cdp_access = "deny" +auto_review = "deny" +persistent_approval = true +access_approval_lifetime = "thread" + +[computer_use] +allow_locked_computer_use = false +allow_persistent_approval = false +default_app_access = "deny" + +[computer_use.macos.bundle_ids] +"com.apple.Safari" = "allow" + +[computer_use.windows.aumids] +"Microsoft.Paint_8wekyb3d8bbwe!App" = "allow" + +[[computer_use.windows.exes]] +publisher_name = "CN=Google LLC" +product_name = "Google Chrome" +binary_name = "chrome.exe" +access = "deny" "#, )?; let mut mcp = TestAppServer::builder() @@ -234,12 +282,64 @@ disable_auto_review = true let request_id = mcp.send_config_requirements_read_request().await?; let response: ConfigRequirementsReadResponse = timeout(DEFAULT_READ_TIMEOUT, mcp.read_response(request_id)).await??; + let requirements = response + .requirements + .expect("managed requirements should be returned"); + assert_eq!(requirements.allow_browser_and_computer_use, Some(false)); assert_eq!( - response - .requirements - .and_then(|requirements| requirements.browser_use) - .and_then(|browser_use| browser_use.disable_auto_review), - Some(true) + requirements.browser_use, + Some(BrowserUseRequirements { + allow_history_access: Some(false), + disable_auto_review: Some(true), + allow_global_persistent_approval: Some(false), + default_origin_policy: Some(BrowserUseOriginPolicy { + access: Some(AllowDenyRequirement::Deny), + downloads: Some(AllowDenyRequirement::Allow), + uploads: Some(AllowDenyRequirement::Deny), + full_cdp_access: Some(AllowDenyRequirement::Allow), + auto_review: Some(AllowDenyRequirement::Deny), + persistent_approval: Some(false), + access_approval_lifetime: Some(BrowserUseAccessApprovalLifetime::Turn), + }), + origins: Some(BTreeMap::from([( + "https://example.com".to_string(), + BrowserUseOriginPolicy { + access: Some(AllowDenyRequirement::Allow), + downloads: Some(AllowDenyRequirement::Deny), + uploads: Some(AllowDenyRequirement::Allow), + full_cdp_access: Some(AllowDenyRequirement::Deny), + auto_review: Some(AllowDenyRequirement::Deny), + persistent_approval: Some(true), + access_approval_lifetime: Some(BrowserUseAccessApprovalLifetime::Thread), + }, + )])), + }) + ); + assert_eq!( + requirements.computer_use, + Some(ComputerUseRequirements { + allow_locked_computer_use: Some(false), + allow_persistent_approval: Some(false), + default_app_access: Some(AllowDenyRequirement::Deny), + macos: Some(ComputerUseMacosRequirements { + bundle_ids: Some(BTreeMap::from([( + "com.apple.Safari".to_string(), + AllowDenyRequirement::Allow, + )])), + }), + windows: Some(ComputerUseWindowsRequirements { + aumids: Some(BTreeMap::from([( + "Microsoft.Paint_8wekyb3d8bbwe!App".to_string(), + AllowDenyRequirement::Allow, + )])), + exes: Some(vec![ComputerUseWindowsExeRequirement { + publisher_name: "CN=Google LLC".to_string(), + product_name: "Google Chrome".to_string(), + binary_name: Some("chrome.exe".to_string()), + access: AllowDenyRequirement::Deny, + }]), + }), + }) ); Ok(()) }