.tasks/core/FSYNC-002-database-schema.md
Create persistent storage for sync state and history. Define SyncConduit and SyncGeneration entities with SeaORM migrations to track sync relationships and execution history.
Goal: Persistent storage enabling resumable sync, conflict detection, and sync history tracking.
Represents a sync relationship between two directories.
// Location: core/src/entities/sync_conduit.rs
pub struct Model {
pub id: i32,
pub uuid: Uuid,
// Endpoints - both must be Entry records of type Directory
pub source_entry_id: i32,
pub target_entry_id: i32,
// Configuration
pub sync_mode: String, // "mirror" | "bidirectional" | "selective"
pub enabled: bool,
pub schedule: String, // "instant" | "interval:5m" | "manual"
// Index settings
pub use_index_rules: bool, // Default: true
pub index_mode_override: Option<String>,
// Performance tuning
pub parallel_transfers: i32,
pub bandwidth_limit_mbps: Option<i32>,
// State tracking
pub last_sync_completed_at: Option<DateTimeUtc>,
pub sync_generation: i64,
pub last_sync_error: Option<String>,
// Statistics
pub total_syncs: i64,
pub files_synced: i64,
pub bytes_transferred: i64,
pub created_at: DateTimeUtc,
pub updated_at: DateTimeUtc,
}
Tracks individual sync operations for history and verification.
// Location: core/src/entities/sync_generation.rs
pub struct Model {
pub id: i32,
pub conduit_id: i32,
pub generation: i64,
pub started_at: DateTimeUtc,
pub completed_at: Option<DateTimeUtc>,
// Operation summary
pub files_copied: i32,
pub files_deleted: i32,
pub conflicts_resolved: i32,
pub bytes_transferred: i64,
pub errors_encountered: i32,
// Verification tracking (Trust Watcher approach)
pub verified_at: Option<DateTimeUtc>,
pub verification_status: String, // "unverified" | "waiting_watcher" | "verified" | "failed:reason"
}
SyncConduit Entity:
core/src/entities/sync_conduit.rsSyncGeneration Entity:
core/src/entities/sync_generation.rs// Location: core/src/migrations/m20250315_000001_create_sync_tables.rs
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
// Create sync_conduit table with all columns
// Create sync_generation table with all columns
// Create indexes:
// - idx_sync_conduit_enabled (enabled)
// - idx_sync_generation_conduit (conduit_id, generation)
}
Add migration to migration list in core/src/migrations/mod.rs
Export new entities in core/src/entities/mod.rs
CREATE TABLE sync_conduit (
id INTEGER PRIMARY KEY AUTOINCREMENT,
uuid BLOB NOT NULL UNIQUE,
source_entry_id INTEGER NOT NULL,
target_entry_id INTEGER NOT NULL,
sync_mode TEXT NOT NULL,
enabled INTEGER NOT NULL DEFAULT 1,
schedule TEXT NOT NULL DEFAULT 'manual',
use_index_rules INTEGER NOT NULL DEFAULT 1,
index_mode_override TEXT,
parallel_transfers INTEGER NOT NULL DEFAULT 3,
bandwidth_limit_mbps INTEGER,
last_sync_completed_at TEXT,
sync_generation INTEGER NOT NULL DEFAULT 0,
last_sync_error TEXT,
total_syncs INTEGER NOT NULL DEFAULT 0,
files_synced INTEGER NOT NULL DEFAULT 0,
bytes_transferred INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
FOREIGN KEY (source_entry_id) REFERENCES entry(id) ON DELETE CASCADE,
FOREIGN KEY (target_entry_id) REFERENCES entry(id) ON DELETE CASCADE
);
CREATE INDEX idx_sync_conduit_enabled ON sync_conduit(enabled);
CREATE TABLE sync_generation (
id INTEGER PRIMARY KEY AUTOINCREMENT,
conduit_id INTEGER NOT NULL,
generation INTEGER NOT NULL,
started_at TEXT NOT NULL,
completed_at TEXT,
files_copied INTEGER NOT NULL DEFAULT 0,
files_deleted INTEGER NOT NULL DEFAULT 0,
conflicts_resolved INTEGER NOT NULL DEFAULT 0,
bytes_transferred INTEGER NOT NULL DEFAULT 0,
errors_encountered INTEGER NOT NULL DEFAULT 0,
verified_at TEXT,
verification_status TEXT NOT NULL DEFAULT 'unverified',
FOREIGN KEY (conduit_id) REFERENCES sync_conduit(id) ON DELETE CASCADE
);
CREATE INDEX idx_sync_generation_conduit ON sync_generation(conduit_id, generation);
2025-10-15: COMPLETE
core/src/infra/db/entities/sync_conduit.rs, ~130 lines)core/src/infra/db/entities/sync_generation.rs, ~105 lines)m20251015_000002_create_sync_tables.rs, ~250 lines)cargo run --example test_migrationsync_conduit
├─> entry (source_entry_id)
├─> entry (target_entry_id)
└─> sync_generation (one-to-many)
Both source and target entries must be directories (kind=1). The conduit creates a directed relationship, though Bidirectional mode allows changes to flow both ways.
Verification Status Values:
unverified - Sync completed, not yet verifiedwaiting_watcher - Waiting for filesystem watcher to update indexwaiting_library_sync - Waiting for library sync to propagate changesverified - Verification query confirms consistencyfailed:<reason> - Verification detected remaining differencesWhy Trust Watcher? Option A (Trust Watcher) chosen over Option B (Eager Update) because: