mod dynamodb;
mod firebase;
mod sqlite;
use std::path::Path;
use std::sync::Arc;
use crate::infra::cluster::registry::WorkerRegistryRecord;
use crate::infra::execution::placement::ProjectRuntimePlacement;
use crate::platform::error::PlatformError;
use crate::platform::model::{
DataAdapterKind, HubAssetPackage, HubAssetVersion, HubAuthority, HubPublisher, HubToken,
McpSession, PipelineInvocationEntry, PipelineInvocationLogStats, PipelineMeta,
PlatformHubRepository, PlatformOffice, PlatformOfficeNode, PlatformProject,
PlatformServiceInstance, PlatformUser, ProjectCredential, ProjectDbConnection,
ProjectHubRepository, ProjectInvite, ProjectMember, ProjectOperationRecord, ProjectPolicy,
ProjectPolicyBinding, StoredUser,
};
pub trait DataAdapter: Send + Sync {
fn id(&self) -> &'static str;
fn get_user_auth(&self, owner: &str) -> Result<Option<StoredUser>, PlatformError>;
fn put_user(&self, user: &StoredUser) -> Result<(), PlatformError>;
fn list_users(&self) -> Result<Vec<PlatformUser>, PlatformError>;
fn get_project(
&self,
owner: &str,
project: &str,
) -> Result<Option<PlatformProject>, PlatformError>;
fn put_project(&self, project: &PlatformProject) -> Result<(), PlatformError>;
fn list_projects(&self, owner: &str) -> Result<Vec<PlatformProject>, PlatformError>;
fn delete_project(&self, owner: &str, project: &str) -> Result<(), PlatformError>;
fn get_project_credential(
&self,
owner: &str,
project: &str,
credential_id: &str,
) -> Result<Option<ProjectCredential>, PlatformError>;
fn put_project_credential(&self, credential: &ProjectCredential) -> Result<(), PlatformError>;
fn list_project_credentials(
&self,
owner: &str,
project: &str,
) -> Result<Vec<ProjectCredential>, PlatformError>;
fn delete_project_credential(
&self,
owner: &str,
project: &str,
credential_id: &str,
) -> Result<(), PlatformError>;
fn get_project_db_connection(
&self,
owner: &str,
project: &str,
connection_slug: &str,
) -> Result<Option<ProjectDbConnection>, PlatformError>;
fn put_project_db_connection(
&self,
connection: &ProjectDbConnection,
) -> Result<(), PlatformError>;
fn list_project_db_connections(
&self,
owner: &str,
project: &str,
) -> Result<Vec<ProjectDbConnection>, PlatformError>;
fn delete_project_db_connection(
&self,
owner: &str,
project: &str,
connection_slug: &str,
) -> Result<(), PlatformError>;
fn put_project_hub_repository(
&self,
repository: &ProjectHubRepository,
) -> Result<(), PlatformError> {
let _ = repository;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"hub repositories are not supported by this adapter",
))
}
fn list_project_hub_repositories(
&self,
owner: &str,
project: &str,
) -> Result<Vec<ProjectHubRepository>, PlatformError> {
let _ = (owner, project);
Ok(vec![])
}
fn delete_project_hub_repository(
&self,
owner: &str,
project: &str,
repository_id: &str,
) -> Result<(), PlatformError> {
let _ = (owner, project, repository_id);
Ok(())
}
fn put_platform_hub_repository(
&self,
repository: &PlatformHubRepository,
) -> Result<(), PlatformError> {
let _ = repository;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"platform hub repositories are not supported by this adapter",
))
}
fn list_platform_hub_repositories(
&self,
owner: &str,
) -> Result<Vec<PlatformHubRepository>, PlatformError> {
let _ = owner;
Ok(vec![])
}
fn delete_platform_hub_repository(
&self,
owner: &str,
repository_id: &str,
) -> Result<(), PlatformError> {
let _ = (owner, repository_id);
Ok(())
}
fn put_hub_publisher(&self, publisher: &HubPublisher) -> Result<(), PlatformError> {
let _ = publisher;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"hub publishers are not supported by this adapter",
))
}
fn list_hub_publishers(
&self,
owner: &str,
project: &str,
) -> Result<Vec<HubPublisher>, PlatformError> {
let _ = (owner, project);
Ok(vec![])
}
fn get_hub_publisher(
&self,
owner: &str,
project: &str,
publisher_id: &str,
) -> Result<Option<HubPublisher>, PlatformError> {
let _ = (owner, project, publisher_id);
Ok(None)
}
fn delete_hub_publisher(
&self,
owner: &str,
project: &str,
publisher_id: &str,
) -> Result<(), PlatformError> {
let _ = (owner, project, publisher_id);
Ok(())
}
fn put_hub_asset_package(&self, package: &HubAssetPackage) -> Result<(), PlatformError> {
let _ = package;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"hub packages are not supported by this adapter",
))
}
fn list_hub_asset_packages(&self) -> Result<Vec<HubAssetPackage>, PlatformError> {
Ok(vec![])
}
fn get_hub_asset_package(
&self,
package_id: &str,
) -> Result<Option<HubAssetPackage>, PlatformError> {
let _ = package_id;
Ok(None)
}
fn put_hub_asset_version(&self, version: &HubAssetVersion) -> Result<(), PlatformError> {
let _ = version;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"hub package versions are not supported by this adapter",
))
}
fn list_hub_asset_versions(
&self,
package_id: &str,
) -> Result<Vec<HubAssetVersion>, PlatformError> {
let _ = package_id;
Ok(vec![])
}
fn get_hub_asset_version(
&self,
package_id: &str,
version: &str,
) -> Result<Option<HubAssetVersion>, PlatformError> {
let _ = (package_id, version);
Ok(None)
}
fn put_hub_token(&self, token: &HubToken) -> Result<(), PlatformError> {
let _ = token;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"hub tokens are not supported by this adapter",
))
}
fn get_hub_token(&self, token_id: &str) -> Result<Option<HubToken>, PlatformError> {
let _ = token_id;
Ok(None)
}
fn list_hub_tokens(&self, owner: &str, project: &str) -> Result<Vec<HubToken>, PlatformError> {
let _ = (owner, project);
Ok(vec![])
}
fn list_all_hub_tokens(&self) -> Result<Vec<HubToken>, PlatformError> {
Ok(vec![])
}
fn delete_hub_token(&self, token_id: &str) -> Result<(), PlatformError> {
let _ = token_id;
Ok(())
}
fn put_pipeline_meta(&self, meta: &PipelineMeta) -> Result<(), PlatformError>;
fn delete_pipeline_meta(
&self,
owner: &str,
project: &str,
file_rel_path: &str,
) -> Result<(), PlatformError>;
fn list_pipeline_meta(
&self,
owner: &str,
project: &str,
) -> Result<Vec<PipelineMeta>, PlatformError>;
fn put_project_policy(&self, policy: &ProjectPolicy) -> Result<(), PlatformError>;
fn list_project_policies(
&self,
owner: &str,
project: &str,
) -> Result<Vec<ProjectPolicy>, PlatformError>;
fn put_project_policy_binding(
&self,
binding: &ProjectPolicyBinding,
) -> Result<(), PlatformError>;
fn list_project_policy_bindings(
&self,
owner: &str,
project: &str,
) -> Result<Vec<ProjectPolicyBinding>, PlatformError>;
fn delete_project_policy(
&self,
owner: &str,
project: &str,
policy_id: &str,
) -> Result<(), PlatformError>;
fn delete_project_policy_binding(
&self,
owner: &str,
project: &str,
subject_id: &str,
) -> Result<(), PlatformError>;
fn get_project_member(
&self,
owner: &str,
project: &str,
user_id: &str,
) -> Result<Option<ProjectMember>, PlatformError>;
fn put_project_member(&self, member: &ProjectMember) -> Result<(), PlatformError>;
fn list_project_members(
&self,
owner: &str,
project: &str,
) -> Result<Vec<ProjectMember>, PlatformError>;
fn delete_project_member(
&self,
owner: &str,
project: &str,
user_id: &str,
) -> Result<(), PlatformError>;
fn get_project_invite(
&self,
owner: &str,
project: &str,
invite_id: &str,
) -> Result<Option<ProjectInvite>, PlatformError>;
fn put_project_invite(&self, invite: &ProjectInvite) -> Result<(), PlatformError>;
fn list_project_invites(
&self,
owner: &str,
project: &str,
) -> Result<Vec<ProjectInvite>, PlatformError>;
fn delete_project_invite(
&self,
owner: &str,
project: &str,
invite_id: &str,
) -> Result<(), PlatformError>;
fn get_hub_authority(
&self,
owner: &str,
project: &str,
) -> Result<Option<HubAuthority>, PlatformError> {
let _ = (owner, project);
Ok(None)
}
fn put_hub_authority(&self, authority: &HubAuthority) -> Result<(), PlatformError> {
let _ = authority;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"hub authorities are not supported by this adapter",
))
}
fn list_hub_authorities(&self) -> Result<Vec<HubAuthority>, PlatformError> {
Ok(vec![])
}
fn get_platform_office(
&self,
office_id: &str,
) -> Result<Option<PlatformOffice>, PlatformError> {
let _ = office_id;
Ok(None)
}
fn put_platform_office(&self, office: &PlatformOffice) -> Result<(), PlatformError> {
let _ = office;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"platform offices are not supported by this adapter",
))
}
fn list_platform_offices(&self) -> Result<Vec<PlatformOffice>, PlatformError> {
Ok(vec![])
}
fn get_platform_service_instance(
&self,
service_instance_id: &str,
) -> Result<Option<PlatformServiceInstance>, PlatformError> {
let _ = service_instance_id;
Ok(None)
}
fn put_platform_service_instance(
&self,
service: &PlatformServiceInstance,
) -> Result<(), PlatformError> {
let _ = service;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"platform service instances are not supported by this adapter",
))
}
fn list_platform_service_instances(
&self,
) -> Result<Vec<PlatformServiceInstance>, PlatformError> {
Ok(vec![])
}
fn get_platform_office_node(
&self,
node_id: &str,
) -> Result<Option<PlatformOfficeNode>, PlatformError> {
let _ = node_id;
Ok(None)
}
fn put_platform_office_node(&self, node: &PlatformOfficeNode) -> Result<(), PlatformError> {
let _ = node;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"platform office nodes are not supported by this adapter",
))
}
fn list_platform_office_nodes(&self) -> Result<Vec<PlatformOfficeNode>, PlatformError> {
Ok(vec![])
}
fn get_worker_registry_record(
&self,
node_id: &str,
) -> Result<Option<WorkerRegistryRecord>, PlatformError>;
fn put_worker_registry_record(
&self,
record: &WorkerRegistryRecord,
) -> Result<(), PlatformError>;
fn list_worker_registry_records(&self) -> Result<Vec<WorkerRegistryRecord>, PlatformError>;
fn delete_worker_registry_record(&self, node_id: &str) -> Result<(), PlatformError>;
fn get_project_runtime_placement(
&self,
owner: &str,
project: &str,
) -> Result<Option<ProjectRuntimePlacement>, PlatformError>;
fn put_project_runtime_placement(
&self,
placement: &ProjectRuntimePlacement,
) -> Result<(), PlatformError>;
fn list_project_runtime_placements(
&self,
) -> Result<Vec<ProjectRuntimePlacement>, PlatformError>;
fn delete_project_runtime_placement(
&self,
owner: &str,
project: &str,
) -> Result<(), PlatformError>;
fn get_project_operation(
&self,
owner: &str,
project: &str,
operation_id: &str,
) -> Result<Option<ProjectOperationRecord>, PlatformError> {
let _ = (owner, project, operation_id);
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"project operations are not supported by this adapter",
))
}
fn put_project_operation(&self, record: &ProjectOperationRecord) -> Result<(), PlatformError> {
let _ = record;
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"project operations are not supported by this adapter",
))
}
fn list_project_operations(
&self,
owner: &str,
project: &str,
limit: usize,
) -> Result<Vec<ProjectOperationRecord>, PlatformError> {
let _ = (owner, project, limit);
Ok(vec![])
}
fn list_all_mcp_sessions(&self) -> Result<Vec<McpSession>, PlatformError>;
fn put_mcp_session(&self, session: &McpSession) -> Result<(), PlatformError>;
fn delete_mcp_session(&self, token: &str) -> Result<(), PlatformError>;
fn admin_list_collections(&self) -> Result<Vec<(String, usize)>, PlatformError> {
Err(PlatformError::new(
"ADMIN_DB_UNAVAILABLE",
"Admin DB access not supported by this adapter",
))
}
fn admin_raw_query(
&self,
pipeline_json: &str,
) -> Result<Vec<serde_json::Value>, PlatformError> {
let _ = pipeline_json;
Err(PlatformError::new(
"ADMIN_DB_UNAVAILABLE",
"Admin DB access not supported by this adapter",
))
}
fn admin_get_node(&self, slug: &str) -> Result<Option<String>, PlatformError> {
let _ = slug;
Err(PlatformError::new(
"ADMIN_DB_UNAVAILABLE",
"Admin DB access not supported by this adapter",
))
}
fn admin_delete_node(&self, slug: &str) -> Result<bool, PlatformError> {
let _ = slug;
Err(PlatformError::new(
"ADMIN_DB_UNAVAILABLE",
"Admin DB access not supported by this adapter",
))
}
fn log_pipeline_invocation(
&self,
_owner: &str,
_project: &str,
_file_rel_path: &str,
_entry: &PipelineInvocationEntry,
_max_n: usize,
_max_age_secs: Option<i64>,
) -> Result<(), PlatformError> {
Ok(())
}
fn get_pipeline_invocations(
&self,
_owner: &str,
_project: &str,
_file_rel_path: &str,
_max_age_secs: Option<i64>,
) -> Result<Vec<PipelineInvocationEntry>, PlatformError> {
Ok(vec![])
}
fn get_pipeline_invocation_log_stats(
&self,
_owner: &str,
_project: &str,
) -> Result<PipelineInvocationLogStats, PlatformError> {
Ok(PipelineInvocationLogStats::default())
}
fn clear_pipeline_invocation_logs(
&self,
_owner: &str,
_project: &str,
_file_rel_path: Option<&str>,
) -> Result<u64, PlatformError> {
Ok(0)
}
fn transfer_project_owner(
&self,
_old_owner: &str,
_project: &str,
_new_owner: &str,
_new_owner_user_id: &str,
) -> Result<(), PlatformError> {
Err(PlatformError::new(
"PLATFORM_ADAPTER_UNAVAILABLE",
"transfer_project_owner not supported by this adapter",
))
}
}
pub fn build_data_adapter(
kind: DataAdapterKind,
data_root: &Path,
) -> Result<Arc<dyn DataAdapter>, PlatformError> {
match kind {
DataAdapterKind::Sqlite => Ok(Arc::new(sqlite::SqliteDataAdapter::new(data_root)?)),
DataAdapterKind::DynamoDb => Ok(Arc::new(dynamodb::DynamoDbDataAdapter::default())),
DataAdapterKind::Firebase => Ok(Arc::new(firebase::FirebaseDataAdapter::default())),
}
}
pub fn build_hub_data_adapter(
kind: DataAdapterKind,
db_path: &Path,
) -> Result<Arc<dyn DataAdapter>, PlatformError> {
match kind {
DataAdapterKind::Sqlite => Ok(Arc::new(sqlite::SqliteDataAdapter::new_at_db_path(
db_path,
)?)),
DataAdapterKind::DynamoDb | DataAdapterKind::Firebase => Err(PlatformError::new(
"PLATFORM_HUB_ADAPTER_UNAVAILABLE",
"office-hosted hub service storage currently requires sqlite",
)),
}
}