Initial scaffold for kestrove-core
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "kv-store"
|
||||
description = "Local encrypted replica (SQLite). Holds ciphertext only."
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
publish.workspace = true
|
||||
|
||||
[dependencies]
|
||||
kv-proto.workspace = true
|
||||
uuid.workspace = true
|
||||
thiserror.workspace = true
|
||||
@@ -0,0 +1,42 @@
|
||||
//! Local encrypted replica (milestone M1, kestrove-spec/docs/07).
|
||||
//!
|
||||
//! The store holds the same `Envelope` bytes the server holds, plus sync
|
||||
//! bookkeeping. It never sees plaintext. Planned schema (rusqlite, bundled):
|
||||
//!
|
||||
//! ```sql
|
||||
//! CREATE TABLE vault (vault_id BLOB PRIMARY KEY, sealed_key TEXT, meta TEXT, cursor INTEGER, manifest_version INTEGER, manifest_hash BLOB);
|
||||
//! CREATE TABLE item (vault_id BLOB, item_id BLOB, revision INTEGER, deleted INTEGER,
|
||||
//! wrapped_item_key TEXT, payload TEXT,
|
||||
//! state TEXT CHECK(state IN ('clean','pending')), base_revision INTEGER, base_payload TEXT,
|
||||
//! PRIMARY KEY (vault_id, item_id));
|
||||
//! CREATE TABLE history (vault_id BLOB, item_id BLOB, revision INTEGER, wrapped_item_key TEXT, payload TEXT);
|
||||
//! ```
|
||||
|
||||
use kv_proto::ItemRecord;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum StoreError {
|
||||
#[error("storage I/O: {0}")]
|
||||
Io(String),
|
||||
#[error("not found")]
|
||||
NotFound,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SyncState {
|
||||
Clean,
|
||||
/// Edited locally; `base_revision` is what the edit was made against.
|
||||
Pending { base_revision: u64 },
|
||||
}
|
||||
|
||||
/// Storage backend. The SQLite implementation and an in-memory one for tests come in M1.
|
||||
pub trait Store: Send + Sync {
|
||||
fn cursor(&self, vault: Uuid) -> Result<u64, StoreError>;
|
||||
fn set_cursor(&self, vault: Uuid, revision: u64) -> Result<(), StoreError>;
|
||||
fn put_remote(&self, vault: Uuid, record: &ItemRecord) -> Result<(), StoreError>;
|
||||
fn put_local(&self, vault: Uuid, record: &ItemRecord, state: SyncState) -> Result<(), StoreError>;
|
||||
fn pending(&self, vault: Uuid) -> Result<Vec<(ItemRecord, u64)>, StoreError>;
|
||||
fn get(&self, vault: Uuid, item: Uuid) -> Result<(ItemRecord, SyncState), StoreError>;
|
||||
fn list(&self, vault: Uuid) -> Result<Vec<ItemRecord>, StoreError>;
|
||||
}
|
||||
Reference in New Issue
Block a user