use crate::helpers::event::PolicyUpdated; use crate::*; use near_sdk::require; #[near] impl Contract { // ==================== Policy Management Getters ==================== /// Get a specific policy by ID (public view version) pub fn get_policy_by_id(&self, policy_id: String) -> Option { self.get_effective_policy(&policy_id) } /// Get all policies with pagination pub fn get_all_policies( &self, from_index: Option, limit: Option, ) -> Vec<(String, Policy)> { let start = from_index.unwrap_or(0) as usize; let max_limit = limit.unwrap_or(50).min(100) as usize; self.kernel_state .policies .iter() .skip(start) .take(max_limit) .map(|(policy_id, policy)| (policy_id.clone(), policy.clone())) .collect() } /// Get specific pending policy by ID pub fn get_pending_policy(&self, policy_id: String) -> Option { self.kernel_state.pending_policies.get(&policy_id).cloned() } /// Get all pending policy with pagination pub fn get_all_pending_policies( &self, from_index: Option, limit: Option, ) -> Vec<(String, Policy)> { let start = from_index.unwrap_or(0) as usize; let max_limit = limit.unwrap_or(50).min(100) as usize; self.kernel_state .pending_policies .iter() .skip(start) .take(max_limit) .map(|(policy_id, policy)| (policy_id.clone(), policy.clone())) .collect() } /// Count total number of policies pub fn get_policy_count(&self) -> u32 { self.kernel_state.policies.len() } } impl Contract { /// Validate policy configuration before storing fn internal_validate_policy(&self, policy: &Policy) { // Check policy ID is not empty require!(!policy.id.trim().is_empty(), "Policy ID cannot be empty"); // Check required vote count is greater than 0 require!( policy.required_vote_count > 0, "required_vote_count must be greater than 0" ); // Check proposal expiry time is greater than 0 require!( policy.proposal_expiry_time_nanosec.0 > 0, "proposal_expiry_time_nanosec must be greater than 0" ); // Check policy_type matches policy_details variant let type_matches = match policy.policy_type { PolicyType::KernelConfiguration => { matches!( policy.policy_details, permission::PolicyDetails::KernelConfiguration ) } PolicyType::ChainSigTransaction => { matches!( policy.policy_details, permission::PolicyDetails::ChainSigTransaction(_) ) } PolicyType::NearNativeTransaction => { matches!( policy.policy_details, permission::PolicyDetails::NearNativeTransaction(_) ) } PolicyType::ChainSigMessage => { matches!( policy.policy_details, permission::PolicyDetails::ChainSigMessage(_) ) } }; require!( type_matches, format!( "policy_type {:?} does not match policy_details variant", policy.policy_type ) ); } /// Validate policy change timing and type consistency fn internal_validate_policy_change_constraints(&mut self, policy_id: &str) { if let Some(policy) = self.internal_get_active_policy(policy_id) { let current_time = near_sdk::env::block_timestamp() as u128; let min_interval = self .policy_change_control .min_interval_between_updates_nanosec .0; // Check minimum interval since last activation for this policy require!( current_time >= policy.activation_time.0 + min_interval, "Policy change too soon. Minimum interval not met. Please wait before making another policy change." ); } } /// Propose a policy change with activation delay pub fn internal_propose_policy_change(&mut self, policy_id: String, mut new_policy: Policy) { // Validate policy ID matches require!( new_policy.id == policy_id, "Policy ID mismatch. Policy ID must match the target policy ID." ); self.internal_validate_policy_change_constraints(&policy_id); self.internal_validate_policy(&new_policy); let activation_delay = self.policy_change_control.activation_delay_nanosec.0; let current_time = near_sdk::env::block_timestamp() as u128; new_policy.activation_time = U128(current_time + activation_delay); if activation_delay == 0 { // activate immediately self.kernel_state .policies .insert(policy_id.clone(), new_policy.clone()); } else { // Store pending policy for delayed activation self.kernel_state .pending_policies .insert(policy_id.clone(), new_policy.clone()); } // Emit policy updated event PolicyUpdated { policy_id: &policy_id, updater: &near_sdk::env::predecessor_account_id(), activation_time: new_policy.activation_time, } .emit(); } /// Cancel pending policy change pub fn internal_cancel_pending_policy(&mut self, policy_id: String) { self.kernel_state.pending_policies.remove(&policy_id); } /// Force activate pending policy immediately (owner only, emergency use) pub fn internal_force_activate_policy(&mut self, policy_id: String) { if let Some(pending) = self.kernel_state.pending_policies.remove(&policy_id) { self.kernel_state.policies.insert(policy_id, pending); } } }