Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ROADMAP.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* [x] CLI with subcommands (init, start, drift, provenance, history, status, octad, doctor, gc, validate, version)
* [x] Manifest parser (verisimiser.toml with `[tier1]`/`[tier2]`/`[retention]` config)
* [x] Concerns octad fixed canonical (ADR-0004): Data, Metadata, Provenance, Lineage, Constraints, AccessControl, Temporal, Simulation
* [x] Tier 1 data types per concern (ProvenanceRecord, TemporalVersion, DriftReport, AccessPredicate)
* [x] Tier 1 data types per concern (ProvenanceEntry, TemporalVersion, DriftReport, AccessPredicate)
* [x] ABI module stubs (Idris2 + Zig FFI) and domain-tagged `compute_hash`
* [x] Drift categories pinned (ADR-0003): input / distance / threshold per category
* [x] README rewritten around concerns octad (V-L1-A2, #20)
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/TOPOLOGY.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ verisimiser/
│ ├── src/manifest/ — TOML manifest parsing (verisimiser.toml)
│ ├── src/tier1/ — Tier 1 piggyback data types
│ │ ├── drift.rs — DriftReport, DriftCategory (8 categories)
│ │ ├── provenance.rs — ProvenanceRecord, SHA-256 hash chain
│ │ ├── provenance.rs — SHA-256 hash-chain write path (canonical ProvenanceEntry lives in src/abi/)
│ │ └── temporal.rs — TemporalVersion, point-in-time snapshots
│ ├── src/tier2/ — Tier 2 overlay stubs (graph, vector, tensor, semantic, document, spatial)
│ ├── src/intercept/ — Per-backend interception strategies
Expand Down
71 changes: 14 additions & 57 deletions src/tier1/provenance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,69 +14,26 @@
// `abi::ProvenanceEntry::compute_hash` (domain-tagged + length-prefixed
// — see ADR-0002 / #27); this module just persists the entries.

use crate::abi::ProvenanceEntry;
use chrono::{DateTime, Utc};
use rusqlite::{params, Connection, TransactionBehavior};
use serde::{Deserialize, Serialize};

// =========================================================================
// Public re-export: the canonical entry shape
// Canonical entry shape
// =========================================================================

/// A single link in the provenance hash chain. Mirrors
/// `abi::ProvenanceEntry` 1:1 — kept here for backward compatibility
/// with code that imported `tier1::provenance::ProvenanceRecord`. New
/// callers should prefer the canonical type in `abi`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProvenanceRecord {
pub hash: String,
pub previous_hash: String,
pub entity_id: String,
pub operation: String,
pub actor: String,
pub timestamp: DateTime<Utc>,
pub before_snapshot: Option<String>,
pub transformation: Option<String>,
}

impl ProvenanceRecord {
/// Backward-compat shim. Computes the canonical hash via
/// `abi::ProvenanceEntry::compute_hash` rather than the older
/// string-based form.
pub fn compute_hash(
previous_hash: &str,
entity_id: &str,
operation: &str,
actor: &str,
timestamp: &DateTime<Utc>,
before_snapshot: Option<&str>,
transformation: Option<&str>,
) -> String {
ProvenanceEntry::compute_hash(
previous_hash,
entity_id,
operation,
actor,
timestamp,
before_snapshot,
transformation,
)
}

/// Verify that this record's stored hash matches a fresh recompute.
pub fn verify(&self) -> bool {
let expected = Self::compute_hash(
&self.previous_hash,
&self.entity_id,
&self.operation,
&self.actor,
&self.timestamp,
self.before_snapshot.as_deref(),
self.transformation.as_deref(),
);
self.hash == expected
}
}
// The provenance entry type is defined once, in `crate::abi`. It is the
// canonical representation used across the Rust CLI, the Idris2 ABI
// proofs, and the Zig FFI bridge, and it is the type persisted at the
// SQLite boundary by `append_provenance` below.
//
// This module previously carried a byte-for-byte duplicate struct
// (same fields, its own `compute_hash`/`verify`) under a different
// name. It was orphaned — nothing constructed it — and a second copy of
// the hash function is an integrity hazard: a future change to one
// `compute_hash` would silently leave the other broken (#26). The
// duplicate has been deleted; the canonical type is re-exported here so
// `tier1::provenance::ProvenanceEntry` resolves to the one definition.
pub use crate::abi::ProvenanceEntry;

// =========================================================================
// SQLite sidecar schema
Expand Down
Loading