Files
mnote/rust/crates/control-plane/src/model.rs
T

520 lines
14 KiB
Rust
Raw Normal View History

//! SQLite 控制面 Phase 1 的最小数据模型。
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
pub type EntityId = String;
pub type Timestamp = String;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserRecord {
pub id: EntityId,
pub email: Option<String>,
pub username: String,
pub display_name: String,
pub role: String,
pub status: String,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
pub fn session_token_hash(raw_token: &str) -> String {
let mut hasher = Sha256::new();
hasher.update(raw_token.as_bytes());
hex::encode(hasher.finalize())
}
pub fn password_hash_v1(password: &str) -> String {
let mut hasher = Sha256::new();
hasher.update(b"mnote-password-v1:");
hasher.update(password.as_bytes());
format!("sha256-v1:{}", hex::encode(hasher.finalize()))
}
pub fn share_token_hash_v1(token: &str) -> String {
let mut hasher = Sha256::new();
hasher.update(b"mnote-share-token-v1:");
hasher.update(token.as_bytes());
format!("sha256-v1:{}", hex::encode(hasher.finalize()))
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpsertUserInput {
pub id: Option<EntityId>,
pub email: Option<String>,
pub username: String,
pub display_name: String,
pub role: Option<String>,
pub password_hash: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CreatePasswordIdentityInput {
pub user_id: EntityId,
pub email: Option<String>,
pub username: String,
pub password: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuthenticatePasswordInput {
pub account: String,
pub password: String,
pub session_id: Option<EntityId>,
pub token_hash: String,
pub user_agent: Option<String>,
pub ip_hash: Option<String>,
pub expires_at: Option<Timestamp>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuthSessionRecord {
pub id: EntityId,
pub user_id: EntityId,
pub token_hash: String,
pub user_agent: Option<String>,
pub ip_hash: Option<String>,
pub created_at: Timestamp,
pub expires_at: Timestamp,
pub revoked_at: Option<Timestamp>,
pub last_seen_at: Timestamp,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CreateSessionInput {
pub id: Option<EntityId>,
pub user_id: EntityId,
pub token_hash: String,
pub user_agent: Option<String>,
pub ip_hash: Option<String>,
pub expires_at: Option<Timestamp>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ResolvedAuthSession {
pub session: AuthSessionRecord,
pub user: UserRecord,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkspaceRecord {
pub id: EntityId,
pub owner_user_id: EntityId,
pub name: String,
pub kind: String,
pub root_uri: String,
pub root_path: String,
pub source_kind: String,
pub status: String,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DirectoryGrantRecord {
pub id: EntityId,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub root_uri: String,
pub root_path: String,
pub permission: String,
pub recursive: bool,
pub capabilities_json: String,
pub source: String,
pub status: String,
pub created_by: Option<EntityId>,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DirectoryGrantLookup {
pub grant_id: Option<EntityId>,
pub user_id: Option<EntityId>,
pub root_uri: Option<String>,
pub include_revoked: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DirectoryGrantInput {
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub root_uri: String,
pub root_path: String,
pub permission: String,
pub recursive: bool,
pub capabilities: Vec<String>,
pub source: String,
pub created_by: Option<EntityId>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ResolvedAccess {
pub user_id: EntityId,
pub root_uri: String,
pub permission: String,
pub grant_ids: Vec<EntityId>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct OutboxEventRecord {
pub id: EntityId,
pub topic: String,
pub event_type: String,
pub payload_json: String,
pub created_at: Timestamp,
pub delivered_at: Option<Timestamp>,
pub attempts: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct OutboxEventInput {
pub topic: String,
pub event_type: String,
pub payload_json: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SidebarShortcutRecord {
pub id: EntityId,
pub user_id: EntityId,
pub workspace_id: EntityId,
pub root_uri: Option<String>,
pub kind: String,
pub source_kind: String,
pub target_id: String,
pub relative_path: Option<String>,
pub document_id: Option<String>,
pub title: String,
pub icon: Option<String>,
pub sort_order: i64,
pub status: String,
pub metadata_json: String,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpsertSidebarShortcutInput {
pub id: Option<EntityId>,
pub user_id: EntityId,
pub workspace_id: EntityId,
pub root_uri: Option<String>,
pub kind: String,
pub source_kind: String,
pub target_id: String,
pub relative_path: Option<String>,
pub document_id: Option<String>,
pub title: String,
pub icon: Option<String>,
pub sort_order: i64,
pub metadata_json: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserUiPreferenceRecord {
pub id: EntityId,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub source_kind: Option<String>,
pub scope_kind: String,
pub scope_id: String,
pub key: String,
pub value_json: String,
pub status: String,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpsertUserUiPreferenceInput {
pub id: Option<EntityId>,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub source_kind: Option<String>,
pub scope_kind: String,
pub scope_id: String,
pub key: String,
pub value_json: String,
}
2026-06-01 09:29:12 +08:00
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AiAgentProfileRecord {
pub id: EntityId,
pub agent_id: String,
pub profile_kind: String,
pub owner_user_id: Option<EntityId>,
pub base_profile_name: String,
pub isolated_profile_name: String,
pub display_name: String,
pub status: String,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AiAgentProfileGrantRecord {
pub id: EntityId,
pub profile_id: EntityId,
pub user_id: Option<EntityId>,
pub role: String,
pub can_run: bool,
pub can_manage_skills: bool,
pub can_manage_config: bool,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AiAgentProfileAccessRecord {
pub profile: AiAgentProfileRecord,
pub grant: AiAgentProfileGrantRecord,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct NavigationRecentRecord {
pub id: EntityId,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub kind: String,
pub source_kind: String,
pub root_uri: String,
pub target_key: String,
pub relative_path: Option<String>,
pub document_id: Option<String>,
pub title: String,
pub status: String,
pub metadata_json: String,
pub visited_at: Timestamp,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpsertNavigationRecentInput {
pub id: Option<EntityId>,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub kind: String,
pub source_kind: String,
pub root_uri: String,
pub relative_path: Option<String>,
pub document_id: Option<String>,
pub title: String,
pub metadata_json: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AiPolicyRecord {
pub id: EntityId,
pub user_id: Option<EntityId>,
pub workspace_id: Option<EntityId>,
pub allowed_roots_json: String,
pub model_policy_json: String,
pub quota_json: String,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpsertAiPolicyInput {
pub id: Option<EntityId>,
pub user_id: Option<EntityId>,
pub workspace_id: Option<EntityId>,
pub allowed_roots_json: String,
pub model_policy_json: String,
pub quota_json: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SyncStateRecord {
pub id: EntityId,
pub workspace_id: EntityId,
pub remote_kind: String,
pub remote_id: Option<String>,
pub cursor: Option<String>,
pub last_synced_at: Option<Timestamp>,
pub status: String,
pub error_json: Option<String>,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpsertSyncStateInput {
pub id: Option<EntityId>,
pub workspace_id: EntityId,
pub remote_kind: String,
pub remote_id: Option<String>,
pub cursor: Option<String>,
pub last_synced_at: Option<Timestamp>,
pub status: String,
pub error_json: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AiRuntimeRunRecord {
pub id: EntityId,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub document_id: Option<String>,
pub session_id: EntityId,
pub run_id: EntityId,
pub title: Option<String>,
pub profile: String,
pub acp_runtime: String,
pub trace_id: Option<String>,
pub status: String,
pub runtime_json: String,
pub payload_json: String,
pub deleted_at: Option<Timestamp>,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpsertAiRuntimeRunInput {
pub id: Option<EntityId>,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub document_id: Option<String>,
pub session_id: EntityId,
pub run_id: EntityId,
pub title: Option<String>,
pub profile: String,
pub acp_runtime: String,
pub trace_id: Option<String>,
pub status: String,
pub runtime_json: String,
pub payload_json: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AiRuntimeEventRecord {
pub id: EntityId,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub document_id: Option<String>,
pub session_id: EntityId,
pub run_id: EntityId,
pub profile: String,
pub acp_runtime: String,
pub event_type: String,
pub payload_json: String,
pub created_at: Timestamp,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AppendAiRuntimeEventInput {
pub id: Option<EntityId>,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub document_id: Option<String>,
pub session_id: EntityId,
pub run_id: EntityId,
pub profile: String,
pub acp_runtime: String,
pub event_type: String,
pub payload_json: String,
}
2026-06-01 09:29:12 +08:00
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AiExternalConversationBindingRecord {
pub id: EntityId,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub mnote_session_id: EntityId,
pub acp_session_id: Option<EntityId>,
pub agent_id: String,
pub profile: String,
pub provider: String,
pub remote_conversation_id: String,
pub remote_url: Option<String>,
pub status: String,
pub metadata_json: String,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub deleted_at: Option<Timestamp>,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpsertAiExternalConversationBindingInput {
pub id: Option<EntityId>,
pub user_id: EntityId,
pub workspace_id: Option<EntityId>,
pub mnote_session_id: EntityId,
pub acp_session_id: Option<EntityId>,
pub agent_id: String,
pub profile: String,
pub provider: String,
pub remote_conversation_id: String,
pub remote_url: Option<String>,
pub status: String,
pub metadata_json: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ShareLinkRecord {
pub id: EntityId,
pub workspace_id: EntityId,
pub resource_kind: String,
pub resource_id: String,
pub token_hash: String,
pub permission: String,
pub created_by: EntityId,
pub expires_at: Option<Timestamp>,
pub revoked_at: Option<Timestamp>,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub revision: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CreateShareLinkInput {
pub id: Option<EntityId>,
pub workspace_id: EntityId,
pub resource_kind: String,
pub resource_id: String,
pub token: Option<String>,
pub permission: String,
pub created_by: EntityId,
pub expires_at: Option<Timestamp>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CreatedShareLink {
pub link: ShareLinkRecord,
pub token: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuditLogRecord {
pub id: EntityId,
pub actor_user_id: Option<EntityId>,
pub action: String,
pub target_kind: String,
pub target_id: Option<EntityId>,
pub metadata_json: String,
pub created_at: Timestamp,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AppendAuditInput {
pub actor_user_id: Option<EntityId>,
pub action: String,
pub target_kind: String,
pub target_id: Option<EntityId>,
pub metadata_json: String,
}