1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use stack_ids::{
4 AccessPurposeMatrixId, ApplicabilityContextId, ApprovalMatrixId, AuditExtractionPolicyId,
5 ConflictClassCatalogId, ContinuityPolicyProfileId, CrossBoundaryTransferClassId,
6 DelegationMatrixId, DelegationPolicyProfileId, EffectPolicyProfileId, EscalationClockPolicyId,
7 EvidenceCollectionPlanId, HazardLibraryId, HazardScenarioId, IncidentTaxonomyId,
8 LocalityExceptionId, MitigationPlaybookId, MonitorCatalogId, PagerRouteProfileId,
9 PrivacyRetentionProfileId, ProfileExceptionBundleId, ProfileSetId, RecertificationScheduleId,
10 RedactionRuleSetId, RegulatoryRegimeProfileId, ReleasePolicyProfileId, RequirementControlMapId,
11 ResidencyPolicyProfileId, RoleCatalogId, SeverityMatrixId, TenantBoundaryProfileId,
12 VendorCertificationAdapterId, VendorEvidenceTranslationId, VendorRevocationHandlingId,
13 VendorTrustRootBindingId,
14};
15
16pub const PROFILE_SET_V1_SCHEMA: &str = "profile_set_v1";
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Default)]
19pub struct ProfileRefGroupV1 {
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub privacy_retention_profile_id: Option<PrivacyRetentionProfileId>,
22 #[serde(default, skip_serializing_if = "Vec::is_empty")]
23 pub redaction_rule_set_ids: Vec<RedactionRuleSetId>,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub access_purpose_matrix_id: Option<AccessPurposeMatrixId>,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub audit_extraction_policy_id: Option<AuditExtractionPolicyId>,
28 #[serde(default, skip_serializing_if = "Option::is_none")]
29 pub residency_policy_profile_id: Option<ResidencyPolicyProfileId>,
30 #[serde(default, skip_serializing_if = "Option::is_none")]
31 pub tenant_boundary_profile_id: Option<TenantBoundaryProfileId>,
32 #[serde(default, skip_serializing_if = "Vec::is_empty")]
33 pub cross_boundary_transfer_class_ids: Vec<CrossBoundaryTransferClassId>,
34 #[serde(default, skip_serializing_if = "Vec::is_empty")]
35 pub locality_exception_ids: Vec<LocalityExceptionId>,
36 #[serde(default, skip_serializing_if = "Option::is_none")]
37 pub role_catalog_id: Option<RoleCatalogId>,
38 #[serde(default, skip_serializing_if = "Option::is_none")]
39 pub delegation_matrix_id: Option<DelegationMatrixId>,
40 #[serde(default, skip_serializing_if = "Option::is_none")]
41 pub approval_matrix_id: Option<ApprovalMatrixId>,
42 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub conflict_class_catalog_id: Option<ConflictClassCatalogId>,
44 #[serde(default, skip_serializing_if = "Option::is_none")]
45 pub regulatory_regime_profile_id: Option<RegulatoryRegimeProfileId>,
46 #[serde(default, skip_serializing_if = "Option::is_none")]
47 pub requirement_control_map_id: Option<RequirementControlMapId>,
48 #[serde(default, skip_serializing_if = "Option::is_none")]
49 pub evidence_collection_plan_id: Option<EvidenceCollectionPlanId>,
50 #[serde(default, skip_serializing_if = "Option::is_none")]
51 pub recertification_schedule_id: Option<RecertificationScheduleId>,
52 #[serde(default, skip_serializing_if = "Option::is_none")]
53 pub hazard_library_id: Option<HazardLibraryId>,
54 #[serde(default, skip_serializing_if = "Vec::is_empty")]
55 pub hazard_scenario_ids: Vec<HazardScenarioId>,
56 #[serde(default, skip_serializing_if = "Option::is_none")]
57 pub monitor_catalog_id: Option<MonitorCatalogId>,
58 #[serde(default, skip_serializing_if = "Vec::is_empty")]
59 pub mitigation_playbook_ids: Vec<MitigationPlaybookId>,
60 #[serde(default, skip_serializing_if = "Option::is_none")]
61 pub vendor_certification_adapter_id: Option<VendorCertificationAdapterId>,
62 #[serde(default, skip_serializing_if = "Option::is_none")]
63 pub vendor_evidence_translation_id: Option<VendorEvidenceTranslationId>,
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 pub vendor_trust_root_binding_id: Option<VendorTrustRootBindingId>,
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 pub vendor_revocation_handling_id: Option<VendorRevocationHandlingId>,
68 #[serde(default, skip_serializing_if = "Option::is_none")]
69 pub incident_taxonomy_id: Option<IncidentTaxonomyId>,
70 #[serde(default, skip_serializing_if = "Option::is_none")]
71 pub severity_matrix_id: Option<SeverityMatrixId>,
72 #[serde(default, skip_serializing_if = "Option::is_none")]
73 pub pager_route_profile_id: Option<PagerRouteProfileId>,
74 #[serde(default, skip_serializing_if = "Option::is_none")]
75 pub escalation_clock_policy_id: Option<EscalationClockPolicyId>,
76 #[serde(default, skip_serializing_if = "Option::is_none")]
77 pub effect_policy_profile_id: Option<EffectPolicyProfileId>,
78 #[serde(default, skip_serializing_if = "Option::is_none")]
79 pub delegation_policy_profile_id: Option<DelegationPolicyProfileId>,
80 #[serde(default, skip_serializing_if = "Option::is_none")]
81 pub release_policy_profile_id: Option<ReleasePolicyProfileId>,
82 #[serde(default, skip_serializing_if = "Option::is_none")]
83 pub continuity_policy_profile_id: Option<ContinuityPolicyProfileId>,
84}
85
86impl ProfileRefGroupV1 {
87 pub fn all_profile_refs(&self) -> Vec<String> {
89 let mut refs = Vec::new();
90 macro_rules! push_opt {
91 ($field:expr) => {
92 if let Some(value) = &$field {
93 refs.push(value.to_string());
94 }
95 };
96 }
97 macro_rules! push_vec {
98 ($field:expr) => {
99 refs.extend($field.iter().map(ToString::to_string));
100 };
101 }
102
103 push_opt!(self.privacy_retention_profile_id);
104 push_vec!(self.redaction_rule_set_ids);
105 push_opt!(self.access_purpose_matrix_id);
106 push_opt!(self.audit_extraction_policy_id);
107 push_opt!(self.residency_policy_profile_id);
108 push_opt!(self.tenant_boundary_profile_id);
109 push_vec!(self.cross_boundary_transfer_class_ids);
110 push_vec!(self.locality_exception_ids);
111 push_opt!(self.role_catalog_id);
112 push_opt!(self.delegation_matrix_id);
113 push_opt!(self.approval_matrix_id);
114 push_opt!(self.conflict_class_catalog_id);
115 push_opt!(self.regulatory_regime_profile_id);
116 push_opt!(self.requirement_control_map_id);
117 push_opt!(self.evidence_collection_plan_id);
118 push_opt!(self.recertification_schedule_id);
119 push_opt!(self.hazard_library_id);
120 push_vec!(self.hazard_scenario_ids);
121 push_opt!(self.monitor_catalog_id);
122 push_vec!(self.mitigation_playbook_ids);
123 push_opt!(self.vendor_certification_adapter_id);
124 push_opt!(self.vendor_evidence_translation_id);
125 push_opt!(self.vendor_trust_root_binding_id);
126 push_opt!(self.vendor_revocation_handling_id);
127 push_opt!(self.incident_taxonomy_id);
128 push_opt!(self.severity_matrix_id);
129 push_opt!(self.pager_route_profile_id);
130 push_opt!(self.escalation_clock_policy_id);
131 push_opt!(self.effect_policy_profile_id);
132 push_opt!(self.delegation_policy_profile_id);
133 push_opt!(self.release_policy_profile_id);
134 push_opt!(self.continuity_policy_profile_id);
135
136 refs.sort();
137 refs.dedup();
138 refs
139 }
140}
141
142#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
143pub struct ProfileOmissionV1 {
144 pub family: String,
145 pub reason: String,
146}
147
148#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
149pub struct ProfileSetV1 {
150 pub schema_version: String,
151 pub profile_set_id: ProfileSetId,
152 pub applicability_context_ref: ApplicabilityContextId,
153 pub profile_refs: ProfileRefGroupV1,
154 #[serde(default, skip_serializing_if = "Vec::is_empty")]
155 pub source_admission_refs: Vec<String>,
156 #[serde(default, skip_serializing_if = "Vec::is_empty")]
157 pub omissions: Vec<ProfileOmissionV1>,
158 #[serde(default, skip_serializing_if = "Vec::is_empty")]
159 pub active_exception_refs: Vec<ProfileExceptionBundleId>,
160 #[serde(default, skip_serializing_if = "Vec::is_empty")]
161 pub normalized_profile_order: Vec<String>,
162}
163
164impl ProfileSetV1 {
165 pub fn new(
167 applicability_context_ref: ApplicabilityContextId,
168 profile_refs: ProfileRefGroupV1,
169 source_admission_refs: Vec<String>,
170 ) -> Self {
171 let normalized_profile_order = profile_refs.all_profile_refs();
172 Self {
173 schema_version: PROFILE_SET_V1_SCHEMA.into(),
174 profile_set_id: ProfileSetId::generate(),
175 applicability_context_ref,
176 profile_refs,
177 source_admission_refs,
178 omissions: Vec::new(),
179 active_exception_refs: Vec::new(),
180 normalized_profile_order,
181 }
182 }
183
184 pub fn refresh_normalized_profile_order(&mut self) {
186 self.normalized_profile_order = self.profile_refs.all_profile_refs();
187 }
188
189 pub fn all_profile_refs(&self) -> Vec<String> {
191 self.profile_refs.all_profile_refs()
192 }
193}