1use crate::deployment_truth::{DeploymentInventoryV1, RoleArtifactManifestV1};
2use serde::{Deserialize, Serialize};
3use std::str::FromStr;
4use thiserror::Error;
5
6pub const ADOPTION_REPORT_SCHEMA_VERSION: u32 = 1;
7
8#[derive(Clone, Debug)]
12pub struct AdoptionReportRequest<'a> {
13 pub report_id: &'a str,
14 pub generated_at: &'a str,
15 pub profile: AdoptionProfileV1,
16 pub config_source: &'a str,
17 pub inventory: Option<&'a DeploymentInventoryV1>,
18 pub artifact_manifest: Option<&'a RoleArtifactManifestV1>,
19 pub package_metadata: Vec<AdoptionPackageMetadataV1>,
20}
21
22#[derive(Debug, Eq, Error, PartialEq)]
26pub enum AdoptionReportError {
27 #[error("invalid config: {0}")]
28 InvalidConfig(String),
29
30 #[error("missing required [fleet].name in canic.toml")]
31 MissingFleetName,
32}
33
34#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
38pub enum AdoptionProfileV1 {
39 Brownfield,
40 Partial,
41 Standalone,
42 LeafOnly,
43 HybridExternalWasm,
44 Minimal,
45}
46
47impl FromStr for AdoptionProfileV1 {
48 type Err = String;
49
50 fn from_str(value: &str) -> Result<Self, Self::Err> {
51 match value {
52 "brownfield" => Ok(Self::Brownfield),
53 "partial" => Ok(Self::Partial),
54 "standalone" => Ok(Self::Standalone),
55 "leaf-only" => Ok(Self::LeafOnly),
56 "hybrid-external-wasm" => Ok(Self::HybridExternalWasm),
57 "minimal" => Ok(Self::Minimal),
58 other => Err(format!("invalid adoption profile: {other}")),
59 }
60 }
61}
62
63#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
67pub struct AdoptionReportV1 {
68 pub schema_version: u32,
69 pub report_id: String,
70 pub generated_at: String,
71 pub fleet: String,
72 pub profile: AdoptionProfileV1,
73 pub inputs: AdoptionReportInputsV1,
74 pub summary: AdoptionReportSummaryV1,
75 pub role_findings: Vec<AdoptionRoleFindingV1>,
76 pub observed_canisters: Vec<AdoptionObservedCanisterFindingV1>,
77 pub recommendations: Vec<AdoptionRecommendationV1>,
78 pub blocked_actions: Vec<String>,
79 pub warnings: Vec<String>,
80}
81
82#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
86pub struct AdoptionReportInputsV1 {
87 pub config_present: bool,
88 pub inventory_id: Option<String>,
89 pub artifact_manifest_id: Option<String>,
90 pub package_metadata_count: usize,
91 pub missing_or_stale_evidence: Vec<String>,
92}
93
94#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
98pub struct AdoptionReportSummaryV1 {
99 pub managed_configured_roles: usize,
100 pub declared_only_roles: usize,
101 pub attached_unobserved_roles: usize,
102 pub observed_only_canisters: usize,
103 pub user_controlled_canisters: usize,
104 pub external_controller_required: usize,
105 pub evidence_conflicts: usize,
106 pub mutating_actions_performed: usize,
107}
108
109#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
113pub struct AdoptionRoleFindingV1 {
114 pub fleet: String,
115 pub role: String,
116 pub classifications: Vec<AdoptionClassificationV1>,
117 pub declaration_state: AdoptionDeclarationStateV1,
118 pub topology_state: AdoptionTopologyStateV1,
119 pub package_state: AdoptionPackageStateV1,
120 pub observation_state: AdoptionObservationStateV1,
121 pub authority_state: AdoptionAuthorityStateV1,
122 pub artifact_state: AdoptionArtifactStateV1,
123 pub evidence: Vec<String>,
124 pub recommendations: Vec<AdoptionRecommendationV1>,
125 pub warnings: Vec<String>,
126}
127
128#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
132pub struct AdoptionObservedCanisterFindingV1 {
133 pub canister_id: String,
134 pub matched_fleet: Option<String>,
135 pub matched_role: Option<String>,
136 pub confidence: AdoptionMatchConfidenceV1,
137 pub classifications: Vec<AdoptionClassificationV1>,
138 pub controllers: Vec<String>,
139 pub wasm_evidence: Option<String>,
140 pub deployment_target_evidence: Option<String>,
141 pub recommendations: Vec<AdoptionRecommendationV1>,
142 pub warnings: Vec<String>,
143}
144
145#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
149pub struct AdoptionRecommendationV1 {
150 pub kind: String,
151 pub severity: AdoptionRecommendationSeverityV1,
152 pub description: String,
153 pub suggested_action: Option<String>,
154 pub suggested_action_effect: AdoptionSuggestedActionEffectV1,
155 pub suggested_action_support: AdoptionSuggestedActionSupportV1,
156 pub suggested_action_availability: AdoptionSuggestedActionAvailabilityV1,
157 pub operator_action_requirement: AdoptionOperatorActionRequirementV1,
158}
159
160#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
164pub struct AdoptionPackageMetadataV1 {
165 pub package: String,
166 pub fleet: Option<String>,
167 pub role: Option<String>,
168}
169
170#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
174pub enum AdoptionClassificationV1 {
175 Managed,
176 DeclaredOnly,
177 ObservedOnly,
178 AttachedUnobserved,
179 UserControlled,
180 ExternalControllerRequired,
181 ImportedPoolCandidate,
182 EvidenceConflict,
183}
184
185#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
189pub enum AdoptionDeclarationStateV1 {
190 Undeclared,
191 Declared,
192}
193
194#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
198pub enum AdoptionTopologyStateV1 {
199 Unattached,
200 Attached,
201}
202
203#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
207pub enum AdoptionObservationStateV1 {
208 Unobserved,
209 Observed,
210 CandidateMatch,
211 ConflictingMatch,
212}
213
214#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
218pub enum AdoptionAuthorityStateV1 {
219 CanicAuthorized,
220 UserControlled,
221 External,
222 Unknown,
223}
224
225#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
229pub enum AdoptionArtifactStateV1 {
230 CanicBuilt,
231 ExternalWasm,
232 Unknown,
233}
234
235#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
239pub enum AdoptionPackageStateV1 {
240 UndeclaredRole,
241 NotChecked,
242 Matches,
243 MissingFleet,
244 MissingRole,
245 Mismatch,
246}
247
248#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
252pub enum AdoptionMatchConfidenceV1 {
253 None,
254 Candidate,
255 ExplicitEvidence,
256 Conflict,
257}
258
259#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
263pub enum AdoptionRecommendationSeverityV1 {
264 Info,
265 Warning,
266 Blocked,
267}
268
269#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
273pub enum AdoptionSuggestedActionEffectV1 {
274 ReadOnly,
275 MutatesState,
276}
277
278#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
282pub enum AdoptionSuggestedActionSupportV1 {
283 SupportedByAdoption,
284 UnsupportedByAdoption,
285}
286
287#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
291pub enum AdoptionSuggestedActionAvailabilityV1 {
292 AllowedIn0500,
293 BlockedIn0500,
294}
295
296#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
300pub enum AdoptionOperatorActionRequirementV1 {
301 Required,
302 NotRequired,
303}