Skip to main content

ahri_tre_protocol/
resource_discovery.rs

1use crate::{
2    domain::DomainSummary,
3    refs::{AssetRef, DataFileRef, DatasetRef, StudyRef, TagSummary, VersionRef},
4    study::BrowserContentSummaryPolicy,
5};
6use serde::{Deserialize, Serialize};
7
8pub const BROWSER_RESOURCE_ERROR_TARGET_DATASTORE: &str = "browser_resource.datastore";
9pub const BROWSER_RESOURCE_ERROR_TARGET_STUDY: &str = "browser_resource.study";
10pub const BROWSER_RESOURCE_ERROR_TARGET_SERVICE: &str = "browser_resource.service";
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct BrowserResourceDiscoveryRequest {
14    pub datastore_id: crate::PublicUuid,
15    pub study: StudyRef,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub struct BrowserResourceDiscoveryEmptyState {
20    pub code: String,
21    pub message: String,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25pub struct BrowserResourceAccessCondition {
26    pub duo_id: String,
27    pub code: String,
28    pub label: String,
29    #[serde(default, skip_serializing_if = "Option::is_none")]
30    pub qualifier_ontology_namespace: Option<String>,
31    #[serde(default, skip_serializing_if = "Option::is_none")]
32    pub qualifier_ontology_id: Option<String>,
33    #[serde(default, skip_serializing_if = "Option::is_none")]
34    pub qualifier_text: Option<String>,
35    #[serde(default, skip_serializing_if = "Option::is_none")]
36    pub qualifier_date: Option<chrono::NaiveDate>,
37    #[serde(default, skip_serializing_if = "Option::is_none")]
38    pub qualifier_integer: Option<i32>,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
42pub struct BrowserDatasetAccessRequestReference {
43    pub datastore_id: crate::PublicUuid,
44    pub study: StudyRef,
45    pub dataset: DatasetRef,
46    #[serde(default, skip_serializing_if = "Option::is_none")]
47    pub version: Option<VersionRef>,
48}
49
50#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
51pub struct BrowserDataFileAccessRequestReference {
52    pub datastore_id: crate::PublicUuid,
53    pub study: StudyRef,
54    pub datafile: DataFileRef,
55    #[serde(default, skip_serializing_if = "Option::is_none")]
56    pub version: Option<VersionRef>,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
60#[serde(tag = "status", rename_all = "snake_case")]
61pub enum BrowserAssetVersionLifecycle {
62    Available,
63    Withdrawn {
64        withdrawn_at: chrono::DateTime<chrono::Utc>,
65    },
66}
67
68#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
69pub struct BrowserDatasetVersionDiscoveryRecord {
70    pub asset: AssetRef,
71    pub dataset: DatasetRef,
72    pub version: VersionRef,
73    pub major: i32,
74    pub minor: i32,
75    pub patch: i32,
76    #[serde(default, skip_serializing_if = "Option::is_none")]
77    pub version_label: Option<String>,
78    #[serde(default, skip_serializing_if = "Option::is_none")]
79    pub version_note: Option<String>,
80    #[serde(default, skip_serializing_if = "Option::is_none")]
81    pub doi: Option<String>,
82    #[serde(default, skip_serializing_if = "Option::is_none")]
83    pub is_latest: Option<bool>,
84    #[serde(default, skip_serializing_if = "Option::is_none")]
85    pub created_at: Option<chrono::DateTime<chrono::Utc>>,
86    pub lifecycle: BrowserAssetVersionLifecycle,
87    #[serde(default)]
88    pub tags: Vec<TagSummary>,
89    #[serde(default)]
90    pub access_conditions: Vec<BrowserResourceAccessCondition>,
91    pub access_request: BrowserDatasetAccessRequestReference,
92}
93
94#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
95pub struct BrowserDataFileVersionDiscoveryRecord {
96    pub asset: AssetRef,
97    pub datafile: DataFileRef,
98    pub version: VersionRef,
99    pub major: i32,
100    pub minor: i32,
101    pub patch: i32,
102    #[serde(default, skip_serializing_if = "Option::is_none")]
103    pub version_label: Option<String>,
104    #[serde(default, skip_serializing_if = "Option::is_none")]
105    pub version_note: Option<String>,
106    #[serde(default, skip_serializing_if = "Option::is_none")]
107    pub doi: Option<String>,
108    #[serde(default, skip_serializing_if = "Option::is_none")]
109    pub is_latest: Option<bool>,
110    #[serde(default, skip_serializing_if = "Option::is_none")]
111    pub created_at: Option<chrono::DateTime<chrono::Utc>>,
112    pub lifecycle: BrowserAssetVersionLifecycle,
113    pub format: String,
114    /// Size in bytes of the managed stored artifact, when known.
115    #[serde(default, skip_serializing_if = "Option::is_none")]
116    pub size_bytes: Option<u64>,
117    #[serde(default, skip_serializing_if = "Option::is_none")]
118    pub compressed: Option<bool>,
119    #[serde(default, skip_serializing_if = "Option::is_none")]
120    pub encrypted: Option<bool>,
121    #[serde(default)]
122    pub tags: Vec<TagSummary>,
123    #[serde(default)]
124    pub access_conditions: Vec<BrowserResourceAccessCondition>,
125    pub access_request: BrowserDataFileAccessRequestReference,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
129pub struct BrowserDatasetDiscoveryRecord {
130    pub asset: AssetRef,
131    pub dataset: DatasetRef,
132    pub study: StudyRef,
133    pub name: String,
134    #[serde(default, skip_serializing_if = "Option::is_none")]
135    pub description: Option<String>,
136    #[serde(default, skip_serializing_if = "Option::is_none")]
137    pub documentation: Option<String>,
138    #[serde(default)]
139    pub domains: Vec<DomainSummary>,
140    #[serde(default)]
141    pub tags: Vec<TagSummary>,
142    #[serde(default)]
143    pub versions: Vec<BrowserDatasetVersionDiscoveryRecord>,
144    pub access_request: BrowserDatasetAccessRequestReference,
145}
146
147#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
148pub struct BrowserDataFileDiscoveryRecord {
149    pub asset: AssetRef,
150    pub datafile: DataFileRef,
151    pub study: StudyRef,
152    pub name: String,
153    #[serde(default, skip_serializing_if = "Option::is_none")]
154    pub description: Option<String>,
155    #[serde(default, skip_serializing_if = "Option::is_none")]
156    pub documentation: Option<String>,
157    #[serde(default, skip_serializing_if = "Option::is_none")]
158    pub date_created: Option<chrono::DateTime<chrono::Utc>>,
159    #[serde(default)]
160    pub domains: Vec<DomainSummary>,
161    #[serde(default)]
162    pub tags: Vec<TagSummary>,
163    #[serde(default)]
164    pub versions: Vec<BrowserDataFileVersionDiscoveryRecord>,
165    pub access_request: BrowserDataFileAccessRequestReference,
166}
167
168/// Browser resource discovery is a broad Discovery metadata projection.
169///
170/// It intentionally excludes dataset rows, datafile bytes, previews,
171/// Content-derived summaries, storage paths, raw SQL, credentials, diagnostics,
172/// and runtime handles.
173#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
174pub struct BrowserResourceDiscoveryResponse {
175    pub authority: String,
176    pub datastore_id: crate::PublicUuid,
177    pub study: StudyRef,
178    #[serde(default)]
179    pub domains: Vec<DomainSummary>,
180    #[serde(default)]
181    pub datasets: Vec<BrowserDatasetDiscoveryRecord>,
182    #[serde(default)]
183    pub datafiles: Vec<BrowserDataFileDiscoveryRecord>,
184    #[serde(default, skip_serializing_if = "Option::is_none")]
185    pub datasets_empty_state: Option<BrowserResourceDiscoveryEmptyState>,
186    #[serde(default, skip_serializing_if = "Option::is_none")]
187    pub datafiles_empty_state: Option<BrowserResourceDiscoveryEmptyState>,
188    pub content_derived_summaries: BrowserContentSummaryPolicy,
189}