CRUMB a card from devarno-cloud

TNP System Architecture Overview

tnp beginner 5 min read

ELI5

A city’s street-map only shows you one version of the city, but TNP is like a map that remembers every historical layout and lets you branch off into “what if the highway had gone this way instead” — each branch is a real, navigable timeline, and you can merge them back together later.

Technical Deep Dive

Module Boundaries

src/lib.rs defines TemporalNavigationProtocol and re-exports six sub-modules:

ModuleExported typesResponsibility
dagDAGNode, TemporalDAG, NodeIDDirected acyclic graph of operations
timelineTimeline, TimelineID, TimelineStatusPer-branch operation lists
forkForkInfo, ForkAnalyzerFork detection and storage overhead analysis
mergeTimelineMerger, MergeStrategyCanonical/KeepBranches/Manual merge
navigationNavigationIndex, TimelineNavigatorTimestamp-based historical queries
compressionDeltaEncoder, CompressionStatsDelta storage for branch timelines

Top-level Struct

pub struct TemporalNavigationProtocol {
config: TNPConfig,
dag: TemporalDAG,
timelines: HashMap<TimelineID, Timeline>,
canonical_timeline: TimelineID,
}

The canonical timeline is always created at construction time with TimelineStatus::Official. All other timelines are branches with a status of Draft, Experimental, or Archived.

Configuration Defaults (TNPConfig)

max_active_timelines: 100
archive_threshold_days: 30
enable_compression: true
max_storage_overhead_percent: 500 // 5× canonical

Component Interaction Diagram

flowchart TD
TNP["TemporalNavigationProtocol"]
TNP --> DAG["TemporalDAG\n(dag.rs)"]
TNP --> TL["HashMap<TimelineID, Timeline>\n(timeline.rs)"]
TNP --> CANON["canonical_timeline: TimelineID"]
DAG --> NODE["DAGNode\n(id, operation, state_hash,\nparents, timestamp_ms, replica_id)"]
TL --> TOBJ["Timeline\n(id, status, nodes, timestamps)"]
TOBJ -->|status| STATUS["Official | Draft\nExperimental | Archived"]
TNP -->|uses| FORK["ForkAnalyzer (fork.rs)"]
TNP -->|uses| MERGE["TimelineMerger (merge.rs)"]
TNP -->|uses| NAV["TimelineNavigator (navigation.rs)"]
TNP -->|uses| DELTA["DeltaEncoder (compression.rs)"]

API Surface

MethodDescription
add_operation(op_data, state_hash)Appends node to canonical timeline
fork_timeline(name, status)Creates branch; returns new TimelineID
navigate_to_timestamp(id, ts_ms)Returns Vec<NodeID> before timestamp
merge_timeline(id)Merges branch into canonical
current_state_hash()XOR-fold state hash of canonical
fork_probability()Ratio: fork_nodes / total_nodes
timeline_stats()HashMap of aggregate counters

Key Terms

  • TemporalNavigationProtocol → top-level coordinator struct; holds config, DAG, and all timelines
  • canonical_timeline → the always-present TimelineStatus::Official timeline seeded at TimelineID::new(b"canonical")
  • TNPConfig → configuration struct controlling timeline limits and compression toggles
  • TNPError → enum of five error variants: TimelineNotFound, OperationNotFound, MergeConflict, InvalidStateTransition, StorageError

Q&A

Q: What error is returned when fork_timeline is called but timelines.len() >= max_active_timelines? A: TNPError::InvalidStateTransition("Too many active timelines").

Q: Does add_operation add the node to all timelines or only the canonical? A: Only the canonical timeline. The node is inserted into self.dag via dag.add_node, then a reference is pushed to self.timelines[canonical_timeline].nodes.

Q: What does timeline_stats count as “active”? A: Timelines whose status is Official or Draft; Experimental and Archived are excluded.

Examples

let mut tnp = TemporalNavigationProtocol::new();
let node = tnp.add_operation(b"insert:hello".to_vec(), vec![0xAB]).unwrap();
let branch = tnp.fork_timeline("draft-v2".to_string(), TimelineStatus::Draft).unwrap();
let stats = tnp.timeline_stats();
// stats["total_timelines"] == 2
// stats["active_timelines"] == 2 (Official + Draft)

neighbors on the map