|
3 | 3 | //! This module owns auditable command inputs and command results. Runtime code |
4 | 4 | //! executes these commands and records state changes. |
5 | 5 |
|
| 6 | +use crate::error::types::SupervisorError; |
6 | 7 | use crate::id::types::{ChildId, SupervisorPath}; |
7 | 8 | use crate::shutdown::coordinator::ShutdownResult; |
8 | 9 | use serde::{Deserialize, Serialize}; |
@@ -75,6 +76,20 @@ impl CommandMeta { |
75 | 76 | reason: reason.into(), |
76 | 77 | } |
77 | 78 | } |
| 79 | + |
| 80 | + /// Validates audit metadata before command dispatch. |
| 81 | + /// |
| 82 | + /// # Arguments |
| 83 | + /// |
| 84 | + /// This function has no arguments. |
| 85 | + /// |
| 86 | + /// # Returns |
| 87 | + /// |
| 88 | + /// Returns `Ok(())` when actor and reason fields are non-empty. |
| 89 | + pub(crate) fn validate(&self) -> Result<(), SupervisorError> { |
| 90 | + validate_required_text(&self.requested_by, "requested_by")?; |
| 91 | + validate_required_text(&self.reason, "reason") |
| 92 | + } |
78 | 93 | } |
79 | 94 |
|
80 | 95 | /// Runtime command sent to the control loop. |
@@ -158,6 +173,38 @@ impl ControlCommand { |
158 | 173 | | Self::CurrentState { meta } => meta, |
159 | 174 | } |
160 | 175 | } |
| 176 | + |
| 177 | + /// Validates audit metadata attached to this command. |
| 178 | + /// |
| 179 | + /// # Arguments |
| 180 | + /// |
| 181 | + /// This function has no arguments. |
| 182 | + /// |
| 183 | + /// # Returns |
| 184 | + /// |
| 185 | + /// Returns `Ok(())` when the command carries auditable metadata. |
| 186 | + pub(crate) fn validate_audit_metadata(&self) -> Result<(), SupervisorError> { |
| 187 | + self.meta().validate() |
| 188 | + } |
| 189 | +} |
| 190 | + |
| 191 | +/// Validates one required text field. |
| 192 | +/// |
| 193 | +/// # Arguments |
| 194 | +/// |
| 195 | +/// - `value`: Text value supplied by the command caller. |
| 196 | +/// - `field`: Field name used in the diagnostic message. |
| 197 | +/// |
| 198 | +/// # Returns |
| 199 | +/// |
| 200 | +/// Returns `Ok(())` when the value is not blank. |
| 201 | +fn validate_required_text(value: &str, field: &str) -> Result<(), SupervisorError> { |
| 202 | + if value.trim().is_empty() { |
| 203 | + return Err(SupervisorError::InvalidTransition { |
| 204 | + message: format!("control command {field} must not be empty"), |
| 205 | + }); |
| 206 | + } |
| 207 | + Ok(()) |
161 | 208 | } |
162 | 209 |
|
163 | 210 | /// State assigned to a managed child by the control loop. |
|
0 commit comments