0.6 rust重构01

This commit is contained in:
lix-2026
2026-04-14 13:22:29 +08:00
parent 71fb1aee7e
commit 84a8454fa9
401 changed files with 5841 additions and 1512 deletions
+101
View File
@@ -0,0 +1,101 @@
use crate::common::{ActorPayload, AffectedObject, SourcePayload, TargetRef};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CommandEnvelope<T> {
pub name: String,
pub command_id: String,
pub idempotency_key: Option<String>,
pub actor: ActorPayload,
pub source: SourcePayload,
pub target: Option<TargetRef>,
pub payload: T,
pub reason: Option<String>,
pub refs: Vec<String>,
pub dry_run: bool,
pub validate_only: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CommandResult {
pub ok: bool,
pub command_id: String,
pub event_ids: Vec<String>,
pub affected_objects: Vec<AffectedObject>,
pub revision: Option<u64>,
pub warnings: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CreateWorkspace {
pub name: String,
pub slug: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CreatePage {
pub title: String,
pub parent_page_id: Option<String>,
pub position: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UpdatePageTitle {
pub page_id: String,
pub title: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UpdatePageStats {
pub page_id: String,
pub word_count: i64,
pub character_count: i64,
pub block_count: i64,
pub todo_total: i64,
pub todo_done: i64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UpdatePageOptions {
pub page_id: String,
pub wide_layout: Option<bool>,
pub small_text: Option<bool>,
pub show_heading_numbers: Option<bool>,
pub show_toc: Option<bool>,
pub show_structure: Option<bool>,
pub protect_editing: Option<bool>,
pub show_word_count: Option<bool>,
pub collapse_backlinks: Option<bool>,
pub page_font: Option<String>,
pub layout_density: Option<String>,
pub hide_child_pages: Option<bool>,
pub show_block_ref_count: Option<bool>,
pub embed_default_block_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InsertBlock {
pub page_id: String,
pub block_type: String,
pub content: String,
pub parent_block_id: Option<String>,
pub prev_block_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UpdateBlock {
pub block_id: String,
pub patch_content: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MoveBlock {
pub block_id: String,
pub new_parent_block_id: Option<String>,
pub new_page_id: Option<String>,
pub prev_block_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DeleteBlock {
pub block_id: String,
}
+59
View File
@@ -0,0 +1,59 @@
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ActorPayload {
pub actor_type: String,
pub actor_id: String,
pub session_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SourcePayload {
pub channel: String,
pub client: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TargetRef {
pub workspace_id: Option<String>,
pub page_id: Option<String>,
pub block_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RequestMeta {
pub idempotency_key: Option<String>,
pub validate_only: bool,
pub dry_run: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AffectedObject {
pub object_type: String,
pub object_id: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ResponseMeta {
pub request_id: String,
pub trace_id: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OkPayload<T> {
pub data: T,
pub meta: ResponseMeta,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ErrorDetail {
pub field: Option<String>,
pub reason: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ErrorPayload {
pub code: String,
pub message: String,
pub details: Vec<ErrorDetail>,
pub retryable: bool,
pub meta: ResponseMeta,
}
+116
View File
@@ -0,0 +1,116 @@
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AccessContext {
pub tenant_id: Option<String>,
pub workspace_id: String,
pub actor_id: String,
pub actor_type: String,
pub source: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AccessDecision {
Allow,
Deny(AccessDenyReason),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AccessDenyReason {
MissingTenant,
MissingWorkspace,
PermissionDenied,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum JobStatus {
Pending,
Running,
Succeeded,
Failed,
RetryScheduled,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct JobTicket {
pub job_id: String,
pub job_type: String,
pub request_id: String,
pub trace_id: String,
pub workspace_id: String,
pub status: JobStatus,
}
impl JobTicket {
pub fn new(
job_id: impl Into<String>,
job_type: impl Into<String>,
request_id: impl Into<String>,
trace_id: impl Into<String>,
workspace_id: impl Into<String>,
status: JobStatus,
) -> Self {
Self {
job_id: job_id.into(),
job_type: job_type.into(),
request_id: request_id.into(),
trace_id: trace_id.into(),
workspace_id: workspace_id.into(),
status,
}
}
}
pub fn decide_access(context: &AccessContext) -> AccessDecision {
if context.tenant_id.is_none() {
return AccessDecision::Deny(AccessDenyReason::MissingTenant);
}
if context.workspace_id.trim().is_empty() {
return AccessDecision::Deny(AccessDenyReason::MissingWorkspace);
}
AccessDecision::Allow
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn access_requires_tenant() {
let context = AccessContext {
tenant_id: None,
workspace_id: "ws-1".to_string(),
actor_id: "user-1".to_string(),
actor_type: "human".to_string(),
source: "react-next".to_string(),
};
assert_eq!(
decide_access(&context),
AccessDecision::Deny(AccessDenyReason::MissingTenant)
);
}
#[test]
fn access_allows_valid_context() {
let context = AccessContext {
tenant_id: Some("tenant-1".to_string()),
workspace_id: "ws-1".to_string(),
actor_id: "user-1".to_string(),
actor_type: "human".to_string(),
source: "react-next".to_string(),
};
assert_eq!(decide_access(&context), AccessDecision::Allow);
}
#[test]
fn job_ticket_keeps_trace_fields() {
let ticket = JobTicket::new(
"job-1",
"rebuild-index",
"req-1",
"trace-1",
"ws-1",
JobStatus::Pending,
);
assert_eq!(ticket.trace_id, "trace-1");
assert_eq!(ticket.status, JobStatus::Pending);
}
}
+50
View File
@@ -0,0 +1,50 @@
pub mod command;
pub mod common;
pub mod governance;
pub mod query;
pub mod tool;
pub use command::{
CommandEnvelope, CreatePage, CreateWorkspace, DeleteBlock, InsertBlock, MoveBlock,
UpdateBlock, UpdatePageStats, UpdatePageTitle,
};
pub use common::{
ActorPayload, AffectedObject, ErrorDetail, ErrorPayload, OkPayload, RequestMeta, ResponseMeta,
SourcePayload, TargetRef,
};
pub use query::{GetPage, ListPageBlocks, QueryEnvelope, SearchBlocks, SearchPages};
pub use tool::{InvocationKind, ToolInvocation};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn command_envelope_keeps_validate_only_flag() {
let envelope = CommandEnvelope::<CreateWorkspace> {
name: "create_workspace".into(),
command_id: "cmd_1".into(),
idempotency_key: Some("idem_1".into()),
actor: ActorPayload {
actor_type: "human".into(),
actor_id: "user_1".into(),
session_id: Some("session_1".into()),
},
source: SourcePayload {
channel: "cli".into(),
client: "mnote-cli".into(),
},
target: None,
payload: CreateWorkspace {
name: "demo".into(),
slug: Some("demo".into()),
},
reason: Some("初始化工作区".into()),
refs: vec![],
dry_run: false,
validate_only: true,
};
assert!(envelope.validate_only);
}
}
+36
View File
@@ -0,0 +1,36 @@
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct QueryEnvelope<T> {
pub name: String,
pub payload: T,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Pagination {
pub limit: u32,
pub cursor: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GetPage {
pub page_id: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ListPageBlocks {
pub page_id: String,
pub pagination: Pagination,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SearchPages {
pub query: String,
pub workspace_id: Option<String>,
pub pagination: Pagination,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SearchBlocks {
pub query: String,
pub page_id: Option<String>,
pub pagination: Pagination,
}
+13
View File
@@ -0,0 +1,13 @@
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InvocationKind {
Command,
Query,
Job,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ToolInvocation {
pub tool: String,
pub kind: InvocationKind,
pub args_json: String,
}