Skip to main content

ic_query/ic/
model.rs

1//! Module: ic::model
2//!
3//! Responsibility: public IC Dashboard canister requests, source data, reports, and errors.
4//! Does not own: HTTP transport, source validation, report assembly, or rendering.
5//! Boundary: preserves raw Dashboard values and explicit off-chain provenance.
6
7#[cfg(feature = "host")]
8use crate::runtime::RuntimeError;
9use serde::Serialize;
10#[cfg(feature = "host")]
11use thiserror::Error as ThisError;
12
13///
14/// IcCanisterRequest
15///
16/// Request accepted by the official Dashboard canister report builder.
17///
18
19#[derive(Clone, Debug, Eq, PartialEq)]
20pub struct IcCanisterRequest {
21    /// Dashboard API base endpoint.
22    pub source_endpoint: String,
23    /// Collection time as Unix seconds.
24    pub now_unix_secs: u64,
25    /// Canister principal to inspect.
26    pub canister_id: String,
27}
28
29impl IcCanisterRequest {
30    /// Construct a live Dashboard canister request.
31    #[must_use]
32    pub fn new(
33        source_endpoint: impl Into<String>,
34        now_unix_secs: u64,
35        canister_id: impl Into<String>,
36    ) -> Self {
37        Self {
38            source_endpoint: source_endpoint.into(),
39            now_unix_secs,
40            canister_id: canister_id.into(),
41        }
42    }
43}
44
45///
46/// IcCanisterUpgrade
47///
48/// One proposal-linked canister upgrade recorded by the Dashboard API.
49///
50
51#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
52pub struct IcCanisterUpgrade {
53    /// Proposal execution time as raw Unix seconds.
54    pub executed_timestamp_seconds: u64,
55    /// Wasm module hash as raw lowercase hexadecimal text.
56    pub module_hash: String,
57    /// NNS proposal that installed this module.
58    pub proposal_id: u64,
59}
60
61///
62/// IcCanisterReport
63///
64/// One live canister metadata report from the official Dashboard API.
65///
66
67#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
68pub struct IcCanisterReport {
69    /// Report schema version.
70    pub schema_version: u32,
71    /// Network represented by the official Dashboard API.
72    pub network: String,
73    /// Authority that supplied the report fields.
74    pub authority: String,
75    /// Dashboard API base endpoint queried by the source.
76    pub source_endpoint: String,
77    /// Time this report was collected.
78    pub fetched_at: String,
79    /// Collector identity.
80    pub fetched_by: String,
81    /// Whether the API response is cryptographically certified IC state.
82    pub certified: bool,
83    /// Whether every returned value is guaranteed to describe one point in time.
84    pub point_in_time_guaranteed: bool,
85    /// Canonical canister principal.
86    pub canister_id: String,
87    /// Dashboard database row identifier.
88    pub dashboard_id: u64,
89    /// Raw optional Dashboard canister classification.
90    pub canister_type: Option<String>,
91    /// Raw Dashboard canister name; an empty string means no name was recorded.
92    pub name: String,
93    /// Canonical Subnet principal recorded by the Dashboard.
94    pub subnet_id: String,
95    /// Canonically ordered controller principals recorded by the Dashboard.
96    pub controllers: Vec<String>,
97    /// Raw Dashboard language label; an empty string means no language was recorded.
98    pub language: String,
99    /// Raw current module hash; an empty string means no hash was recorded.
100    pub module_hash: String,
101    /// Raw Dashboard row update timestamp.
102    pub dashboard_updated_at: String,
103    /// Number of proposal-linked upgrades when history is available.
104    pub upgrade_count: Option<usize>,
105    /// Proposal-linked upgrade history, or `None` when the Dashboard returned `null`.
106    pub upgrades: Option<Vec<IcCanisterUpgrade>>,
107}
108
109///
110/// IcSourceRequest
111///
112/// Shared endpoint and collection provenance for IC Dashboard source calls.
113///
114
115#[cfg(feature = "host")]
116#[derive(Clone, Debug, Eq, PartialEq)]
117pub struct IcSourceRequest {
118    /// Dashboard API base endpoint.
119    pub endpoint: String,
120    /// Collection timestamp in UTC.
121    pub fetched_at: String,
122    /// Collector identity recorded in report provenance.
123    pub fetched_by: String,
124}
125
126#[cfg(feature = "host")]
127impl IcSourceRequest {
128    /// Construct source-call provenance.
129    #[must_use]
130    pub fn new(
131        endpoint: impl Into<String>,
132        fetched_at: impl Into<String>,
133        fetched_by: impl Into<String>,
134    ) -> Self {
135        Self {
136            endpoint: endpoint.into(),
137            fetched_at: fetched_at.into(),
138            fetched_by: fetched_by.into(),
139        }
140    }
141}
142
143///
144/// IcCanisterSourceData
145///
146/// Raw canister metadata and provenance returned by an IC Dashboard source.
147///
148
149#[cfg(feature = "host")]
150#[derive(Clone, Debug, Eq, PartialEq)]
151pub struct IcCanisterSourceData {
152    /// Dashboard API base endpoint used by the source.
153    pub source_endpoint: String,
154    /// Collection timestamp supplied in the source request.
155    pub fetched_at: String,
156    /// Collector identity supplied in the source request.
157    pub fetched_by: String,
158    /// Canister principal returned by the Dashboard.
159    pub canister_id: String,
160    /// Dashboard database row identifier.
161    pub dashboard_id: u64,
162    /// Raw optional Dashboard canister classification.
163    pub canister_type: Option<String>,
164    /// Raw Dashboard canister name.
165    pub name: String,
166    /// Subnet principal returned by the Dashboard.
167    pub subnet_id: String,
168    /// Controller principals returned by the Dashboard.
169    pub controllers: Vec<String>,
170    /// Raw Dashboard language label.
171    pub language: String,
172    /// Raw current module hash.
173    pub module_hash: String,
174    /// Raw Dashboard row update timestamp.
175    pub dashboard_updated_at: String,
176    /// Proposal-linked upgrades, or `None` when the Dashboard returned `null`.
177    pub upgrades: Option<Vec<IcCanisterUpgrade>>,
178}
179
180///
181/// IcHostError
182///
183/// Typed error returned by IC Dashboard report builders and live sources.
184///
185
186#[cfg(feature = "host")]
187#[derive(Debug, ThisError)]
188pub enum IcHostError {
189    /// The synchronous adapter could not create its local async runtime.
190    #[error("failed to run IC Dashboard query: {0}")]
191    Runtime(#[from] RuntimeError),
192
193    /// A request supplied an invalid canister principal.
194    #[error("invalid {field}: {reason}")]
195    InvalidPrincipal {
196        /// Principal field being validated.
197        field: &'static str,
198        /// Principal parser diagnostic.
199        reason: String,
200    },
201
202    /// The Dashboard API base endpoint is malformed or unsupported.
203    #[error("invalid IC Dashboard endpoint {endpoint}: {reason}")]
204    InvalidEndpoint {
205        /// Rejected endpoint.
206        endpoint: String,
207        /// URL validation diagnostic.
208        reason: String,
209    },
210
211    /// The HTTP client could not be constructed.
212    #[error("failed to build IC Dashboard HTTP client: {reason}")]
213    HttpClientBuild {
214        /// HTTP client construction diagnostic.
215        reason: String,
216    },
217
218    /// The live Dashboard request failed before a response was received.
219    #[error("IC Dashboard request to {url} failed: {reason}")]
220    HttpRequest {
221        /// Fully resolved request URL.
222        url: String,
223        /// HTTP transport error.
224        reason: String,
225    },
226
227    /// The Dashboard returned a non-success HTTP status.
228    #[error("IC Dashboard request to {url} returned HTTP status {status}")]
229    HttpStatus {
230        /// Fully resolved request URL.
231        url: String,
232        /// Numeric HTTP status.
233        status: u16,
234    },
235
236    /// The Dashboard response did not match the expected JSON shape.
237    #[error("failed to decode IC Dashboard response from {url}: {reason}")]
238    JsonDecode {
239        /// Fully resolved request URL.
240        url: String,
241        /// JSON response decoding error.
242        reason: String,
243    },
244
245    /// A source capability returned data that violates its public result contract.
246    #[error("invalid IC Dashboard canister source data: {reason}")]
247    InvalidSourceData {
248        /// Deterministic invariant failure.
249        reason: String,
250    },
251}