Skip to main content

ahri_tre_protocol/
semantic_discovery.rs

1//! Browser-safe semantic catalog and provenance Discovery metadata DTOs.
2
3use crate::{
4    domain::DomainSummary,
5    refs::{
6        DataFileRef, DatasetRef, DomainRef, EntityRef, RelationRef, StudyRef, TagSummary,
7        TransformationRef,
8    },
9    resource_discovery::BrowserResourceAccessCondition,
10    study::BrowserContentSummaryPolicy,
11};
12use chrono::{DateTime, Utc};
13use serde::{Deserialize, Serialize};
14
15pub const BROWSER_SEMANTIC_ERROR_TARGET_DATASTORE: &str = "datastore";
16pub const BROWSER_SEMANTIC_ERROR_TARGET_DATASTORE_UNAVAILABLE: &str = "datastore_unavailable";
17pub const BROWSER_SEMANTIC_ERROR_TARGET_STUDY: &str = "study";
18pub const BROWSER_SEMANTIC_ERROR_TARGET_SERVICE: &str = "semantic_catalog";
19
20#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
21pub struct BrowserSemanticCatalogDiscoveryRequest {
22    pub datastore_id: crate::PublicUuid,
23    pub study: StudyRef,
24}
25
26#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
27pub struct BrowserSemanticCatalogDiscoveryEmptyState {
28    pub code: String,
29    pub message: String,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
33pub struct BrowserEntityDiscoveryRecord {
34    pub entity: EntityRef,
35    pub domain: DomainRef,
36    pub name: String,
37    #[serde(default, skip_serializing_if = "Option::is_none")]
38    pub description: Option<String>,
39    #[serde(default)]
40    pub tags: Vec<TagSummary>,
41}
42
43#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
44pub struct BrowserEntityRelationDiscoveryRecord {
45    pub relation: RelationRef,
46    pub domain: DomainRef,
47    pub name: String,
48    #[serde(default, skip_serializing_if = "Option::is_none")]
49    pub description: Option<String>,
50    pub subject_entity: EntityRef,
51    pub object_entity: EntityRef,
52    #[serde(default)]
53    pub tags: Vec<TagSummary>,
54}
55
56/// A public researcher identity approved for broad provenance discovery.
57///
58/// Arbitrary datastore actor strings are not accepted as responsible people.
59/// The app projection emits this record only when the persisted actor uses an
60/// explicit ORCID-backed datastore-role namespace and carries a checksum-valid
61/// ORCID. A bare ORCID-shaped actor string is not an approval marker.
62#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
63pub struct BrowserProvenanceResponsiblePerson {
64    pub orcid: String,
65}
66
67/// A browser-navigable catalogue reference with explicit lineage direction.
68///
69/// These references identify public catalogue metadata only. They never carry
70/// storage locations, digests, repository evidence, or content authority.
71#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
72#[serde(tag = "kind", rename_all = "snake_case")]
73pub enum BrowserProvenanceCatalogueReference {
74    Dataset {
75        study: StudyRef,
76        dataset: DatasetRef,
77    },
78    DataFile {
79        study: StudyRef,
80        datafile: DataFileRef,
81    },
82}
83
84/// A deliberately small provenance projection. Repository URLs, commit hashes,
85/// file paths, private actors, record counts, and workflow internals remain
86/// outside broad discovery.
87#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
88pub struct BrowserProvenanceSummaryDiscoveryRecord {
89    pub transformation: TransformationRef,
90    pub transformation_type: String,
91    pub description: String,
92    #[serde(default, skip_serializing_if = "Option::is_none")]
93    pub responsible_person: Option<BrowserProvenanceResponsiblePerson>,
94    #[serde(default, skip_serializing_if = "Option::is_none")]
95    pub transformation_date: Option<DateTime<Utc>>,
96    #[serde(default)]
97    pub inputs: Vec<BrowserProvenanceCatalogueReference>,
98    #[serde(default)]
99    pub outputs: Vec<BrowserProvenanceCatalogueReference>,
100}
101
102/// Browser semantic catalog discovery is a metadata-only projection.
103///
104/// It intentionally excludes semantic instance values, protected content,
105/// Content-derived summaries, raw SQL, credentials, paths, runtime handles,
106/// and privileged workflow evidence.
107#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
108pub struct BrowserSemanticCatalogDiscoveryResponse {
109    pub authority: String,
110    pub datastore_id: crate::PublicUuid,
111    pub study: StudyRef,
112    #[serde(default)]
113    pub domains: Vec<DomainSummary>,
114    #[serde(default)]
115    pub entities: Vec<BrowserEntityDiscoveryRecord>,
116    #[serde(default)]
117    pub relations: Vec<BrowserEntityRelationDiscoveryRecord>,
118    #[serde(default)]
119    pub provenance_summaries: Vec<BrowserProvenanceSummaryDiscoveryRecord>,
120    #[serde(default)]
121    pub access_conditions: Vec<BrowserResourceAccessCondition>,
122    #[serde(default, skip_serializing_if = "Option::is_none")]
123    pub empty_state: Option<BrowserSemanticCatalogDiscoveryEmptyState>,
124    pub content_derived_summaries: BrowserContentSummaryPolicy,
125}