greentic_interfaces/
validate.rs1use greentic_types::error::{ErrorCode, GResult, GreenticError};
4use semver::Version;
5
6fn invalid_input(message: impl Into<String>) -> GreenticError {
7 GreenticError::new(ErrorCode::InvalidInput, message)
8}
9
10pub fn validate_provider_meta(meta: crate::abi::v0_6_0::provider::ProviderMeta) -> GResult<()> {
12 if meta.name.trim().is_empty() {
13 return Err(invalid_input("provider name must not be empty"));
14 }
15
16 Version::parse(&meta.version)
17 .map_err(|err| invalid_input(format!("invalid semantic version: {err}")))?;
18
19 for domain in &meta.allow_list.domains {
20 if domain.trim().is_empty() {
21 return Err(invalid_input(
22 "allow-list domains must not contain empty entries",
23 ));
24 }
25 }
26
27 for port in &meta.allow_list.ports {
28 if *port == 0 {
29 return Err(invalid_input("allow-list ports must be greater than zero"));
30 }
31 }
32
33 for protocol in &meta.allow_list.protocols {
34 if let crate::canonical::types::Protocol::Custom(value) = protocol
35 && value.trim().is_empty()
36 {
37 return Err(invalid_input(
38 "custom protocol identifiers must not be empty",
39 ));
40 }
41 }
42
43 if meta.network_policy.deny_on_miss {
44 let allow = &meta.network_policy.egress;
46 if allow.domains.is_empty() && allow.ports.is_empty() && allow.protocols.is_empty() {
47 return Err(invalid_input(
48 "network policy denying misses requires explicit allow rules",
49 ));
50 }
51 }
52
53 Ok(())
54}