2026-05-22 17:45:22 +08:00
|
|
|
//! 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,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-28 17:04:27 +08:00
|
|
|
/// 会话令牌哈希(领域前缀,避免与 share/password 等 token 类型混淆)。
|
|
|
|
|
/// 注意:改前缀会使既有 session 行失效,需用户重新登录。
|
2026-05-22 17:45:22 +08:00
|
|
|
pub fn session_token_hash(raw_token: &str) -> String {
|
|
|
|
|
let mut hasher = Sha256::new();
|
2026-07-28 17:04:27 +08:00
|
|
|
hasher.update(b"mnote-session-token-v1:");
|
2026-05-22 17:45:22 +08:00
|
|
|
hasher.update(raw_token.as_bytes());
|
2026-07-28 17:04:27 +08:00
|
|
|
format!("sha256-v1:{}", hex::encode(hasher.finalize()))
|
2026-05-22 17:45:22 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-28 17:04:27 +08:00
|
|
|
/// 密码哈希 v1:SHA-256 + 固定领域前缀(兼容既有 `sha256-v1:` 存档)。
|
|
|
|
|
/// 技术债:生产应迁移 Argon2id + 每用户随机盐;在此保持算法兼容以免批量锁死账号。
|
2026-05-22 17:45:22 +08:00
|
|
|
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()))
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-28 17:04:27 +08:00
|
|
|
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
2026-05-22 17:45:22 +08:00
|
|
|
pub struct UpsertUserInput {
|
|
|
|
|
pub id: Option<EntityId>,
|
|
|
|
|
pub email: Option<String>,
|
|
|
|
|
pub username: String,
|
|
|
|
|
pub display_name: String,
|
|
|
|
|
pub role: Option<String>,
|
2026-07-28 17:04:27 +08:00
|
|
|
/// 密码哈希;Debug 脱敏,避免日志泄露。
|
2026-05-22 17:45:22 +08:00
|
|
|
pub password_hash: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-28 17:04:27 +08:00
|
|
|
impl std::fmt::Debug for UpsertUserInput {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
f.debug_struct("UpsertUserInput")
|
|
|
|
|
.field("id", &self.id)
|
|
|
|
|
.field("email", &self.email)
|
|
|
|
|
.field("username", &self.username)
|
|
|
|
|
.field("display_name", &self.display_name)
|
|
|
|
|
.field("role", &self.role)
|
|
|
|
|
.field(
|
|
|
|
|
"password_hash",
|
|
|
|
|
&self
|
|
|
|
|
.password_hash
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|_| "<redacted>")
|
|
|
|
|
.unwrap_or("None"),
|
|
|
|
|
)
|
|
|
|
|
.finish()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
2026-05-22 17:45:22 +08:00
|
|
|
pub struct CreatePasswordIdentityInput {
|
|
|
|
|
pub user_id: EntityId,
|
|
|
|
|
pub email: Option<String>,
|
|
|
|
|
pub username: String,
|
2026-07-28 17:04:27 +08:00
|
|
|
/// 明文密码仅用于创建身份;Debug/Serialize 必须脱敏。
|
2026-05-22 17:45:22 +08:00
|
|
|
pub password: String,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-28 17:04:27 +08:00
|
|
|
impl Serialize for CreatePasswordIdentityInput {
|
|
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
|
where
|
|
|
|
|
S: serde::Serializer,
|
|
|
|
|
{
|
|
|
|
|
use serde::ser::SerializeStruct;
|
|
|
|
|
let mut state = serializer.serialize_struct("CreatePasswordIdentityInput", 4)?;
|
|
|
|
|
state.serialize_field("user_id", &self.user_id)?;
|
|
|
|
|
state.serialize_field("email", &self.email)?;
|
|
|
|
|
state.serialize_field("username", &self.username)?;
|
|
|
|
|
state.serialize_field("password", "<redacted>")?;
|
|
|
|
|
state.end()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Debug for CreatePasswordIdentityInput {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
f.debug_struct("CreatePasswordIdentityInput")
|
|
|
|
|
.field("user_id", &self.user_id)
|
|
|
|
|
.field("email", &self.email)
|
|
|
|
|
.field("username", &self.username)
|
|
|
|
|
.field("password", &"<redacted>")
|
|
|
|
|
.finish()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
2026-05-22 17:45:22 +08:00
|
|
|
pub struct AuthenticatePasswordInput {
|
|
|
|
|
pub account: String,
|
2026-07-28 17:04:27 +08:00
|
|
|
/// 明文密码仅用于鉴权;Debug/Serialize 脱敏。
|
2026-05-22 17:45:22 +08:00
|
|
|
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>,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-28 17:04:27 +08:00
|
|
|
impl Serialize for AuthenticatePasswordInput {
|
|
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
|
where
|
|
|
|
|
S: serde::Serializer,
|
|
|
|
|
{
|
|
|
|
|
use serde::ser::SerializeStruct;
|
|
|
|
|
let mut state = serializer.serialize_struct("AuthenticatePasswordInput", 7)?;
|
|
|
|
|
state.serialize_field("account", &self.account)?;
|
|
|
|
|
state.serialize_field("password", "<redacted>")?;
|
|
|
|
|
state.serialize_field("session_id", &self.session_id)?;
|
|
|
|
|
state.serialize_field("token_hash", "<redacted>")?;
|
|
|
|
|
state.serialize_field("user_agent", &self.user_agent)?;
|
|
|
|
|
state.serialize_field("ip_hash", &self.ip_hash)?;
|
|
|
|
|
state.serialize_field("expires_at", &self.expires_at)?;
|
|
|
|
|
state.end()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Debug for AuthenticatePasswordInput {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
f.debug_struct("AuthenticatePasswordInput")
|
|
|
|
|
.field("account", &self.account)
|
|
|
|
|
.field("password", &"<redacted>")
|
|
|
|
|
.field("session_id", &self.session_id)
|
|
|
|
|
.field("token_hash", &"<redacted>")
|
|
|
|
|
.field("user_agent", &self.user_agent)
|
|
|
|
|
.field("ip_hash", &self.ip_hash)
|
|
|
|
|
.field("expires_at", &self.expires_at)
|
|
|
|
|
.finish()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 17:45:22 +08:00
|
|
|
#[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,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-03 13:24:20 +08:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct UpsertWorkspaceInput {
|
|
|
|
|
pub id: Option<EntityId>,
|
|
|
|
|
pub owner_user_id: EntityId,
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub kind: Option<String>,
|
|
|
|
|
pub root_uri: String,
|
|
|
|
|
pub root_path: String,
|
|
|
|
|
pub source_kind: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 17:45:22 +08:00
|
|
|
#[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,
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-27 11:31:12 +08:00
|
|
|
#[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,
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-28 22:01:44 +08:00
|
|
|
#[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,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-15 23:12:15 +08:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct KnowledgeBaseRecord {
|
|
|
|
|
pub id: EntityId,
|
|
|
|
|
pub user_id: EntityId,
|
|
|
|
|
pub workspace_id: Option<EntityId>,
|
|
|
|
|
pub root_uri: Option<String>,
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub description: Option<String>,
|
|
|
|
|
pub provider: String,
|
|
|
|
|
pub provider_kb_id: String,
|
|
|
|
|
pub default_tool_enabled: bool,
|
|
|
|
|
pub can_write: bool,
|
|
|
|
|
pub source_count: i64,
|
|
|
|
|
pub chunk_count: 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 UpsertKnowledgeBaseInput {
|
|
|
|
|
pub id: Option<EntityId>,
|
|
|
|
|
pub user_id: EntityId,
|
|
|
|
|
pub workspace_id: Option<EntityId>,
|
|
|
|
|
pub root_uri: Option<String>,
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub description: Option<String>,
|
|
|
|
|
pub provider: String,
|
|
|
|
|
pub provider_kb_id: String,
|
|
|
|
|
pub default_tool_enabled: bool,
|
|
|
|
|
pub can_write: bool,
|
|
|
|
|
pub source_count: i64,
|
|
|
|
|
pub chunk_count: i64,
|
|
|
|
|
pub status: String,
|
|
|
|
|
pub metadata_json: String,
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 17:45:22 +08:00
|
|
|
#[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,
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-09 18:48:46 +08:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct AiRuntimeJournalEventRecord {
|
|
|
|
|
pub seq: i64,
|
|
|
|
|
pub event: AiRuntimeEventRecord,
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 17:45:22 +08:00
|
|
|
#[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,
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 17:45:22 +08:00
|
|
|
#[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,
|
|
|
|
|
}
|
2026-07-04 21:47:42 +08:00
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// P2: AI tool events (receipts) and file patches — 7-71
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct AiToolEventRecord {
|
|
|
|
|
pub id: EntityId,
|
|
|
|
|
pub user_id: EntityId,
|
|
|
|
|
pub workspace_id: Option<EntityId>,
|
|
|
|
|
pub session_id: EntityId,
|
|
|
|
|
pub run_id: Option<EntityId>,
|
|
|
|
|
pub provider: String,
|
|
|
|
|
pub provider_session_id: Option<String>,
|
|
|
|
|
pub tool_name: String,
|
|
|
|
|
pub allowed: bool,
|
|
|
|
|
pub deny_reason: Option<String>,
|
|
|
|
|
pub root_uri: String,
|
|
|
|
|
pub page_path: Option<String>,
|
|
|
|
|
pub normalized_file_path: Option<String>,
|
|
|
|
|
pub diff_summary: Option<String>,
|
|
|
|
|
pub citation_count: i64,
|
|
|
|
|
pub before_file_version: Option<String>,
|
|
|
|
|
pub after_file_version: Option<String>,
|
|
|
|
|
pub payload_json: String,
|
|
|
|
|
pub created_at: Timestamp,
|
|
|
|
|
pub deleted_at: Option<Timestamp>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct AppendAiToolEventInput {
|
|
|
|
|
pub id: Option<EntityId>,
|
|
|
|
|
pub user_id: EntityId,
|
|
|
|
|
pub workspace_id: Option<EntityId>,
|
|
|
|
|
pub session_id: EntityId,
|
|
|
|
|
pub run_id: Option<EntityId>,
|
|
|
|
|
pub provider: String,
|
|
|
|
|
pub provider_session_id: Option<String>,
|
|
|
|
|
pub tool_name: String,
|
|
|
|
|
pub allowed: bool,
|
|
|
|
|
pub deny_reason: Option<String>,
|
|
|
|
|
pub root_uri: String,
|
|
|
|
|
pub page_path: Option<String>,
|
|
|
|
|
pub normalized_file_path: Option<String>,
|
|
|
|
|
pub diff_summary: Option<String>,
|
|
|
|
|
pub citation_count: i64,
|
|
|
|
|
pub before_file_version: Option<String>,
|
|
|
|
|
pub after_file_version: Option<String>,
|
|
|
|
|
pub payload_json: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct AiFilePatchRecord {
|
|
|
|
|
pub id: EntityId,
|
|
|
|
|
pub user_id: EntityId,
|
|
|
|
|
pub workspace_id: Option<EntityId>,
|
|
|
|
|
pub session_id: EntityId,
|
|
|
|
|
pub run_id: Option<EntityId>,
|
|
|
|
|
pub tool_event_id: EntityId,
|
|
|
|
|
pub root_uri: String,
|
|
|
|
|
pub relative_path: String,
|
|
|
|
|
pub before_file_version: Option<String>,
|
|
|
|
|
pub after_file_version: Option<String>,
|
|
|
|
|
pub patch_summary_json: String,
|
|
|
|
|
pub created_at: Timestamp,
|
|
|
|
|
pub deleted_at: Option<Timestamp>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct AppendAiFilePatchInput {
|
|
|
|
|
pub id: Option<EntityId>,
|
|
|
|
|
pub user_id: EntityId,
|
|
|
|
|
pub workspace_id: Option<EntityId>,
|
|
|
|
|
pub session_id: EntityId,
|
|
|
|
|
pub run_id: Option<EntityId>,
|
|
|
|
|
pub tool_event_id: EntityId,
|
|
|
|
|
pub root_uri: String,
|
|
|
|
|
pub relative_path: String,
|
|
|
|
|
pub before_file_version: Option<String>,
|
|
|
|
|
pub after_file_version: Option<String>,
|
|
|
|
|
pub patch_summary_json: String,
|
|
|
|
|
}
|