@@ -573,7 +573,7 @@ use openshell_core::proto::{
573573} ;
574574use openshell_providers:: {
575575 CredentialRefreshProfile , ProfileValidationDiagnostic , ProviderTypeProfile , default_profiles,
576- get_default_profile, normalize_profile_id, normalize_provider_type , validate_profile_set,
576+ get_default_profile, normalize_profile_id, validate_profile_set,
577577} ;
578578use std:: sync:: Arc ;
579579use tonic:: { Request , Response } ;
@@ -928,18 +928,6 @@ async fn profile_conflict_diagnostics(
928928 } ) ;
929929 continue ;
930930 }
931- if let Some ( provider_type) = normalize_provider_type ( & id) {
932- diagnostics. push ( ProfileValidationDiagnostic {
933- source : source. clone ( ) ,
934- profile_id : id. clone ( ) ,
935- field : "id" . to_string ( ) ,
936- message : format ! (
937- "provider profile id '{id}' is reserved for legacy provider type '{provider_type}'"
938- ) ,
939- severity : "error" . to_string ( ) ,
940- } ) ;
941- continue ;
942- }
943931 if store
944932 . get_message_by_name :: < StoredProviderProfile > ( & id)
945933 . await
@@ -1514,6 +1502,29 @@ mod tests {
15141502 }
15151503 }
15161504
1505+ async fn import_test_refresh_profile ( state : & Arc < ServerState > , id : & str , credential_key : & str ) {
1506+ let mut profile = custom_profile ( id) ;
1507+ profile. category = ProviderProfileCategory :: Messaging as i32 ;
1508+ profile. credentials = vec ! [ refreshable_credential( "access_token" , credential_key) ] ;
1509+ handle_import_provider_profiles (
1510+ state,
1511+ Request :: new ( ImportProviderProfilesRequest {
1512+ profiles : vec ! [ ProviderProfileImportItem {
1513+ profile: Some ( profile) ,
1514+ source: format!( "{id}.yaml" ) ,
1515+ } ] ,
1516+ } ) ,
1517+ )
1518+ . await
1519+ . unwrap ( ) ;
1520+ }
1521+
1522+ const TEST_GRAPH_PROVIDER_TYPE : & str = "test-msgraph" ;
1523+
1524+ async fn import_test_graph_refresh_profile ( state : & Arc < ServerState > ) {
1525+ import_test_refresh_profile ( state, TEST_GRAPH_PROVIDER_TYPE , "MS_GRAPH_ACCESS_TOKEN" ) . await ;
1526+ }
1527+
15171528 fn static_credential ( name : & str , env_var : & str , required : bool ) -> ProviderProfileCredential {
15181529 ProviderProfileCredential {
15191530 name : name. to_string ( ) ,
@@ -1560,6 +1571,13 @@ mod tests {
15601571 . unwrap ( )
15611572 . into_inner ( ) ;
15621573
1574+ let ids = response
1575+ . profiles
1576+ . iter ( )
1577+ . map ( |profile| profile. id . as_str ( ) )
1578+ . collect :: < Vec < _ > > ( ) ;
1579+ assert_eq ! ( ids, vec![ "claude-code" , "github" , "nvidia" ] ) ;
1580+
15631581 let github = response
15641582 . profiles
15651583 . iter ( )
@@ -1569,13 +1587,6 @@ mod tests {
15691587 github. category,
15701588 ProviderProfileCategory :: SourceControl as i32
15711589 ) ;
1572- assert ! (
1573- response
1574- . profiles
1575- . iter( )
1576- . all( |profile| profile. id != "generic" ) ,
1577- "generic remains a legacy provider type without a v2 profile"
1578- ) ;
15791590 }
15801591
15811592 #[ tokio:: test]
@@ -1685,38 +1696,36 @@ mod tests {
16851696 }
16861697
16871698 #[ tokio:: test]
1688- async fn import_provider_profile_rejects_legacy_provider_type_ids ( ) {
1699+ async fn import_provider_profile_allows_legacy_provider_type_ids_without_built_in_profiles ( ) {
16891700 let state = test_server_state ( ) . await ;
16901701 let response = handle_import_provider_profiles (
16911702 & state,
16921703 Request :: new ( ImportProviderProfilesRequest {
16931704 profiles : vec ! [ ProviderProfileImportItem {
1694- profile: Some ( custom_profile( "generic " ) ) ,
1695- source: "generic .yaml" . to_string( ) ,
1705+ profile: Some ( custom_profile( "codex " ) ) ,
1706+ source: "codex .yaml" . to_string( ) ,
16961707 } ] ,
16971708 } ) ,
16981709 )
16991710 . await
17001711 . unwrap ( )
17011712 . into_inner ( ) ;
17021713
1703- assert ! ( !response. imported) ;
1704- assert ! (
1705- response
1706- . diagnostics
1707- . iter( )
1708- . any( |diagnostic| diagnostic. message. contains( "reserved" ) )
1709- ) ;
1714+ assert ! ( response. imported) ;
1715+ assert ! ( response. diagnostics. is_empty( ) ) ;
17101716
1711- let missing = handle_get_provider_profile (
1717+ let imported = handle_get_provider_profile (
17121718 & state,
17131719 Request :: new ( GetProviderProfileRequest {
1714- id : "generic " . to_string ( ) ,
1720+ id : "codex " . to_string ( ) ,
17151721 } ) ,
17161722 )
17171723 . await
1718- . unwrap_err ( ) ;
1719- assert_eq ! ( missing. code( ) , Code :: NotFound ) ;
1724+ . unwrap ( )
1725+ . into_inner ( )
1726+ . profile
1727+ . expect ( "codex profile should be returned" ) ;
1728+ assert_eq ! ( imported. id, "codex" ) ;
17201729 }
17211730
17221731 #[ tokio:: test]
@@ -2022,6 +2031,7 @@ mod tests {
20222031 #[ tokio:: test]
20232032 async fn configure_provider_refresh_stores_scoped_status_and_provider_expiry ( ) {
20242033 let state = test_server_state ( ) . await ;
2034+ import_test_graph_refresh_profile ( & state) . await ;
20252035 create_provider_record (
20262036 state. store . as_ref ( ) ,
20272037 Provider {
@@ -2031,7 +2041,7 @@ mod tests {
20312041 created_at_ms : 0 ,
20322042 labels : HashMap :: new ( ) ,
20332043 } ) ,
2034- r#type : "outlook" . to_string ( ) ,
2044+ r#type : TEST_GRAPH_PROVIDER_TYPE . to_string ( ) ,
20352045 credentials : std:: iter:: once ( (
20362046 "MS_GRAPH_ACCESS_TOKEN" . to_string ( ) ,
20372047 "token" . to_string ( ) ,
@@ -2133,6 +2143,7 @@ mod tests {
21332143 #[ tokio:: test]
21342144 async fn delete_provider_refresh_preserves_manually_updated_expiry ( ) {
21352145 let state = test_server_state ( ) . await ;
2146+ import_test_graph_refresh_profile ( & state) . await ;
21362147 create_provider_record (
21372148 state. store . as_ref ( ) ,
21382149 Provider {
@@ -2142,7 +2153,7 @@ mod tests {
21422153 created_at_ms : 0 ,
21432154 labels : HashMap :: new ( ) ,
21442155 } ) ,
2145- r#type : "outlook" . to_string ( ) ,
2156+ r#type : TEST_GRAPH_PROVIDER_TYPE . to_string ( ) ,
21462157 credentials : std:: iter:: once ( (
21472158 "MS_GRAPH_ACCESS_TOKEN" . to_string ( ) ,
21482159 "token" . to_string ( ) ,
@@ -2225,6 +2236,7 @@ mod tests {
22252236 #[ tokio:: test]
22262237 async fn configure_provider_refresh_rejects_credential_key_collision_for_attached_sandbox ( ) {
22272238 let state = test_server_state ( ) . await ;
2239+ import_test_graph_refresh_profile ( & state) . await ;
22282240 create_provider_record (
22292241 state. store . as_ref ( ) ,
22302242 Provider {
@@ -2234,7 +2246,7 @@ mod tests {
22342246 created_at_ms : 0 ,
22352247 labels : HashMap :: new ( ) ,
22362248 } ) ,
2237- r#type : "outlook" . to_string ( ) ,
2249+ r#type : TEST_GRAPH_PROVIDER_TYPE . to_string ( ) ,
22382250 credentials : std:: iter:: once ( (
22392251 "MS_GRAPH_ACCESS_TOKEN" . to_string ( ) ,
22402252 "existing-token" . to_string ( ) ,
@@ -2255,7 +2267,7 @@ mod tests {
22552267 created_at_ms : 0 ,
22562268 labels : HashMap :: new ( ) ,
22572269 } ) ,
2258- r#type : "outlook" . to_string ( ) ,
2270+ r#type : TEST_GRAPH_PROVIDER_TYPE . to_string ( ) ,
22592271 credentials : std:: iter:: once ( ( "OTHER_TOKEN" . to_string ( ) , "other" . to_string ( ) ) )
22602272 . collect ( ) ,
22612273 config : HashMap :: new ( ) ,
@@ -2312,6 +2324,7 @@ mod tests {
23122324 #[ tokio:: test]
23132325 async fn configure_provider_refresh_treats_existing_refresh_state_keys_as_reserved ( ) {
23142326 let state = test_server_state ( ) . await ;
2327+ import_test_graph_refresh_profile ( & state) . await ;
23152328 for name in [ "first-graph" , "second-graph" ] {
23162329 create_provider_record (
23172330 state. store . as_ref ( ) ,
@@ -2322,7 +2335,7 @@ mod tests {
23222335 created_at_ms : 0 ,
23232336 labels : HashMap :: new ( ) ,
23242337 } ) ,
2325- r#type : "outlook" . to_string ( ) ,
2338+ r#type : TEST_GRAPH_PROVIDER_TYPE . to_string ( ) ,
23262339 credentials : HashMap :: new ( ) ,
23272340 config : HashMap :: new ( ) ,
23282341 credential_expires_at_ms : HashMap :: new ( ) ,
@@ -2395,6 +2408,7 @@ mod tests {
23952408 #[ tokio:: test]
23962409 async fn configure_provider_refresh_rejects_profile_endpoint_override_and_missing_material ( ) {
23972410 let state = test_server_state ( ) . await ;
2411+ import_test_graph_refresh_profile ( & state) . await ;
23982412 create_provider_record (
23992413 state. store . as_ref ( ) ,
24002414 Provider {
@@ -2404,7 +2418,7 @@ mod tests {
24042418 created_at_ms : 0 ,
24052419 labels : HashMap :: new ( ) ,
24062420 } ) ,
2407- r#type : "outlook" . to_string ( ) ,
2421+ r#type : TEST_GRAPH_PROVIDER_TYPE . to_string ( ) ,
24082422 credentials : std:: iter:: once ( (
24092423 "MS_GRAPH_ACCESS_TOKEN" . to_string ( ) ,
24102424 "token" . to_string ( ) ,
@@ -2773,25 +2787,6 @@ mod tests {
27732787 . unwrap_err ( ) ;
27742788 assert_eq ! ( create_missing_credentials. code( ) , Code :: InvalidArgument ) ;
27752789
2776- let refresh_bootstrap_provider = create_provider_record (
2777- store,
2778- Provider {
2779- metadata : Some ( openshell_core:: proto:: datamodel:: v1:: ObjectMeta {
2780- id : String :: new ( ) ,
2781- name : "outlook-no-token-yet" . to_string ( ) ,
2782- created_at_ms : 1_000_000 ,
2783- labels : HashMap :: new ( ) ,
2784- } ) ,
2785- r#type : "outlook" . to_string ( ) ,
2786- credentials : HashMap :: new ( ) ,
2787- config : HashMap :: new ( ) ,
2788- credential_expires_at_ms : HashMap :: new ( ) ,
2789- } ,
2790- )
2791- . await
2792- . unwrap ( ) ;
2793- assert ! ( refresh_bootstrap_provider. credentials. is_empty( ) ) ;
2794-
27952790 handle_import_provider_profiles (
27962791 & state,
27972792 Request :: new ( ImportProviderProfilesRequest {
0 commit comments