enact_core/kernel/persistence/mod.rs
1//! Persistence Layer - Storage Abstractions
2//!
3//! This module defines the core storage traits for the Enact execution engine.
4//! The kernel interacts only with these traits; concrete implementations live
5//! in the `enact-persistence` crate.
6//!
7//! ## Store Roles
8//!
9//! | Store | Role | Mutable? | Authoritative? |
10//! |-------|------|----------|----------------|
11//! | EventStore | Source of truth | Append-only | Yes |
12//! | StateStore | Cache/snapshot | Yes | No |
13//! | VectorStore | Semantic recall | Yes | No |
14//!
15//! ## Key Invariants
16//!
17//! 1. Kernel NEVER imports concrete implementations
18//! 2. All stores implement `StorageBackend` for mode validation
19//! 3. EventStore is append-only and authoritative
20//! 4. StateStore/VectorStore are non-authoritative caches
21//!
22//! @see docs/TECHNICAL/14-PERSISTENCE-LAYER.md
23
24mod event_store;
25mod message_store;
26mod state_store;
27mod vector_store;
28
29pub use event_store::{EventStore, ExecutionEventData, StoredEvent};
30pub use message_store::{
31 CostInfo, ExecutionStats, FinishReason, InMemoryMessageStore, Message, MessageMetadata,
32 MessagePart, MessageRole, MessageStore, Thread, TokenUsage,
33};
34pub use state_store::{ExecutionSnapshot, StateStore, StateStoreJsonExt};
35pub use vector_store::{
36 CollectionInfo, DistanceMetric, VectorDocument, VectorFilter, VectorSearchResult, VectorStore,
37};
38
39use async_trait::async_trait;
40
41/// Base trait for all storage backends
42///
43/// This trait provides metadata about the backend's capabilities,
44/// enabling runtime mode validation (e.g., air-gapped mode rejection
45/// of network-requiring backends).
46#[async_trait]
47pub trait StorageBackend: Send + Sync {
48 /// Human-readable name of this backend (e.g., "sqlite", "postgres", "qdrant")
49 fn name(&self) -> &str;
50
51 /// Does this backend require network access?
52 ///
53 /// Returns `true` for backends like Postgres, Redis, remote Qdrant.
54 /// Returns `false` for SQLite, filesystem, embedded Qdrant.
55 fn requires_network(&self) -> bool;
56
57 /// Can this backend operate in air-gapped mode?
58 ///
59 /// Default implementation returns `!requires_network()`.
60 fn supports_air_gapped(&self) -> bool {
61 !self.requires_network()
62 }
63
64 /// Health check - verify the backend is operational
65 ///
66 /// Should return `Ok(())` if the backend is ready to accept operations.
67 /// Should return an error if the backend is unavailable or misconfigured.
68 async fn health_check(&self) -> anyhow::Result<()>;
69
70 /// Graceful shutdown
71 ///
72 /// Called when the runtime is shutting down. Implementations should
73 /// flush any pending writes and close connections.
74 async fn shutdown(&self) -> anyhow::Result<()> {
75 Ok(())
76 }
77}
78
79/// Store guarantees - documented contracts for each store type
80#[allow(clippy::mixed_attributes_style)]
81pub mod guarantees {
82 //! # Store Guarantees
83 //!
84 //! These guarantees are contractual and must be tested.
85 //!
86 //! ## EventStore
87 //! - **Durability**: Event is durable before `append()` returns
88 //! - **Ordering**: Events are strictly ordered per execution
89 //! - **Immutability**: Events are append-only, never modified
90 //! - **Authority**: EventStore is the source of truth
91 //!
92 //! ## StateStore
93 //! - **Durability**: Best-effort - may be lost on failure
94 //! - **Freshness**: May be stale - always verify with EventStore
95 //! - **Authority**: Non-authoritative - cache only
96 //! - **Availability**: Designed for fast reads, not durability
97 //!
98 //! ## VectorStore
99 //! - **Consistency**: Eventually consistent
100 //! - **Authority**: Non-authoritative - for recall only
101 //! - **Availability**: Search may return stale results
102 //! - **Durability**: Documents are durable after `upsert()` returns
103}