@@ -8,7 +8,7 @@ use anyhow::{anyhow, bail, Context, Result};
88use component2json:: {
99 component_exports_to_json_schema, create_placeholder_results, json_to_vals, vals_to_json,
1010} ;
11- use futures:: stream :: TryStreamExt ;
11+ use futures:: TryStreamExt ;
1212use policy_mcp:: PolicyParser ;
1313use serde:: { Deserialize , Serialize } ;
1414use serde_json:: Value ;
@@ -310,7 +310,7 @@ trait Loadable: Sized {
310310 async fn from_local_file ( path : & Path ) -> Result < DownloadedResource > ;
311311 async fn from_oci_reference (
312312 reference : & str ,
313- oci_client : & oci_wasm :: WasmClient , // TODO: change to oci_client::Client
313+ oci_client : & oci_client:: Client ,
314314 ) -> Result < DownloadedResource > ;
315315 async fn from_url ( url : & str , http_client : & reqwest:: Client ) -> Result < DownloadedResource > ;
316316}
@@ -344,11 +344,11 @@ impl Loadable for ComponentResource {
344344
345345 async fn from_oci_reference (
346346 reference : & str ,
347- oci_client : & oci_wasm :: WasmClient ,
347+ oci_client : & oci_client :: Client ,
348348 ) -> Result < DownloadedResource > {
349349 let reference: oci_client:: Reference =
350350 reference. parse ( ) . context ( "Failed to parse OCI reference" ) ?;
351- let data = oci_client
351+ let data = oci_wasm :: WasmClient :: from ( oci_client. clone ( ) )
352352 . pull ( & reference, & oci_client:: secrets:: RegistryAuth :: Anonymous )
353353 . await ?;
354354 let ( downloaded_resource, mut file) = DownloadedResource :: new_temp_file (
@@ -410,9 +410,9 @@ impl Loadable for PolicyResource {
410410
411411 async fn from_oci_reference (
412412 _reference : & str ,
413- _oci_client : & oci_wasm :: WasmClient ,
413+ _oci_client : & oci_client :: Client ,
414414 ) -> Result < DownloadedResource > {
415- bail ! ( "OCI policy pulling not implemented yet . Use file:// or https:// URIs for now ." ) ;
415+ bail ! ( "OCI references are not supported for policy resources . Use ' file://' or ' https://' schemes instead ." )
416416 }
417417
418418 async fn from_url ( url : & str , http_client : & reqwest:: Client ) -> Result < DownloadedResource > {
@@ -509,14 +509,7 @@ impl LifecycleManager {
509509 let engine = Arc :: new ( wasmtime:: Engine :: new ( & config) ?) ;
510510
511511 // Create the lifecycle manager
512- Self :: new_with_policy (
513- engine,
514- components_dir,
515- oci_client,
516- http_client,
517- WasiStateTemplate :: default ( ) ,
518- )
519- . await
512+ Self :: new_with_policy ( engine, components_dir, oci_client, http_client) . await
520513 }
521514
522515 /// Creates a lifecycle manager with custom clients and WASI state template
@@ -526,7 +519,6 @@ impl LifecycleManager {
526519 plugin_dir : impl AsRef < Path > ,
527520 oci_client : oci_client:: Client ,
528521 http_client : reqwest:: Client ,
529- _wasi_state_template : WasiStateTemplate ,
530522 ) -> Result < Self > {
531523 info ! ( "Creating new LifecycleManager" ) ;
532524
@@ -751,6 +743,11 @@ impl LifecycleManager {
751743 policy_template. build ( )
752744 }
753745
746+ /// Attaches a policy to a component. The policy can be a local file or a URL.
747+ /// This function will download the policy from the given URI and store it
748+ /// in the plugin directory specified by the `plugin_dir`, co-located with
749+ /// the component. The component_id must be the ID of a component that is
750+ /// already loaded.
754751 pub async fn attach_policy ( & self , component_id : & str , policy_uri : & str ) -> Result < ( ) > {
755752 info ! ( component_id, policy_uri, "Attaching policy to component" ) ;
756753
@@ -762,8 +759,7 @@ impl LifecycleManager {
762759 load_resource :: < PolicyResource > ( policy_uri, & self . oci_client , & self . http_client )
763760 . await ?;
764761
765- let policy_content = tokio:: fs:: read_to_string ( downloaded_policy. as_ref ( ) ) . await ?;
766- let policy = PolicyParser :: parse_str ( & policy_content) ?;
762+ let policy = PolicyParser :: parse_file ( downloaded_policy. as_ref ( ) ) ?;
767763
768764 let policy_path = self . get_component_policy_path ( component_id) ;
769765 tokio:: fs:: copy ( downloaded_policy. as_ref ( ) , & policy_path) . await ?;
@@ -790,6 +786,8 @@ impl LifecycleManager {
790786 Ok ( ( ) )
791787 }
792788
789+ /// Detaches a policy from a component. This will remove the policy from the
790+ /// component and remove the policy file from the plugin directory.
793791 pub async fn detach_policy ( & self , component_id : & str ) -> Result < ( ) > {
794792 info ! ( component_id, "Detaching policy from component" ) ;
795793
@@ -815,9 +813,14 @@ impl LifecycleManager {
815813 Ok ( ( ) )
816814 }
817815
816+ /// Returns information about the policy attached to a component.
817+ /// Returns `None` if no policy is attached to the component.
818+ ///
819+ /// The information contains the policy ID, source URI, local path, component ID,
820+ /// and creation time.
818821 pub async fn get_policy_info ( & self , component_id : & str ) -> Option < PolicyInfo > {
819822 let policy_path = self . get_component_policy_path ( component_id) ;
820- if !policy_path. exists ( ) {
823+ if !tokio :: fs :: try_exists ( & policy_path) . await . unwrap_or ( false ) {
821824 return None ;
822825 }
823826
@@ -946,28 +949,15 @@ impl LifecycleManager {
946949 component_id,
947950 permission_type, "Granting permission to component"
948951 ) ;
949-
950- // 1. Validate component exists
951952 if !self . components . read ( ) . await . contains_key ( component_id) {
952953 return Err ( anyhow ! ( "Component not found: {}" , component_id) ) ;
953954 }
954955
955- // 2. Parse permission rule
956956 let permission_rule = self . parse_permission_rule ( permission_type, details) ?;
957-
958- // 3. Validate permission rule
959957 self . validate_permission_rule ( & permission_rule) ?;
960-
961- // 4. Load or create component policy
962958 let mut policy = self . load_or_create_component_policy ( component_id) . await ?;
963-
964- // 5. Add permission rule to policy
965959 self . add_permission_rule_to_policy ( & mut policy, permission_rule) ?;
966-
967- // 6. Save updated policy
968960 self . save_component_policy ( component_id, & policy) . await ?;
969-
970- // 7. Update runtime policy registry
971961 self . update_policy_registry ( component_id, & policy) . await ?;
972962
973963 info ! (
@@ -1037,8 +1027,7 @@ impl LifecycleManager {
10371027 Ok ( policy_mcp:: PolicyDocument {
10381028 version : "1.0" . to_string ( ) ,
10391029 description : Some ( format ! (
1040- "Auto-generated policy for component: {}" ,
1041- component_id
1030+ "Auto-generated policy for component: {component_id}"
10421031 ) ) ,
10431032 permissions : Default :: default ( ) ,
10441033 } )
0 commit comments