use serde::{Deserialize, Serialize};
use crate::grounding::{Capabilities, ParserIdentity};
use crate::verify_types::CapabilityLimit;
pub const EVIDENCE_ANCHOR_REQUEST_ARTIFACT_TYPE: &str = "ethos.evidence_anchor_request.v1";
pub const EVIDENCE_ANCHOR_REPORT_ARTIFACT_TYPE: &str = "ethos.evidence_anchor_report.v1";
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct EvidenceAnchorRequest {
pub artifact_type: String,
pub schema_version: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_fingerprint: Option<String>,
pub evidence_refs: Vec<EvidenceRef>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct EvidenceRef {
pub evidence_id: String,
pub evidence_kind: EvidenceKind,
pub required_anchor_level: AnchorLevel,
pub locator: EvidenceLocator,
#[serde(skip_serializing_if = "Option::is_none")]
pub expected_text: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expected_text_sha256: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub text_normalization_profile: Option<TextNormalizationProfile>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EvidenceKind {
Page,
Text,
TextRegion,
TableCell,
Region,
Other,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AnchorLevel {
None,
Page,
Text,
Bbox,
TextBbox,
TableCell,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct EvidenceLocator {
#[serde(skip_serializing_if = "Option::is_none")]
pub page_index: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub element_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub span_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bbox: Option<[i64; 4]>,
#[serde(skip_serializing_if = "Option::is_none")]
pub table_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cell: Option<AnchorCellRef>,
#[serde(skip_serializing_if = "Option::is_none")]
pub coordinate_profile: Option<CoordinateProfile>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AnchorCellRef {
pub row: u32,
pub col: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TextNormalizationProfile {
EthosCollapseWhitespaceV1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CoordinateProfile {
EthosQuantizedTopLeftV1,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct EvidenceAnchorReport {
pub artifact_type: String,
pub schema_version: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_fingerprint: Option<String>,
pub grounding: EvidenceAnchorGrounding,
pub anchors: Vec<EvidenceAnchor>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct EvidenceAnchorGrounding {
pub parser: ParserIdentity,
pub capabilities: Capabilities,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct EvidenceAnchor {
pub evidence_id: String,
pub evidence_kind: EvidenceKind,
pub anchor_status: AnchorStatus,
pub required_anchor_level: AnchorLevel,
pub achieved_anchor_level: AnchorLevel,
pub checks: AnchorChecks,
pub capability_limits: Vec<CapabilityLimit>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AnchorStatus {
Bound,
Mismatch,
NotFound,
StaleFingerprint,
CapabilityLimited,
UnsupportedEvidenceKind,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AnchorChecks {
pub fingerprint: FingerprintCheck,
pub page: PageCheck,
pub text: TextCheck,
pub bbox: BboxCheck,
pub table_cell: TableCellCheck,
}
impl Default for AnchorChecks {
fn default() -> Self {
AnchorChecks {
fingerprint: FingerprintCheck::NotChecked,
page: PageCheck::NotChecked,
text: TextCheck::NotChecked,
bbox: BboxCheck::NotChecked,
table_cell: TableCellCheck::NotChecked,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum FingerprintCheck {
Matched,
Stale,
NotChecked,
CapabilityLimited,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PageCheck {
Found,
NotFound,
NotChecked,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TextCheck {
Matched,
Mismatch,
NotFound,
NotChecked,
CapabilityLimited,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum BboxCheck {
Valid,
Invalid,
NotFound,
NotChecked,
CapabilityLimited,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TableCellCheck {
Matched,
Mismatch,
NotFound,
NotChecked,
CapabilityLimited,
}