Skip to main content

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}