mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Allow EDU accounts to fetch cloud config bundles (#25963)
## Summary Allow EDU ChatGPT workspaces to fetch cloud config bundles. The existing cloud config eligibility gate only allowed business-like and enterprise plans, which meant EDU admins could configure managed policies in the UI but the Codex client would skip fetching them. This keeps individual/pro and team-like usage-based plans excluded, and adds service-level coverage for both `edu` and `education` plan aliases. ## Validation - `just fmt` - `just test -p codex-cloud-config` - Built the Codex app locally, created a new EDU ChatGPT workspace, and verified config bundles can be fetched and are properly applied.
This commit is contained in:
committed by
GitHub
Unverified
parent
271d5cecf2
commit
1fd2a6d328
@@ -49,7 +49,8 @@ fn cloud_config_eligible_auth(auth: &CodexAuth) -> bool {
|
||||
return false;
|
||||
};
|
||||
auth.uses_codex_backend()
|
||||
&& (plan_type.is_business_like() || matches!(plan_type, PlanType::Enterprise))
|
||||
&& (plan_type.is_business_like()
|
||||
|| matches!(plan_type, PlanType::Enterprise | PlanType::Edu))
|
||||
}
|
||||
|
||||
fn optional_bundle(bundle: CloudConfigBundle) -> Option<CloudConfigBundle> {
|
||||
|
||||
@@ -351,7 +351,7 @@ async fn get_bundle_skips_non_chatgpt_auth() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_bundle_skips_non_business_or_enterprise_plan() {
|
||||
async fn get_bundle_skips_individual_plan() {
|
||||
let fetcher = Arc::new(StaticBundleClient::new(test_bundle()));
|
||||
let codex_home = tempdir().expect("tempdir");
|
||||
let service = CloudConfigBundleService::new(
|
||||
@@ -365,6 +365,46 @@ async fn get_bundle_skips_non_business_or_enterprise_plan() {
|
||||
assert_eq!(fetcher.request_count.load(Ordering::SeqCst), 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_bundle_allows_eligible_workspace_plans_and_writes_cache() {
|
||||
for plan_type in [
|
||||
"business",
|
||||
"enterprise_cbp_usage_based",
|
||||
"enterprise",
|
||||
"hc",
|
||||
"edu",
|
||||
"education",
|
||||
] {
|
||||
let bundle = test_bundle();
|
||||
let fetcher = Arc::new(StaticBundleClient::new(bundle.clone()));
|
||||
let codex_home = tempdir().expect("tempdir");
|
||||
let service = CloudConfigBundleService::new(
|
||||
auth_manager_with_plan(plan_type).await,
|
||||
fetcher.clone(),
|
||||
codex_home.path().to_path_buf(),
|
||||
CLOUD_CONFIG_BUNDLE_TIMEOUT,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
service.load_startup_bundle().await,
|
||||
Ok(Some(bundle)),
|
||||
"plan_type: {plan_type}"
|
||||
);
|
||||
assert_eq!(
|
||||
fetcher.request_count.load(Ordering::SeqCst),
|
||||
1,
|
||||
"plan_type: {plan_type}"
|
||||
);
|
||||
assert!(
|
||||
codex_home
|
||||
.path()
|
||||
.join(CLOUD_CONFIG_BUNDLE_CACHE_FILENAME)
|
||||
.exists(),
|
||||
"plan_type: {plan_type}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_bundle_skips_team_like_usage_based_plan() {
|
||||
let fetcher = Arc::new(StaticBundleClient::new(test_bundle()));
|
||||
@@ -380,31 +420,6 @@ async fn get_bundle_skips_team_like_usage_based_plan() {
|
||||
assert_eq!(fetcher.request_count.load(Ordering::SeqCst), 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_bundle_allows_business_plan_and_writes_cache() {
|
||||
let bundle = test_bundle();
|
||||
let codex_home = tempdir().expect("tempdir");
|
||||
let fetcher = Arc::new(StaticBundleClient::new(bundle.clone()));
|
||||
let service = CloudConfigBundleService::new(
|
||||
auth_manager_with_plan("business").await,
|
||||
fetcher.clone(),
|
||||
codex_home.path().to_path_buf(),
|
||||
CLOUD_CONFIG_BUNDLE_TIMEOUT,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
service.load_startup_bundle().await,
|
||||
Ok(Some(bundle.clone()))
|
||||
);
|
||||
assert_eq!(fetcher.request_count.load(Ordering::SeqCst), 1);
|
||||
assert!(
|
||||
codex_home
|
||||
.path()
|
||||
.join(CLOUD_CONFIG_BUNDLE_CACHE_FILENAME)
|
||||
.exists()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_bundle_rejects_invalid_remote_bundle_before_cache_write() {
|
||||
let codex_home = tempdir().expect("tempdir");
|
||||
@@ -468,36 +483,6 @@ async fn get_bundle_ignores_invalid_cache_and_refetches() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_bundle_allows_business_like_usage_based_plan() {
|
||||
let fetcher = Arc::new(StaticBundleClient::new(test_bundle()));
|
||||
let codex_home = tempdir().expect("tempdir");
|
||||
let service = CloudConfigBundleService::new(
|
||||
auth_manager_with_plan("enterprise_cbp_usage_based").await,
|
||||
fetcher.clone(),
|
||||
codex_home.path().to_path_buf(),
|
||||
CLOUD_CONFIG_BUNDLE_TIMEOUT,
|
||||
);
|
||||
|
||||
assert_eq!(service.load_startup_bundle().await, Ok(Some(test_bundle())));
|
||||
assert_eq!(fetcher.request_count.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_bundle_allows_hc_plan_as_enterprise() {
|
||||
let fetcher = Arc::new(StaticBundleClient::new(test_bundle()));
|
||||
let codex_home = tempdir().expect("tempdir");
|
||||
let service = CloudConfigBundleService::new(
|
||||
auth_manager_with_plan("hc").await,
|
||||
fetcher.clone(),
|
||||
codex_home.path().to_path_buf(),
|
||||
CLOUD_CONFIG_BUNDLE_TIMEOUT,
|
||||
);
|
||||
|
||||
assert_eq!(service.load_startup_bundle().await, Ok(Some(test_bundle())));
|
||||
assert_eq!(fetcher.request_count.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_bundle_empty_response_is_success_and_cached() {
|
||||
let codex_home = tempdir().expect("tempdir");
|
||||
|
||||
Reference in New Issue
Block a user