backup: preserve pre-native-foundation runtime work
This commit is contained in:
parent
a4cba27d3c
commit
71dbcd62ec
23 changed files with 3647 additions and 196 deletions
|
|
@ -38,7 +38,7 @@ url = "2"
|
|||
reqwest = { version = "0.13.2", default-features = false, features = ["cookies", "form", "json", "rustls", "stream"] }
|
||||
rust_xlsxwriter = "=0.64.2"
|
||||
zip = { version = "=0.6.6", default-features = false, features = ["deflate"] }
|
||||
tokio = { version = "1", features = ["io-util", "process", "time"] }
|
||||
tokio = { version = "1", features = ["io-util", "process", "sync", "time"] }
|
||||
futures-util = "0.3"
|
||||
minisign-verify = "0.2.5"
|
||||
qrcode = { version = "0.14", default-features = false, features = ["svg"] }
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ mod code_repo_login;
|
|||
mod direct_local_broker;
|
||||
mod direct_local_session;
|
||||
mod dynamic_capability_routing;
|
||||
mod execution_limb_training;
|
||||
mod enterprise_work_channel;
|
||||
mod execution_limb_training;
|
||||
mod external_ai_gateway;
|
||||
mod glp_envelope;
|
||||
mod gls_bootstrap_compiler;
|
||||
|
|
@ -23,6 +23,7 @@ mod mobile_sync;
|
|||
mod module_package_runtime;
|
||||
mod native_composition;
|
||||
mod number_coordinate_tree;
|
||||
mod number_database;
|
||||
mod numbered_ipc;
|
||||
mod numbered_ipc_dispatch;
|
||||
mod numbered_language_input;
|
||||
|
|
@ -64,7 +65,8 @@ pub fn run() {
|
|||
.plugin(tauri_plugin_dialog::init())
|
||||
.manage(numbered_ipc::NumberedIpcState::default())
|
||||
.manage(mobile_sync::MobileSyncState::default())
|
||||
.invoke_handler(tauri::generate_handler![numbered_ipc::numbered_ipc,]) .setup(|app| {
|
||||
.invoke_handler(tauri::generate_handler![numbered_ipc::numbered_ipc,])
|
||||
.setup(|app| {
|
||||
// GLS 是 HoloLake 产品内核,不是开发机旁路服务。合同、依赖闭包、
|
||||
// 自举编译器或回执账本任一不可用时,产品启动失败关闭。
|
||||
gls_protocol_kernel::start_on_application_open(app.handle())?;
|
||||
|
|
@ -73,6 +75,7 @@ pub fn run() {
|
|||
module_package_runtime::start_on_application_open(app.handle())?;
|
||||
online_marketplace::start_on_application_open(app.handle())?;
|
||||
number_coordinate_tree::start_on_application_open()?;
|
||||
number_database::start_on_application_open(app.handle())?;
|
||||
numbered_language_input::validate_contract()?;
|
||||
numbered_ipc::start_on_application_open(app.handle())?;
|
||||
human_authorization::start_on_application_open()?;
|
||||
|
|
|
|||
|
|
@ -1620,7 +1620,6 @@ mod tests {
|
|||
assert!(is_sha256(&digest));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn bundled_web_novel_family_uses_one_signed_lifecycle_and_exact_numbers() {
|
||||
let expected = [
|
||||
|
|
|
|||
|
|
@ -11,16 +11,33 @@ struct NumberTree {
|
|||
state: String,
|
||||
root_number: String,
|
||||
coordinate_count: usize,
|
||||
module_node_count: usize,
|
||||
route_count: usize,
|
||||
identity_node_count: usize,
|
||||
protocol_node_count: usize,
|
||||
reference_only_node_count: usize,
|
||||
module_nodes: Vec<ModuleNode>,
|
||||
identity_nodes: Vec<IdentityNode>,
|
||||
protocol_nodes: Vec<ProtocolNode>,
|
||||
routes: Vec<NumberRoute>,
|
||||
invariants: NumberTreeInvariants,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct ModuleNode {
|
||||
node_kind: String,
|
||||
node_number: String,
|
||||
module_number: String,
|
||||
transport: String,
|
||||
operation_count: usize,
|
||||
operation_numbers: Vec<String>,
|
||||
scheduling_policy: String,
|
||||
execution_state: String,
|
||||
evidence: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct IdentityNode {
|
||||
|
|
@ -73,6 +90,7 @@ struct NumberTreeInvariants {
|
|||
every_accepted_call_has_evidence_class: bool,
|
||||
every_protocol_reference_has_number_coordinate: bool,
|
||||
reference_only_nodes_never_executable: bool,
|
||||
one_module_one_runtime_root_path: bool,
|
||||
unresolved_number_reference_count: usize,
|
||||
mismatched_coordinate: String,
|
||||
}
|
||||
|
|
@ -88,8 +106,10 @@ fn validate_tree() -> Result<(), String> {
|
|||
|| tree.record_id != "HLP-UNIFIED-NUMBER-TREE-001"
|
||||
|| tree.state != "MACHINE_COMPILED_STARTUP_ENFORCED"
|
||||
|| tree.root_number != "HLP-NUMBER-WORLD-ROOT-001"
|
||||
|| tree.coordinate_count != 273
|
||||
|| tree.route_count != 170
|
||||
|| tree.coordinate_count != 324
|
||||
|| tree.module_node_count != 46
|
||||
|| tree.module_nodes.len() != tree.module_node_count
|
||||
|| tree.route_count != 175
|
||||
|| tree.routes.len() != tree.route_count
|
||||
|| tree.identity_node_count != 4
|
||||
|| tree.identity_nodes.len() != tree.identity_node_count
|
||||
|
|
@ -97,7 +117,10 @@ fn validate_tree() -> Result<(), String> {
|
|||
|| tree.protocol_nodes.len() != tree.protocol_node_count
|
||||
|| tree.reference_only_node_count != 16
|
||||
|| tree.coordinate_count
|
||||
!= tree.route_count + tree.identity_node_count + tree.protocol_node_count
|
||||
!= tree.module_node_count
|
||||
+ tree.route_count
|
||||
+ tree.identity_node_count
|
||||
+ tree.protocol_node_count
|
||||
|| !tree.invariants.number_is_stable_coordinate_not_authority
|
||||
|| !tree.invariants.path_is_unique_navigation
|
||||
|| !tree.invariants.admission_is_separate_from_identity
|
||||
|
|
@ -107,6 +130,7 @@ fn validate_tree() -> Result<(), String> {
|
|||
.invariants
|
||||
.every_protocol_reference_has_number_coordinate
|
||||
|| !tree.invariants.reference_only_nodes_never_executable
|
||||
|| !tree.invariants.one_module_one_runtime_root_path
|
||||
|| tree.invariants.unresolved_number_reference_count != 0
|
||||
|| tree.invariants.mismatched_coordinate != "FAIL_CLOSED"
|
||||
{
|
||||
|
|
@ -116,6 +140,27 @@ fn validate_tree() -> Result<(), String> {
|
|||
let mut coordinates = HashSet::new();
|
||||
let mut node_numbers = HashSet::new();
|
||||
let mut protocol_ids = HashSet::new();
|
||||
let mut module_numbers = HashSet::new();
|
||||
for node in &tree.module_nodes {
|
||||
if node.node_kind != "EXECUTION_MODULE"
|
||||
|| node.node_number != node.module_number
|
||||
|| node.module_number.is_empty()
|
||||
|| node.transport.is_empty()
|
||||
|| node.operation_count == 0
|
||||
|| node.operation_numbers.len() != node.operation_count
|
||||
|| node.scheduling_policy != "ONE_MODULE_ONE_NUMBER_PATH_SERIAL"
|
||||
|| node.execution_state != "RUNTIME_NUMBER_DATABASE_INDEXED"
|
||||
|| node.evidence != "UNIFIED_NUMBER_ROUTE_MEMBERSHIP"
|
||||
|| node.path != format!("HLP-NUMBER-WORLD-ROOT-001/MODULE/{}", node.module_number)
|
||||
|| !paths.insert(node.path.as_str())
|
||||
|| !node_numbers.insert(node.node_number.as_str())
|
||||
|| !module_numbers.insert(node.module_number.as_str())
|
||||
|| node.operation_numbers.iter().collect::<HashSet<_>>().len()
|
||||
!= node.operation_numbers.len()
|
||||
{
|
||||
return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_MODULE_NODE_INVALID".into());
|
||||
}
|
||||
}
|
||||
for node in &tree.identity_nodes {
|
||||
if node.node_kind != "IDENTITY_NAMESPACE"
|
||||
|| !node.node_number.starts_with("HLP-IDENTITY-NS-")
|
||||
|
|
@ -183,6 +228,7 @@ fn validate_tree() -> Result<(), String> {
|
|||
|| route.admission.is_empty()
|
||||
|| !matches!(route.effect.as_str(), "READ_OR_STATUS" | "STATE_CHANGE")
|
||||
|| route.evidence.is_empty()
|
||||
|| !module_numbers.contains(route.module_number.as_str())
|
||||
|| !route.path.starts_with("HLP-NUMBER-WORLD-ROOT-001/")
|
||||
|| !paths.insert(route.path.as_str())
|
||||
|| !coordinates.insert(coordinate)
|
||||
|
|
@ -190,6 +236,22 @@ fn validate_tree() -> Result<(), String> {
|
|||
return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_ROUTE_INVALID".into());
|
||||
}
|
||||
}
|
||||
for node in &tree.module_nodes {
|
||||
let observed = tree
|
||||
.routes
|
||||
.iter()
|
||||
.filter(|route| route.module_number == node.module_number)
|
||||
.map(|route| route.operation_number.as_str())
|
||||
.collect::<HashSet<_>>();
|
||||
let declared = node
|
||||
.operation_numbers
|
||||
.iter()
|
||||
.map(String::as_str)
|
||||
.collect::<HashSet<_>>();
|
||||
if observed != declared {
|
||||
return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_MODULE_MEMBERSHIP_INVALID".into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,691 @@
|
|||
//! 光湖编号数据库。
|
||||
//!
|
||||
//! 编号树是唯一正本;本数据库是由该正本事务化生成的运行时索引,不接受手工登记。
|
||||
//! 它把“编号 → 唯一模块根路径 → 操作叶片 → 证据 → 调度规则”变成所有执行入口
|
||||
//! 都能查询的机器事实。树哈希变化时数据库整体重建,未知或错配坐标一律失败关闭。
|
||||
|
||||
use ring::digest::{digest, SHA256};
|
||||
use rusqlite::{params, Connection, OptionalExtension, TransactionBehavior};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tauri::{AppHandle, Manager};
|
||||
|
||||
const TREE: &str = include_str!("../../generated/unified-number-coordinate-tree.json");
|
||||
const DATABASE_ID: &str = "HLP-NUMBER-DATABASE-0001";
|
||||
const DATABASE_SCHEMA: &str = "hololake.number-database/v1";
|
||||
const DATABASE_STATE: &str = "READY_RUNTIME_REMINDER_INDEX";
|
||||
const SCHEDULING_POLICY: &str = "ONE_MODULE_ONE_NUMBER_PATH_SERIAL";
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct NumberTree {
|
||||
schema: String,
|
||||
record_id: String,
|
||||
state: String,
|
||||
root_number: String,
|
||||
coordinate_count: usize,
|
||||
module_node_count: usize,
|
||||
route_count: usize,
|
||||
identity_node_count: usize,
|
||||
protocol_node_count: usize,
|
||||
sources: Vec<NumberSource>,
|
||||
module_nodes: Vec<ModuleNode>,
|
||||
routes: Vec<NumberRoute>,
|
||||
identity_nodes: Vec<IdentityNode>,
|
||||
protocol_nodes: Vec<ProtocolNode>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct NumberSource {
|
||||
record_id: String,
|
||||
sha256: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct ModuleNode {
|
||||
module_number: String,
|
||||
transport: String,
|
||||
operation_count: usize,
|
||||
operation_numbers: Vec<String>,
|
||||
scheduling_policy: String,
|
||||
execution_state: String,
|
||||
evidence: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct NumberRoute {
|
||||
transport: String,
|
||||
protocol_version: String,
|
||||
caller_number: String,
|
||||
channel_number: String,
|
||||
module_number: String,
|
||||
operation_number: String,
|
||||
target_number: String,
|
||||
alias: String,
|
||||
admission: String,
|
||||
effect: String,
|
||||
evidence: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct IdentityNode {
|
||||
node_number: String,
|
||||
namespace_id: String,
|
||||
subject_kind: String,
|
||||
domain_scope: String,
|
||||
admission: String,
|
||||
execution_state: String,
|
||||
evidence: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct ProtocolNode {
|
||||
node_number: String,
|
||||
protocol_id: String,
|
||||
source_state: String,
|
||||
execution_state: String,
|
||||
evidence: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RuntimeRouteResolution {
|
||||
pub database_id: &'static str,
|
||||
pub source_tree_record_id: String,
|
||||
pub source_tree_sha256: String,
|
||||
pub transport: String,
|
||||
pub protocol_version: String,
|
||||
pub caller_number: String,
|
||||
pub channel_number: String,
|
||||
pub module_number: String,
|
||||
pub operation_number: String,
|
||||
pub target_number: String,
|
||||
pub alias: String,
|
||||
pub module_root_path: String,
|
||||
pub route_path: String,
|
||||
pub admission: String,
|
||||
pub effect: String,
|
||||
pub evidence: String,
|
||||
pub scheduling_policy: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct NumberCoordinateReminder {
|
||||
pub schema: &'static str,
|
||||
pub database_id: &'static str,
|
||||
pub database_state: &'static str,
|
||||
pub query: String,
|
||||
pub coordinate_kind: String,
|
||||
pub canonical_number: String,
|
||||
pub path: String,
|
||||
pub module_root_path: Option<String>,
|
||||
pub route_path: Option<String>,
|
||||
pub scheduling_policy: Option<String>,
|
||||
pub evidence: String,
|
||||
pub related_operation_numbers: Vec<String>,
|
||||
pub source_tree_record_id: String,
|
||||
pub source_tree_sha256: String,
|
||||
pub reminder: &'static str,
|
||||
}
|
||||
|
||||
fn sha256_hex(bytes: &[u8]) -> String {
|
||||
digest(&SHA256, bytes)
|
||||
.as_ref()
|
||||
.iter()
|
||||
.map(|byte| format!("{byte:02x}"))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn tree_sha256() -> String {
|
||||
sha256_hex(TREE.as_bytes())
|
||||
}
|
||||
|
||||
fn load_tree() -> Result<NumberTree, String> {
|
||||
let tree: NumberTree = serde_json::from_str(TREE)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_TREE_INVALID: {error}"))?;
|
||||
if tree.schema != "hololake.unified-number-coordinate-tree/v2"
|
||||
|| tree.record_id != "HLP-UNIFIED-NUMBER-TREE-001"
|
||||
|| tree.state != "MACHINE_COMPILED_STARTUP_ENFORCED"
|
||||
|| tree.root_number != "HLP-NUMBER-WORLD-ROOT-001"
|
||||
|| tree.coordinate_count
|
||||
!= tree.module_node_count
|
||||
+ tree.route_count
|
||||
+ tree.identity_node_count
|
||||
+ tree.protocol_node_count
|
||||
|| tree.module_nodes.len() != tree.module_node_count
|
||||
|| tree.routes.len() != tree.route_count
|
||||
|| tree.identity_nodes.len() != tree.identity_node_count
|
||||
|| tree.protocol_nodes.len() != tree.protocol_node_count
|
||||
{
|
||||
return Err("HOLOLAKE_NUMBER_DATABASE_TREE_BOUNDARY_INVALID".into());
|
||||
}
|
||||
Ok(tree)
|
||||
}
|
||||
|
||||
fn database_path(app: &AppHandle) -> Result<PathBuf, String> {
|
||||
let root = app
|
||||
.path()
|
||||
.app_data_dir()
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_HOME_FAILED: {error}"))?
|
||||
.join("guanghu-number-world-v1");
|
||||
fs::create_dir_all(&root)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_HOME_CREATE_FAILED: {error}"))?;
|
||||
Ok(root.join("number-coordinates.sqlite3"))
|
||||
}
|
||||
|
||||
fn open_database(path: &Path) -> Result<Connection, String> {
|
||||
let connection = Connection::open(path)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_OPEN_FAILED: {error}"))?;
|
||||
connection
|
||||
.execute_batch(
|
||||
"PRAGMA journal_mode=WAL;
|
||||
PRAGMA foreign_keys=ON;
|
||||
PRAGMA busy_timeout=5000;
|
||||
CREATE TABLE IF NOT EXISTS metadata(
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS module_paths(
|
||||
module_number TEXT PRIMARY KEY,
|
||||
transport TEXT NOT NULL,
|
||||
module_root_path TEXT NOT NULL UNIQUE,
|
||||
scheduling_policy TEXT NOT NULL,
|
||||
operation_count INTEGER NOT NULL,
|
||||
operation_numbers_json TEXT NOT NULL,
|
||||
execution_state TEXT NOT NULL,
|
||||
evidence TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS route_coordinates(
|
||||
operation_number TEXT PRIMARY KEY,
|
||||
alias TEXT NOT NULL UNIQUE,
|
||||
transport TEXT NOT NULL,
|
||||
protocol_version TEXT NOT NULL,
|
||||
caller_number TEXT NOT NULL,
|
||||
channel_number TEXT NOT NULL,
|
||||
module_number TEXT NOT NULL REFERENCES module_paths(module_number),
|
||||
target_number TEXT NOT NULL,
|
||||
module_root_path TEXT NOT NULL,
|
||||
route_path TEXT NOT NULL UNIQUE,
|
||||
admission TEXT NOT NULL,
|
||||
effect TEXT NOT NULL,
|
||||
evidence TEXT NOT NULL,
|
||||
UNIQUE(transport,protocol_version,caller_number,channel_number,module_number,operation_number,target_number)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS identity_coordinates(
|
||||
node_number TEXT PRIMARY KEY,
|
||||
namespace_id TEXT NOT NULL UNIQUE,
|
||||
subject_kind TEXT NOT NULL,
|
||||
domain_scope TEXT NOT NULL,
|
||||
admission TEXT NOT NULL,
|
||||
execution_state TEXT NOT NULL,
|
||||
evidence TEXT NOT NULL,
|
||||
path TEXT NOT NULL UNIQUE
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS protocol_coordinates(
|
||||
node_number TEXT PRIMARY KEY,
|
||||
protocol_id TEXT NOT NULL UNIQUE,
|
||||
source_state TEXT NOT NULL,
|
||||
execution_state TEXT NOT NULL,
|
||||
evidence TEXT NOT NULL,
|
||||
path TEXT NOT NULL UNIQUE
|
||||
);",
|
||||
)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_SCHEMA_FAILED: {error}"))?;
|
||||
Ok(connection)
|
||||
}
|
||||
|
||||
fn put_metadata(
|
||||
transaction: &rusqlite::Transaction<'_>,
|
||||
key: &str,
|
||||
value: impl AsRef<str>,
|
||||
) -> Result<(), String> {
|
||||
transaction
|
||||
.execute(
|
||||
"INSERT INTO metadata(key,value) VALUES(?1,?2)",
|
||||
params![key, value.as_ref()],
|
||||
)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_METADATA_WRITE_FAILED: {error}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn materialize_at(path: &Path) -> Result<(), String> {
|
||||
let tree = load_tree()?;
|
||||
let source_sha256 = tree_sha256();
|
||||
let mut connection = open_database(path)?;
|
||||
let transaction = connection
|
||||
.transaction_with_behavior(TransactionBehavior::Immediate)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_REBUILD_FAILED: {error}"))?;
|
||||
transaction
|
||||
.execute_batch(
|
||||
"DELETE FROM route_coordinates;
|
||||
DELETE FROM module_paths;
|
||||
DELETE FROM identity_coordinates;
|
||||
DELETE FROM protocol_coordinates;
|
||||
DELETE FROM metadata;",
|
||||
)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_REBUILD_FAILED: {error}"))?;
|
||||
|
||||
for module in &tree.module_nodes {
|
||||
if module.scheduling_policy != SCHEDULING_POLICY
|
||||
|| module.path != format!("{}/MODULE/{}", tree.root_number, module.module_number)
|
||||
|| module.operation_count != module.operation_numbers.len()
|
||||
{
|
||||
return Err("HOLOLAKE_NUMBER_DATABASE_MODULE_ROOT_INVALID".into());
|
||||
}
|
||||
transaction
|
||||
.execute(
|
||||
"INSERT INTO module_paths(module_number,transport,module_root_path,scheduling_policy,operation_count,operation_numbers_json,execution_state,evidence)
|
||||
VALUES(?1,?2,?3,?4,?5,?6,?7,?8)",
|
||||
params![
|
||||
module.module_number,
|
||||
module.transport,
|
||||
module.path,
|
||||
module.scheduling_policy,
|
||||
module.operation_count as i64,
|
||||
serde_json::to_string(&module.operation_numbers).map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_MODULE_OPERATIONS_INVALID: {error}"))?,
|
||||
module.execution_state,
|
||||
module.evidence,
|
||||
],
|
||||
)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_MODULE_WRITE_FAILED: {error}"))?;
|
||||
}
|
||||
for route in &tree.routes {
|
||||
let module_root_path: String = transaction
|
||||
.query_row(
|
||||
"SELECT module_root_path FROM module_paths WHERE module_number=?1",
|
||||
params![route.module_number],
|
||||
|row| row.get(0),
|
||||
)
|
||||
.map_err(|error| {
|
||||
format!("HOLOLAKE_NUMBER_DATABASE_MODULE_RESOLUTION_FAILED: {error}")
|
||||
})?;
|
||||
transaction
|
||||
.execute(
|
||||
"INSERT INTO route_coordinates(operation_number,alias,transport,protocol_version,caller_number,channel_number,module_number,target_number,module_root_path,route_path,admission,effect,evidence)
|
||||
VALUES(?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13)",
|
||||
params![route.operation_number,route.alias,route.transport,route.protocol_version,route.caller_number,route.channel_number,route.module_number,route.target_number,module_root_path,route.path,route.admission,route.effect,route.evidence],
|
||||
)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_ROUTE_WRITE_FAILED: {error}"))?;
|
||||
}
|
||||
for node in &tree.identity_nodes {
|
||||
transaction
|
||||
.execute(
|
||||
"INSERT INTO identity_coordinates(node_number,namespace_id,subject_kind,domain_scope,admission,execution_state,evidence,path)
|
||||
VALUES(?1,?2,?3,?4,?5,?6,?7,?8)",
|
||||
params![node.node_number,node.namespace_id,node.subject_kind,node.domain_scope,node.admission,node.execution_state,node.evidence,node.path],
|
||||
)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_IDENTITY_WRITE_FAILED: {error}"))?;
|
||||
}
|
||||
for node in &tree.protocol_nodes {
|
||||
transaction
|
||||
.execute(
|
||||
"INSERT INTO protocol_coordinates(node_number,protocol_id,source_state,execution_state,evidence,path)
|
||||
VALUES(?1,?2,?3,?4,?5,?6)",
|
||||
params![node.node_number,node.protocol_id,node.source_state,node.execution_state,node.evidence,node.path],
|
||||
)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_PROTOCOL_WRITE_FAILED: {error}"))?;
|
||||
}
|
||||
|
||||
put_metadata(&transaction, "database_id", DATABASE_ID)?;
|
||||
put_metadata(&transaction, "database_schema", DATABASE_SCHEMA)?;
|
||||
put_metadata(&transaction, "database_state", DATABASE_STATE)?;
|
||||
put_metadata(&transaction, "source_tree_record_id", &tree.record_id)?;
|
||||
put_metadata(&transaction, "source_tree_sha256", &source_sha256)?;
|
||||
put_metadata(&transaction, "root_number", &tree.root_number)?;
|
||||
put_metadata(
|
||||
&transaction,
|
||||
"coordinate_count",
|
||||
tree.coordinate_count.to_string(),
|
||||
)?;
|
||||
put_metadata(
|
||||
&transaction,
|
||||
"module_node_count",
|
||||
tree.module_node_count.to_string(),
|
||||
)?;
|
||||
put_metadata(&transaction, "route_count", tree.route_count.to_string())?;
|
||||
put_metadata(
|
||||
&transaction,
|
||||
"identity_node_count",
|
||||
tree.identity_node_count.to_string(),
|
||||
)?;
|
||||
put_metadata(
|
||||
&transaction,
|
||||
"protocol_node_count",
|
||||
tree.protocol_node_count.to_string(),
|
||||
)?;
|
||||
put_metadata(
|
||||
&transaction,
|
||||
"source_records_json",
|
||||
serde_json::to_string(
|
||||
&tree
|
||||
.sources
|
||||
.iter()
|
||||
.map(|source| (&source.record_id, &source.sha256))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_SOURCE_RECORD_INVALID: {error}"))?,
|
||||
)?;
|
||||
transaction
|
||||
.commit()
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_REBUILD_COMMIT_FAILED: {error}"))?;
|
||||
verify_at(path)
|
||||
}
|
||||
|
||||
fn metadata(connection: &Connection, key: &str) -> Result<String, String> {
|
||||
connection
|
||||
.query_row(
|
||||
"SELECT value FROM metadata WHERE key=?1",
|
||||
params![key],
|
||||
|row| row.get(0),
|
||||
)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_METADATA_READ_FAILED: {error}"))
|
||||
}
|
||||
|
||||
fn table_count(connection: &Connection, table: &str) -> Result<usize, String> {
|
||||
let query = match table {
|
||||
"module_paths" => "SELECT COUNT(*) FROM module_paths",
|
||||
"route_coordinates" => "SELECT COUNT(*) FROM route_coordinates",
|
||||
"identity_coordinates" => "SELECT COUNT(*) FROM identity_coordinates",
|
||||
"protocol_coordinates" => "SELECT COUNT(*) FROM protocol_coordinates",
|
||||
_ => return Err("HOLOLAKE_NUMBER_DATABASE_TABLE_UNKNOWN".into()),
|
||||
};
|
||||
connection
|
||||
.query_row(query, [], |row| row.get::<_, i64>(0))
|
||||
.map(|count| count as usize)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_COUNT_FAILED: {error}"))
|
||||
}
|
||||
|
||||
fn verify_at(path: &Path) -> Result<(), String> {
|
||||
let tree = load_tree()?;
|
||||
let connection = open_database(path)?;
|
||||
if metadata(&connection, "database_id")? != DATABASE_ID
|
||||
|| metadata(&connection, "database_schema")? != DATABASE_SCHEMA
|
||||
|| metadata(&connection, "database_state")? != DATABASE_STATE
|
||||
|| metadata(&connection, "source_tree_record_id")? != tree.record_id
|
||||
|| metadata(&connection, "source_tree_sha256")? != tree_sha256()
|
||||
|| table_count(&connection, "module_paths")? != tree.module_node_count
|
||||
|| table_count(&connection, "route_coordinates")? != tree.route_count
|
||||
|| table_count(&connection, "identity_coordinates")? != tree.identity_node_count
|
||||
|| table_count(&connection, "protocol_coordinates")? != tree.protocol_node_count
|
||||
{
|
||||
return Err("HOLOLAKE_NUMBER_DATABASE_VERIFY_FAILED".into());
|
||||
}
|
||||
let mismatched_modules: i64 = connection
|
||||
.query_row(
|
||||
"SELECT COUNT(*) FROM module_paths m
|
||||
WHERE m.scheduling_policy != ?1
|
||||
OR m.operation_count != (SELECT COUNT(*) FROM route_coordinates r WHERE r.module_number=m.module_number)
|
||||
OR m.module_root_path != ?2 || '/MODULE/' || m.module_number",
|
||||
params![SCHEDULING_POLICY, tree.root_number],
|
||||
|row| row.get(0),
|
||||
)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_MODULE_VERIFY_FAILED: {error}"))?;
|
||||
if mismatched_modules != 0 {
|
||||
return Err("HOLOLAKE_NUMBER_DATABASE_MODULE_VERIFY_FAILED".into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn start_on_application_open(app: &AppHandle) -> Result<(), String> {
|
||||
materialize_at(&database_path(app)?)
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_runtime_route(
|
||||
app: &AppHandle,
|
||||
transport: &str,
|
||||
protocol_version: &str,
|
||||
caller_number: &str,
|
||||
channel_number: &str,
|
||||
module_number: &str,
|
||||
operation_number: &str,
|
||||
target_number: &str,
|
||||
) -> Result<RuntimeRouteResolution, String> {
|
||||
let connection = open_database(&database_path(app)?)?;
|
||||
let source_tree_record_id = metadata(&connection, "source_tree_record_id")?;
|
||||
let source_tree_sha256 = metadata(&connection, "source_tree_sha256")?;
|
||||
connection
|
||||
.query_row(
|
||||
"SELECT r.transport,r.protocol_version,r.caller_number,r.channel_number,r.module_number,
|
||||
r.operation_number,r.target_number,r.alias,r.module_root_path,r.route_path,
|
||||
r.admission,r.effect,r.evidence,m.scheduling_policy
|
||||
FROM route_coordinates r JOIN module_paths m ON m.module_number=r.module_number
|
||||
WHERE r.transport=?1 AND r.protocol_version=?2 AND r.caller_number=?3
|
||||
AND r.channel_number=?4 AND r.module_number=?5 AND r.operation_number=?6
|
||||
AND r.target_number=?7",
|
||||
params![transport,protocol_version,caller_number,channel_number,module_number,operation_number,target_number],
|
||||
|row| {
|
||||
Ok(RuntimeRouteResolution {
|
||||
database_id: DATABASE_ID,
|
||||
source_tree_record_id: source_tree_record_id.clone(),
|
||||
source_tree_sha256: source_tree_sha256.clone(),
|
||||
transport: row.get(0)?,
|
||||
protocol_version: row.get(1)?,
|
||||
caller_number: row.get(2)?,
|
||||
channel_number: row.get(3)?,
|
||||
module_number: row.get(4)?,
|
||||
operation_number: row.get(5)?,
|
||||
target_number: row.get(6)?,
|
||||
alias: row.get(7)?,
|
||||
module_root_path: row.get(8)?,
|
||||
route_path: row.get(9)?,
|
||||
admission: row.get(10)?,
|
||||
effect: row.get(11)?,
|
||||
evidence: row.get(12)?,
|
||||
scheduling_policy: row.get(13)?,
|
||||
})
|
||||
},
|
||||
)
|
||||
.optional()
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_ROUTE_READ_FAILED: {error}"))?
|
||||
.ok_or_else(|| "HOLOLAKE_NUMBER_DATABASE_ROUTE_COORDINATE_MISMATCH".to_string())
|
||||
}
|
||||
|
||||
fn validate_query(number: &str) -> Result<&str, String> {
|
||||
let number = number.trim();
|
||||
if number.is_empty()
|
||||
|| number.len() > 160
|
||||
|| number
|
||||
.chars()
|
||||
.any(|character| character.is_control() || character.is_whitespace())
|
||||
{
|
||||
return Err("HOLOLAKE_NUMBER_DATABASE_QUERY_INVALID".into());
|
||||
}
|
||||
Ok(number)
|
||||
}
|
||||
|
||||
fn resolve_number_coordinate_at(
|
||||
path: &Path,
|
||||
number: &str,
|
||||
) -> Result<NumberCoordinateReminder, String> {
|
||||
let number = validate_query(number)?;
|
||||
let connection = open_database(path)?;
|
||||
let source_tree_record_id = metadata(&connection, "source_tree_record_id")?;
|
||||
let source_tree_sha256 = metadata(&connection, "source_tree_sha256")?;
|
||||
|
||||
if let Some((module_number, module_root_path, policy, evidence, operations_json)) = connection
|
||||
.query_row(
|
||||
"SELECT module_number,module_root_path,scheduling_policy,evidence,operation_numbers_json
|
||||
FROM module_paths WHERE module_number=?1",
|
||||
params![number],
|
||||
|row| Ok((row.get::<_, String>(0)?,row.get::<_, String>(1)?,row.get::<_, String>(2)?,row.get::<_, String>(3)?,row.get::<_, String>(4)?)),
|
||||
)
|
||||
.optional()
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_MODULE_READ_FAILED: {error}"))?
|
||||
{
|
||||
return Ok(NumberCoordinateReminder {
|
||||
schema: "hololake.number-coordinate-reminder/v1",
|
||||
database_id: DATABASE_ID,
|
||||
database_state: DATABASE_STATE,
|
||||
query: number.into(),
|
||||
coordinate_kind: "EXECUTION_MODULE".into(),
|
||||
canonical_number: module_number,
|
||||
path: module_root_path.clone(),
|
||||
module_root_path: Some(module_root_path),
|
||||
route_path: None,
|
||||
scheduling_policy: Some(policy),
|
||||
evidence,
|
||||
related_operation_numbers: serde_json::from_str(&operations_json).map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_MODULE_OPERATIONS_INVALID: {error}"))?,
|
||||
source_tree_record_id,
|
||||
source_tree_sha256,
|
||||
reminder: "有则按唯一编号路径进入;无则明确未知,不猜路径。",
|
||||
});
|
||||
}
|
||||
|
||||
if let Some((operation_number, module_root_path, route_path, evidence, policy)) = connection
|
||||
.query_row(
|
||||
"SELECT r.operation_number,r.module_root_path,r.route_path,r.evidence,m.scheduling_policy
|
||||
FROM route_coordinates r JOIN module_paths m ON m.module_number=r.module_number
|
||||
WHERE r.operation_number=?1 OR r.alias=?1",
|
||||
params![number],
|
||||
|row| Ok((row.get::<_, String>(0)?,row.get::<_, String>(1)?,row.get::<_, String>(2)?,row.get::<_, String>(3)?,row.get::<_, String>(4)?)),
|
||||
)
|
||||
.optional()
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_ROUTE_READ_FAILED: {error}"))?
|
||||
{
|
||||
return Ok(NumberCoordinateReminder {
|
||||
schema: "hololake.number-coordinate-reminder/v1",
|
||||
database_id: DATABASE_ID,
|
||||
database_state: DATABASE_STATE,
|
||||
query: number.into(),
|
||||
coordinate_kind: "OPERATION_ROUTE".into(),
|
||||
canonical_number: operation_number.clone(),
|
||||
path: route_path.clone(),
|
||||
module_root_path: Some(module_root_path),
|
||||
route_path: Some(route_path),
|
||||
scheduling_policy: Some(policy),
|
||||
evidence,
|
||||
related_operation_numbers: vec![operation_number],
|
||||
source_tree_record_id,
|
||||
source_tree_sha256,
|
||||
reminder: "先回到模块唯一根路径,再进入当前操作叶片。",
|
||||
});
|
||||
}
|
||||
|
||||
if let Some((node_number, path, evidence)) = connection
|
||||
.query_row(
|
||||
"SELECT node_number,path,evidence FROM identity_coordinates WHERE node_number=?1 OR namespace_id=?1",
|
||||
params![number],
|
||||
|row| Ok((row.get::<_, String>(0)?,row.get::<_, String>(1)?,row.get::<_, String>(2)?)),
|
||||
)
|
||||
.optional()
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_IDENTITY_READ_FAILED: {error}"))?
|
||||
{
|
||||
return Ok(NumberCoordinateReminder {
|
||||
schema: "hololake.number-coordinate-reminder/v1", database_id: DATABASE_ID,
|
||||
database_state: DATABASE_STATE, query: number.into(), coordinate_kind: "IDENTITY_NAMESPACE".into(),
|
||||
canonical_number: node_number, path, module_root_path: None, route_path: None,
|
||||
scheduling_policy: None, evidence, related_operation_numbers: vec![],
|
||||
source_tree_record_id, source_tree_sha256,
|
||||
reminder: "身份编号只定位权威登记路径,不自行授予身份或执行权。",
|
||||
});
|
||||
}
|
||||
|
||||
if let Some((node_number, path, evidence)) = connection
|
||||
.query_row(
|
||||
"SELECT node_number,path,evidence FROM protocol_coordinates WHERE node_number=?1 OR protocol_id=?1",
|
||||
params![number],
|
||||
|row| Ok((row.get::<_, String>(0)?,row.get::<_, String>(1)?,row.get::<_, String>(2)?)),
|
||||
)
|
||||
.optional()
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_PROTOCOL_READ_FAILED: {error}"))?
|
||||
{
|
||||
return Ok(NumberCoordinateReminder {
|
||||
schema: "hololake.number-coordinate-reminder/v1", database_id: DATABASE_ID,
|
||||
database_state: DATABASE_STATE, query: number.into(), coordinate_kind: "GLS_PROTOCOL".into(),
|
||||
canonical_number: node_number, path, module_root_path: None, route_path: None,
|
||||
scheduling_policy: None, evidence, related_operation_numbers: vec![],
|
||||
source_tree_record_id, source_tree_sha256,
|
||||
reminder: "协议编号先定位来源与执行状态;引用节点不得冒充可执行协议。",
|
||||
});
|
||||
}
|
||||
Err("HOLOLAKE_NUMBER_DATABASE_COORDINATE_UNKNOWN".into())
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_number_coordinate(
|
||||
app: &AppHandle,
|
||||
input: Value,
|
||||
) -> Result<NumberCoordinateReminder, String> {
|
||||
let number = input
|
||||
.get("number")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or_else(|| "HOLOLAKE_NUMBER_DATABASE_NUMBER_REQUIRED".to_string())?;
|
||||
resolve_number_coordinate_at(&database_path(app)?, number)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn tree_materializes_into_a_verified_runtime_number_database() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let path = directory.path().join("numbers.sqlite3");
|
||||
materialize_at(&path).unwrap();
|
||||
let connection = open_database(&path).unwrap();
|
||||
assert_eq!(metadata(&connection, "database_id").unwrap(), DATABASE_ID);
|
||||
assert_eq!(table_count(&connection, "module_paths").unwrap(), 46);
|
||||
assert_eq!(table_count(&connection, "route_coordinates").unwrap(), 175);
|
||||
assert_eq!(table_count(&connection, "identity_coordinates").unwrap(), 4);
|
||||
assert_eq!(
|
||||
table_count(&connection, "protocol_coordinates").unwrap(),
|
||||
99
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_persona_conversation_operation_resolves_to_one_module_root() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let path = directory.path().join("numbers.sqlite3");
|
||||
materialize_at(&path).unwrap();
|
||||
for operation in [
|
||||
"HLP-NIPC-OP-0158",
|
||||
"HLP-NIPC-OP-0159",
|
||||
"HLP-NIPC-OP-0160",
|
||||
"HLP-NIPC-OP-0161",
|
||||
"HLP-NIPC-OP-0164",
|
||||
"HLP-NIPC-OP-0165",
|
||||
"HLP-NIPC-OP-0166",
|
||||
"HLP-NIPC-OP-0168",
|
||||
] {
|
||||
let reminder = resolve_number_coordinate_at(&path, operation).unwrap();
|
||||
assert_eq!(
|
||||
reminder.module_root_path.as_deref(),
|
||||
Some("HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0035")
|
||||
);
|
||||
assert_eq!(
|
||||
reminder.scheduling_policy.as_deref(),
|
||||
Some(SCHEDULING_POLICY)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reminder_resolves_module_alias_and_protocol_but_unknowns_fail_closed() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let path = directory.path().join("numbers.sqlite3");
|
||||
materialize_at(&path).unwrap();
|
||||
let module = resolve_number_coordinate_at(&path, "HLP-NIPC-MOD-0035").unwrap();
|
||||
assert_eq!(module.coordinate_kind, "EXECUTION_MODULE");
|
||||
assert_eq!(module.related_operation_numbers.len(), 8);
|
||||
let alias = resolve_number_coordinate_at(&path, "create_conversation").unwrap();
|
||||
assert_eq!(alias.canonical_number, "HLP-NIPC-OP-0165");
|
||||
let protocol = resolve_number_coordinate_at(&path, "GLS-0001").unwrap();
|
||||
assert_eq!(protocol.coordinate_kind, "GLS_PROTOCOL");
|
||||
assert_eq!(
|
||||
resolve_number_coordinate_at(&path, "UNKNOWN-999").unwrap_err(),
|
||||
"HOLOLAKE_NUMBER_DATABASE_COORDINATE_UNKNOWN"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ use serde_json::{Map, Value};
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use tauri::{AppHandle, Manager, State};
|
||||
use uuid::Uuid;
|
||||
|
|
@ -164,6 +164,7 @@ pub struct NumberedIpcState {
|
|||
signing_key: hmac::Key,
|
||||
grants: Mutex<HashMap<String, GrantRecord>>,
|
||||
ledger: Mutex<()>,
|
||||
module_paths: Mutex<HashMap<String, Arc<tokio::sync::Mutex<()>>>>,
|
||||
}
|
||||
|
||||
impl Default for NumberedIpcState {
|
||||
|
|
@ -177,10 +178,25 @@ impl Default for NumberedIpcState {
|
|||
signing_key: hmac::Key::new(hmac::HMAC_SHA256, &secret),
|
||||
grants: Mutex::new(HashMap::new()),
|
||||
ledger: Mutex::new(()),
|
||||
module_paths: Mutex::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn module_path_lock(
|
||||
state: &NumberedIpcState,
|
||||
module_root_path: &str,
|
||||
) -> Result<Arc<tokio::sync::Mutex<()>>, String> {
|
||||
let mut paths = state
|
||||
.module_paths
|
||||
.lock()
|
||||
.map_err(|_| "HOLOLAKE_NUMBERED_IPC_MODULE_PATH_LOCK_POISONED".to_string())?;
|
||||
Ok(paths
|
||||
.entry(module_root_path.to_string())
|
||||
.or_insert_with(|| Arc::new(tokio::sync::Mutex::new(())))
|
||||
.clone())
|
||||
}
|
||||
|
||||
fn default_ttl_ms() -> u64 {
|
||||
10_000
|
||||
}
|
||||
|
|
@ -763,6 +779,52 @@ pub async fn numbered_ipc(
|
|||
)
|
||||
}
|
||||
};
|
||||
let runtime_route = match crate::number_database::resolve_runtime_route(
|
||||
&app,
|
||||
"TAURI_WEBVIEW_NUMBERED_IPC",
|
||||
&request.envelope.coordinate.protocol_version,
|
||||
&request.envelope.coordinate.caller_number,
|
||||
&request.envelope.coordinate.channel_number,
|
||||
&request.envelope.coordinate.module_number,
|
||||
&request.envelope.coordinate.operation_number,
|
||||
&request.envelope.coordinate.target_number,
|
||||
) {
|
||||
Ok(runtime_route)
|
||||
if runtime_route.alias == route.alias
|
||||
&& runtime_route.admission == route.admission
|
||||
&& runtime_route.effect == route.effect =>
|
||||
{
|
||||
runtime_route
|
||||
}
|
||||
Ok(_) => {
|
||||
return response(
|
||||
&app,
|
||||
&state,
|
||||
"NUMBER_DATABASE_REJECTED",
|
||||
"DENY",
|
||||
&operation_number,
|
||||
&digest,
|
||||
None,
|
||||
None,
|
||||
Some("HOLOLAKE_NUMBER_DATABASE_REGISTRY_MISMATCH".into()),
|
||||
now,
|
||||
)
|
||||
}
|
||||
Err(error) => {
|
||||
return response(
|
||||
&app,
|
||||
&state,
|
||||
"NUMBER_DATABASE_REJECTED",
|
||||
"DENY",
|
||||
&operation_number,
|
||||
&digest,
|
||||
None,
|
||||
None,
|
||||
Some(error),
|
||||
now,
|
||||
)
|
||||
}
|
||||
};
|
||||
let authority_binding = match enforce_admission(&app, route) {
|
||||
Ok(binding) => binding,
|
||||
Err(error) => {
|
||||
|
|
@ -873,6 +935,8 @@ pub async fn numbered_ipc(
|
|||
)
|
||||
}
|
||||
};
|
||||
let module_lock = module_path_lock(&state, &runtime_route.module_root_path)?;
|
||||
let _module_path_guard = module_lock.lock().await;
|
||||
match crate::numbered_ipc_dispatch::dispatch(
|
||||
app.clone(),
|
||||
&route.handler,
|
||||
|
|
@ -934,10 +998,23 @@ mod tests {
|
|||
#[test]
|
||||
fn registry_is_closed_and_contains_every_migrated_command() {
|
||||
let registry = load_registry().unwrap();
|
||||
assert_eq!(registry.operations.len(), 145);
|
||||
assert_eq!(registry.operations.len(), 150);
|
||||
assert!(!registry.runtime.legacy_direct_commands_allowed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_module_root_reuses_one_runtime_execution_lane() {
|
||||
let state = NumberedIpcState::default();
|
||||
let first =
|
||||
module_path_lock(&state, "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0035").unwrap();
|
||||
let second =
|
||||
module_path_lock(&state, "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0035").unwrap();
|
||||
let other =
|
||||
module_path_lock(&state, "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0018").unwrap();
|
||||
assert!(Arc::ptr_eq(&first, &second));
|
||||
assert!(!Arc::ptr_eq(&first, &other));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn route_coordinates_cannot_be_mixed() {
|
||||
let registry = load_registry().unwrap();
|
||||
|
|
|
|||
|
|
@ -392,21 +392,37 @@ pub(crate) async fn dispatch(
|
|||
"persona_language_channel::discover_model_providers" => {
|
||||
json(crate::persona_language_channel::discover_model_providers(app).await?)
|
||||
}
|
||||
"persona_language_channel::upsert_model_provider" => {
|
||||
json(crate::persona_language_channel::upsert_model_provider(app, input(&payload)?).await?)
|
||||
}
|
||||
"persona_language_channel::upsert_model_provider" => json(
|
||||
crate::persona_language_channel::upsert_model_provider(app, input(&payload)?).await?,
|
||||
),
|
||||
"persona_language_channel::get_conversation" => {
|
||||
json(crate::persona_language_channel::get_conversation(app, input(&payload)?).await?)
|
||||
}
|
||||
"persona_language_channel::list_conversations" => {
|
||||
json(crate::persona_language_channel::list_conversations(app, input(&payload)?).await?)
|
||||
}
|
||||
"persona_language_channel::create_conversation" => {
|
||||
json(crate::persona_language_channel::create_conversation(app, input(&payload)?).await?)
|
||||
}
|
||||
"persona_language_channel::delete_conversation" => {
|
||||
json(crate::persona_language_channel::delete_conversation(app, input(&payload)?).await?)
|
||||
}
|
||||
"persona_language_channel::send_message" => {
|
||||
json(crate::persona_language_channel::send_message(app, input(&payload)?).await?)
|
||||
}
|
||||
"persona_language_channel::preview_hldp_tool_program" => json(
|
||||
crate::persona_language_channel::preview_hldp_tool_program(input(&payload)?).await?,
|
||||
),
|
||||
"execution_limb_training::get_execution_limb_snapshot" => {
|
||||
json(crate::execution_limb_training::get_execution_limb_snapshot(app).await?)
|
||||
}
|
||||
"execution_limb_training::run_execution_limb_training_drill" => {
|
||||
json(crate::execution_limb_training::run_execution_limb_training_drill(app, input(&payload)?).await?)
|
||||
}
|
||||
"execution_limb_training::run_execution_limb_training_drill" => json(
|
||||
crate::execution_limb_training::run_execution_limb_training_drill(
|
||||
app,
|
||||
input(&payload)?,
|
||||
)
|
||||
.await?,
|
||||
),
|
||||
"persona_time_authority::issue_persona_time_ticket" => json(
|
||||
crate::persona_time_authority::issue_persona_time_ticket(app, input(&payload)?).await?,
|
||||
),
|
||||
|
|
@ -562,6 +578,12 @@ pub(crate) async fn dispatch(
|
|||
"zero_core_numbering::get_zero_core_numbering_kernel" => {
|
||||
json(crate::zero_core_numbering::get_zero_core_numbering_kernel().await?)
|
||||
}
|
||||
"number_database::resolve_number_coordinate" => {
|
||||
json(crate::number_database::resolve_number_coordinate(
|
||||
&app,
|
||||
payload.get("input").cloned().unwrap_or(Value::Null),
|
||||
)?)
|
||||
}
|
||||
"zero_point::zero_point_bind" => json(
|
||||
crate::zero_point::zero_point_bind(
|
||||
app.state::<crate::zero_point::ZeroPointState>(),
|
||||
|
|
|
|||
|
|
@ -79,7 +79,6 @@ pub struct PersonaChannelBodySnapshot {
|
|||
pub history_mutation_allowed: bool,
|
||||
}
|
||||
|
||||
|
||||
/// 语言频道读取已注册人格体摘要的共用入口(2026-08-20 正向合并:自语言人格频道线移植)。
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub(crate) fn require_registered_persona(
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue