use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use super::RevisionProjectionRow;
use crate::model::{
ActorId, DiffSnapshot, EventId, JournalId, ObjectId, ReviewEndpoint, RevisionId,
RevisionSource, TrackId,
};
use crate::session::assessment::{AssessmentView, CurrentAssessmentView};
use crate::session::input_request::InputRequestView;
use crate::session::observation::ObservationView;
use crate::session::state::ProjectionDiagnostic;
use crate::session::workflow::ValidationCheckView;
use crate::session::{
ActorAttributesMap, DelegationMap, EndorsementReadback, EventVerificationPolicy,
EventVerificationStatus, PrincipalResolution, RemovalPolicy, RevisionCommitRangeView, TrustSet,
principal_resolution_for_writer,
};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RevisionShowOptions {
pub(super) repo: PathBuf,
pub(super) revision_id: Option<RevisionId>,
pub(super) track: Option<String>,
pub(super) include_body: bool,
pub(super) verification_policy: Option<EventVerificationPolicy>,
pub(super) trust_set: TrustSet,
pub(super) removal_policy: RemovalPolicy,
pub(super) actor_attributes: Option<ActorAttributesMap>,
pub(super) delegation_map: Option<DelegationMap>,
pub(super) read_for_display: bool,
pub(super) exact: bool,
}
impl RevisionShowOptions {
pub fn new(repo: impl AsRef<Path>) -> Self {
Self {
repo: repo.as_ref().to_path_buf(),
revision_id: None,
track: None,
include_body: false,
verification_policy: None,
trust_set: TrustSet::default(),
removal_policy: RemovalPolicy::default(),
actor_attributes: None,
delegation_map: None,
read_for_display: false,
exact: false,
}
}
pub fn with_revision_id(mut self, revision_id: RevisionId) -> Self {
self.revision_id = Some(revision_id);
self
}
pub fn with_track(mut self, track: impl Into<String>) -> Self {
self.track = Some(track.into());
self
}
pub fn with_include_body(mut self, include_body: bool) -> Self {
self.include_body = include_body;
self
}
pub fn with_verification_policy(mut self, policy: EventVerificationPolicy) -> Self {
self.verification_policy = Some(policy);
self
}
pub fn with_trust_set(mut self, trust_set: TrustSet) -> Self {
self.trust_set = trust_set;
self
}
pub fn with_removal_policy(mut self, removal_policy: RemovalPolicy) -> Self {
self.removal_policy = removal_policy;
self
}
pub fn with_actor_attributes(mut self, actor_attributes: Option<ActorAttributesMap>) -> Self {
self.actor_attributes = actor_attributes;
self
}
pub fn with_delegation_map(mut self, delegation_map: DelegationMap) -> Self {
self.delegation_map = Some(delegation_map);
self
}
pub fn with_read_for_display(mut self, value: bool) -> Self {
self.read_for_display = value;
self
}
pub fn with_exact(mut self, value: bool) -> Self {
self.exact = value;
self
}
}
pub(super) fn principal_diagnostics<'a>(
members: impl Iterator<Item = (&'a ActorId, &'a str)>,
map: &DelegationMap,
) -> Vec<ProjectionDiagnostic> {
let mut diagnostics = Vec::new();
for (writer_actor, occurred_at) in members {
let agent = writer_actor.as_str();
match principal_resolution_for_writer(writer_actor, map, occurred_at) {
Some(PrincipalResolution::None(reason)) => diagnostics.push(ProjectionDiagnostic {
code: "principal_unresolvable".to_owned(),
message: format!(
"agent {agent} has no resolvable principal at {occurred_at} ({})",
reason.as_str()
),
}),
Some(PrincipalResolution::Ambiguous(principals)) => {
let candidates = principals
.iter()
.map(ActorId::as_str)
.collect::<Vec<_>>()
.join(", ");
diagnostics.push(ProjectionDiagnostic {
code: "principal_ambiguous".to_owned(),
message: format!(
"agent {agent} resolves to multiple principals at {occurred_at}: {candidates}"
),
});
}
Some(PrincipalResolution::Resolved(_)) | None => {}
}
}
diagnostics
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct MemberReadback {
pub verification_status: Option<EventVerificationStatus>,
pub endorsements: Vec<EndorsementReadback>,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum SnapshotContentState {
#[default]
Present,
SuppressedPresent,
PhysicallyRemoved,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RevisionShowResult {
pub event_set_hash: String,
pub event_count: usize,
pub revision: RevisionProjectionIdentity,
pub snapshot: DiffSnapshot,
pub removed_snapshot_content_hash: Option<String>,
pub snapshot_content_state: SnapshotContentState,
pub filters: RevisionShowFilters,
pub summary: RevisionProjectionSummary,
pub current_assessment: CurrentAssessmentView,
pub observations: Vec<ObservationView>,
pub input_requests: Vec<InputRequestView>,
pub assessments: Vec<AssessmentView>,
pub validation_checks: Vec<ValidationCheckView>,
pub rows: Vec<RevisionProjectionRow>,
pub commit_range: RevisionCommitRangeView,
pub member_readbacks: BTreeMap<EventId, MemberReadback>,
pub diagnostics: Vec<ProjectionDiagnostic>,
}
impl RevisionShowResult {
pub fn snapshot_is_removed(&self) -> bool {
self.removed_snapshot_content_hash.is_some()
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RevisionProjectionIdentity {
pub id: RevisionId,
pub journal_id: JournalId,
pub source: RevisionSource,
pub base: ReviewEndpoint,
pub target: ReviewEndpoint,
pub revision_id: RevisionId,
pub object_id: ObjectId,
pub object_artifact_content_hash: String,
pub capture_event_id: EventId,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RevisionShowFilters {
pub revision_id: RevisionId,
pub track_id: Option<TrackId>,
pub include_body: bool,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct RevisionProjectionSummary {
pub file_count: usize,
pub row_count: usize,
pub narrative_row_count: usize,
pub snapshot_row_count: usize,
pub snapshot_remainder_row_count: usize,
pub observation_count: usize,
pub input_request_count: usize,
pub assessment_count: usize,
pub validation_check_count: usize,
}