foundry_mcp/core/backends/
mod.rs

1//! Backend abstraction for pluggable storage systems
2
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5
6use crate::types::{
7    project::{Project, ProjectConfig, ProjectMetadata},
8    spec::{Spec, SpecConfig, SpecFileType, SpecMetadata},
9};
10
11/// Core backend trait defining storage contracts
12#[async_trait::async_trait]
13pub trait FoundryBackend: Send + Sync {
14    // Project operations
15    async fn create_project(&self, config: ProjectConfig) -> Result<Project>;
16    async fn project_exists(&self, name: &str) -> Result<bool>;
17    async fn list_projects(&self) -> Result<Vec<ProjectMetadata>>;
18    async fn load_project(&self, name: &str) -> Result<Project>;
19
20    // Spec operations
21    async fn create_spec(&self, config: SpecConfig) -> Result<Spec>;
22    async fn list_specs(&self, project_name: &str) -> Result<Vec<SpecMetadata>>;
23    async fn load_spec(&self, project_name: &str, spec_name: &str) -> Result<Spec>;
24    async fn update_spec_content(
25        &self,
26        project_name: &str,
27        spec_name: &str,
28        file_type: SpecFileType,
29        content: &str,
30    ) -> Result<()>;
31    async fn delete_spec(&self, project_name: &str, spec_name: &str) -> Result<()>;
32
33    // Helper operations
34    async fn get_latest_spec(&self, project_name: &str) -> Result<Option<SpecMetadata>>;
35    async fn count_specs(&self, project_name: &str) -> Result<usize>;
36
37    // Capabilities introspection
38    fn capabilities(&self) -> BackendCapabilities;
39}
40
41/// Backend capability flags
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct BackendCapabilities {
44    pub supports_documents: bool,
45    pub supports_subtasks: bool,
46    pub url_deeplinks: bool,
47    pub atomic_replace: bool,
48    pub strong_consistency: bool,
49}
50
51/// Resource locator for different backend types
52#[derive(Debug, Clone, Serialize, Deserialize)]
53#[serde(rename_all = "snake_case")]
54pub enum ResourceLocator {
55    FilesystemPath(String),
56    // Future: Linear { project_id: String, issue_id: String, urls: Vec<String> },
57}
58
59/// Content store abstraction for EditEngine I/O via façade
60#[async_trait::async_trait]
61pub trait SpecContentStore: Send + Sync {
62    async fn read_spec_file(
63        &self,
64        project_name: &str,
65        spec_name: &str,
66        file_type: SpecFileType,
67    ) -> Result<String>;
68
69    async fn write_spec_file(
70        &self,
71        project_name: &str,
72        spec_name: &str,
73        file_type: SpecFileType,
74        content: &str,
75    ) -> Result<()>;
76
77    async fn is_file_modified(
78        &self,
79        project_name: &str,
80        spec_name: &str,
81        file_type: SpecFileType,
82        new_content: &str,
83    ) -> Result<bool>;
84}
85
86// Re-export filesystem backend
87pub mod filesystem;
88
89// Re-export memory backend for testing
90pub mod memory;
91
92// Backend testing infrastructure
93mod tests;
94
95// Re-export factory functions
96pub use crate::core::foundry::get_default_foundry;