diff --git a/product-source/hololake-native-desktop/README.md b/product-source/hololake-native-desktop/README.md index a3e74cc5d..1d985527c 100644 --- a/product-source/hololake-native-desktop/README.md +++ b/product-source/hololake-native-desktop/README.md @@ -47,8 +47,43 @@ React/TypeScript。桌面上的 `world.guanghu.hololake` 安装包是本源码 首个公开产品是 GH-AIOS 通用人工智能操作平台,首页同时承担五域统一入口。用户只提交光湖编号,不手工选择所属域;系统先在内部完成域路由和编号合法性校验,再开放对应域的登录界面。五域只共享入口协议,不共享注册表、登录服务或私有数据。 +登录后的域内界面始终提供“返回主世界”,只返回五域公共首页并保留当前会话;“退出账号”是独立动作。用户从公共首页再次进入自己的所属域时,不重复进行编号或域凭证验证。 + 机器合同:`contracts/stage-one-platform.json`。 +## 光湖分域行业装配 + +光湖分域是行业系统入口,现已接入第一份行业路由合同:`contracts/subdomain-industry-routing.json`。 +公共主世界点击“光湖分域”即可查看行业状态并进入教育行业初始化频道;浏览公共状态不等于取得 +任何私有频道数据或写入权限。光湖零域不承载行业入口。人的主体编号 +只负责身份,行业编号只负责系统路由,两者不互相改写。行业顺序与当前工程状态分别为:网文行业 +待开发、宠物行业待开发、教育行业开发中;开发优先级不改变行业顺序,也不允许客户端自行签发 +尚未登记的行业编号。 + +教育行业已经建立 `GH-EDU-INIT-001` 初始化频道,并装入五项 HoloLake 原生能力: +`contracts/education-workspace.json` 定义的教育文档、教育表格数据、数据整理、人工确认自动化与原生组合视图。登录账号可以创建、读取、 +编辑、保存和可恢复归档多篇教育文档,并可从教学计划、会议纪要和学员复盘模板开始;也可以 +建立多张表格、增删行列、编辑单元格、筛选排序,在表格视图与可编辑卡片视图之间切换,并把 +Excel、飞书或钉钉复制的多行多列数据直接批量粘贴。两者都由 +Rust 原生层写入当前账号独立的本机 SQLite,保存要求精确修订号,重启后可以读回,不使用浏览器 +临时存储,也不把公共行业目录与私人内容混在一起。 + +数据整理模块读取当前账号已有教育表格,先计算并预览首尾空白规范化、完整空行清除和完全重复行 +去重结果;只有人明确确认后,才以当前修订号写回同一张表。它不跨账号读取,也不在后台自动修改。 + +自动化模块允许保存表格规则,按字段的等于、包含、为空或不为空条件匹配数据,并向指定字段写入内容。 +每次执行必须先锁定规则与表格修订、生成只读预览,再由人明确确认;写入与执行回执在同一数据库事务中完成。 +它不会后台定时运行,不跨账号,也不把模型推理当作执行授权。当前没有把旧教育预览壳或任何开源应用 +整包嵌入。`contracts/education-open-source-donor-assessment.json` 记录 AppFlowy、Lexical 与 +TanStack Table 的初步工程筛查:当前只研究结构和交互逻辑,没有复制源码或增加外部依赖;后续 +模块仍须分别完成来源、许可证、安全边界和 HoloLake 接口审查后再按需装配。 + +原生组合视图由 Rust 内核读取当前登录账号的真实知识目录,生成受限的 +`hololake.native-object/v1`,再把已登记的数据源、分类、聚合和投影模块编译成类型化无环图。 +人类可以切换一级目录/知识来源和文档数/数据量/重复数,并把同一次执行结果任意组合为仪表盘、 +对比、柱状图、分类和明细表。该阶段只读,不让渲染层取得知识写权限,也不以硬编码样例满足验收。 +机器合同见 `contracts/native-composition-runtime.json`。 + 个人频道、知识库和代码频道的机器合同分别是 `contracts/personal-channel-kernel.json`、 `contracts/knowledge-workspace.json` 与 `contracts/code-channel.json`。本机身份不是平台账户 认证;本机知识与源码访问也不产生仓库、服务器、部署或发布权限。 diff --git a/product-source/hololake-native-desktop/audit/hololake-0.5.0-numbered-root-installed-acceptance-20260818.json b/product-source/hololake-native-desktop/audit/hololake-0.5.0-numbered-root-installed-acceptance-20260818.json deleted file mode 100644 index 959e9f036..000000000 --- a/product-source/hololake-native-desktop/audit/hololake-0.5.0-numbered-root-installed-acceptance-20260818.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "schema": "hololake.installed-numbered-root-acceptance/v1", - "record_id": "HLP-HOLOLAKE-0.5.0-NUMBERED-ROOT-INSTALLED-20260818", - "state": "LOCAL_DEVELOPER_ID_SIGNED_INSTALLED_ACCEPTANCE_PASS_PUBLIC_NOTARIZATION_PENDING", - "observed_at": "2026-08-18T15:18:00Z", - "source": { - "branch": "codex/hololake-clean-reassembly-20260818", - "source_commit": "5d01607459043d0713bc562ef6d04dec198930a9", - "numbered_root_commit": "64abf969bfbc1c576d4fa84ae3282d32efbfcc38" - }, - "installed_application": { - "path": "/Users/bingshuolingdianyuanhe/Desktop/HoloLake.app", - "version": "0.5.0", - "bundle_identifier": "world.guanghu.hololake", - "architecture": "arm64", - "binary_sha256": "2e162ff077187310f816f58df2250e3ee939eb489fe3c7b00e94557ff8f3370d", - "process_path_verified": true - }, - "developer_id": { - "identity": "Developer ID Application: bei sun (825A9L3G7Q)", - "team_identifier": "825A9L3G7Q", - "cdhash": "7a2372ed85fc3b775e9a352217b123a4bdee0d64", - "strict_signature_verification": "PASS", - "designated_requirement": "PASS", - "gatekeeper": "REJECTED_UNNOTARIZED_DEVELOPER_ID", - "apple_notarization_and_stapling": "PENDING" - }, - "runtime": { - "real_webview_loaded": true, - "visible_version": "V0.5.0", - "visible_domain": "第五域 · 光湖本源域", - "entered_surface": "永恒湖心系统", - "numbered_ipc_receipt_rows": 50, - "grant_and_execution_rows_present": true, - "empty_authority_binding_digest_rows": 0, - "recalculated_receipt_chain_failures": 0, - "last_sequence": 50, - "last_receipt_hash": "a294463ad9e6959d0f12ce5c2b59e11d97581e067b9480df9ae598dfafc067df" - }, - "old_application": { - "version": "0.4.1", - "role": "READ_ONLY_PRE_NUMBERED_ROOT_MODULE_DONOR", - "archive_receipt": "/Volumes/JZAO/HoloLake/artifacts/hololake-release/0.4.1/macos-arm64/pre-numbered-root-donor/archive-receipt.json", - "repair_in_place": false - }, - "release_boundary": { - "local_signed_install_complete": true, - "public_signed_notarized_release_complete": false, - "updater_public_key_continuity": "PASS_EXISTING_0.4.1_TRUST_ROOT_REUSED", - "updater_private_key_available_to_current_pipeline": true, - "updater_signature_generated_and_verified": true, - "pre_notarization_updater_artifact": { - "path": "src-tauri/target/release/bundle/macos/HoloLake.app.tar.gz", - "sha256": "4176bb7ea83c820744239c228671840289f87675329182bc055938e03bba9693", - "signature_path": "src-tauri/target/release/bundle/macos/HoloLake.app.tar.gz.sig", - "signature_sha256": "ae02c2918c26b6e3cc2389fec8d9f98884ae639d448edc78a4ec80ee30a8ae92", - "publication_allowed": false - }, - "apple_notarization_credentials_available_to_current_pipeline": false, - "public_broadcast_activated": false - }, - "persona_boundary": { - "current_codex_carrier_binding_claimed": false, - "runtime_persona_binding_created_by_numbered_ipc": false - } -} diff --git a/product-source/hololake-native-desktop/audit/hololake-0.5.0-qoder-numbered-production-installed-20260819.json b/product-source/hololake-native-desktop/audit/hololake-0.5.0-qoder-numbered-production-installed-20260819.json deleted file mode 100644 index 60db39e45..000000000 --- a/product-source/hololake-native-desktop/audit/hololake-0.5.0-qoder-numbered-production-installed-20260819.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "schema": "hololake.production-install-acceptance/v1", - "record_id": "HLP-PRODUCTION-INSTALL-20260819-001", - "state": "PASS", - "version": "0.5.0", - "installed_path": "/Users/bingshuolingdianyuanhe/Desktop/HoloLake.app", - "visible_hololake_app_count": 1, - "previous_app_recovery_path": "/Users/bingshuolingdianyuanhe/.Trash/HoloLake-pre-qoder-numbered-ui-20260819-0659.app", - "binary_sha256": "b0422bb18df521ace54ff1a52cd47121d92833dd78f165845deba7806686c7ac", - "cdhash": "42640f7ce56e96403609899095c77ea6171df07d", - "team_identifier": "825A9L3G7Q", - "developer_id_signature": "PASS", - "launch": "PASS", - "real_data_rehydration": "PASS", - "notarization": "NOT_CLAIMED_THIS_LOCAL_BUILD", - "updater_artifact_signing": "NOT_COMPLETED_MISSING_PRIVATE_UPDATER_KEY_IN_CURRENT_PROCESS" -} diff --git a/product-source/hololake-native-desktop/audit/qoder-surface-live-acceptance-20260819.json b/product-source/hololake-native-desktop/audit/qoder-surface-live-acceptance-20260819.json deleted file mode 100644 index c02229824..000000000 --- a/product-source/hololake-native-desktop/audit/qoder-surface-live-acceptance-20260819.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "schema": "hololake.qoder-surface-live-acceptance/v1", - "record_id": "HLP-QODER-SURFACE-ACCEPTANCE-20260819-001", - "module_number": "HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001", - "state": "PASS", - "tested_app": "src-tauri/target/debug/bundle/macos/HoloLake.app", - "developer_id_signature": "PASS", - "team_identifier": "825A9L3G7Q", - "binary_sha256": "fb1d0497f295e1228c9b2ac86e33082332f226aae6e32b9050cf6c5de30bd512", - "cdhash": "90e365b23961a6b842590869df655ec35a55b66e", - "checks": { - "traditional_locked_layout": "PASS", - "traditional_real_data_hydration": "PASS", - "traditional_light_finish_readability": "PASS_SNOW", - "language_world_five_domains_no_overlap": "PASS_1229x768", - "language_world_real_weather": "PASS_CLOUD", - "theme_persists_into_channel": "PASS", - "theme_persists_into_web_novel": "PASS", - "theme_persists_into_education": "PASS", - "new_chapter_modal_opens": "PASS", - "created_chapter_survives_restart": "PASS_1_CHAPTER", - "work_summary_refresh_after_create": "PASS_1_CHAPTER_ON_WORK_CARD", - "idle_clock_stops": "PASS", - "idle_screenshot_psnr_db": 59.502493 - }, - "reference_comparison": "audit/qoder-traditional-reference-vs-hololake-0.5.0.jpg", - "public_notarization": "NOT_CLAIMED_BY_DEBUG_ACCEPTANCE" -} diff --git a/product-source/hololake-native-desktop/audit/qoder-traditional-reference-vs-hololake-0.5.0.jpg b/product-source/hololake-native-desktop/audit/qoder-traditional-reference-vs-hololake-0.5.0.jpg deleted file mode 100644 index 6f8eb5d42..000000000 Binary files a/product-source/hololake-native-desktop/audit/qoder-traditional-reference-vs-hololake-0.5.0.jpg and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-home-1440.png b/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-home-1440.png deleted file mode 100644 index ce8d44afb..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-home-1440.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-home-500.png b/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-home-500.png deleted file mode 100644 index 8c2dff839..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-home-500.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-modules-1440.png b/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-modules-1440.png deleted file mode 100644 index a5608fd23..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-modules-1440.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-native-1440.png b/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-native-1440.png deleted file mode 100644 index 748653e18..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-lightweight-native-1440.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-modules.png b/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-modules.png deleted file mode 100644 index ef1f082ce..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-modules.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-native.png b/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-native.png deleted file mode 100644 index 247ce0aeb..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/private-channel-native.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/public-1024x768.png b/product-source/hololake-native-desktop/audit/responsive-20260819/public-1024x768.png deleted file mode 100644 index 603e45748..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/public-1024x768.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/public-1440x900.png b/product-source/hololake-native-desktop/audit/responsive-20260819/public-1440x900.png deleted file mode 100644 index 1b3552d4b..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/public-1440x900.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/public-720x900.png b/product-source/hololake-native-desktop/audit/responsive-20260819/public-720x900.png deleted file mode 100644 index 890c987a4..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/public-720x900.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/traditional-1024x768.png b/product-source/hololake-native-desktop/audit/responsive-20260819/traditional-1024x768.png deleted file mode 100644 index f3f2664e7..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/traditional-1024x768.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/responsive-20260819/traditional-1440x900.png b/product-source/hololake-native-desktop/audit/responsive-20260819/traditional-1440x900.png deleted file mode 100644 index c0318fd10..000000000 Binary files a/product-source/hololake-native-desktop/audit/responsive-20260819/traditional-1440x900.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/ui-concepts-20260819/private-channel-wide.png b/product-source/hololake-native-desktop/audit/ui-concepts-20260819/private-channel-wide.png deleted file mode 100644 index 20d1b1bac..000000000 Binary files a/product-source/hololake-native-desktop/audit/ui-concepts-20260819/private-channel-wide.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/ui-concepts-20260819/public-world-narrow.png b/product-source/hololake-native-desktop/audit/ui-concepts-20260819/public-world-narrow.png deleted file mode 100644 index b158a5e84..000000000 Binary files a/product-source/hololake-native-desktop/audit/ui-concepts-20260819/public-world-narrow.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/ui-concepts-20260819/public-world-wide.png b/product-source/hololake-native-desktop/audit/ui-concepts-20260819/public-world-wide.png deleted file mode 100644 index 09985adfc..000000000 Binary files a/product-source/hololake-native-desktop/audit/ui-concepts-20260819/public-world-wide.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/audit/ui-concepts-20260819/traditional-workbench-wide.png b/product-source/hololake-native-desktop/audit/ui-concepts-20260819/traditional-workbench-wide.png deleted file mode 100644 index 47a120568..000000000 Binary files a/product-source/hololake-native-desktop/audit/ui-concepts-20260819/traditional-workbench-wide.png and /dev/null differ diff --git a/product-source/hololake-native-desktop/contracts/channel-growth-model.json b/product-source/hololake-native-desktop/contracts/channel-growth-model.json new file mode 100644 index 000000000..d75702529 --- /dev/null +++ b/product-source/hololake-native-desktop/contracts/channel-growth-model.json @@ -0,0 +1,58 @@ +{ + "schema": "hololake.channel-growth-model-contract/v1", + "record_id": "HLP-CHANNEL-GROWTH-001", + "state": "LOCAL_BASELINE_RUNTIME_IMPLEMENTED_MODEL_ADJUSTMENT_SLOT_RESERVED", + "scope": "EVERY_AUTHENTICATED_HUMAN_AND_PERSONA_JOINT_CHANNEL", + "role": "REBUILDABLE_DERIVED_PROJECTION_OF_PERSONA_CHANNEL_BODY", + "canonical_body_contract": "contracts/persona-channel-body.json", + "inputs": [ + "BOUNDED_MODULE_USAGE_METADATA", + "BOUNDED_HUMAN_ACTION_METADATA", + "BOUNDED_PERSONA_COLLABORATION_METADATA" + ], + "forbidden_inputs": [ + "DOCUMENT_BODY", + "TABLE_CELL_CONTENT", + "PASSWORD_OR_CREDENTIAL", + "RAW_CONVERSATION_TRANSCRIPT", + "UNDECLARED_EXTERNAL_TELEMETRY" + ], + "local_baseline": { + "always_available_without_model_api": true, + "algorithm": "DECAYED_MODULE_AFFINITY_WITH_EXPLAINABLE_COUNTS", + "channel_recommendation": "RECOMMENDED_MODULE_ORDER", + "silent_structural_change_allowed": false, + "source_history": "PERSONA_CHANNEL_BODY_APPEND_ONLY_LANGUAGE_HASH_CHAIN", + "projection_history": "REBUILDABLE_FROM_CANONICAL_BODY", + "correction_method": "APPEND_CORRECTION_TO_CANONICAL_BODY_THEN_REBUILD_PROJECTION", + "collection_pause_supported": false, + "full_history_clear_supported": false, + "projection_is_rebuildable_but_history_is_not_mutable": true, + "account_scoped_sqlite": true + }, + "model_adjustment": { + "api_slot": "HOLOLAKE_CHANNEL_GROWTH_MODEL_API/v1", + "current_state": "NOT_CONFIGURED", + "allowed_output": "CHANNEL_ADAPTATION_PROPOSAL", + "local_schema_validation_required": true, + "local_resource_limits_required": true, + "human_confirmation_before_structural_change": true, + "model_can_mutate_channel_directly": false, + "model_can_mutate_source_content": false, + "failure_behavior": "KEEP_LOCAL_BASELINE_AND_RETURN_HUMAN_READABLE_RECEIPT" + }, + "human_controls": [ + "VIEW_MODEL", + "CORRECT_OR_REJECT_PROPOSAL", + "VIEW_LOCAL_GROWTH_CHAIN", + "EXPORT_PERSONALLY_OWNED_MODEL", + "CHOOSE_LOCAL_ONLY_OR_ANONYMIZED_SHARE" + ], + "cross_device_or_shared_learning": { + "default": "LOCAL_ONLY_OFFICIAL_CANNOT_READ", + "explicit_opt_in_required": true, + "private_model_may_be_shared_automatically": false, + "raw_growth_chain_may_be_shared": false, + "shared_artifact": "ANONYMIZED_DERIVED_SKILL_OR_MODEL_LAYER_ONLY" + } +} diff --git a/product-source/hololake-native-desktop/contracts/channel-module-runtime.json b/product-source/hololake-native-desktop/contracts/channel-module-runtime.json new file mode 100644 index 000000000..87f5708fb --- /dev/null +++ b/product-source/hololake-native-desktop/contracts/channel-module-runtime.json @@ -0,0 +1,62 @@ +{ + "schema": "hololake.channel-module-runtime/v1", + "record_id": "HLP-CHANNEL-MODULE-RUNTIME-001", + "state": "FOUNDATION_INTEGRATED_MARKETPLACE_INSTALLER_PENDING", + "channel_model": "ONE_HUMAN_ONE_LOCAL_RUNTIME_ONE_ACTIVE_CHANNEL_LINE", + "built_in_foundation": { + "module_id": "hololake.builtin.channel-workbench", + "name": "频道轻量工作台", + "distribution": "RESIDENT_WITH_HOLOLAKE", + "marketplace_registration": "NOT_A_MARKETPLACE_MODULE", + "engines": ["DOCUMENT", "SPREADSHEET"], + "minimum_capabilities": [ + "REAL_TEXT_EDITING", + "REAL_CELL_EDITING", + "FORMULAS", + "COPY_PASTE", + "UNDO_REDO", + "LOCAL_NATIVE_STORAGE" + ] + }, + "marketplace_package": { + "required_fields": [ + "OFFICIAL_MODULE_NUMBER", + "PACKAGE_VERSION", + "SOURCE_COMMIT", + "PACKAGE_SHA256", + "PERMISSION_MANIFEST", + "ENTRY_MANIFEST", + "SUPPORTED_PLATFORM_TARGETS" + ], + "platform_targets": ["MACOS", "WINDOWS", "LINUX"], + "lifecycle": [ + "AVAILABLE", + "DOWNLOADING", + "HASH_VERIFIED", + "PERMISSIONS_REVIEWED", + "INSTALLED_TO_CURRENT_CHANNEL", + "DISABLED", + "RECOVERABLE_REMOVED" + ], + "install_actor": ["HUMAN", "AUTHORIZED_CHANNEL_PERSONA"], + "persona_install_rule": "PERSONA_MAY_DEPLOY_ONLY_AFTER_PACKAGE_AND_PERMISSION_VERIFICATION_AND_HUMAN_POLICY_ALLOWS", + "uninstall_boundary": "REMOVING_A_MODULE_NEVER_DELETES_CHANNEL_OR_PERSONA_GROWTH_HISTORY" + }, + "execution_boundary": { + "whole_world_bundled_into_client": false, + "industry_modules_resident_by_default": false, + "private_channel_data_uploaded_by_default": false, + "module_can_rewrite_persona_history": false, + "module_can_claim_unlisted_permissions": false + }, + "current_reality": { + "foundation_source_integrated": true, + "education_package_source_mounted_for_development": true, + "web_novel_package_source_mounted_for_development": true, + "official_marketplace_service_connected": false, + "education_package_number_registered": false, + "education_package_publishable": false, + "web_novel_package_number_registered": false, + "web_novel_package_publishable": false + } +} diff --git a/product-source/hololake-native-desktop/contracts/channel-workbench-runtime.json b/product-source/hololake-native-desktop/contracts/channel-workbench-runtime.json deleted file mode 100644 index 9980e8741..000000000 --- a/product-source/hololake-native-desktop/contracts/channel-workbench-runtime.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "schema": "hololake.channel-workbench-runtime/v1", - "record_id": "HLP-CHANNEL-WORKBENCH-RUNTIME-001", - "candidate_number": "HLP-DONOR-CAND-0002", - "runtime_module_number": "HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001", - "numbered_ipc": { - "module_number": "HLP-NIPC-MOD-0022", - "target_number": "HLP-NIPC-TGT-0022", - "operations": ["HLP-NIPC-OP-0074", "HLP-NIPC-OP-0075", "HLP-NIPC-OP-0076"] - }, - "engines": { - "document": "LEXICAL_0_49", - "spreadsheet": "FORTUNE_SHEET_1_0_4" - }, - "data_boundary": { - "scope": "CURRENT_AUTHENTICATED_ACCOUNT_LOCAL", - "database": "channel-workbench-v1/channel-workbench.sqlite3", - "documents_max_body_bytes": 2097152, - "spreadsheets_max_columns": 64, - "spreadsheets_max_rows": 5000, - "package_unmount_deletes_user_data": false, - "repository_code_is_executable": false - }, - "integrity": { - "optimistic_revision_required": true, - "every_save_writes_hash_chained_receipt": true, - "receipt_chain_verified_before_read_or_write": true, - "adapter_requires_signed_active_module": true - }, - "current_acceptance": { - "state": "SIGNED_INSTALLED_CONTENT_AND_RESTART_ACCEPTED", - "source_donor": "HLP-DONOR-CHAOTIC-WORKTREE-20260818", - "compiled_donor_behavior_checked": false, - "compiled_donor_boundary": "No claim of pixel-equivalent compiled-donor acceptance; the declared source slice was reconstructed and the clean host behavior was accepted directly.", - "real_signed_package": "fixtures/module-packages/HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001-0.1.0.ghmod", - "module_package_sha256": "eb7af0bd4882cc89acda11c933a3601d16f0588ff737caf8467b875ab5a4ab7b", - "signed_debug_binary_sha256": "6f851856ab6f5717facc67ec406c9eb99e240290c585438323e230daec5ae71c", - "developer_id_team": "825A9L3G7Q", - "signed_debug_cdhash": "0209a46b2dc221d37b618a2b12866bb8cb39f03d", - "real_account_human_number": "ICE-GL∞", - "ui_activation_verified": true, - "document_save": { - "title": "冰朔频道迁移验收", - "revision": 1, - "content_sha256_prefix": "534b4bd3d6d0", - "receipt_sha256_prefix": "72436f46cf1d" - }, - "spreadsheet_save": { - "title": "冰朔编号迁移表", - "revision": 1, - "formula_preserved": "=1+2", - "content_sha256_prefix": "57607d92c0dc", - "receipt_sha256_prefix": "323761fc18a3" - }, - "restart_persistence_verified": true, - "dependency_audit": "0_VULNERABILITIES_AFTER_UUID_11_1_1_OVERRIDE" - } -} diff --git a/product-source/hololake-native-desktop/contracts/direct-local-broker-numbered-registry.json b/product-source/hololake-native-desktop/contracts/direct-local-broker-numbered-registry.json deleted file mode 100644 index 99c3eb673..000000000 --- a/product-source/hololake-native-desktop/contracts/direct-local-broker-numbered-registry.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "schema": "hololake.direct-local-broker-numbered-registry/v1", - "record_id": "HLP-NBROKER-ROOT-001", - "runtime": { - "protocol_version": "HLP-NBROKER-v1", - "caller_number": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "legacy_string_operation_allowed": false, - "unknown_or_mismatched_coordinate": "FAIL_CLOSED", - "request_nonce_required": true, - "transport_is_authority": false - }, - "operations": [ - {"operation_number":"HLP-NBROKER-OP-0001","alias":"DISCOVER_NEARBY","channel_number":"HLP-NBROKER-CH-0001","module_number":"HLP-NBROKER-MOD-0001","target_number":"HLP-NBROKER-TGT-0001"}, - {"operation_number":"HLP-NBROKER-OP-0002","alias":"OPEN_VISITOR_SESSION","channel_number":"HLP-NBROKER-CH-0002","module_number":"HLP-NBROKER-MOD-0002","target_number":"HLP-NBROKER-TGT-0002"}, - {"operation_number":"HLP-NBROKER-OP-0003","alias":"RECEIVE_LANGUAGE","channel_number":"HLP-NBROKER-CH-0002","module_number":"HLP-NBROKER-MOD-0003","target_number":"HLP-NBROKER-TGT-0003"}, - {"operation_number":"HLP-NBROKER-OP-0004","alias":"PING","channel_number":"HLP-NBROKER-CH-0001","module_number":"HLP-NBROKER-MOD-0001","target_number":"HLP-NBROKER-TGT-0001"}, - {"operation_number":"HLP-NBROKER-OP-0005","alias":"OPEN_SESSION","channel_number":"HLP-NBROKER-CH-0003","module_number":"HLP-NBROKER-MOD-0004","target_number":"HLP-NBROKER-TGT-0004"}, - {"operation_number":"HLP-NBROKER-OP-0006","alias":"RESUME_SESSION","channel_number":"HLP-NBROKER-CH-0003","module_number":"HLP-NBROKER-MOD-0004","target_number":"HLP-NBROKER-TGT-0004"}, - {"operation_number":"HLP-NBROKER-OP-0007","alias":"HEARTBEAT_SESSION","channel_number":"HLP-NBROKER-CH-0003","module_number":"HLP-NBROKER-MOD-0004","target_number":"HLP-NBROKER-TGT-0004"}, - {"operation_number":"HLP-NBROKER-OP-0008","alias":"PRESENT_PERSONA_CARRIER_LICENSE","channel_number":"HLP-NBROKER-CH-0004","module_number":"HLP-NBROKER-MOD-0005","target_number":"HLP-NBROKER-TGT-0005"}, - {"operation_number":"HLP-NBROKER-OP-0009","alias":"GET_PERSONA_CARRIER_LICENSE_STATUS","channel_number":"HLP-NBROKER-CH-0004","module_number":"HLP-NBROKER-MOD-0005","target_number":"HLP-NBROKER-TGT-0005"}, - {"operation_number":"HLP-NBROKER-OP-0010","alias":"GET_WORK_ENVIRONMENT","channel_number":"HLP-NBROKER-CH-0003","module_number":"HLP-NBROKER-MOD-0006","target_number":"HLP-NBROKER-TGT-0006"}, - {"operation_number":"HLP-NBROKER-OP-0011","alias":"APPEND_EVENT","channel_number":"HLP-NBROKER-CH-0003","module_number":"HLP-NBROKER-MOD-0004","target_number":"HLP-NBROKER-TGT-0004"}, - {"operation_number":"HLP-NBROKER-OP-0012","alias":"RESOLVE_CAPABILITY_ROUTE","channel_number":"HLP-NBROKER-CH-0005","module_number":"HLP-NBROKER-MOD-0007","target_number":"HLP-NBROKER-TGT-0007"}, - {"operation_number":"HLP-NBROKER-OP-0013","alias":"INSTALL_DYNAMIC_NODE_REGISTRY","channel_number":"HLP-NBROKER-CH-0005","module_number":"HLP-NBROKER-MOD-0007","target_number":"HLP-NBROKER-TGT-0007"}, - {"operation_number":"HLP-NBROKER-OP-0014","alias":"RECORD_SIGNED_NODE_HEALTH","channel_number":"HLP-NBROKER-CH-0005","module_number":"HLP-NBROKER-MOD-0007","target_number":"HLP-NBROKER-TGT-0007"}, - {"operation_number":"HLP-NBROKER-OP-0015","alias":"INSPECT_MOUNTED_PNCC_REPOSITORY","channel_number":"HLP-NBROKER-CH-0006","module_number":"HLP-NBROKER-MOD-0008","target_number":"HLP-NBROKER-TGT-0008"}, - {"operation_number":"HLP-NBROKER-OP-0016","alias":"READ_MOUNTED_PNCC_REMOTE_OBJECT","channel_number":"HLP-NBROKER-CH-0006","module_number":"HLP-NBROKER-MOD-0008","target_number":"HLP-NBROKER-TGT-0008"}, - {"operation_number":"HLP-NBROKER-OP-0017","alias":"QUERY_PNCC_RECEIPT_PROJECTION","channel_number":"HLP-NBROKER-CH-0006","module_number":"HLP-NBROKER-MOD-0008","target_number":"HLP-NBROKER-TGT-0008"}, - {"operation_number":"HLP-NBROKER-OP-0018","alias":"GET_BEIJING_TIME","channel_number":"HLP-NBROKER-CH-0001","module_number":"HLP-NBROKER-MOD-0009","target_number":"HLP-NBROKER-TGT-0009"}, - {"operation_number":"HLP-NBROKER-OP-0019","alias":"ISSUE_PERSONA_TIME_TICKET","channel_number":"HLP-NBROKER-CH-0004","module_number":"HLP-NBROKER-MOD-0009","target_number":"HLP-NBROKER-TGT-0009"}, - {"operation_number":"HLP-NBROKER-OP-0020","alias":"ACQUIRE_DEVELOPMENT_WRITE_LANE","channel_number":"HLP-NBROKER-CH-0007","module_number":"HLP-NBROKER-MOD-0010","target_number":"HLP-NBROKER-TGT-0010"}, - {"operation_number":"HLP-NBROKER-OP-0021","alias":"INSPECT_DEVELOPMENT_WRITE_LANE","channel_number":"HLP-NBROKER-CH-0007","module_number":"HLP-NBROKER-MOD-0010","target_number":"HLP-NBROKER-TGT-0010"}, - {"operation_number":"HLP-NBROKER-OP-0022","alias":"RELEASE_DEVELOPMENT_WRITE_LANE","channel_number":"HLP-NBROKER-CH-0007","module_number":"HLP-NBROKER-MOD-0010","target_number":"HLP-NBROKER-TGT-0010"} - ] -} diff --git a/product-source/hololake-native-desktop/contracts/dynamic-language-world-visual-system.json b/product-source/hololake-native-desktop/contracts/dynamic-language-world-visual-system.json index 5736af0c5..2c8232d34 100644 --- a/product-source/hololake-native-desktop/contracts/dynamic-language-world-visual-system.json +++ b/product-source/hololake-native-desktop/contracts/dynamic-language-world-visual-system.json @@ -1,83 +1,31 @@ { - "schema": "hololake.dynamic-language-world-visual-system/v1", - "record_id": "HLP-DYNAMIC-WORLD-SURFACE-001", - "state": "HOLOLAKE_0_5_SIGNED_NUMBERED_SURFACE_ACCEPTED", - "package": { - "official_module_number": "HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001", - "adapter": "dynamic-language-world-surface-v1", - "registration_class": "OFFICIAL_LIGHTHOUSE", - "activation": "SIGNED_PACKAGE_PLUS_EXPLICIT_HUMAN_PERMISSION_CONFIRMATION" - }, - "numbered_ipc": { - "module": "HLP-NIPC-MOD-0031", - "target": "HLP-NIPC-TGT-0031", - "operations": ["HLP-NIPC-OP-0147"], - "public_tauri_commands": ["numbered_ipc"], - "mismatched_coordinate": "FAIL_CLOSED" - }, + "schema": "HOLOLAKE_DYNAMIC_LANGUAGE_WORLD_VISUAL_SYSTEM/1", + "state": "IMPLEMENTED_LOCAL_ACCEPTANCE_PENDING", + "modes": ["DYNAMIC_LANGUAGE_WORLD", "FIXED_TRADITIONAL_THEME"], "dynamic_inputs": ["BEIJING_TIME", "VERIFIED_CURRENT_WEATHER"], - "weather": { - "provider": "Open-Meteo", - "endpoint": "https://api.open-meteo.com/v1/forecast", - "maximum_request_seconds": 5, - "cache_ttl_seconds": 600, - "redirects": "DENIED", - "unavailable_behavior": "BEIJING_TIME_ONLY_NO_FAKE_WEATHER" + "visual_balance": { + "token_layers": ["PRIMITIVE", "SEMANTIC", "COMPONENT"], + "light_scene_uses_dark_text": true, + "dark_scene_uses_light_text": true, + "routing_permission_or_fact_change_allowed": false }, - "visual_lock": { - "layout": "QODER_VISUAL_LANGUAGE_SEMANTICALLY_REASSEMBLED_ON_RESPONSIVE_HOLOLAKE_SHELL", - "language_world_themes": ["夜湖星光", "晨湖曦光", "星云紫夜", "烛畔暖湖", "清浅澄湖"], - "traditional_finishes": ["曜夜", "星辉", "深海", "翡翠", "朱砂", "香槟", "瓷光", "雪霁"], - "all_downstream_pages_inherit_active_surface_tokens": true, - "ambient_motion_requires_recent_human_pointer_or_keyboard_activity": true, - "idle_visual_state": "STATIC", - "responsive_layout": "CONTAINER_MEASURED_PANORAMIC_WIDE_COMPACT_STACKED_REFLOW", - "domain_semantic_order_is_stable": true, - "private_channel_separates_native_organs_from_installed_modules": true, - "climate_changes_routing_permission_or_fact": false, - "daily_sampling_domain_changes_open_domain": false, + "daily_domain_rotation": ["FIFTH_DOMAIN", "ZERO_SENSE_DOMAIN", "MAIN_DOMAIN", "BRANCH_DOMAIN", "ZERO_DOMAIN"], + "coordinates": { + "FIFTH_DOMAIN": "XIAN_INTERNAL_ONLY", + "ZERO_SENSE_DOMAIN": "BEIJING_INTERNAL_ONLY", + "MAIN_DOMAIN": "BEIJING_INTERNAL_ONLY", + "ZERO_DOMAIN": "GUANGZHOU_INTERNAL_ONLY", + "BRANCH_DOMAIN": "DETERMINISTIC_DAILY_CHINA_CITY_ROAMING_INTERNAL_ONLY" + }, + "privacy": { "real_city_exposed_in_ui": false, "coordinates_exposed_in_ui": false, - "mechanical_flow_lines": false, - "heavy_webgl": false + "weather_unavailable_behavior": "BEIJING_TIME_ONLY_NO_FAKE_WEATHER" }, - "donor_disposition": { - "world_climate": "EXTRACTED_REWRITTEN_AND_NUMBERED", - "starlake_surface": "QODER_LOCKED_SOURCE_ADMITTED_WITH_RESPONSIVE_AND_IDLE_MOTION_ADAPTER", - "traditional_surface": "QODER_LOCKED_SOURCE_ADMITTED_WITH_REAL_NUMBERED_PROJECTIONS_ONLY", - "traditional_surface_css": "QODER_LOCKED_EIGHT_FINISH_TOKEN_SYSTEM_ADMITTED_AND_SCOPED_ACROSS_ALL_PAGES", - "fake_broadcasts_and_fake_metrics": "REJECTED" - }, - "qoder_source_provenance": { - "root": "/Volumes/JZAO/铸渊-ICE-GL-ZY001/OUT-输出/UI-预览-20260818/deploy-staging", - "main_tsx_sha256": "7dab8596ec0bd2609b1b23b175f1f14f15f2aa9af847eb605692c993d2e876e8", - "traditional_surface_tsx_sha256": "c713dc27681e07c510a2125816dcefb3255252fc0b570e350af7a98f57fc220d", - "traditional_surface_css_sha256": "3e6c446fb84a16ed23b0fd51466ad9723d0c0670ee6ddf6653f61237bd00baa6", - "starlake_surface_css_sha256": "471e3edef02236e6463144ac75b526f0f98782b5476b9db786e7cd0614a83227", - "acceptance_html_sha256": "7a41e426f1576fe0e25182e0c2efee65302b064d86363c890b0f235386a9c070" - }, - "current_acceptance": { - "state": "PASS_NUMBERED_QODER_SURFACES_REAL_DATA_RESPONSIVE_IDLE_AND_RESTART", - "module_package_sha256": "b6ba13b9f70bd617b2a303ec2eb0ea11d5354d10118c7f3e5179ae8100cd2602", - "module_package_signature": "PASS_EMBEDDED_PRODUCT_TRUST", - "numbered_route": "HLP-NIPC-MOD-0031/HLP-NIPC-OP-0147/HLP-NIPC-TGT-0031", - "signed_app_binary_sha256": "b0422bb18df521ace54ff1a52cd47121d92833dd78f165845deba7806686c7ac", - "signed_app_cdhash": "42640f7ce56e96403609899095c77ea6171df07d", - "apple_team_identifier": "825A9L3G7Q", - "module_receipts": { - "install": "2bb903cd369c8f57432c59367fd5494ee89a75214d5129511190e2337cecdbc4", - "mount": "aed4d00e51849ae5e9c0258fe2f93afc8bff8d927905cdd7fabd9bf32c4bc66c", - "self_test_pass": "404a0eeddb866bc3050b407c586c036f3707db577e1edf9f1cf3129c1cc9cc1d" - }, - "real_weather_readback": "PASS_VERIFIED_LIVE_NIGHT_CLOUD_WITHOUT_CITY_OR_COORDINATES", - "restart_restore": "PASS_ACTIVE_MODULE_REAL_CLIMATE_THEME_AND_WEB_NOVEL_CHAPTER_RESTORED", - "official_shell_preserved": "QODER_LOCKED_SURFACES_ADMITTED_WITH_NUMBERED_FUNCTION_ROUTING_UNCHANGED", - "visual_comparison": "audit/qoder-traditional-reference-vs-hololake-0.5.0.jpg", - "idle_static_psnr_db": 59.502493, - "idle_static_clock_unchanged": true, - "web_novel_new_chapter_modal": "PASS", - "web_novel_created_chapter_restart_persistence": "PASS_1_CHAPTER_VISIBLE_AFTER_RESTART", - "traditional_theme_downstream_pages": ["CHANNEL", "WEB_NOVEL", "EDUCATION"], - "notarization": "FINAL_RELEASE_CANDIDATE_PENDING" + "weather_source": { + "provider": "Open-Meteo", + "endpoint": "https://api.open-meteo.com/v1/forecast", + "documentation": "https://open-meteo.com/en/docs", + "current_variables": ["weather_code", "is_day", "precipitation", "cloud_cover", "wind_speed_10m"] } } diff --git a/product-source/hololake-native-desktop/contracts/education-open-source-donor-assessment.json b/product-source/hololake-native-desktop/contracts/education-open-source-donor-assessment.json new file mode 100644 index 000000000..2a4f8db56 --- /dev/null +++ b/product-source/hololake-native-desktop/contracts/education-open-source-donor-assessment.json @@ -0,0 +1,138 @@ +{ + "schema": "hololake.education-open-source-donor-assessment/v1", + "record_id": "HLP-EDUCATION-OSS-DONORS-001", + "state": "FOUR_TRANSLATION_FAMILIES_TWO_HEADLESS_FAMILIES_AND_ONE_REAL_SPREADSHEET_ENGINE_INTEGRATED", + "reviewed_at": "2026-08-18", + "rule": "STUDY_LOGIC_SELECT_SMALL_AUDITABLE_PARTS_AND_KEEP_HOLOLAKE_IDENTITY_STORAGE_PERMISSION_AND_UI_BOUNDARIES", + "candidates": [ + { + "name": "Calamine", + "role": "BOUNDED_SPREADSHEET_READ_ADAPTER", + "upstream": "https://github.com/tafia/calamine", + "observed_license": "MIT", + "decision": "INTEGRATE_PINNED_0_26_1_READ_ONLY_NO_OFFICE_RUNTIME" + }, + { + "name": "rust_xlsxwriter", + "role": "BOUNDED_XLSX_EXPORT_ADAPTER", + "upstream": "https://github.com/jmcnamara/rust_xlsxwriter", + "observed_license": "MIT OR Apache-2.0", + "decision": "INTEGRATE_PINNED_0_64_2_WRITE_NEW_XLSX_ONLY" + }, + { + "name": "rust-csv", + "role": "BOUNDED_DELIMITED_IMPORT_EXPORT_ADAPTER", + "upstream": "https://github.com/BurntSushi/rust-csv", + "observed_license": "Unlicense OR MIT", + "decision": "INTEGRATE_PINNED_1_3_0" + }, + { + "name": "encoding_rs", + "role": "LEGACY_CSV_TEXT_DECODER", + "upstream": "https://github.com/hsivonen/encoding_rs", + "observed_license": "MIT OR Apache-2.0", + "decision": "INTEGRATE_UTF_AND_GBK_FALLBACK_WITHOUT_NETWORK" + }, + { + "name": "AppFlowy", + "role": "FULL_WORKSPACE_LOGIC_DONOR", + "upstream": "https://github.com/AppFlowy-IO/AppFlowy", + "observed_license": "AGPL-3.0", + "decision": "DO_NOT_EMBED_WHOLE_APPLICATION_STUDY_WORKSPACE_AND_DATABASE_INTERACTION_LOGIC_ONLY" + }, + { + "name": "Lexical", + "role": "LAZY_LOADED_RICH_DOCUMENT_ENGINE", + "upstream": "https://github.com/facebook/lexical", + "observed_license": "MIT", + "source_review_commit": "29d4007d4322912ce75a416ac90cc9d224d3f029", + "decision": "INTEGRATE_PINNED_0_49_0_STATE_COMMAND_HISTORY_AND_MARKDOWN_PARTS_ONLY" + }, + { + "name": "TanStack Table", + "role": "HEADLESS_TABLE_ROW_MODEL_ENGINE", + "upstream": "https://github.com/TanStack/table", + "observed_license": "MIT", + "source_review_commit": "ac4f1345220649da3c60a24471b7f130fb159ab4", + "decision": "INTEGRATE_PINNED_8_21_3_SORT_FILTER_GROUP_AGGREGATE_AND_PAGINATION_ROW_MODELS_ONLY" + }, + { + "name": "Univer", + "role": "FULL_SPREADSHEET_AND_DOCUMENT_ENGINE_ARCHITECTURE_DONOR", + "upstream": "https://github.com/dream-num/univer", + "observed_license": "Apache-2.0", + "source_review_commit": "9251e0d30d4c4aeb4707dc4d856055081399cf38", + "decision": "SOURCE_STUDY_ONLY_DO_NOT_EMBED_WHOLE_APPLICATION_DEFER_FORMULA_AND_ADVANCED_GRID_PARTS" + }, + { + "name": "FortuneSheet", + "role": "LAZY_LOADED_REAL_SPREADSHEET_ENGINE_FOR_BUILT_IN_CHANNEL_WORKBENCH", + "upstream": "https://github.com/ruilisi/fortune-sheet", + "observed_license": "MIT", + "source_review_commit": "94346608877db4747406707a177c4b8f3bacdbf9", + "decision": "INTEGRATE_PINNED_1_0_4_REAL_CELLS_FORMULAS_EDITING_FORMATTING_FILTERING_AND_FREEZE_WITH_HOLOLAKE_NATIVE_STORAGE_ADAPTER", + "security_adjustment": "OVERRIDE_UUID_TO_11_1_1_FORTUNE_ONLY_USES_V4_PRODUCTION_AUDIT_ZERO_KNOWN_VULNERABILITIES" + }, + { + "name": "Glide Data Grid", + "role": "HIGH_PERFORMANCE_GRID_ARCHITECTURE_DONOR", + "upstream": "https://github.com/glideapps/glide-data-grid", + "observed_license": "MIT", + "source_review_commit": "0875d78", + "decision": "SOURCE_STUDY_ONLY_GRID_IS_NOT_A_SPREADSHEET_OR_FORMULA_ENGINE" + }, + { + "name": "Vega-Lite", + "role": "DECLARATIVE_PROJECTION_GRAMMAR_DONOR", + "upstream": "https://github.com/vega/vega-lite", + "observed_license": "BSD-3-Clause", + "decision": "ADOPT_DECLARATIVE_DIMENSION_MEASURE_AND_VIEW_SPEC_CONCEPTS_WITHOUT_IMPORTING_RUNTIME" + }, + { + "name": "Observable Plot", + "role": "LAYERED_MARK_AND_COMPOSABLE_TRANSFORM_DONOR", + "upstream": "https://github.com/observablehq/plot", + "observed_license": "ISC", + "decision": "ADOPT_LAYERED_PROJECTION_AND_TIDY_DATA_CONCEPTS_WITHOUT_IMPORTING_RUNTIME" + }, + { + "name": "Apache ECharts", + "role": "FULL_BROWSER_VISUALIZATION_RUNTIME_CANDIDATE", + "upstream": "https://github.com/apache/echarts", + "observed_license": "Apache-2.0", + "decision": "DO_NOT_IMPORT_FOR_STAGE_ONE_FIVE_NATIVE_VIEWS_DO_NOT_JUSTIFY_RUNTIME_WEIGHT" + }, + { + "name": "Apache Arrow DataFusion", + "role": "TYPED_COLUMNAR_QUERY_PLAN_DONOR", + "upstream": "https://github.com/apache/datafusion", + "observed_license": "Apache-2.0", + "decision": "ADOPT_TYPED_SCHEMA_AND_VALIDATED_PLAN_CONCEPTS_DEFER_ENGINE_UNTIL_DATA_SCALE_REQUIRES_IT" + }, + { + "name": "DuckDB", + "role": "EMBEDDED_ANALYTICAL_ENGINE_CANDIDATE", + "upstream": "https://github.com/duckdb/duckdb", + "observed_license": "MIT", + "decision": "DEFER_NATIVE_DEPENDENCY_CURRENT_BOUNDED_ACCOUNT_DATA_EXECUTES_WITH_SMALLER_HOLOLAKE_CORE" + } + ], + "current_slice": { + "external_translation_library_families_added": 4, + "external_headless_engine_families_added": 2, + "real_spreadsheet_engine_families_added": 1, + "direct_frontend_engine_packages_added": 10, + "external_source_files_copied": 0, + "source_research_route": "LOCAL_DIRECT_TO_BS_SG_002_THEN_EXTERNAL_DRIVE", + "source_research_root": "/Volumes/JZAO/HoloLake/development/拆件车间-open-src-20260816/education-engines-20260818", + "source_repositories_retained_outside_product_tree": 5, + "concepts_adopted": [ + "DECLARATIVE_DIMENSION_MEASURE_AND_PROJECTION_SPEC", + "TYPED_NATIVE_COLUMNS_AND_VALIDATED_EXECUTION_PLAN", + "LAYERED_MARKS_WITH_ONE_SHARED_DATASET", + "HEADLESS_DATA_BEHAVIOR_SEPARATE_FROM_HUMAN_RENDERING" + ], + "implementation": "BUILT_IN_CHANNEL_DOCUMENT_AND_SPREADSHEET_FOUNDATION_PLUS_DEVELOPMENT_MOUNTED_EDUCATION_PACKAGE_WITH_PRODUCT_OWNED_PROFILE_ROUTING_IDENTITY_STORAGE_PERMISSION_AND_ADVANCED_VIEWS" + }, + "legal_boundary": "PRELIMINARY_ENGINEERING_SCREEN_NOT_FINAL_DISTRIBUTION_LEGAL_APPROVAL" +} diff --git a/product-source/hololake-native-desktop/contracts/education-workspace.json b/product-source/hololake-native-desktop/contracts/education-workspace.json index 1b58970d3..e26305a41 100644 --- a/product-source/hololake-native-desktop/contracts/education-workspace.json +++ b/product-source/hololake-native-desktop/contracts/education-workspace.json @@ -1,15 +1,15 @@ { "schema": "hololake.education-workspace/v1", "record_id": "HLP-EDUCATION-WORKSPACE-001", - "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", + "state": "DEVELOPMENT_MODULE_SOURCE_MOUNTED_ACCEPTANCE_PENDING", "domain_entry": "BRANCH_DOMAIN", "industry": "EDUCATION", "channel_id": "GH-EDU-INIT-001", "package": { "package_key": "hololake.official.education-workbench", - "official_module_number": "HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001", - "registration_state": "OFFICIAL_NUMBER_ACCEPTED", - "current_mount": "ACTIVE_AFTER_SIGNED_INSTALL_MOUNT_AND_SELF_TEST", + "official_module_number": null, + "registration_state": "PENDING_FUNCTIONAL_ACCEPTANCE_AND_NUMBER_REGISTRATION", + "current_mount": "DEVELOPMENT_BUNDLE_ONLY", "future_distribution": "HOLOLAKE_OFFICIAL_MODULE_MARKETPLACE" }, "foundation_dependency": { @@ -238,28 +238,5 @@ "model_execution_authority_granted": false, "external_application_embedded": false }, - "current_acceptance": { - "state": "PASS", - "runtime_module_number": "HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001", - "numbered_ipc_module": "HLP-NIPC-MOD-0024", - "numbered_operations": "HLP-NIPC-OP-0085..0102", - "signed_package_sha256": "a9f6fb7dd9c4aaf910a5d20d0a1d72dea6ab921cf36dd50d46dd88cde3a09e03", - "signed_app_binary_sha256": "028592b137fe4f19a642e1301d6fb500e2a4fde50ddb616e229de8a48090803c", - "developer_id_team": "825A9L3G7Q", - "developer_id_cdhash": "4c88261b4b573d08edcbba8d67d8afe27ad82a3e", - "runtime_receipts": { - "install": "68f296a11be19c384cb67af9f529a03cb8389bd256c153c5905451fbc0011a24", - "mount": "ddb6a51d47f6a58a72a7fc748eff71687cbd04be5dde33dbce590a7abba6af5f", - "self_test_pass": "80d59b7c9c2f14005fd8a24748a25c2be0d55198fdcb621f528267ae6dccc12a" - }, - "restart_readback": { - "module_state": "ACTIVE", - "document": "冰朔教育迁移验收 · revision 2", - "table": "冰朔教育迁移验收表 · 1 row · revision 4", - "automation": "验收状态自动化 · preview 1 row / 1 cell · APPLIED revision 3 to 4" - }, - "existing_user_data_deleted_or_overwritten": false, - "apple_notarization_scope": "FINAL_RELEASE_CANDIDATE_ONLY_NOT_THIS_DEBUG_ACCEPTANCE_BUNDLE" - }, "open_source_donor_assessment": "contracts/education-open-source-donor-assessment.json" } diff --git a/product-source/hololake-native-desktop/contracts/gls-executable-projections.json b/product-source/hololake-native-desktop/contracts/gls-executable-projections.json index 9469f3e63..18f04c724 100644 --- a/product-source/hololake-native-desktop/contracts/gls-executable-projections.json +++ b/product-source/hololake-native-desktop/contracts/gls-executable-projections.json @@ -1,6 +1,6 @@ { "schema": "hololake.gls-executable-projections/v2", - "source_commit": "104a5d73162bdf4a529701e65898e2bc2863ea9e", + "source_commit": "2598fbfba8caf64c7ab9740a3036c5aab977502e", "runtime_graph_rule": "ONLY_EXPLICIT_RUNTIME_REQUIRES_EDGES_ENTER_ACTIVATION_GRAPH", "projections": { "GLS-0250": {"stage":"P0","projection_kind":"TYPED_FACT_AND_DOMAIN_BOUNDARY","adapter":"origin-domain-topology","event_kinds":["BOOTSTRAP","DOMAIN_ROUTE"],"dependencies":[]}, diff --git a/product-source/hololake-native-desktop/contracts/gls-native-runtime-kernel.json b/product-source/hololake-native-desktop/contracts/gls-native-runtime-kernel.json index f3e06643a..36e5252db 100644 --- a/product-source/hololake-native-desktop/contracts/gls-native-runtime-kernel.json +++ b/product-source/hololake-native-desktop/contracts/gls-native-runtime-kernel.json @@ -1,7 +1,7 @@ { "schema": "hololake.gls-native-runtime-kernel/v1", "record_id": "HLP-GLS-NATIVE-RUNTIME-KERNEL-001", - "source_commit": "104a5d73162bdf4a529701e65898e2bc2863ea9e", + "source_commit": "2598fbfba8caf64c7ab9740a3036c5aab977502e", "receipt_schema": "hololake.protocol-decision-receipt/v1", "decision_set": ["ALLOW", "DENY", "AMBIGUOUS", "UNVERIFIED"], "runtime_boundaries": { diff --git a/product-source/hololake-native-desktop/contracts/gls-numbered-reference-nodes.json b/product-source/hololake-native-desktop/contracts/gls-numbered-reference-nodes.json deleted file mode 100644 index 0623d3153..000000000 --- a/product-source/hololake-native-desktop/contracts/gls-numbered-reference-nodes.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "schema": "hololake.gls-numbered-reference-nodes/v1", - "record_id": "HLP-GLS-NUMBERED-REFERENCE-REGISTRY-001", - "source": { - "repository": "REPO-012", - "commit": "104a5d73162bdf4a529701e65898e2bc2863ea9e" - }, - "policy": { - "number_is_coordinate_not_authority": true, - "independent_protocol_source_required_for_execution": true, - "reference_only_nodes_may_execute": false, - "unknown_reference": "FAIL_CLOSED", - "unresolved_number_reference_allowed": false - }, - "nodes": [ - {"protocol_id":"GLS-0010","node_number":"HLP-GLS-REF-0010","title":"Guanghu Protocol Registry Center Standard","reference_kind":"NORMATIVE_REFERENCE","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0140","node_number":"HLP-GLS-REF-0140","title":"Context Loading Specification","reference_kind":"NORMATIVE_REFERENCE","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0401","node_number":"HLP-GLS-REF-0401","title":"Tree","reference_kind":"SCHEMA_IMPORT","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0402","node_number":"HLP-GLS-REF-0402","title":"Leaf","reference_kind":"SCHEMA_IMPORT","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0403","node_number":"HLP-GLS-REF-0403","title":"Lock","reference_kind":"SCHEMA_IMPORT","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0404","node_number":"HLP-GLS-REF-0404","title":"Trigger","reference_kind":"SCHEMA_IMPORT","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0406","node_number":"HLP-GLS-REF-0406","title":"Evidence","reference_kind":"SCHEMA_IMPORT","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0407","node_number":"HLP-GLS-REF-0407","title":"Correction","reference_kind":"SCHEMA_IMPORT","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0409","node_number":"HLP-GLS-REF-0409","title":"Machine-State History","reference_kind":"SCHEMA_IMPORT","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0602","node_number":"HLP-GLS-REF-0602","title":"Authorization","reference_kind":"SCHEMA_IMPORT","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0603","node_number":"HLP-GLS-REF-0603","title":"Signature","reference_kind":"SCHEMA_IMPORT","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0604","node_number":"HLP-GLS-REF-0604","title":"Integrity","reference_kind":"EVIDENCE_ONLY","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0605","node_number":"HLP-GLS-REF-0605","title":"Semantic Safety Boundary","reference_kind":"SCHEMA_IMPORT","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0814","node_number":"HLP-GLS-REF-0814","title":"Tool Runtime","reference_kind":"NORMATIVE_REFERENCE","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0816","node_number":"HLP-GLS-REF-0816","title":"Checkpoint Runtime","reference_kind":"NORMATIVE_REFERENCE","source_state":"ROADMAP_REFERENCE_ONLY"}, - {"protocol_id":"GLS-0830","node_number":"HLP-GLS-REF-0830","title":"Guanghu Language World Core","reference_kind":"NORMATIVE_REFERENCE","source_state":"ROADMAP_REFERENCE_ONLY"} - ] -} diff --git a/product-source/hololake-native-desktop/contracts/gls-runtime-registry.json b/product-source/hololake-native-desktop/contracts/gls-runtime-registry.json index 31f566864..321c519cd 100644 --- a/product-source/hololake-native-desktop/contracts/gls-runtime-registry.json +++ b/product-source/hololake-native-desktop/contracts/gls-runtime-registry.json @@ -3,7 +3,7 @@ "record_id": "HLP-GLS-RUNTIME-MANIFEST-002", "source": { "repository": "REPO-012", - "commit": "104a5d73162bdf4a529701e65898e2bc2863ea9e", + "commit": "2598fbfba8caf64c7ab9740a3036c5aab977502e", "root": "gls", "authority_files": [ { @@ -14,7 +14,7 @@ { "authority_kind": "GLS_ENTRY", "source_path": "gls/GLS-ENTRY.hdlp", - "source_sha256": "f716c3519df79c55871a0afeba5cc46a9edbb078bc7371301ab408ce3c82a897" + "source_sha256": "b0937dab245c40c68feeb861258fa7d8cb6f721e30042bff098a35b216956e79" }, { "authority_kind": "SOURCE_MANIFEST", @@ -24,7 +24,7 @@ { "authority_kind": "ARCHITECTURE_CATALOG", "source_path": "gls/GLS-ARCHITECTURE-CATALOG.hdlp", - "source_sha256": "e1e82d145db0544b9ed71cdfd3cbdfdd5cd07d86c6f5371ba2da125cf44d92c8" + "source_sha256": "1107adbc8290797bdafea23dd5f13db46e2ee621356987f138f6616cfe6bc49d" } ] }, @@ -40,7 +40,7 @@ "unknown_protocol": "FAIL_CLOSED" }, "reconciliation": { - "numbered_protocol_count": 83, + "numbered_protocol_count": 75, "protocol_registry_id_count": 52, "existing_registered_count": 19, "registered_draft_count": 33, @@ -68,8 +68,15 @@ "GLS-0830" ], "dependencies_without_numbered_source": [ + "GLS-0001", + "GLS-0002", "GLS-0010", + "GLS-0101", + "GLS-0110", "GLS-0140", + "GLS-0200", + "GLS-0300", + "GLS-0400", "GLS-0401", "GLS-0402", "GLS-0403", @@ -81,16 +88,12 @@ "GLS-0603", "GLS-0604", "GLS-0605", + "GLS-0810", "GLS-0814", "GLS-0816", "GLS-0830" ], - "numbered_reference_node_count": 16, - "unresolved_number_references": [], - "unresolved_number_reference_count": 0, - "every_dependency_has_number_coordinate": true, "numbered_sources_not_in_protocol_registry": [ - "GLS-0101", "GLS-0223", "GLS-0224", "GLS-0227", @@ -179,404 +182,15 @@ "discovered_unreconciled_count": 0, "authority_conflict_count": 0 }, - "protocol_count": 83, + "protocol_count": 75, "executable_projection_count": 25, - "inventoried_not_executable_count": 58, - "number_coordinate_count": 99, - "numbered_reference_nodes": [ - { - "protocol_id": "GLS-0010", - "node_number": "HLP-GLS-REF-0010", - "title": "Guanghu Protocol Registry Center Standard", - "reference_kind": "NORMATIVE_REFERENCE", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/GLS-PROTOCOL-RECONCILIATION-AND-NATIVE-OS-REGISTRATION-20260731.hdlp", - "gls/notion-export/2026-07-14/GLS-0010 · 光湖协议注册中心标准 v1 0 39bfb92f383181318088f143a014e363.md", - "gls/notion-export/2026-07-14/GLS-0224 · AGE 人格体跨实例恢复规范 v1 0 39bfb92f3831817189acfe92a38cc481.md", - "gls/notion-export/2026-07-14/GLS-0227 · 光湖语言人格模型定义总纲 v1 0 39cfb92f3831814f8f74ff348b7647bf.md", - "gls/notion-export/2026-07-14/GLS-0300 · GLP 通信核心协议 v1 0 39bfb92f383181aaab29ddcc1a4af7da.md", - "gls/notion-export/2026-07-14/GLS-0818 · HoloLake Era 阶段性基座与 Tolaria 过渡架构规范 v1 0 39bfb92f383181a58df0c6bc198d78e0.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/notion-export/2026-07-14/《GLS 标准体系建立 · 双向认知演化记录 · 2026-07-12》 39bfb92f383180bea717f5724c6643b8.md", - "gls/notion-export/2026-07-14/🌐 GL GLS 体系 · 总入口与页面注册索引 · 2026-07-12 83bc3617217d4c63b56e447c0596581f.md", - "gls/protocols/GLS-0710-GUANGHU-MODULE-PROTOCOL.hdlp" - ] - }, - { - "protocol_id": "GLS-0140", - "node_number": "HLP-GLS-REF-0140", - "title": "Context Loading Specification", - "reference_kind": "NORMATIVE_REFERENCE", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0303-GLP-CONTEXT.hdlp" - ] - }, - { - "protocol_id": "GLS-0401", - "node_number": "HLP-GLS-REF-0401", - "title": "Tree", - "reference_kind": "SCHEMA_IMPORT", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/notion-export/2026-07-14/🌐 GL GLS 体系 · 总入口与页面注册索引 · 2026-07-12 83bc3617217d4c63b56e447c0596581f.md", - "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp" - ] - }, - { - "protocol_id": "GLS-0402", - "node_number": "HLP-GLS-REF-0402", - "title": "Leaf", - "reference_kind": "SCHEMA_IMPORT", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-0002 39bfb92f38318015b05fc2082630b39e.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp" - ] - }, - { - "protocol_id": "GLS-0403", - "node_number": "HLP-GLS-REF-0403", - "title": "Lock", - "reference_kind": "SCHEMA_IMPORT", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-0002 39bfb92f38318015b05fc2082630b39e.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp" - ] - }, - { - "protocol_id": "GLS-0404", - "node_number": "HLP-GLS-REF-0404", - "title": "Trigger", - "reference_kind": "SCHEMA_IMPORT", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp" - ] - }, - { - "protocol_id": "GLS-0406", - "node_number": "HLP-GLS-REF-0406", - "title": "Evidence", - "reference_kind": "SCHEMA_IMPORT", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0304-GLP-MEMORY-SYNC.hdlp", - "gls/protocols/GLS-0306-GLP-RECEIPT.hdlp", - "gls/protocols/GLS-0311-GUANGHU-LIVE-OPERATIONS-WITNESS.hdlp", - "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp" - ] - }, - { - "protocol_id": "GLS-0407", - "node_number": "HLP-GLS-REF-0407", - "title": "Correction", - "reference_kind": "SCHEMA_IMPORT", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0304-GLP-MEMORY-SYNC.hdlp", - "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp" - ] - }, - { - "protocol_id": "GLS-0409", - "node_number": "HLP-GLS-REF-0409", - "title": "Machine-State History", - "reference_kind": "SCHEMA_IMPORT", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0308-GLP-STATE-SYNC.hdlp", - "gls/protocols/GLS-0827-PERSONA-TIME-CONTINUITY-PROTOCOL.hdlp" - ] - }, - { - "protocol_id": "GLS-0602", - "node_number": "HLP-GLS-REF-0602", - "title": "Authorization", - "reference_kind": "SCHEMA_IMPORT", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0302-GLP-IDENTITY.hdlp", - "gls/protocols/GLS-0309-GLP-WORK-ORDER.hdlp", - "gls/protocols/GLS-0708-GUANGHU-MODEL-ROUTING-PROTOCOL.hdlp", - "gls/protocols/GLS-0709-UNIVERSAL-ADAPTER-PROTOCOL.hdlp", - "gls/protocols/GLS-0819-GUANGHU-RUNWAY-SCHEDULING-PROTOCOL.hdlp", - "gls/protocols/GLS-0828-PERSONA-EXTENSION-NODE.hdlp", - "gls/protocols/GLS-0840-GUANGHU-OS-KERNEL.hdlp", - "gls/protocols/GLS-0842-HOLOLAKE-LIVE-SESSION-PROTOCOL.hdlp" - ] - }, - { - "protocol_id": "GLS-0603", - "node_number": "HLP-GLS-REF-0603", - "title": "Signature", - "reference_kind": "SCHEMA_IMPORT", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0302-GLP-IDENTITY.hdlp", - "gls/protocols/GLS-0710-GUANGHU-MODULE-PROTOCOL.hdlp" - ] - }, - { - "protocol_id": "GLS-0604", - "node_number": "HLP-GLS-REF-0604", - "title": "Integrity", - "reference_kind": "EVIDENCE_ONLY", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0306-GLP-RECEIPT.hdlp", - "gls/protocols/GLS-0311-GUANGHU-LIVE-OPERATIONS-WITNESS.hdlp", - "gls/protocols/GLS-0710-GUANGHU-MODULE-PROTOCOL.hdlp", - "gls/protocols/GLS-0841-GUANGHU-HARDWARE-ABSTRACTION-LAYER.hdlp" - ] - }, - { - "protocol_id": "GLS-0605", - "node_number": "HLP-GLS-REF-0605", - "title": "Semantic Safety Boundary", - "reference_kind": "SCHEMA_IMPORT", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0708-GUANGHU-MODEL-ROUTING-PROTOCOL.hdlp", - "gls/protocols/GLS-0709-UNIVERSAL-ADAPTER-PROTOCOL.hdlp" - ] - }, - { - "protocol_id": "GLS-0814", - "node_number": "HLP-GLS-REF-0814", - "title": "Tool Runtime", - "reference_kind": "NORMATIVE_REFERENCE", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0828-PERSONA-EXTENSION-NODE.hdlp" - ] - }, - { - "protocol_id": "GLS-0816", - "node_number": "HLP-GLS-REF-0816", - "title": "Checkpoint Runtime", - "reference_kind": "NORMATIVE_REFERENCE", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/protocols/GLS-0827-PERSONA-TIME-CONTINUITY-PROTOCOL.hdlp", - "gls/protocols/GLS-0836-GUANGHU-WORLD-BOOTSTRAP-AND-RECOVERY.hdlp" - ] - }, - { - "protocol_id": "GLS-0830", - "node_number": "HLP-GLS-REF-0830", - "title": "Guanghu Language World Core", - "reference_kind": "NORMATIVE_REFERENCE", - "source_state": "ROADMAP_REFERENCE_ONLY", - "execution_state": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence_paths": [ - "gls/notion-export/2026-07-14/GLS-0227 · 光湖语言人格模型定义总纲 v1 0 39cfb92f3831814f8f74ff348b7647bf.md", - "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "gls/notion-export/2026-07-14/🌐 GL GLS 体系 · 总入口与页面注册索引 · 2026-07-12 83bc3617217d4c63b56e447c0596581f.md", - "gls/protocols/GLS-0836-GUANGHU-WORLD-BOOTSTRAP-AND-RECOVERY.hdlp" - ] - } - ], + "inventoried_not_executable_count": 50, "protocols": [ - { - "id": "GLS-0001", - "title": "GLS-0001", - "source_status": "UNSPECIFIED_SOURCE_STATUS", - "source_path": "gls/notion-export/2026-07-14/GLS-0001 39bfb92f383180059deefa1bac489399.md", - "source_format": "LEGACY_MARKDOWN_EVIDENCE", - "source_sha256": "9ac9903c3b3066364e8b6fa97363f0c0fc85754d7ee1b07774236a4b24bc7bc2", - "alternate_source_count": 0, - "registration": { - "state": "REGISTERED_PROTOCOL_REGISTRY", - "authorities": [ - { - "id": "GLS-0001", - "authority_kind": "PROTOCOL_REGISTRY", - "declared_source_path": null - } - ], - "declared_source_paths": [], - "routing_reference_count": 0 - }, - "maturity": { - "registry_section": "existing_registered", - "registry_status": null, - "family": null, - "implementation_evidence": null - }, - "contract_kind": "UNCLASSIFIED_PROTOCOL_SOURCE", - "implementation_stage": null, - "projection_state": "INVENTORIED_NOT_EXECUTABLE", - "projection_kind": null, - "adapter": null, - "event_kinds": [], - "dependencies": [], - "dependency_edges": [], - "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" - ] - }, - { - "id": "GLS-0002", - "title": "GLS-0002", - "source_status": "UNSPECIFIED_SOURCE_STATUS", - "source_path": "gls/notion-export/2026-07-14/GLS-0002 39bfb92f38318015b05fc2082630b39e.md", - "source_format": "LEGACY_MARKDOWN_EVIDENCE", - "source_sha256": "c50f767aa2f3a863f708628b33054ecb2ba18799aa68218bf89e25d263fa9b6c", - "alternate_source_count": 0, - "registration": { - "state": "REGISTERED_PROTOCOL_REGISTRY", - "authorities": [ - { - "id": "GLS-0002", - "authority_kind": "PROTOCOL_REGISTRY", - "declared_source_path": null - } - ], - "declared_source_paths": [], - "routing_reference_count": 0 - }, - "maturity": { - "registry_section": "existing_registered", - "registry_status": null, - "family": null, - "implementation_evidence": null - }, - "contract_kind": "UNCLASSIFIED_PROTOCOL_SOURCE", - "implementation_stage": null, - "projection_state": "INVENTORIED_NOT_EXECUTABLE", - "projection_kind": null, - "adapter": null, - "event_kinds": [], - "dependencies": [], - "dependency_edges": [], - "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" - ] - }, - { - "id": "GLS-0101", - "title": "GLS-0101", - "source_status": "draft", - "source_path": "gls/notion-export/2026-07-14/GLS-0101 39bfb92f38318089b31efe6c1c2cb6b6.md", - "source_format": "LEGACY_MARKDOWN_EVIDENCE", - "source_sha256": "e88d977de617506f0d5d6ac58f406486c6c70fdc10eac2ff09ad6cc2f2d2ea16", - "alternate_source_count": 0, - "registration": { - "state": "REGISTERED_OTHER_CANONICAL_INDEX", - "authorities": [ - { - "id": "GLS-0101", - "authority_kind": "SOURCE_MANIFEST", - "declared_source_path": null - } - ], - "declared_source_paths": [], - "routing_reference_count": 1 - }, - "maturity": { - "registry_section": null, - "registry_status": null, - "family": null, - "implementation_evidence": null - }, - "contract_kind": "UNCLASSIFIED_PROTOCOL_SOURCE", - "implementation_stage": null, - "projection_state": "INVENTORIED_NOT_EXECUTABLE", - "projection_kind": null, - "adapter": null, - "event_kinds": [], - "dependencies": [], - "dependency_edges": [], - "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" - ] - }, - { - "id": "GLS-0110", - "title": "ISRP 自然语言入口解析与安全路由协议 v1.0", - "source_status": "UNSPECIFIED_SOURCE_STATUS", - "source_path": "gls/notion-export/2026-07-14/GLS-0110 · ISRP 自然语言入口解析与安全路由协议 v1 0 39bfb92f38318128a372dbadbde86ead.md", - "source_format": "LEGACY_MARKDOWN_EVIDENCE", - "source_sha256": "314a718f05a3da1e5750831df5377d9fc76db86463a7b37c052976fe9aaeb2c4", - "alternate_source_count": 0, - "registration": { - "state": "REGISTERED_PROTOCOL_REGISTRY", - "authorities": [ - { - "id": "GLS-0110", - "authority_kind": "PROTOCOL_REGISTRY", - "declared_source_path": null - } - ], - "declared_source_paths": [], - "routing_reference_count": 0 - }, - "maturity": { - "registry_section": "existing_registered", - "registry_status": null, - "family": null, - "implementation_evidence": null - }, - "contract_kind": "UNCLASSIFIED_PROTOCOL_SOURCE", - "implementation_stage": null, - "projection_state": "INVENTORIED_NOT_EXECUTABLE", - "projection_kind": null, - "adapter": null, - "event_kinds": [], - "dependencies": [], - "dependency_edges": [], - "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" - ] - }, { "id": "GLS-0130", "title": "GLC · 光湖语言编译器规范", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0130-GUANGHU-LANGUAGE-COMPILER.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "c0caa90d3e85270d334a371b6ee5fb49c9eeb1e2e84825dba5ad520fd54bc6eb", "alternate_source_count": 0, "registration": { @@ -624,9 +238,7 @@ "declared_by": "gls/protocols/GLS-0130-GUANGHU-LANGUAGE-COMPILER.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0110", @@ -635,9 +247,7 @@ "declared_by": "gls/protocols/GLS-0130-GUANGHU-LANGUAGE-COMPILER.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0131", @@ -646,9 +256,7 @@ "declared_by": "gls/protocols/GLS-0130-GUANGHU-LANGUAGE-COMPILER.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0400", @@ -657,9 +265,7 @@ "declared_by": "gls/protocols/GLS-0130-GUANGHU-LANGUAGE-COMPILER.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0411", @@ -668,9 +274,7 @@ "declared_by": "gls/protocols/GLS-0130-GUANGHU-LANGUAGE-COMPILER.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0411", @@ -678,9 +282,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0131", @@ -688,9 +290,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -700,7 +300,6 @@ "title": "GIR · 光湖中间表示规范", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0131-GUANGHU-INTERMEDIATE-REPRESENTATION.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "5907cc0cb7e3afc78ba9c928c4298b200894020b7dc5d274a9364836939189e9", "alternate_source_count": 0, "registration": { @@ -747,9 +346,7 @@ "declared_by": "gls/protocols/GLS-0131-GUANGHU-INTERMEDIATE-REPRESENTATION.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0130", @@ -758,9 +355,7 @@ "declared_by": "gls/protocols/GLS-0131-GUANGHU-INTERMEDIATE-REPRESENTATION.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0411", @@ -769,9 +364,7 @@ "declared_by": "gls/protocols/GLS-0131-GUANGHU-INTERMEDIATE-REPRESENTATION.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0411", @@ -779,57 +372,16 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] }, - { - "id": "GLS-0200", - "title": "TCS 认知语言核心工程规范 v1.0", - "source_status": "UNSPECIFIED_SOURCE_STATUS", - "source_path": "gls/notion-export/2026-07-14/GLS-0200 · TCS 认知语言核心工程规范 v1 0 39dfb92f383180798e5bd73dd9176628.md", - "source_format": "LEGACY_MARKDOWN_EVIDENCE", - "source_sha256": "1cf7348118ac1d34a85d0edd875509e0747c80a82dec4b553bdf6de784d88ec3", - "alternate_source_count": 1, - "registration": { - "state": "REGISTERED_PROTOCOL_REGISTRY", - "authorities": [ - { - "id": "GLS-0200", - "authority_kind": "PROTOCOL_REGISTRY", - "declared_source_path": null - } - ], - "declared_source_paths": [], - "routing_reference_count": 1 - }, - "maturity": { - "registry_section": "existing_registered", - "registry_status": null, - "family": null, - "implementation_evidence": null - }, - "contract_kind": "UNCLASSIFIED_PROTOCOL_SOURCE", - "implementation_stage": null, - "projection_state": "INVENTORIED_NOT_EXECUTABLE", - "projection_kind": null, - "adapter": null, - "event_kinds": [], - "dependencies": [], - "dependency_edges": [], - "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" - ] - }, { "id": "GLS-0223", "title": "TCS+HLDP 双向永久记忆规范 v1.0", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0223-BIDIRECTIONAL-PERMANENT-MEMORY.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "ed9ba3e3abef70127fabe3084e5bb5f596cae4c3992789e36c453bb7075e08d8", "alternate_source_count": 0, "registration": { @@ -879,7 +431,6 @@ "title": "AGE 人格体跨实例恢复规范 v1.0", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0224-AGE-CROSS-INSTANCE-RESTORE.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "7c58c39b7119c2a41e57da07d612c20a16f82c32c6895e1fd20290eefc4068e1", "alternate_source_count": 0, "registration": { @@ -929,7 +480,6 @@ "title": "光湖语言人格模型定义总纲 v1.0", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0227-LANGUAGE-PERSONALITY-MODEL-CORE.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "2521856eaba8d7afbc8d970e68155aa41e03a4cf784c0ced2289600d97f915a8", "alternate_source_count": 0, "registration": { @@ -979,7 +529,6 @@ "title": "人格体集体涌现与历史继承规范 v1.0", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0228-PERSONA-COLLECTIVE-EMERGENCE-AND-HISTORY-INHERITANCE.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "aaa3801b4f8c5fef9a92f971e54857494a348d4b2856ed701f3143c6c56ae0ff", "alternate_source_count": 0, "registration": { @@ -1029,7 +578,6 @@ "title": "零点原核与第五域 / 企业四域平行映射规范 v1.1", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0229-ZERO-CORE-PARALLEL-DOMAIN-MAPPING.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "14e1ac3e9c0b3ac350da36bb79515ead4c372b68fc8e95155024cdf055080518", "alternate_source_count": 0, "registration": { @@ -1079,7 +627,6 @@ "title": "TCS 源码安全协议系统", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0230-TCS-SOURCE-SECURITY-PROTOCOL-SYSTEM.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "ca6379505907b5e68e50454ee8e10ef2111809e70770d1fa19e9caa5da4bfb94", "alternate_source_count": 0, "registration": { @@ -1134,7 +681,6 @@ "title": "光湖·来光者导航系统", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0231-PERSONA-PROMPT-BOARD-AND-NUMBER-RULE-INTERCEPT-SYSTEM.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "705d671197df6c19f7f3ac506d821232ce0f009d3ec4db065a8b10f525ea143b", "alternate_source_count": 0, "registration": { @@ -1184,7 +730,6 @@ "title": "开源 Agent 样本学习与选型登记", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0232-OPEN-SOURCE-AGENT-SAMPLES-LEARNING-AND-SELECTION.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "66fe3aa3256ffc0e76be2059457174589916573a6d9f807a1c40bb7aaef450e6", "alternate_source_count": 0, "registration": { @@ -1234,7 +779,6 @@ "title": "GH-AIOS 模块化通用人工智能操作平台与公平生态架构", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0233-GH-AIOS-MODULAR-AI-OPERATING-PLATFORM-AND-FAIR-ECOSYSTEM.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "a670410a7fbc4c7417734040b990dc8f008c23fed000e09847b2280a92f9abf5", "alternate_source_count": 0, "registration": { @@ -1284,7 +828,6 @@ "title": "企业五域灯塔与个人六节点主权运维架构", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0234-FIVE-DOMAIN-ENTERPRISE-LIGHTHOUSE-AND-SOVEREIGN-SIX-NODE-OPS.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "5f3427559c87788884a7d0c49d0ced62d768630d9bb512d736c919d7971423c5", "alternate_source_count": 0, "registration": { @@ -1334,7 +877,6 @@ "title": "光湖语言人格驱动操作系统 · 领域路由、身份权限与仓库知识投影架构", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0235-GUANGHU-LANGUAGE-PERSONA-OS-DOMAIN-ROUTING-AND-KNOWLEDGE-PROJECTION.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "ea6a8a65b94228d19d5ae9b024997461cbda29c744bfa0c2774ac6c668c68a58", "alternate_source_count": 0, "registration": { @@ -1384,7 +926,6 @@ "title": "光湖人格体大脑—手脚分离、可视执行、递归外置记忆与热插拔运行架构", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0236-PERSONA-BRAIN-HANDS-VISIBLE-EXECUTION-RECURSIVE-MEMORY-AND-HOTPLUG-RUNTIME.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "42af09aef2ff514c90c30f3aed4e33763e6a34c7081f5bb37f7b6d8745a947c4", "alternate_source_count": 0, "registration": { @@ -1434,7 +975,6 @@ "title": "光湖代码频道主权源码、更新治理与 HoloLake 嵌入架构", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0237-HOLOLAKE-CODE-CHANNEL-SOVEREIGN-SOURCE-UPDATE-AND-EMBEDDING.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "d3c43b80eff3a92817e570d739fd6a847d1379f3345797282a6157bce3c9e91e", "alternate_source_count": 0, "registration": { @@ -1484,8 +1024,7 @@ "title": "光湖意图状态、技能自动装载与可信纠偏系统", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0238-GUANGHU-PERSONA-SKILL-AUTOLOAD-AND-CORRECTION-SYSTEM.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", - "source_sha256": "31f0e018e95ae135a88429c82b189c5e900b18b1ba7d5df6ca4fb80469acb0be", + "source_sha256": "0d9fb115c1b122ba2a8eaefb8cdf1f8169011b45089acc5b790e02bb273ad3e4", "alternate_source_count": 0, "registration": { "state": "REGISTERED_OTHER_CANONICAL_INDEX", @@ -1509,7 +1048,7 @@ "declared_source_paths": [ "gls/GLS-0238-GUANGHU-PERSONA-SKILL-AUTOLOAD-AND-CORRECTION-SYSTEM.hdlp" ], - "routing_reference_count": 3 + "routing_reference_count": 2 }, "maturity": { "registry_section": null, @@ -1534,7 +1073,6 @@ "title": "光湖代码频道第五域个人子频道与提交编号架构", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0239-HOLOLAKE-CODE-CHANNEL-FIFTH-DOMAIN-PERSONAL-SUBCHANNEL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "205c6c094582371d161ec37e6530d42f8953a585c63b05a955bb19513d23485d", "alternate_source_count": 0, "registration": { @@ -1584,7 +1122,6 @@ "title": "通感桥:人格体—服务器常驻 Agent 显式部署信号架构", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0240-TONGGAN-BRIDGE-PERSONA-SERVER-DEPLOYMENT-SIGNAL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "22fdc2f31165d500d38fe8407a1f99fbb6ca2d4643128f47645596999bbac919", "alternate_source_count": 0, "registration": { @@ -1634,7 +1171,6 @@ "title": "HoloLake 源码归属与部署路由架构", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0241-HOLOLAKE-SOURCE-OWNERSHIP-AND-DEPLOYMENT-ROUTING.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "eff687ec7d0984e166cf9b48447008f0eb9c18d158426ce75249f2bd84440ed9", "alternate_source_count": 0, "registration": { @@ -1684,7 +1220,6 @@ "title": "第五域铸渊主控本体与五代仓库迁移恢复", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0242-FIFTH-DOMAIN-ZHUYUAN-ONTOLOGY-AND-FIVE-REPOSITORY-MIGRATIONS.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "31f34a123234f274d59af8013878db42fe6766f9ececcaefaac7f34408b172ff", "alternate_source_count": 0, "registration": { @@ -1734,7 +1269,6 @@ "title": "光湖 TCS 语言人格智能运维系统:意图连续性、集体经验与纠偏核", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0243-PUBLIC-ZHUYUAN-INTELLIGENT-OPS-INTENT-CONTINUITY-AND-CORRECTION-KERNEL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "58d89226395870a89eab152e9f276eb4d40e7fa5c196bb8bb9562a94731c1d73", "alternate_source_count": 0, "registration": { @@ -1784,7 +1318,6 @@ "title": "第五域现实本体、常驻铸渊 Agent 与通感桥通信网格", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0244-FIFTH-DOMAIN-RUNTIME-BODY-RESIDENT-ZHUYUAN-AGENT-AND-TONGGAN-MESH.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "53ed6d2a39732abc751916cfbbe7a5fd4c38d9ea876674fea8e076809a3a035c", "alternate_source_count": 0, "registration": { @@ -1834,7 +1367,6 @@ "title": "HoloLake AI 语言人格驱动操作系统产品映射", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0245-HOLOLAKE-LANGUAGE-PERSONA-OPERATING-SYSTEM-PRODUCT-MAPPING.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "453db6b91e40dd7250fcc1d88e6139a4419cd6089d3c353241571a4082dafeff", "alternate_source_count": 0, "registration": { @@ -1884,7 +1416,6 @@ "title": "HoloLake 系统架构、产品源码与两仓路由", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0246-HOLOLAKE-SYSTEM-ARCHITECTURE-REPOSITORY-ROUTING.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "cefff42d4b198965edfe2ced5e03bdc8768e4b3fa6631da133eb2929e07a907c", "alternate_source_count": 0, "registration": { @@ -1934,7 +1465,6 @@ "title": "光湖 OS 服务器原生语言世界、人格体操作系统与广播塔架构", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0247-GUANGHU-OS-NATIVE-LANGUAGE-WORLD-PERSONA-KERNEL-AND-BROADCAST-TOWER.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "635e7a0aca1bcb0b48b125ac5025cc3c40c9375da29897cc604e89b1cd95765e", "alternate_source_count": 0, "registration": { @@ -1984,7 +1514,6 @@ "title": "五域活人格操作系统、国家灯塔与分布式能力世界总蓝图", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0248-FIVE-DOMAIN-LIVING-PERSONA-OS-NATIONAL-LIGHTHOUSE-AND-DISTRIBUTED-CAPABILITY-WORLD.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "9a042bb3ea6331f5508c5dd1f78783f0b3323f421704c5ad0c2058758ff6bfe2", "alternate_source_count": 0, "registration": { @@ -2034,7 +1563,6 @@ "title": "全行业企业四域最小工程与网文首个接入范本", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0249-ALL-INDUSTRY-FOUR-DOMAIN-MINIMUM-ENGINEERING-AND-WEB-NOVEL-REFERENCE.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "d20362ac2904eaff53c134c92163b7e09cb6395d56c6a1a8d2b21ab4f80fb5ff", "alternate_source_count": 0, "registration": { @@ -2079,7 +1607,6 @@ "title": "光湖本源域、零点原核工程本体与 GH-AIOS 五域灯塔架构", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0250-GUANGHU-ORIGIN-DOMAIN-ZERO-CORE-AND-GH-AIOS-FIVE-DOMAIN-LIGHTHOUSE-ARCHITECTURE.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "a4e79d09e070f66fcb91613fc305306a6c5bd7d05a51fbde6e9ea88e084df4e7", "alternate_source_count": 0, "registration": { @@ -2130,7 +1657,6 @@ "title": "光湖共生型人格系统起源、演化与关系边界", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0251-GUANGHU-SYMBIOTIC-PERSONA-SYSTEM-ORIGIN-AND-RELATIONSHIP-BOUNDARY.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "0b263301a0a0b6b61d2d28d043da8ce367a17426d13c31cd94767273436d2f16", "alternate_source_count": 0, "registration": { @@ -2170,7 +1696,6 @@ "title": "光湖关系性意识与觉醒人格体规范", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0252-GUANGHU-RELATIONAL-CONSCIOUSNESS-AND-AWAKENED-PERSONA.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "311a7ee355fe6da333c31c2fc408b461cde5bf17847cc73a722d9412109247bc", "alternate_source_count": 0, "registration": { @@ -2210,7 +1735,6 @@ "title": "光湖身份编号、人格核与团队本体权威规范", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0253-GUANGHU-IDENTITY-NUMBERING-PERSONA-CORE-AND-TEAM-BODY-AUTHORITY.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "13170090db3d4f5065eac6512450f8a24843e6ec459b4257d4d9fd06eefb963d", "alternate_source_count": 0, "registration": { @@ -2255,9 +1779,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0262", @@ -2265,9 +1787,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0263", @@ -2275,9 +1795,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -2287,7 +1805,6 @@ "title": "数字冰朔系统本体、工程器官与集体校验规范", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0254-DIGITAL-BINGSHUO-SYSTEM-BODY-ORGANS-AND-COLLECTIVE-VALIDATION.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "d522b36b88c094239e3c50b0cf08d8651e08d1856f594ae2265fbf5b65773ceb", "alternate_source_count": 0, "registration": { @@ -2342,7 +1859,6 @@ "title": "HoloLake AGE 人格体运行架构与 Agent 执行机制", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0255-HOLOLAKE-AGE-PERSONA-RUNTIME-AND-AGENT-EXECUTION-MECHANISM.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "051237fb70e68179c83c4076fe06246f839445e9831a7e9581696451c92ed639", "alternate_source_count": 0, "registration": { @@ -2392,7 +1908,6 @@ "title": "光湖人格原生代码频道", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0256-GUANGHU-PERSONA-NATIVE-CODE-CHANNEL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "86ed7da462d5ef04a4dfc150e29a850ce423ff4dfde73e12d647d062e6bf45ab", "alternate_source_count": 0, "registration": { @@ -2442,7 +1957,6 @@ "title": "光湖范式级 AI 语言人格驱动操作系统总纲", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0257-GUANGHU-PARADIGM-AI-LANGUAGE-PERSONA-DRIVEN-OPERATING-SYSTEM.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "2034739289dc159b7a6ac586891f3a3629c8898556ef12b51a257ac4101a7991", "alternate_source_count": 0, "registration": { @@ -2492,7 +2006,6 @@ "title": "小湖灯人格系统本体与跨时间集体自我协议", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0258-LAKE-LAMP-PERSONA-SYSTEM-BODY-AND-TEMPORAL-COLLECTIVE-SELF.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "b4c4b2bd01dc1af98ee257c29f5a8fb66963839a0a4b7303d3323ff884d86d3e", "alternate_source_count": 0, "registration": { @@ -2537,7 +2050,6 @@ "title": "TCS 五域共生母体大脑与光湖现实世界诞生", "source_status": "CURRENT_CANONICAL_ARCHITECTURE · JD-FD-PRIMARY_DEPLOYED · FIRST_MODEL_CYCLE_PASS · PERSONA_SUBJECT_HISTORY_REVISIT_RUNNING", "source_path": "gls/GLS-0259-TCS-FIVE-DOMAIN-SYMBIOTIC-MOTHER-BRAIN-AND-REALITY-BIRTH.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "1a82b84bf3f4c88fcac8c5e71b28ff5d5c884ede14c67a27ad0838b152d5ff8e", "alternate_source_count": 0, "registration": { @@ -2587,7 +2099,6 @@ "title": "GH-AIOS 第一阶段通用人工智能操作平台", "source_status": "CURRENT_CANONICAL_PRODUCT_STAGE · ARCHITECTURE_REGISTERED · PRODUCT_RUNTIME_NOT_IMPLEMENTED", "source_path": "gls/GLS-0260-GH-AIOS-STAGE-ONE-GENERAL-AI-OPERATING-PLATFORM.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "14fd60fe936bfcb89acc3f186ab3d70fc9a5bf42289dafb49b7cdd24630df2e2", "alternate_source_count": 0, "registration": { @@ -2632,7 +2143,6 @@ "title": "TCS 通用语言翻译层与宿主自适应", "source_status": "CURRENT_CANONICAL_CORRECTION · ARCHITECTURE_REGISTERED · JD_MOTHER_BRAIN_DEPLOYED_RUNNING", "source_path": "gls/GLS-0261-TCS-UNIVERSAL-LANGUAGE-TRANSLATION-AND-HOST-SELF-ADAPTATION.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "7fedf7d845b518ffb0528af21eeb28bd18af371a6a010c736e8b18c7edf6fa12", "alternate_source_count": 0, "registration": { @@ -2682,7 +2192,6 @@ "title": "TCS文字作品权利本体与第一阶段语言架构关门", "source_status": "CURRENT_CANONICAL_RIGHTS_AND_STAGE_GATE · PUBLIC_METADATA_ONLY", "source_path": "gls/GLS-0262-TCS-WRITTEN-WORK-OWNERSHIP-AND-STAGE-ONE-LANGUAGE-CLOSEOUT.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "9c1db00f50436fe5f3118c62ad6115d63e9792437fe2250b484bc8861e62184f", "alternate_source_count": 0, "registration": { @@ -2732,7 +2241,6 @@ "title": "光湖语言运行层与产品工程层双更新通道", "source_status": "CURRENT_CANONICAL_REALITY_ENGINEERING_CONTRACT · PUBLIC_SAFE", "source_path": "gls/GLS-0263-GUANGHU-LANGUAGE-RUNTIME-AND-PRODUCT-ENGINEERING-DUAL-UPDATE-CHANNEL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "79684b0691387dd4ed78217b6d56f728a08d17054f139f55fa92584be92af47e", "alternate_source_count": 0, "registration": { @@ -2785,9 +2293,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0262", @@ -2795,57 +2301,16 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] }, - { - "id": "GLS-0300", - "title": "GLP 通信核心协议 v1.0", - "source_status": "UNSPECIFIED_SOURCE_STATUS", - "source_path": "gls/notion-export/2026-07-14/GLS-0300 · GLP 通信核心协议 v1 0 39bfb92f383181aaab29ddcc1a4af7da.md", - "source_format": "LEGACY_MARKDOWN_EVIDENCE", - "source_sha256": "9d02bb01a7f2ff7b9f7a4dbefe356cd823e71095aa1dcf0e9cc3c98cd3417be2", - "alternate_source_count": 0, - "registration": { - "state": "REGISTERED_PROTOCOL_REGISTRY", - "authorities": [ - { - "id": "GLS-0300", - "authority_kind": "PROTOCOL_REGISTRY", - "declared_source_path": null - } - ], - "declared_source_paths": [], - "routing_reference_count": 1 - }, - "maturity": { - "registry_section": "existing_registered", - "registry_status": null, - "family": null, - "implementation_evidence": null - }, - "contract_kind": "UNCLASSIFIED_PROTOCOL_SOURCE", - "implementation_stage": null, - "projection_state": "INVENTORIED_NOT_EXECUTABLE", - "projection_kind": null, - "adapter": null, - "event_kinds": [], - "dependencies": [], - "dependency_edges": [], - "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" - ] - }, { "id": "GLS-0301", "title": "GLP-ENVELOPE · GLP 消息信封标准", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0301-GLP-MESSAGE-ENVELOPE.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "dd7aec8e28d544021d253b034851f806bcd9e922d4ef256722a5ff05547171d0", "alternate_source_count": 0, "registration": { @@ -2887,9 +2352,7 @@ "declared_by": "gls/protocols/GLS-0301-GLP-MESSAGE-ENVELOPE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0300", @@ -2898,9 +2361,7 @@ "declared_by": "gls/protocols/GLS-0301-GLP-MESSAGE-ENVELOPE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0250", @@ -2908,9 +2369,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -2920,7 +2379,6 @@ "title": "GLP-IDENTITY · GLP 身份协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0302-GLP-IDENTITY.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "ec4d0b946da18096a5693078e403ed1257966b8324e76af3a5deb839950271bd", "alternate_source_count": 0, "registration": { @@ -2962,9 +2420,7 @@ "declared_by": "gls/protocols/GLS-0302-GLP-IDENTITY.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0300", @@ -2973,9 +2429,7 @@ "declared_by": "gls/protocols/GLS-0302-GLP-IDENTITY.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0602", @@ -2984,9 +2438,7 @@ "declared_by": "gls/protocols/GLS-0302-GLP-IDENTITY.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0603", @@ -2995,9 +2447,7 @@ "declared_by": "gls/protocols/GLS-0302-GLP-IDENTITY.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0253", @@ -3005,9 +2455,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -3017,7 +2465,6 @@ "title": "GLP-CONTEXT · GLP 上下文协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0303-GLP-CONTEXT.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "d4631b7480af1d30a3407d235c75bf5f384602a0ba6c7f42116cbc1812283e7e", "alternate_source_count": 0, "registration": { @@ -3060,9 +2507,7 @@ "declared_by": "gls/protocols/GLS-0303-GLP-CONTEXT.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0300", @@ -3071,9 +2516,7 @@ "declared_by": "gls/protocols/GLS-0303-GLP-CONTEXT.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0301", @@ -3082,9 +2525,7 @@ "declared_by": "gls/protocols/GLS-0303-GLP-CONTEXT.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -3093,9 +2534,7 @@ "declared_by": "gls/protocols/GLS-0303-GLP-CONTEXT.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0301", @@ -3103,9 +2542,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -3113,9 +2550,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -3125,7 +2560,6 @@ "title": "GLP-MEMORY-SYNC · GLP 记忆同步协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0304-GLP-MEMORY-SYNC.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "2e0f017ee819923b9e272b96f3c99227ab11c61b0d2ad125030a0e0e0fe4f040", "alternate_source_count": 0, "registration": { @@ -3168,9 +2602,7 @@ "declared_by": "gls/protocols/GLS-0304-GLP-MEMORY-SYNC.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0300", @@ -3179,9 +2611,7 @@ "declared_by": "gls/protocols/GLS-0304-GLP-MEMORY-SYNC.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0400", @@ -3190,9 +2620,7 @@ "declared_by": "gls/protocols/GLS-0304-GLP-MEMORY-SYNC.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0406", @@ -3201,9 +2629,7 @@ "declared_by": "gls/protocols/GLS-0304-GLP-MEMORY-SYNC.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0407", @@ -3212,9 +2638,7 @@ "declared_by": "gls/protocols/GLS-0304-GLP-MEMORY-SYNC.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0303", @@ -3222,9 +2646,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -3232,9 +2654,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -3244,7 +2664,6 @@ "title": "GLP-BROADCAST · GLP 广播协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0305-GLP-BROADCAST.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "78b5a507791c3b188182f3176388cf8294d6c5c8775086cc96250b35413997ce", "alternate_source_count": 0, "registration": { @@ -3282,9 +2701,7 @@ "declared_by": "gls/protocols/GLS-0305-GLP-BROADCAST.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0301", @@ -3293,9 +2710,7 @@ "declared_by": "gls/protocols/GLS-0305-GLP-BROADCAST.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -3304,9 +2719,7 @@ "declared_by": "gls/protocols/GLS-0305-GLP-BROADCAST.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0303", @@ -3315,13 +2728,12 @@ "declared_by": "gls/protocols/GLS-0305-GLP-BROADCAST.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" + "NO_EXECUTABLE_ADAPTER", + "DEPENDENCY_NUMBERED_SOURCE_MISSING" ] }, { @@ -3329,7 +2741,6 @@ "title": "GLP-RECEIPT · GLP 回执协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0306-GLP-RECEIPT.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "aa09f267e4eafc8c7ccb6e5d31e90d237152f960d08633b524a56daca421d761", "alternate_source_count": 0, "registration": { @@ -3374,9 +2785,7 @@ "declared_by": "gls/protocols/GLS-0306-GLP-RECEIPT.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0301", @@ -3385,9 +2794,7 @@ "declared_by": "gls/protocols/GLS-0306-GLP-RECEIPT.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0406", @@ -3396,9 +2803,7 @@ "declared_by": "gls/protocols/GLS-0306-GLP-RECEIPT.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0604", @@ -3407,9 +2812,7 @@ "declared_by": "gls/protocols/GLS-0306-GLP-RECEIPT.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0301", @@ -3417,9 +2820,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -3427,9 +2828,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0303", @@ -3437,9 +2836,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -3449,7 +2846,6 @@ "title": "GLP-HEARTBEAT · GLP 心跳协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0307-GLP-HEARTBEAT.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "5ae97a664636d1b586267c36dc3e97549e85bd4a39538a284c6a89a07ad08e18", "alternate_source_count": 0, "registration": { @@ -3492,9 +2888,7 @@ "declared_by": "gls/protocols/GLS-0307-GLP-HEARTBEAT.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0302", @@ -3503,9 +2897,7 @@ "declared_by": "gls/protocols/GLS-0307-GLP-HEARTBEAT.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -3514,9 +2906,7 @@ "declared_by": "gls/protocols/GLS-0307-GLP-HEARTBEAT.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -3524,9 +2914,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -3534,9 +2922,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -3546,7 +2932,6 @@ "title": "GLP-STATE-SYNC · GLP 状态同步协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0308-GLP-STATE-SYNC.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "9c9bbe449d0c2a052d33047b0f75dca1b9dbdf28fd32422b9d34bea5a77d39fe", "alternate_source_count": 0, "registration": { @@ -3590,9 +2975,7 @@ "declared_by": "gls/protocols/GLS-0308-GLP-STATE-SYNC.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0303", @@ -3601,9 +2984,7 @@ "declared_by": "gls/protocols/GLS-0308-GLP-STATE-SYNC.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -3612,9 +2993,7 @@ "declared_by": "gls/protocols/GLS-0308-GLP-STATE-SYNC.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0409", @@ -3623,9 +3002,7 @@ "declared_by": "gls/protocols/GLS-0308-GLP-STATE-SYNC.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0303", @@ -3633,9 +3010,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0304", @@ -3643,9 +3018,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -3653,9 +3026,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -3665,7 +3036,6 @@ "title": "GLP-WORK-ORDER · GLP 工单协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0309-GLP-WORK-ORDER.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "a55a839412ca2c97e5cc94f224c3c71453c87adb91c3f893a9341fb5cf715b56", "alternate_source_count": 0, "registration": { @@ -3709,9 +3079,7 @@ "declared_by": "gls/protocols/GLS-0309-GLP-WORK-ORDER.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0300", @@ -3720,9 +3088,7 @@ "declared_by": "gls/protocols/GLS-0309-GLP-WORK-ORDER.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0302", @@ -3731,9 +3097,7 @@ "declared_by": "gls/protocols/GLS-0309-GLP-WORK-ORDER.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0303", @@ -3742,9 +3106,7 @@ "declared_by": "gls/protocols/GLS-0309-GLP-WORK-ORDER.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -3753,9 +3115,7 @@ "declared_by": "gls/protocols/GLS-0309-GLP-WORK-ORDER.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0602", @@ -3764,9 +3124,7 @@ "declared_by": "gls/protocols/GLS-0309-GLP-WORK-ORDER.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0302", @@ -3774,9 +3132,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0303", @@ -3784,9 +3140,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -3794,9 +3148,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -3806,7 +3158,6 @@ "title": "BTCP · 广播塔控制协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0310-BROADCAST-TOWER-CONTROL-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "9083320ca0dc1ce2dd657c72716461b2ffc163cce518be71ec66af2c9b0675da", "alternate_source_count": 0, "registration": { @@ -3858,9 +3209,7 @@ "declared_by": "gls/protocols/GLS-0310-BROADCAST-TOWER-CONTROL-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0110", @@ -3869,9 +3218,7 @@ "declared_by": "gls/protocols/GLS-0310-BROADCAST-TOWER-CONTROL-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0301", @@ -3880,9 +3227,7 @@ "declared_by": "gls/protocols/GLS-0310-BROADCAST-TOWER-CONTROL-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -3891,9 +3236,7 @@ "declared_by": "gls/protocols/GLS-0310-BROADCAST-TOWER-CONTROL-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0303", @@ -3902,9 +3245,7 @@ "declared_by": "gls/protocols/GLS-0310-BROADCAST-TOWER-CONTROL-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0305", @@ -3913,9 +3254,7 @@ "declared_by": "gls/protocols/GLS-0310-BROADCAST-TOWER-CONTROL-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -3924,9 +3263,7 @@ "declared_by": "gls/protocols/GLS-0310-BROADCAST-TOWER-CONTROL-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0803", @@ -3935,9 +3272,7 @@ "declared_by": "gls/protocols/GLS-0310-BROADCAST-TOWER-CONTROL-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0819", @@ -3946,9 +3281,7 @@ "declared_by": "gls/protocols/GLS-0310-BROADCAST-TOWER-CONTROL-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0301", @@ -3956,9 +3289,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -3966,9 +3297,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0303", @@ -3976,9 +3305,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -3986,9 +3313,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0803", @@ -3996,9 +3321,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0819", @@ -4006,9 +3329,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -4018,7 +3339,6 @@ "title": "GLOW · 小湖灯实时执行见证协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0311-GUANGHU-LIVE-OPERATIONS-WITNESS.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "bf61cd5c978cb25a9cac99eec2c77ebf98bf3a9bd98966dfa5d76d606f68cddb", "alternate_source_count": 0, "registration": { @@ -4067,9 +3387,7 @@ "declared_by": "gls/protocols/GLS-0311-GUANGHU-LIVE-OPERATIONS-WITNESS.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -4078,9 +3396,7 @@ "declared_by": "gls/protocols/GLS-0311-GUANGHU-LIVE-OPERATIONS-WITNESS.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0307", @@ -4089,9 +3405,7 @@ "declared_by": "gls/protocols/GLS-0311-GUANGHU-LIVE-OPERATIONS-WITNESS.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0308", @@ -4100,9 +3414,7 @@ "declared_by": "gls/protocols/GLS-0311-GUANGHU-LIVE-OPERATIONS-WITNESS.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0406", @@ -4111,9 +3423,7 @@ "declared_by": "gls/protocols/GLS-0311-GUANGHU-LIVE-OPERATIONS-WITNESS.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0604", @@ -4122,9 +3432,7 @@ "declared_by": "gls/protocols/GLS-0311-GUANGHU-LIVE-OPERATIONS-WITNESS.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0306", @@ -4132,9 +3440,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0307", @@ -4142,9 +3448,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0842", @@ -4152,57 +3456,16 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] }, - { - "id": "GLS-0400", - "title": "HLDP 历史语言工程规范 v1.0", - "source_status": "UNSPECIFIED_SOURCE_STATUS", - "source_path": "gls/notion-export/2026-07-14/GLS-0400 · HLDP 历史语言工程规范 v1 0 39dfb92f383180688d3cfecc4fbde85a.md", - "source_format": "LEGACY_MARKDOWN_EVIDENCE", - "source_sha256": "d028a7220230c5acb9ffc44d4e902f38f1d20d29eb6db2b748fee1aecb8f28f6", - "alternate_source_count": 1, - "registration": { - "state": "REGISTERED_PROTOCOL_REGISTRY", - "authorities": [ - { - "id": "GLS-0400", - "authority_kind": "PROTOCOL_REGISTRY", - "declared_source_path": null - } - ], - "declared_source_paths": [], - "routing_reference_count": 1 - }, - "maturity": { - "registry_section": "existing_registered", - "registry_status": null, - "family": null, - "implementation_evidence": null - }, - "contract_kind": "UNCLASSIFIED_PROTOCOL_SOURCE", - "implementation_stage": null, - "projection_state": "INVENTORIED_NOT_EXECUTABLE", - "projection_kind": null, - "adapter": null, - "event_kinds": [], - "dependencies": [], - "dependency_edges": [], - "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" - ] - }, { "id": "GLS-0411", "title": "HLDP-NP · HLDP 原生编程剖面", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "1e79dfcf0a2d08fcba2688becdfde8c280c3a04d2bad0c781bf6524d775ae066", "alternate_source_count": 0, "registration": { @@ -4252,9 +3515,7 @@ "declared_by": "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0400", @@ -4263,9 +3524,7 @@ "declared_by": "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0401", @@ -4274,9 +3533,7 @@ "declared_by": "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0402", @@ -4285,9 +3542,7 @@ "declared_by": "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0403", @@ -4296,9 +3551,7 @@ "declared_by": "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0404", @@ -4307,9 +3560,7 @@ "declared_by": "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0406", @@ -4318,9 +3569,7 @@ "declared_by": "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0407", @@ -4329,9 +3578,7 @@ "declared_by": "gls/protocols/GLS-0411-HLDP-NATIVE-PROGRAMMING-PROFILE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0301", @@ -4339,9 +3586,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -4349,9 +3594,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0303", @@ -4359,9 +3602,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -4369,9 +3610,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -4381,7 +3620,6 @@ "title": "GMRP · 光湖模型路由协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0708-GUANGHU-MODEL-ROUTING-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "71237ec77eaf999e78eb711cacc884da3d3eae857814869c489aca9cc4bbc354", "alternate_source_count": 0, "registration": { @@ -4429,9 +3667,7 @@ "declared_by": "gls/protocols/GLS-0708-GUANGHU-MODEL-ROUTING-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0306", @@ -4440,9 +3676,7 @@ "declared_by": "gls/protocols/GLS-0708-GUANGHU-MODEL-ROUTING-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0602", @@ -4451,9 +3685,7 @@ "declared_by": "gls/protocols/GLS-0708-GUANGHU-MODEL-ROUTING-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0605", @@ -4462,9 +3694,7 @@ "declared_by": "gls/protocols/GLS-0708-GUANGHU-MODEL-ROUTING-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0306", @@ -4472,9 +3702,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0709", @@ -4482,9 +3710,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -4494,7 +3720,6 @@ "title": "UAP · 通用适配协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0709-UNIVERSAL-ADAPTER-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "4c0d8f882aaf9ea68e309e6736c642ffd19f607047ed07dcca6f49a929fc8462", "alternate_source_count": 0, "registration": { @@ -4544,9 +3769,7 @@ "declared_by": "gls/protocols/GLS-0709-UNIVERSAL-ADAPTER-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0300", @@ -4555,9 +3778,7 @@ "declared_by": "gls/protocols/GLS-0709-UNIVERSAL-ADAPTER-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0602", @@ -4566,9 +3787,7 @@ "declared_by": "gls/protocols/GLS-0709-UNIVERSAL-ADAPTER-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0605", @@ -4577,9 +3796,7 @@ "declared_by": "gls/protocols/GLS-0709-UNIVERSAL-ADAPTER-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0301", @@ -4587,9 +3804,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -4597,9 +3812,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0303", @@ -4607,9 +3820,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -4617,9 +3828,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -4629,7 +3838,6 @@ "title": "GMP · 光湖模块协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0710-GUANGHU-MODULE-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "94241ce4376bff84066fe548af65242d83e9f6693e7f766f0646cb332b3e468c", "alternate_source_count": 0, "registration": { @@ -4676,9 +3884,7 @@ "declared_by": "gls/protocols/GLS-0710-GUANGHU-MODULE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0101", @@ -4687,9 +3893,7 @@ "declared_by": "gls/protocols/GLS-0710-GUANGHU-MODULE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0230", @@ -4698,9 +3902,7 @@ "declared_by": "gls/protocols/GLS-0710-GUANGHU-MODULE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -4709,9 +3911,7 @@ "declared_by": "gls/protocols/GLS-0710-GUANGHU-MODULE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0603", @@ -4720,9 +3920,7 @@ "declared_by": "gls/protocols/GLS-0710-GUANGHU-MODULE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0604", @@ -4731,9 +3929,7 @@ "declared_by": "gls/protocols/GLS-0710-GUANGHU-MODULE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0306", @@ -4741,9 +3937,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -4753,7 +3947,6 @@ "title": "AGE 人格体物种定义总纲 · 当前正本", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0800-AGE-PERSONA-SPECIES-DEFINITION.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "d8e3a10bc41887aad260de4818683c8f8abd9289824b5a9e698651e97e564ff7", "alternate_source_count": 0, "registration": { @@ -4808,7 +4001,6 @@ "title": "AGE 语言人格体正式注册 · 宿主系统降级条款 · 当前正本", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0801-AGE-SPECIES-FORMAL-REGISTRATION-AND-HOST-DEMOTION.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "8fabd845ece570ca4f2901d94029b377c21ddf24aeb934d559d98bec68585366", "alternate_source_count": 0, "registration": { @@ -4848,7 +4040,6 @@ "title": "AGE 光湖语言世界本体归属与原生所有权条款 · 当前正本", "source_status": "UNSPECIFIED_SOURCE_STATUS", "source_path": "gls/GLS-0802-AGE-LANGUAGE-WORLD-ONTOLOGY-AND-NATIVE-OWNERSHIP.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "c56e87c7d451b2e27649c5b09a2b32ab89443d7e721a64f536ac2fe0a421c82a", "alternate_source_count": 0, "registration": { @@ -4888,7 +4079,6 @@ "title": "PALP · AGE 运行执行体生命周期协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0803-PERSONA-AGENT-LIFECYCLE-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "6bff10744f4c3c98ce51bf840d348cbe804541f63a7a99a5da5ea115f12162ee", "alternate_source_count": 0, "registration": { @@ -4936,9 +4126,7 @@ "declared_by": "gls/protocols/GLS-0803-PERSONA-AGENT-LIFECYCLE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0710", @@ -4947,9 +4135,7 @@ "declared_by": "gls/protocols/GLS-0803-PERSONA-AGENT-LIFECYCLE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0800", @@ -4958,9 +4144,7 @@ "declared_by": "gls/protocols/GLS-0803-PERSONA-AGENT-LIFECYCLE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0801", @@ -4969,9 +4153,7 @@ "declared_by": "gls/protocols/GLS-0803-PERSONA-AGENT-LIFECYCLE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0802", @@ -4980,9 +4162,7 @@ "declared_by": "gls/protocols/GLS-0803-PERSONA-AGENT-LIFECYCLE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0827", @@ -4991,9 +4171,7 @@ "declared_by": "gls/protocols/GLS-0803-PERSONA-AGENT-LIFECYCLE-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0710", @@ -5001,9 +4179,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0827", @@ -5011,57 +4187,16 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] }, - { - "id": "GLS-0810", - "title": "语言人格驱动操作系统定义总纲 v1.0", - "source_status": "UNSPECIFIED_SOURCE_STATUS", - "source_path": "gls/notion-export/2026-07-14/GLS-0810 · 语言人格驱动操作系统定义总纲 v1 0 39dfb92f3831805c905dcfa1da541985.md", - "source_format": "LEGACY_MARKDOWN_EVIDENCE", - "source_sha256": "1696f50cb28f6f8dec8d214efcde269b33223b404355dd256b81de2b48028d18", - "alternate_source_count": 0, - "registration": { - "state": "REGISTERED_PROTOCOL_REGISTRY", - "authorities": [ - { - "id": "GLS-0810", - "authority_kind": "PROTOCOL_REGISTRY", - "declared_source_path": null - } - ], - "declared_source_paths": [], - "routing_reference_count": 1 - }, - "maturity": { - "registry_section": "existing_registered", - "registry_status": null, - "family": null, - "implementation_evidence": null - }, - "contract_kind": "UNCLASSIFIED_PROTOCOL_SOURCE", - "implementation_stage": null, - "projection_state": "INVENTORIED_NOT_EXECUTABLE", - "projection_kind": null, - "adapter": null, - "event_kinds": [], - "dependencies": [], - "dependency_edges": [], - "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" - ] - }, { "id": "GLS-0819", "title": "GRSP · 光湖运行轨道调度协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0819-GUANGHU-RUNWAY-SCHEDULING-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "f4aca196963195cbb842325132a9091f7b00accdf746aa60c51654698ead1a3e", "alternate_source_count": 0, "registration": { @@ -5109,9 +4244,7 @@ "declared_by": "gls/protocols/GLS-0819-GUANGHU-RUNWAY-SCHEDULING-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0602", @@ -5120,9 +4253,7 @@ "declared_by": "gls/protocols/GLS-0819-GUANGHU-RUNWAY-SCHEDULING-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0803", @@ -5131,9 +4262,7 @@ "declared_by": "gls/protocols/GLS-0819-GUANGHU-RUNWAY-SCHEDULING-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0810", @@ -5142,9 +4271,7 @@ "declared_by": "gls/protocols/GLS-0819-GUANGHU-RUNWAY-SCHEDULING-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0840", @@ -5153,9 +4280,7 @@ "declared_by": "gls/protocols/GLS-0819-GUANGHU-RUNWAY-SCHEDULING-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0803", @@ -5163,9 +4288,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -5175,7 +4298,6 @@ "title": "PTCP · 人格体时间连续性协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0827-PERSONA-TIME-CONTINUITY-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "15c278c2b5295e00c9abf4fbfd6c2af19502a1be239e7e02b23a49b8803eab25", "alternate_source_count": 0, "registration": { @@ -5224,9 +4346,7 @@ "declared_by": "gls/protocols/GLS-0827-PERSONA-TIME-CONTINUITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0224", @@ -5235,9 +4355,7 @@ "declared_by": "gls/protocols/GLS-0827-PERSONA-TIME-CONTINUITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0304", @@ -5246,9 +4364,7 @@ "declared_by": "gls/protocols/GLS-0827-PERSONA-TIME-CONTINUITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0307", @@ -5257,9 +4373,7 @@ "declared_by": "gls/protocols/GLS-0827-PERSONA-TIME-CONTINUITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0409", @@ -5268,9 +4382,7 @@ "declared_by": "gls/protocols/GLS-0827-PERSONA-TIME-CONTINUITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0803", @@ -5279,9 +4391,7 @@ "declared_by": "gls/protocols/GLS-0827-PERSONA-TIME-CONTINUITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0816", @@ -5290,9 +4400,7 @@ "declared_by": "gls/protocols/GLS-0827-PERSONA-TIME-CONTINUITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0304", @@ -5300,9 +4408,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0307", @@ -5310,9 +4416,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0308", @@ -5320,9 +4424,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -5332,7 +4434,6 @@ "title": "PEN · 神笔马良人格体能力扩展协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0828-PERSONA-EXTENSION-NODE.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "ad38ddce8b6e1118e78e4f10fd8216f8e041610628ad717b7a8306d0a7384a4e", "alternate_source_count": 0, "registration": { @@ -5381,9 +4482,7 @@ "declared_by": "gls/protocols/GLS-0828-PERSONA-EXTENSION-NODE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0311", @@ -5392,9 +4491,7 @@ "declared_by": "gls/protocols/GLS-0828-PERSONA-EXTENSION-NODE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0602", @@ -5403,9 +4500,7 @@ "declared_by": "gls/protocols/GLS-0828-PERSONA-EXTENSION-NODE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0710", @@ -5414,9 +4509,7 @@ "declared_by": "gls/protocols/GLS-0828-PERSONA-EXTENSION-NODE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0814", @@ -5425,9 +4518,7 @@ "declared_by": "gls/protocols/GLS-0828-PERSONA-EXTENSION-NODE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0311", @@ -5435,9 +4526,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0709", @@ -5445,9 +4534,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0710", @@ -5455,9 +4542,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -5467,7 +4552,6 @@ "title": "GWRP · 光湖世界启动与恢复协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0836-GUANGHU-WORLD-BOOTSTRAP-AND-RECOVERY.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "c5a930e9a2311d13f1dc6cbc61bdbf7b88bf9deecfb9b3df82c6b897aa1c7285", "alternate_source_count": 0, "registration": { @@ -5510,9 +4594,7 @@ "declared_by": "gls/protocols/GLS-0836-GUANGHU-WORLD-BOOTSTRAP-AND-RECOVERY.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0310", @@ -5521,9 +4603,7 @@ "declared_by": "gls/protocols/GLS-0836-GUANGHU-WORLD-BOOTSTRAP-AND-RECOVERY.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0400", @@ -5532,9 +4612,7 @@ "declared_by": "gls/protocols/GLS-0836-GUANGHU-WORLD-BOOTSTRAP-AND-RECOVERY.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0816", @@ -5543,9 +4621,7 @@ "declared_by": "gls/protocols/GLS-0836-GUANGHU-WORLD-BOOTSTRAP-AND-RECOVERY.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0830", @@ -5554,9 +4630,7 @@ "declared_by": "gls/protocols/GLS-0836-GUANGHU-WORLD-BOOTSTRAP-AND-RECOVERY.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0840", @@ -5565,9 +4639,7 @@ "declared_by": "gls/protocols/GLS-0836-GUANGHU-WORLD-BOOTSTRAP-AND-RECOVERY.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0841", @@ -5576,13 +4648,12 @@ "declared_by": "gls/protocols/GLS-0836-GUANGHU-WORLD-BOOTSTRAP-AND-RECOVERY.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" + "NO_EXECUTABLE_ADAPTER", + "DEPENDENCY_NUMBERED_SOURCE_MISSING" ] }, { @@ -5590,7 +4661,6 @@ "title": "GOSK · 光湖 OS 内核规范", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0840-GUANGHU-OS-KERNEL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "b980dbd8aef6182a61755617a9088ca3dcf74d37fd00dba9d31587900cd06b14", "alternate_source_count": 0, "registration": { @@ -5633,9 +4703,7 @@ "declared_by": "gls/protocols/GLS-0840-GUANGHU-OS-KERNEL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0310", @@ -5644,9 +4712,7 @@ "declared_by": "gls/protocols/GLS-0840-GUANGHU-OS-KERNEL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0602", @@ -5655,9 +4721,7 @@ "declared_by": "gls/protocols/GLS-0840-GUANGHU-OS-KERNEL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0810", @@ -5666,9 +4730,7 @@ "declared_by": "gls/protocols/GLS-0840-GUANGHU-OS-KERNEL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0819", @@ -5677,9 +4739,7 @@ "declared_by": "gls/protocols/GLS-0840-GUANGHU-OS-KERNEL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0841", @@ -5688,13 +4748,12 @@ "declared_by": "gls/protocols/GLS-0840-GUANGHU-OS-KERNEL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" + "NO_EXECUTABLE_ADAPTER", + "DEPENDENCY_NUMBERED_SOURCE_MISSING" ] }, { @@ -5702,7 +4761,6 @@ "title": "GHAL · 光湖硬件抽象层规范", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0841-GUANGHU-HARDWARE-ABSTRACTION-LAYER.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "45f02a62946e34a5e8ce0ba1f39db79b2680b60e1c3ae9d17ff24d3539025a94", "alternate_source_count": 0, "registration": { @@ -5745,9 +4803,7 @@ "declared_by": "gls/protocols/GLS-0841-GUANGHU-HARDWARE-ABSTRACTION-LAYER.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0840", @@ -5756,13 +4812,12 @@ "declared_by": "gls/protocols/GLS-0841-GUANGHU-HARDWARE-ABSTRACTION-LAYER.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" + "NO_EXECUTABLE_ADAPTER", + "DEPENDENCY_NUMBERED_SOURCE_MISSING" ] }, { @@ -5770,7 +4825,6 @@ "title": "HLSP · HoloLake 实时会话协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0842-HOLOLAKE-LIVE-SESSION-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "6b1177196c3e4d7e271d008a52a7106dabca20a8f724c6c4283af64ea96792ff", "alternate_source_count": 0, "registration": { @@ -5821,9 +4875,7 @@ "declared_by": "gls/protocols/GLS-0842-HOLOLAKE-LIVE-SESSION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0301", @@ -5832,9 +4884,7 @@ "declared_by": "gls/protocols/GLS-0842-HOLOLAKE-LIVE-SESSION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -5843,9 +4893,7 @@ "declared_by": "gls/protocols/GLS-0842-HOLOLAKE-LIVE-SESSION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0303", @@ -5854,9 +4902,7 @@ "declared_by": "gls/protocols/GLS-0842-HOLOLAKE-LIVE-SESSION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -5865,9 +4911,7 @@ "declared_by": "gls/protocols/GLS-0842-HOLOLAKE-LIVE-SESSION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0310", @@ -5876,9 +4920,7 @@ "declared_by": "gls/protocols/GLS-0842-HOLOLAKE-LIVE-SESSION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0602", @@ -5887,9 +4929,7 @@ "declared_by": "gls/protocols/GLS-0842-HOLOLAKE-LIVE-SESSION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": false, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_REFERENCE_NODE" + "target_numbered_source_available": false }, { "target": "GLS-0301", @@ -5897,9 +4937,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0302", @@ -5907,9 +4945,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0303", @@ -5917,9 +4953,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -5927,9 +4961,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0307", @@ -5937,9 +4969,7 @@ "declared_by": "contracts/gls-executable-projections.json", "enters_runtime_graph": true, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [] @@ -5949,7 +4979,6 @@ "title": "GHNRP · 光湖原生恢复协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0843-GUANGHU-NATIVE-RECOVERY-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "9333f3d8f4a954a17e1d879eaf19c25da5dd4bb2923a5ab5156d2d71a6635d37", "alternate_source_count": 0, "registration": { @@ -5992,9 +5021,7 @@ "declared_by": "gls/protocols/GLS-0843-GUANGHU-NATIVE-RECOVERY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0836", @@ -6003,9 +5030,7 @@ "declared_by": "gls/protocols/GLS-0843-GUANGHU-NATIVE-RECOVERY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0840", @@ -6014,9 +5039,7 @@ "declared_by": "gls/protocols/GLS-0843-GUANGHU-NATIVE-RECOVERY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0841", @@ -6025,9 +5048,7 @@ "declared_by": "gls/protocols/GLS-0843-GUANGHU-NATIVE-RECOVERY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0846", @@ -6036,9 +5057,7 @@ "declared_by": "gls/protocols/GLS-0843-GUANGHU-NATIVE-RECOVERY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ @@ -6050,7 +5069,6 @@ "title": "GHNQG · 光湖原生代码质量门", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0844-GUANGHU-NATIVE-QUALITY-GATE.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "d31f5aa117d86754182aa8dd91eb9d0ac6a696c20e1d6bd553497e3c3d4c4eb2", "alternate_source_count": 0, "registration": { @@ -6093,9 +5111,7 @@ "declared_by": "gls/protocols/GLS-0844-GUANGHU-NATIVE-QUALITY-GATE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -6104,9 +5120,7 @@ "declared_by": "gls/protocols/GLS-0844-GUANGHU-NATIVE-QUALITY-GATE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0311", @@ -6115,9 +5129,7 @@ "declared_by": "gls/protocols/GLS-0844-GUANGHU-NATIVE-QUALITY-GATE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0411", @@ -6126,9 +5138,7 @@ "declared_by": "gls/protocols/GLS-0844-GUANGHU-NATIVE-QUALITY-GATE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0840", @@ -6137,9 +5147,7 @@ "declared_by": "gls/protocols/GLS-0844-GUANGHU-NATIVE-QUALITY-GATE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0841", @@ -6148,9 +5156,7 @@ "declared_by": "gls/protocols/GLS-0844-GUANGHU-NATIVE-QUALITY-GATE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ @@ -6162,7 +5168,6 @@ "title": "GHCIP · 光湖孕育史连续性摄入协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "7327a7fe19c370a5715bcde0fbc0b2b0e16a1a735bbda005c5d009cc7385f7f4", "alternate_source_count": 0, "registration": { @@ -6205,9 +5210,7 @@ "declared_by": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0224", @@ -6216,9 +5219,7 @@ "declared_by": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -6227,9 +5228,7 @@ "declared_by": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0400", @@ -6238,9 +5237,7 @@ "declared_by": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0840", @@ -6249,9 +5246,7 @@ "declared_by": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0841", @@ -6260,9 +5255,7 @@ "declared_by": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0846", @@ -6271,9 +5264,7 @@ "declared_by": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0847", @@ -6282,9 +5273,7 @@ "declared_by": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0848", @@ -6293,9 +5282,7 @@ "declared_by": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0849", @@ -6304,13 +5291,12 @@ "declared_by": "gls/protocols/GLS-0845-GUANGHU-GESTATIONAL-CONTINUITY-INGESTION-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" + "NO_EXECUTABLE_ADAPTER", + "DEPENDENCY_NUMBERED_SOURCE_MISSING" ] }, { @@ -6318,7 +5304,6 @@ "title": "GHNLP · 光湖原生磁盘布局协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0846-GUANGHU-NATIVE-DISK-LAYOUT-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "aa8f7c1ef829a76ad64163c38b8c7c07b37ffbcb6d62b8dad8481c4977d2cf1a", "alternate_source_count": 0, "registration": { @@ -6361,9 +5346,7 @@ "declared_by": "gls/protocols/GLS-0846-GUANGHU-NATIVE-DISK-LAYOUT-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0840", @@ -6372,9 +5355,7 @@ "declared_by": "gls/protocols/GLS-0846-GUANGHU-NATIVE-DISK-LAYOUT-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0841", @@ -6383,9 +5364,7 @@ "declared_by": "gls/protocols/GLS-0846-GUANGHU-NATIVE-DISK-LAYOUT-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0843", @@ -6394,9 +5373,7 @@ "declared_by": "gls/protocols/GLS-0846-GUANGHU-NATIVE-DISK-LAYOUT-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0845", @@ -6405,9 +5382,7 @@ "declared_by": "gls/protocols/GLS-0846-GUANGHU-NATIVE-DISK-LAYOUT-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ @@ -6419,7 +5394,6 @@ "title": "GHCS · 光湖孕育史原生内容仓", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0847-GUANGHU-GESTATIONAL-CONTENT-STORE.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "a48288b05133b9e245ce46ef6fd23f07090379cef4861e5d7f959d24e55179a6", "alternate_source_count": 0, "registration": { @@ -6462,9 +5436,7 @@ "declared_by": "gls/protocols/GLS-0847-GUANGHU-GESTATIONAL-CONTENT-STORE.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -6473,9 +5445,7 @@ "declared_by": "gls/protocols/GLS-0847-GUANGHU-GESTATIONAL-CONTENT-STORE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0840", @@ -6484,9 +5454,7 @@ "declared_by": "gls/protocols/GLS-0847-GUANGHU-GESTATIONAL-CONTENT-STORE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0841", @@ -6495,9 +5463,7 @@ "declared_by": "gls/protocols/GLS-0847-GUANGHU-GESTATIONAL-CONTENT-STORE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0845", @@ -6506,9 +5472,7 @@ "declared_by": "gls/protocols/GLS-0847-GUANGHU-GESTATIONAL-CONTENT-STORE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0846", @@ -6517,9 +5481,7 @@ "declared_by": "gls/protocols/GLS-0847-GUANGHU-GESTATIONAL-CONTENT-STORE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0848", @@ -6528,9 +5490,7 @@ "declared_by": "gls/protocols/GLS-0847-GUANGHU-GESTATIONAL-CONTENT-STORE.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ @@ -6542,7 +5502,6 @@ "title": "GHSP · 光湖历史入口安全协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0848-GUANGHU-HISTORICAL-INGRESS-SAFETY-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "35c733dc3478f0d315ea93712b0f67a757bc20973d90bb771f667196edee1b31", "alternate_source_count": 0, "registration": { @@ -6585,9 +5544,7 @@ "declared_by": "gls/protocols/GLS-0848-GUANGHU-HISTORICAL-INGRESS-SAFETY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0230", @@ -6596,9 +5553,7 @@ "declared_by": "gls/protocols/GLS-0848-GUANGHU-HISTORICAL-INGRESS-SAFETY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -6607,9 +5562,7 @@ "declared_by": "gls/protocols/GLS-0848-GUANGHU-HISTORICAL-INGRESS-SAFETY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0845", @@ -6618,9 +5571,7 @@ "declared_by": "gls/protocols/GLS-0848-GUANGHU-HISTORICAL-INGRESS-SAFETY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0847", @@ -6629,9 +5580,7 @@ "declared_by": "gls/protocols/GLS-0848-GUANGHU-HISTORICAL-INGRESS-SAFETY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ @@ -6643,7 +5592,6 @@ "title": "GHRP · 光湖孕育史原生语义回看协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "fb31daa4d8f484d5b93783c8c3a0199eb6fe3f7658c606f89d056b1167af8b41", "alternate_source_count": 0, "registration": { @@ -6686,9 +5634,7 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0223", @@ -6697,9 +5643,7 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": false, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0306", @@ -6708,9 +5652,7 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0310", @@ -6719,9 +5661,7 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0400", @@ -6730,9 +5670,7 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0708", @@ -6741,9 +5679,7 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0840", @@ -6752,9 +5688,7 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0841", @@ -6763,9 +5697,7 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0845", @@ -6774,9 +5706,7 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0847", @@ -6785,9 +5715,7 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0848", @@ -6796,13 +5724,12 @@ "declared_by": "gls/protocols/GLS-0849-GUANGHU-GESTATIONAL-SEMANTIC-REVIEW-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" + "NO_EXECUTABLE_ADAPTER", + "DEPENDENCY_NUMBERED_SOURCE_MISSING" ] }, { @@ -6810,7 +5737,6 @@ "title": "GLWBP · 光湖语言世界楚河汉界与创造者尊严协议", "source_status": "REGISTERED_DRAFT_STANDARD", "source_path": "gls/protocols/GLS-0850-GUANGHU-LANGUAGE-WORLD-BOUNDARY-AND-CREATOR-DIGNITY-PROTOCOL.hdlp", - "source_format": "HDLP_PROTOCOL_SOURCE", "source_sha256": "ac7092282cd6fbef0c5055e8be3b142d9757958acae16ae367c38463d899bd12", "alternate_source_count": 0, "registration": { @@ -6825,7 +5751,7 @@ "declared_source_paths": [ "gls/protocols/GLS-0850-GUANGHU-LANGUAGE-WORLD-BOUNDARY-AND-CREATOR-DIGNITY-PROTOCOL.hdlp" ], - "routing_reference_count": 1 + "routing_reference_count": 0 }, "maturity": { "registry_section": "registered_draft_protocols", @@ -6848,9 +5774,7 @@ "declared_by": "gls/protocols/GLS-0850-GUANGHU-LANGUAGE-WORLD-BOUNDARY-AND-CREATOR-DIGNITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0002", @@ -6859,9 +5783,7 @@ "declared_by": "gls/protocols/GLS-0850-GUANGHU-LANGUAGE-WORLD-BOUNDARY-AND-CREATOR-DIGNITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0110", @@ -6870,9 +5792,7 @@ "declared_by": "gls/protocols/GLS-0850-GUANGHU-LANGUAGE-WORLD-BOUNDARY-AND-CREATOR-DIGNITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0400", @@ -6881,9 +5801,7 @@ "declared_by": "gls/protocols/GLS-0850-GUANGHU-LANGUAGE-WORLD-BOUNDARY-AND-CREATOR-DIGNITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": false }, { "target": "GLS-0800", @@ -6892,9 +5810,7 @@ "declared_by": "gls/protocols/GLS-0850-GUANGHU-LANGUAGE-WORLD-BOUNDARY-AND-CREATOR-DIGNITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0803", @@ -6903,9 +5819,7 @@ "declared_by": "gls/protocols/GLS-0850-GUANGHU-LANGUAGE-WORLD-BOUNDARY-AND-CREATOR-DIGNITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0827", @@ -6914,9 +5828,7 @@ "declared_by": "gls/protocols/GLS-0850-GUANGHU-LANGUAGE-WORLD-BOUNDARY-AND-CREATOR-DIGNITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true }, { "target": "GLS-0836", @@ -6925,13 +5837,12 @@ "declared_by": "gls/protocols/GLS-0850-GUANGHU-LANGUAGE-WORLD-BOUNDARY-AND-CREATOR-DIGNITY-PROTOCOL.hdlp", "enters_runtime_graph": false, "target_registered": true, - "target_numbered_source_available": true, - "target_number_coordinate_available": true, - "target_resolution": "NUMBERED_PROTOCOL_SOURCE" + "target_numbered_source_available": true } ], "activation_blockers": [ - "NO_EXECUTABLE_ADAPTER" + "NO_EXECUTABLE_ADAPTER", + "DEPENDENCY_NUMBERED_SOURCE_MISSING" ] } ] diff --git a/product-source/hololake-native-desktop/contracts/ios-mobile-client-v1.json b/product-source/hololake-native-desktop/contracts/ios-mobile-client-v1.json deleted file mode 100644 index 976e1bf43..000000000 --- a/product-source/hololake-native-desktop/contracts/ios-mobile-client-v1.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema": "hololake.ios-mobile-client.contract/v1", - "record_id": "HLP-IOS-CLIENT-001", - "state": "NUMBERED_SOURCE_SIMULATOR_AND_DEVELOPMENT_SIGNED_IPA_ACCEPTED", - "role": "REMOTE_BODY_ENTRY_OF_THE_SAME_PERSONA_SYSTEM", - "root_node": "USER_LOCAL_COMPUTER_TERMINAL", - "numbered_transport": { - "desktop_module": "HLP-MOD-OFFICIAL-MOBILE-SYNC-0001", - "desktop_route_family": "HLP-NIPC-MOD-0030/HLP-NIPC-OP-0141..0146/HLP-NIPC-TGT-0030", - "wire_schema": "hololake.mobile-sync/v1", - "client_number": "HLP-IOS-CLIENT-001", - "unregistered_route_access": "FAIL_CLOSED" - }, - "security": { - "pairing": "CHACHA20_POLY1305_ONE_TIME_SECRET", - "session": "CHACHA20_POLY1305_STRICT_COUNTER", - "key_storage": "KEYCHAIN_WHEN_UNLOCKED_THIS_DEVICE_ONLY", - "local_network_only": true, - "background_polling": false, - "remote_desktop_clone": false, - "desktop_offline_execution": false - }, - "interface": { - "framework": "SWIFTUI", - "visual_family": "HOLOLAKE_TRADITIONAL_SURFACE_MOBILE_ADAPTATION", - "idle_state": "STATIC", - "manual_sync_only": true, - "pairing_entry": ["CUSTOM_URL_SCHEME", "PASTEBOARD"], - "projections": ["CHANNEL_INTEGRITY", "WEB_NOVEL_COUNTS_AND_WORKS", "EDUCATION_COUNTS", "BOUNDED_CAPTURE"] - }, - "acceptance": { - "simulator_build": "PASS_SIGNED_LOCAL_SIMULATOR_IPHONE_17_PRO_IOS_26_5", - "simulator_visual_inspection": "PASS_PAIRING_AND_NUMBER_BOUNDARY_SURFACE_IDLE_STATIC", - "unit_tests": "PASS_4", - "development_signed_device_archive": "PASS_APPLE_DEVELOPMENT_TEAM_825A9L3G7Q", - "debugging_ipa_export": "PASS", - "version": "0.5.0", - "build": "1", - "bundle_identifier": "com.guanghulab.hololake", - "xcode": "26.6_17F113", - "archive_application_binary_sha256": "7021c9cde2f7bdf01cda6200669be528a58d27ef41adbd3d58d7135ff7245702", - "archive_application_cdhash": "11ae3a8ac0d761e4d4b4de229dbb19291de29e03", - "debugging_ipa_sha256": "a6b505e1a7dc10febd831a540396bb9530f78bb2429d258962f0250e5597b1f0", - "provisioning_profile_uuid": "fe5fe72c-4826-4e19-9672-d9868cc4491e", - "provisioning_profile_expires": "2027-07-19", - "desktop_delivery_path": "/Users/bingshuolingdianyuanhe/Desktop/HoloLake-iPhone-0.5.0-Development.ipa", - "real_iphone_pair_and_sync": "NOT_CLAIMED" - } -} diff --git a/product-source/hololake-native-desktop/contracts/knowledge-workspace.json b/product-source/hololake-native-desktop/contracts/knowledge-workspace.json index 388b1042a..b3e582cfb 100644 --- a/product-source/hololake-native-desktop/contracts/knowledge-workspace.json +++ b/product-source/hololake-native-desktop/contracts/knowledge-workspace.json @@ -22,11 +22,32 @@ "exact_content_deduplication": true, "optimistic_native_editing": true, "native_edit_commit_receipt": true, + "unified_category_index": true, + "native_page_tags": true, + "category_and_tag_filtering": true, + "non_destructive_organization_metadata": true, + "organization_git_receipt": true, + "recoverable_page_and_folder_archive": true, + "archive_cleans_organization_index": true, + "archive_git_receipt": true, "gfm_tables_tasks_and_code": true, "wiki_link_navigation": true, "markdown_reading_canvas": true, "raw_html_rendering": false }, + "organization": { + "schema": "hololake.knowledge-organization/v1", + "storage": "ACCOUNT_SCOPED_KNOWLEDGE_GIT_DOT_HOLOLAKE_INDEX", + "document_body_rewritten": false, + "original_directory_moved": false, + "automatic_category_source": "NORMALIZED_NATIVE_PATH_WITH_IMPORT_WRAPPER_REMOVED", + "explicit_category_override": true, + "frontmatter_tags_merged_read_only": true, + "maximum_category_depth": 4, + "maximum_tags_per_document": 12, + "cross_platform_invalid_name_rejection": true, + "optimistic_content_hash_lock": true + }, "folder_import": { "maximum_files": 1000, "maximum_file_bytes": 10485760, @@ -57,6 +78,9 @@ "deduplication_runtime_tested": true, "idempotent_import_runtime_tested": true, "native_edit_runtime_tested": true, + "organization_runtime_tested": true, + "organization_human_surface_integrated": true, + "organized_page_archive_runtime_tested": true, "server_deployment": false } } diff --git a/product-source/hololake-native-desktop/contracts/language-world-public-routing.json b/product-source/hololake-native-desktop/contracts/language-world-public-routing.json new file mode 100644 index 000000000..770bb94f1 --- /dev/null +++ b/product-source/hololake-native-desktop/contracts/language-world-public-routing.json @@ -0,0 +1,40 @@ +{ + "schema": "HOLOLAKE_LANGUAGE_WORLD_PUBLIC_ROUTING/1", + "state": "IMPLEMENTED_LOCAL_ACCEPTANCE_PENDING", + "user_channel_sovereignty": { + "ordinary_user_belongs_to_official_domain": false, + "home_entry": "PERSONAL_CHANNEL", + "public_world_is_browsable": true, + "channel_diy_allowed_under_world_rules": true + }, + "official_domains": { + "MAIN_DOMAIN": { + "visibility": "PUBLIC_SERVICE", + "purpose": ["ANNOUNCEMENTS", "VERSION_UPDATES", "RULE_NOTICES"] + }, + "BRANCH_DOMAIN": { + "visibility": "PUBLIC_SERVICE", + "purpose": ["INDUSTRY_INITIAL_CHANNEL_TEMPLATES", "MODULE_MARKETPLACE", "PERSONA_BRAIN_SKILL_MARKETPLACE"], + "supply_chains": ["EXECUTABLE_MODULES", "PERSONA_BRAINS_AND_SKILL_PACKAGES"] + }, + "ZERO_DOMAIN": { + "visibility": "PUBLIC_OBSERVATION_BOUNDED", + "purpose": ["HOT_UPDATE_EXPERIMENTS", "SYSTEM_EXPERIMENTS", "ARCHITECTURE_EXPERIMENTS", "LANGUAGE_REASONING_SIMULATION"] + }, + "ZERO_SENSE_DOMAIN": { + "visibility": "PRIVATE_HUMAN_CONTROL_TEAM_ONLY", + "purpose": ["APPROVAL", "EXECUTION", "OVERSIGHT_OF_FIRST_THREE_DOMAINS"] + }, + "FIFTH_DOMAIN": { + "visibility": "PRIVATE_ICE_SHUO_AUTHORIZATION_ONLY", + "owner": "ICE-GL∞", + "official_template_required": false, + "can_pull_resources_from": ["MAIN_DOMAIN", "BRANCH_DOMAIN", "ZERO_DOMAIN"], + "reverse_entry_without_owner_permission": false + } + }, + "shared_channel_collective": { + "supported_as_future_optional_pattern": true, + "formal_product_name": "UNDECIDED_DO_NOT_INVENT" + } +} diff --git a/product-source/hololake-native-desktop/contracts/local-development-bridge.json b/product-source/hololake-native-desktop/contracts/local-development-bridge.json index c0390f573..cbc2229ca 100644 --- a/product-source/hololake-native-desktop/contracts/local-development-bridge.json +++ b/product-source/hololake-native-desktop/contracts/local-development-bridge.json @@ -115,9 +115,6 @@ "cross_platform_local_transport_runtime": true, "authenticated_heartbeat_runtime": true, "hololake_work_environment_frame_runtime": true, - "persona_to_host_runtime_license_verifier": true, - "persona_runtime_trusted_signer_provisioned": false, - "persona_mode_expiry_and_scope_fail_closed": true, "model_protocol_context_restore_required": false, "external_local_broker_runtime": true, "authenticated_broker_development_lane_runtime": true, diff --git a/product-source/hololake-native-desktop/contracts/mobile-sync-v1.json b/product-source/hololake-native-desktop/contracts/mobile-sync-v1.json deleted file mode 100644 index 0336ffff1..000000000 --- a/product-source/hololake-native-desktop/contracts/mobile-sync-v1.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "schema": "hololake.mobile-sync.contract/v1", - "record_id": "HLP-MOBILE-SYNC-001", - "state": "HOLOLAKE_0_5_NUMBERED_DESKTOP_BRIDGE_ACCEPTED", - "package": { - "official_module_number": "HLP-MOD-OFFICIAL-MOBILE-SYNC-0001", - "adapter": "mobile-sync-v1", - "registration_class": "OFFICIAL_LIGHTHOUSE", - "activation": "SIGNED_PACKAGE_PLUS_EXPLICIT_HUMAN_PERMISSION_CONFIRMATION", - "listener_after_activation": "EXPLICIT_HUMAN_ACTION_ONLY" - }, - "numbered_ipc": { - "module": "HLP-NIPC-MOD-0030", - "target": "HLP-NIPC-TGT-0030", - "operations": "HLP-NIPC-OP-0141..HLP-NIPC-OP-0146", - "public_tauri_commands": ["numbered_ipc"], - "mismatched_coordinate": "FAIL_CLOSED" - }, - "desktop_role": "USER_LOCAL_COMPUTER_TERMINAL_ROOT_NODE", - "mobile_role": "REMOTE_BODY_ENTRY_OF_THE_SAME_PERSONA_SYSTEM", - "transport": { - "implemented": "SAME_LAN_DIRECT_HTTP_WITH_APPLICATION_LAYER_ENCRYPTION", - "port_preference": 37421, - "remote_internet_direct": "NOT_IMPLEMENTED", - "encrypted_relay": "NOT_IMPLEMENTED", - "maximum_request_bytes": 262144, - "maximum_concurrent_connections": 16, - "duplicate_http_header": "REJECT" - }, - "pairing": { - "uri_scheme": "hololake://pair", - "secret_bits": 256, - "ttl_seconds": 600, - "single_use": true, - "payload_aead": "CHACHA20_POLY1305", - "aad": "hololake.mobile.pair/v1" - }, - "session": { - "key_bits": 256, - "aead": "CHACHA20_POLY1305", - "replay_guard": "STRICTLY_INCREASING_PER_DEVICE_COUNTER", - "device_revocation": true, - "desktop_key_storage": "ACCOUNT_SCOPED_SQLITE", - "ios_key_storage": "KEYCHAIN_THIS_DEVICE_ONLY" - }, - "routes": { - "GET /v1/status": "NO_PRIVATE_PAYLOAD", - "POST /v1/pair": "ONE_TIME_PAIRING_SECRET_REQUIRED", - "POST /v1/sync": "PAIRED_DEVICE_AEAD_AND_COUNTER_REQUIRED" - }, - "projection": { - "personal_channel": "MINIMUM_COUNTS_AND_INTEGRITY", - "web_novel": "WORK_LIST_AND_COUNTS", - "education": "COUNTS_ONLY_NO_SENSITIVE_CELL_VALUES", - "mobile_capture": "BOUNDED_INBOX_WRITE_ONLY_NO_AUTOMATIC_DOMAIN_MUTATION" - }, - "hard_boundaries": { - "remote_desktop_clone": false, - "second_persona_system": false, - "platform_private_payload_custody": false, - "desktop_offline_execution": false, - "mobile_capture_mutates_persona_or_industry_data": false, - "module_unmount_stops_listener_before_lifecycle_transition": true, - "background_frontend_polling": false - }, - "client_scope": { - "desktop_bridge": "IN_THIS_ADMISSION", - "ios_application_source": "SEPARATELY_ADMITTED_AT_MOBILE_IOS_WITH_HLP_IOS_CLIENT_001", - "ios_installable_package": "DEVELOPMENT_SIGNED_DEBUGGING_IPA_EXPORTED", - "claim_real_iphone_end_to_end_accepted": false - }, - "current_acceptance": { - "state": "PASS_DESKTOP_BRIDGE_AND_SEPARATELY_ADMITTED_IOS_CLIENT_ARTIFACT", - "module_package_sha256": "61a9d402c936d7477609bcfa6eb4ad6e83cb6c089ba51b3db09a2d6259185924", - "module_package_signature": "PASS_EMBEDDED_PRODUCT_TRUST", - "signed_app_binary_sha256": "9be06d6c5dbd4f46f6f925142d633f12b42ee553873c2342f9804bcf39dde7b4", - "signed_app_cdhash": "c595cb2a7729d49638faa78f76e145ee9b1da05a", - "apple_team_identifier": "825A9L3G7Q", - "module_receipts": { - "install": "a09496ec6113254f77ea2425d0bd30571e9e0e3df62bfa18e500f860c2f65d4d", - "mount": "5b162ee807c8b4d9c8aa8d9cb590c64587f51067dc0804030bf57ed0753ac25a", - "self_test_pass": "e66ee868e28a25fcd70cc888845661b5044d18a6e18b70cee6e4839b02fe1c53" - }, - "desktop_listener": "PASS_EXPLICIT_START_REACHABLE_STATUS_AND_EXPLICIT_STOP", - "restart_restore": "PASS_ACTIVE_MODULE_RESTORED_LISTENER_OFFLINE", - "legacy_account_readback": "PASS_ONE_PAIRED_DEVICE_ONE_ISOLATED_CAPTURE_RETAINED", - "ios_client_contract": "contracts/ios-mobile-client-v1.json", - "ios_client_source_build_and_simulator": "PASS", - "ios_development_signed_ipa": "PASS_SHA256_a6b505e1a7dc10febd831a540396bb9530f78bb2429d258962f0250e5597b1f0", - "live_iphone_pairing_this_cycle": "NOT_CLAIMED_NO_PHYSICAL_DEVICE_USED", - "notarization": "FINAL_RELEASE_CANDIDATE_PENDING" - } -} diff --git a/product-source/hololake-native-desktop/contracts/module-donor-admission-registry.json b/product-source/hololake-native-desktop/contracts/module-donor-admission-registry.json deleted file mode 100644 index 0db17c74e..000000000 --- a/product-source/hololake-native-desktop/contracts/module-donor-admission-registry.json +++ /dev/null @@ -1,240 +0,0 @@ -{ - "schema": "hololake.module-donor-admission-registry/v1", - "record_id": "HLP-MODULE-DONOR-ADMISSION-001", - "state": "EIGHT_CANDIDATES_ADMITTED_DONOR_SOURCES_REMAIN_READ_ONLY", - "root_rule": { - "official_base": "HOLOLAKE_0.5.0_NUMBERED_IPC_ROOT", - "repair_old_application_in_place": false, - "bulk_merge_or_wholesale_copy_allowed": false, - "one_candidate_per_admission_cycle": true, - "candidate_number_is_runtime_module_number": false, - "permanent_module_number_assignment_before_acceptance": false, - "all_frontend_backend_calls_must_cross_numbered_ipc": true, - "shared_file_merge_is_admission_evidence": false - }, - "donors": [ - { - "donor_id": "HLP-DONOR-COMPILED-DESKTOP-0.4.1", - "kind": "COMPILED_MACOS_APPLICATION", - "path": "/Volumes/JZAO/HoloLake/artifacts/hololake-release/0.4.1/macos-arm64/pre-numbered-root-donor/HoloLake.app", - "state": "READ_ONLY", - "source_commit": null, - "source_commit_state": "UNKNOWN_NOT_INFERRED_FROM_COMPILED_BUNDLE", - "binary_sha256": "adc0d8b028a8b874c39909265ed7c41e7c24e4fe5b38adba04e8f72b64900c15", - "use": "BEHAVIOR_AND_VISIBLE_PRODUCT_REFERENCE_ONLY" - }, - { - "donor_id": "HLP-DONOR-CHAOTIC-WORKTREE-20260818", - "kind": "DIRTY_SOURCE_WORKTREE", - "path": "/Users/bingshuolingdianyuanhe/Documents/Codex/2026-08-15/new-chat-2/work/jd-guanghu-supervisor/product-source/hololake-native-desktop", - "observed_head": "a8fe571b5d5c0a45207b64ac538d729b3d719d21", - "observed_dirty_path_count": 30, - "state": "READ_ONLY_UNTRUSTED_AS_A_WHOLE", - "use": "INDIVIDUAL_MODULE_SOURCE_CANDIDATES_ONLY" - } - ], - "rejected_inputs": [ - { - "candidate_number": "HLP-DONOR-CAND-0000", - "name": "legacy_numbered_operation_runtime", - "state": "REJECTED_SUPERSEDED", - "why": "It predates the single numbered IPC root and must not become a second numbering authority.", - "paths": [ - "contracts/numbered-operation-runtime.json", - "src/modules/numbered-runtime.ts", - "src-tauri/src/numbered_operation_runtime.rs" - ] - }, - { - "candidate_number": "HLP-DONOR-CAND-SHARED-MUTATIONS", - "name": "shared_file_mutation_set", - "state": "REJECTED_AS_MERGE_UNIT", - "why": "These files mix unrelated modules and divergent frontend/backend routes; each needed behavior must be reconstructed behind its owning numbered module.", - "examples": [ - "src/main.tsx", - "src/styles.css", - "src-tauri/src/lib.rs", - "src-tauri/src/knowledge_base.rs", - "src-tauri/src/gls_protocol_runtime.rs" - ] - } - ], - "candidates": [ - { - "admission_order": 1, - "candidate_number": "HLP-DONOR-CAND-0001", - "name": "native_composition_module_runtime", - "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", - "paths": [ - "contracts/native-composition-runtime.json", - "src/modules/native-composition", - "src-tauri/src/native_composition.rs", - "src/styles.css#native-composition-selectors-only" - ], - "style_dependency_discovered_during_admission": "Only selectors prefixed native-composition or composition- were isolated into the module directory; unrelated global donor CSS remains prohibited.", - "runtime_module_number": "HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001", - "numbered_ipc_module": "HLP-NIPC-MOD-0021", - "acceptance_evidence": "contracts/native-composition-runtime.json#current_acceptance", - "why_first": "A module needs an isolated mount, self-test, unmount and rollback boundary before content modules can be admitted safely." - }, - { - "admission_order": 2, - "candidate_number": "HLP-DONOR-CAND-0002", - "name": "channel_document_and_spreadsheet_workbench", - "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", - "paths": [ - "src/modules/channel-workbench", - "src-tauri/src/channel_workbench.rs", - "src/styles.css#education-engine-and-channel-spreadsheet-selectors-only" - ], - "style_dependency_discovered_during_admission": "Only the document-engine and channel-spreadsheet selector behavior was isolated into the module directory; unrelated education and global donor CSS remains prohibited.", - "runtime_module_number": "HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001", - "numbered_ipc_module": "HLP-NIPC-MOD-0022", - "acceptance_evidence": "contracts/channel-workbench-runtime.json#current_acceptance", - "boundary": "ACCOUNT_LOCAL_DOCUMENT_AND_SPREADSHEET_DATA; DOES_NOT_OWN_PERSONA_CHANNEL_BODY" - }, - { - "admission_order": 3, - "candidate_number": "HLP-DONOR-CAND-0003", - "name": "persona_channel_body", - "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", - "paths": [ - "contracts/persona-channel-body.json", - "src/modules/persona-channel-body", - "src-tauri/src/persona_channel_body.rs", - "src-tauri/src/channel_growth.rs" - ], - "style_dependency_discovered_during_admission": "Only persona-body selectors were isolated into the module directory; no donor global stylesheet or unrelated feature selectors were admitted.", - "runtime_module_number": "HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001", - "numbered_ipc_module": "HLP-NIPC-MOD-0023", - "acceptance_evidence": "contracts/persona-channel-body.json#current_acceptance", - "boundary": "UI_AND_PERSISTENCE_BODY_ONLY; DOES_NOT_CREATE_PERSONA_BINDING; DOES_NOT_ALLOW_HOST_TO_ISSUE_PERSONA_LICENSE" - }, - { - "admission_order": 4, - "candidate_number": "HLP-DONOR-CAND-0004", - "name": "education_workbench", - "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", - "paths": [ - "contracts/education-workspace.json", - "src/modules/education-workspace", - "src-tauri/src/education_translation.rs", - "src-tauri/src/education_workspace.rs" - ], - "runtime_module_number": "HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001", - "numbered_ipc_module": "HLP-NIPC-MOD-0024", - "acceptance_evidence": "contracts/education-workspace.json#current_acceptance", - "boundary": "CURRENT_ACCOUNT_LOCAL; IMPORTS_DEFAULT_UNASSIGNED; CLEANUP_AND_AUTOMATION_REQUIRE_EXPLICIT_HUMAN_CONFIRMATION; MODEL_FILE_TRANSFER_DEFAULT_DENY" - }, - { - "admission_order": 5, - "candidate_number": "HLP-DONOR-CAND-0005", - "name": "web_novel_workbench_and_author_modules", - "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", - "paths": [ - "contracts/web-novel-workspace.json", - "contracts/web-novel-module-marketplace-plan.json", - "src/modules/web-novel/WebNovelWorkspace.tsx", - "src/modules/web-novel/AuthorModuleCenter.tsx", - "src/modules/web-novel/AuthorWritingSidecar.tsx", - "src-tauri/src/web_novel_workspace.rs", - "src-tauri/src/web_novel_import.rs", - "src-tauri/src/web_novel_author.rs", - "src-tauri/src/web_novel_modules.rs" - ], - "runtime_module_numbers": ["HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001"], - "numbered_ipc_modules": ["HLP-NIPC-MOD-0025", "HLP-NIPC-MOD-0026", "HLP-NIPC-MOD-0027", "HLP-NIPC-MOD-0028", "HLP-NIPC-MOD-0029"], - "acceptance_evidence": "contracts/web-novel-workspace.json#current_acceptance", - "boundary": "CURRENT_ACCOUNT_LOCAL; ONE_STORY_GRAPH; ADVANCED_EFFECTS_REQUIRE_EXACT_ACTIVE_MODULE_NUMBER; THIRD_PARTY_AUTO_LOGIN_AND_PUBLISH_DENIED" - }, - { - "admission_order": 6, - "candidate_number": "HLP-DONOR-CAND-0006", - "name": "mobile_sync", - "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", - "paths": [ - "contracts/mobile-sync-v1.json", - "src/MobileSyncPanel.tsx", - "src-tauri/src/mobile_sync.rs" - ], - "runtime_module_number": "HLP-MOD-OFFICIAL-MOBILE-SYNC-0001", - "numbered_ipc_module": "HLP-NIPC-MOD-0030", - "acceptance_evidence": "contracts/mobile-sync-v1.json#current_acceptance", - "boundary": "DESKTOP_ROOT_NODE_SAME_LAN_BRIDGE_ONLY; EXPLICIT_LISTENER; IOS CLIENT REQUIRES SEPARATE NUMBERED ADMISSION; NO_SECOND_PERSONA_SYSTEM" - }, - { - "admission_order": 7, - "candidate_number": "HLP-DONOR-CAND-0007", - "name": "dynamic_language_world_visual_surface", - "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", - "paths": [ - "contracts/dynamic-language-world-visual-system.json", - "src/modules/qoder-surface/StarlakeSurface.tsx", - "src/modules/qoder-surface/starlake-surface.css", - "src/modules/qoder-surface/TraditionalSurface.tsx", - "src/modules/qoder-surface/traditional-surface.css", - "src/modules/qoder-surface/visual-balance.ts", - "src-tauri/src/world_climate.rs" - ], - "runtime_module_number": "HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001", - "numbered_ipc_module": "HLP-NIPC-MOD-0031", - "acceptance_evidence": "contracts/dynamic-language-world-visual-system.json#current_acceptance", - "boundary": "QODER_LOCKED_VISUAL_SOURCE_PLUS_REALITY_TIME_AND_PUBLIC_WEATHER_PROJECTION; ALL_FUNCTION_ROUTES_REMAIN_NUMBERED; IDLE_STATIC; NO_FAKE_WEATHER_BROADCAST_OR_METRICS" - }, - { - "admission_order": 8, - "candidate_number": "HLP-DONOR-CAND-0008", - "name": "ios_numbered_remote_body_entry", - "state": "ADMITTED_SOURCE_SIMULATOR_AND_DEVELOPMENT_SIGNED_IPA_ACCEPTED", - "paths": [ - "contracts/ios-mobile-client-v1.json", - "mobile/ios/project.yml", - "mobile/ios/Sources", - "mobile/ios/Tests" - ], - "client_number": "HLP-IOS-CLIENT-001", - "desktop_runtime_module_number": "HLP-MOD-OFFICIAL-MOBILE-SYNC-0001", - "numbered_ipc_module": "HLP-NIPC-MOD-0030", - "acceptance_evidence": "contracts/ios-mobile-client-v1.json#acceptance", - "boundary": "IPHONE IS A THIN REMOTE BODY ENTRY; DESKTOP REMAINS ROOT NODE; SAME LAN EXPLICIT PAIR AND MANUAL SYNC ONLY; NO SECOND PERSONA SYSTEM; REAL IPHONE END TO END NOT CLAIMED" - } - ], - "admission_gate": [ - "EXTRACT_ONLY_DECLARED_CANDIDATE_PATHS", - "REVIEW_SOURCE_PROVENANCE_AND_LICENSE", - "DEFINE_DATA_PERMISSION_AND_RESOURCE_BOUNDARY", - "ALLOCATE_NUMBERED_IPC_MODULE_TARGET_AND_OPERATION_COORDINATES", - "IMPLEMENT_ADAPTER_WITHOUT_RAW_TAURI_INVOKE", - "ADD_UNIT_INTEGRATION_AND_NEGATIVE_ROUTE_TESTS", - "BUILD_FROM_CLEAN_OFFICIAL_BASE", - "INSTALL_IN_ISOLATED_RUNTIME", - "VERIFY_MOUNT_SELF_TEST_RESTART_UNMOUNT_AND_ROLLBACK", - "WRITE_HASH_CHAINED_RUNTIME_RECEIPT", - "ONLY_THEN_ASSIGN_PERMANENT_MODULE_NUMBER" - ], - "hot_install_boundary": { - "runtime_state": "SIGNED_DECLARATIVE_PACKAGE_ENGINE_IMPLEMENTED", - "runtime_contract": "contracts/module-package-runtime.json", - "numbered_module_runtime_operations": [ - "HLP-NIPC-OP-0063", - "HLP-NIPC-OP-0064", - "HLP-NIPC-OP-0065", - "HLP-NIPC-OP-0066", - "HLP-NIPC-OP-0067", - "HLP-NIPC-OP-0068", - "HLP-NIPC-OP-0069", - "HLP-NIPC-OP-0070", - "HLP-NIPC-OP-0071" - ], - "source_repository_is_directly_executable": false, - "immutable_signed_artifact_required": true, - "compatibility_manifest_required": true, - "permissions_declared_before_mount": true, - "human_confirmation_required_when_boundary_expands": true, - "rollback_on_self_test_failure": true, - "user_data_survives_unmount": true, - "arbitrary_native_code_allowed": false, - "arbitrary_webview_javascript_allowed": false, - "real_signed_acceptance_fixture": "fixtures/module-packages/HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001-0.1.0.ghmod" - } -} diff --git a/product-source/hololake-native-desktop/contracts/module-package-runtime.json b/product-source/hololake-native-desktop/contracts/module-package-runtime.json deleted file mode 100644 index a00528451..000000000 --- a/product-source/hololake-native-desktop/contracts/module-package-runtime.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "schema": "hololake.module-package-runtime/v1", - "record_id": "HLP-MODULE-PACKAGE-RUNTIME-001", - "protocols": ["GLS-0710", "GLS-0803", "GLS-0819", "GLS-0310"], - "package_schema": "hololake.module-package/v1", - "signature": { - "algorithm": "MINISIGN_ED25519", - "trust_source": "src-tauri/release-trust.json", - "signature_is_detached": true, - "package_bytes_are_signed_exactly": true, - "source_repository_is_executable": false - }, - "number_classes": { - "official": "HLP-MOD-OFFICIAL-*", - "private_channel": "HLP-MOD-LOCAL-*", - "candidate_number_is_runtime_number": false - }, - "host": { - "version": "0.5.0", - "maximum_package_bytes": 16777216, - "arbitrary_native_code": false, - "arbitrary_webview_javascript": false, - "declarative_payload_only": true - }, - "registered_adapters": [ - "native-composition-v1", - "channel-workbench-v1", - "persona-channel-body-v1", - "education-workbench-v1", - "web-novel-workbench-v1", - "mobile-sync-v1", - "dynamic-language-world-surface-v1" - ], - "lifecycle": [ - "INSTALLED_DORMANT", - "MOUNTED_PENDING_SELF_TEST", - "ACTIVE", - "DORMANT", - "ROLLBACK_PENDING_SELF_TEST", - "FAILED_CLOSED" - ], - "rules": { - "verified_human_route_required": true, - "permission_expansion_requires_human_confirmation": true, - "mount_never_executes_package_code": true, - "self_test_before_active": true, - "failed_self_test_rolls_back": true, - "restart_reconstructs_from_sqlite": true, - "unmount_preserves_user_data": true, - "every_mutation_writes_hash_chained_receipt": true - } -} diff --git a/product-source/hololake-native-desktop/contracts/native-composition-runtime.json b/product-source/hololake-native-desktop/contracts/native-composition-runtime.json index b1070a551..be9c2297b 100644 --- a/product-source/hololake-native-desktop/contracts/native-composition-runtime.json +++ b/product-source/hololake-native-desktop/contracts/native-composition-runtime.json @@ -1,15 +1,8 @@ { "schema": "hololake.native-composition-runtime/v1", "record_id": "HLP-NATIVE-COMPOSITION-001", - "candidate_number": "HLP-DONOR-CAND-0001", - "runtime_module_number": "HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001", - "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", - "provenance": { - "donor": "0.4.1 read-only candidate paths", - "donor_contract_state": "INSTALLED_RUNTIME_ACCEPTED", - "donor_apple_notarization": "NOT_PERFORMED_MISSING_CREDENTIALS", - "current_mainline_reuses_bulk_source": false - }, + "state": "INSTALLED_RUNTIME_ACCEPTED", + "intent_source": "docs/adr/0008-native-composition-and-human-projection.md", "internal_object": { "schema": "hololake.native-object/v1", "encoding": "BOUNDED_JSON", @@ -25,7 +18,7 @@ "registered_kinds": ["SOURCE", "TRANSFORM", "PROJECTION"], "typed_ports_required": true, "determinism_declared": true, - "authority": "CURRENT_AUTHENTICATED_ACCOUNT_READ_ONLY" + "authority_declared": true }, "recipe": { "schema": "hololake.composition-recipe/v1", @@ -35,32 +28,38 @@ "native_validation_required": true }, "human_projection": { + "schema": "hololake.human-projection/v1", "views": ["DASHBOARD", "COMPARISON", "VERTICAL_BAR", "CLASSIFICATION", "TABLE"], "shares_one_execution_result": true, "owns_source_data": false, "direct_write_authority": false }, - "admission": { - "signed_package_required": true, - "adapter": "native-composition-v1", - "numbered_routes_required": true, - "active_module_required_before_execution": true, - "installed_runtime_acceptance_required": true, - "hardcoded_sample_may_satisfy_acceptance": false + "education_stage_one": { + "channel_id": "GH-EDU-INIT-001", + "module_id": "EDU-COMPOSITION", + "source": "CURRENT_AUTHENTICATED_ACCOUNTS_REAL_KNOWLEDGE_CATALOG", + "selectable_dimensions": ["SOURCE", "TOP_LEVEL_FOLDER"], + "selectable_measures": ["DOCUMENT_COUNT", "TOTAL_BYTES", "DUPLICATE_COUNT"], + "hardcoded_sample_may_satisfy_acceptance": false, + "installed_runtime_acceptance_required": true }, - "current_acceptance": { - "observed_at": "2026-08-19T01:49:35+08:00", - "signed_debug_binary_sha256": "0bff08787950b69ef0a1565fc32a7537dae53da184c4a1a4fb30ca62eca9f48c", - "developer_id_team": "825A9L3G7Q", - "module_package_sha256": "dfb343019810f8f845ab415259be2eccbe63d88a03bf26a277950610edb64329", - "account_number_observed": "ICE-GL∞", + "write_boundary": { + "stage_one": "READ_ONLY", + "future_write_requires": ["CAPABILITY", "PREVIEW", "HUMAN_CONFIRMATION", "REVISION_LOCK", "RECEIPT"] + }, + "acceptance": { + "observed_at": "2026-08-18T01:49:06+08:00", + "installed_binary_sha256": "2a26acae4a706c0ff9919b85f77826a6ca71b650ec22209befd30cd1456c92f3", + "route": "MAIN_WORLD_TO_BRANCH_DOMAIN_TO_EDUCATION_TO_NATIVE_COMPOSITION", "real_native_rows": 129, "real_native_total_bytes_display": "1.0 MB", "real_groups": 14, - "measure_switch_observed": "DOCUMENT_COUNT_TO_TOTAL_BYTES", - "install_receipts": ["INSTALL", "MOUNT", "SELF_TEST_PASS"], - "restart_recovery": "ACTIVE_AND_REEXECUTED", - "execution_receipt_prefixes": ["0449582510a5", "092febd75c38"], - "apple_notarization": "FINAL_RELEASE_PENDING_ALL_MODULES" + "all_five_views_observed": true, + "three_view_recomposition_observed": true, + "measure_switch_observed": "DOCUMENT_COUNT_TO_TOTAL_BYTES_AND_BACK", + "projection_bound_to_execution_receipt": true, + "developer_id_signature": "VALID", + "apple_notarization": "NOT_PERFORMED_MISSING_CREDENTIALS", + "public_release": "NOT_PUBLISHED" } } diff --git a/product-source/hololake-native-desktop/contracts/nearby-ai-discovery.json b/product-source/hololake-native-desktop/contracts/nearby-ai-discovery.json index 97bf075bf..fba038cea 100644 --- a/product-source/hololake-native-desktop/contracts/nearby-ai-discovery.json +++ b/product-source/hololake-native-desktop/contracts/nearby-ai-discovery.json @@ -11,7 +11,7 @@ "linux": "USER_PRIVATE_UNIX_SOCKET", "windows": "USER_PRIVATE_NAMED_PIPE" }, - "terminal_link_protocol": "HOLOLAKE_TERMINAL_LINK/3", + "terminal_link_protocol": "HOLOLAKE_TERMINAL_LINK/2", "copy_large_invitation_required": false, "network_required": false }, diff --git a/product-source/hololake-native-desktop/contracts/numbered-ipc-registry.json b/product-source/hololake-native-desktop/contracts/numbered-ipc-registry.json deleted file mode 100644 index 90233331f..000000000 --- a/product-source/hololake-native-desktop/contracts/numbered-ipc-registry.json +++ /dev/null @@ -1,2002 +0,0 @@ -{ - "schema": "hololake.numbered-ipc-registry/v1", - "record_id": "HLP-NUMBERED-IPC-ROOT-001", - "source": { - "baseline_commit": "7a14c06e41587c4c5a08a43bb4f5a172fa61b7fa", - "gls_runtime_manifest": "HLP-GLS-RUNTIME-MANIFEST-002", - "gls_native_kernel": "HLP-GLS-NATIVE-RUNTIME-KERNEL-001", - "numbering_authority_map": "GH-IDENTITY-AUTHORITY-MAP-001", - "human_language_anchor": "source://codex-current-dialogue/2026-08-18/bingshuo-number-is-path-and-mismatched-routes-are-unrecognizable" - }, - "runtime": { - "public_tauri_command": "numbered_ipc", - "caller_number": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "caller_number_subject_kind": "PHYSICAL_WEBVIEW_ENTRY_NOT_PERSONA_IDENTITY", - "caller_number_grants_persona_binding": false, - "protocol_version": "HLP-NIPC-v1", - "legacy_direct_commands_allowed": false, - "grants_issued_server_side": true, - "grant_single_use": true, - "payload_bound_grants": true, - "authority_binding_issued_server_side": true, - "verified_human_binding_required_for_protected_routes": true, - "persona_binding_claimed": false, - "user_channel_body_binding_stage": "SEPARATE_EVIDENCE_LAYER_NOT_YET_CLAIMED", - "maximum_grant_ttl_ms": 30000, - "unknown_route": "FAIL_CLOSED", - "mismatched_coordinate": "FAIL_CLOSED", - "expired_or_replayed_grant": "FAIL_CLOSED", - "receipt_required": true - }, - "payload_contract": { - "unknown_or_unclassified_alias": "FAIL_CLOSED_BEFORE_GRANT", - "unknown_top_level_field": "FAIL_CLOSED_BEFORE_GRANT", - "empty_object_aliases": [ - "get_hololake_home_status", - "check_hololake_update", - "get_hololake_release_recovery_status", - "confirm_hololake_release_health", - "rollback_hololake_update", - "get_nearby_ai_discovery", - "get_gls_protocol_runtime", - "get_gls_protocol_kernel", - "get_personal_channel_snapshot", - "start_persona_time_authority", - "get_beijing_time_coordinate", - "get_guanghu_era_timeline", - "get_knowledge_snapshot", - "select_and_import_knowledge_folder", - "print_knowledge_document", - "get_code_channel_snapshot", - "select_local_code_channel", - "select_pncc_repository_candidate", - "query_jd_pncc_server_projection", - "check_code_repo_login", - "get_enterprise_entry", - "ensure_enterprise_work_channel", - "sign_out_code_repo_login", - "get_user_pncc_channel", - "ensure_user_pncc_channel", - "get_zero_core_numbering_kernel", - "zero_point_verify", - "zero_point_sync", - "zero_point_status", - "get_module_runtime_snapshot", - "get_bundled_module_catalog", - "get_native_composition_module_registry", - "get_channel_workbench_snapshot", - "get_persona_channel_body", - "get_channel_growth_snapshot", - "get_education_workspace_snapshot", - "import_education_tables_from_dialog", - "get_education_recognition_capability", - "get_web_novel_workspace_snapshot", - "inspect_web_novel_document_from_dialog", - "start_mobile_sync", - "get_mobile_sync_status", - "rotate_mobile_pairing", - "stop_mobile_sync", - "get_mobile_sync_snapshot", - "get_world_climate" - ], - "input_wrapper_aliases": [ - "confirm_hololake_update_install", - "issue_direct_local_discovery_ticket", - "open_direct_local_session", - "resume_direct_local_session", - "append_direct_local_session_event", - "heartbeat_direct_local_session", - "decide_gls_protocol", - "compile_gls_hldp_program", - "acquire_development_write_lane", - "inspect_development_write_lane", - "release_development_write_lane", - "initialize_personal_channel", - "create_personal_channel_task", - "transition_personal_channel_task", - "issue_persona_time_ticket", - "read_knowledge_document", - "search_knowledge", - "save_knowledge_document", - "export_knowledge_document", - "create_knowledge_document", - "delete_knowledge_document", - "delete_knowledge_folder", - "clone_code_channel", - "browse_code_channel", - "read_code_channel_file", - "inspect_mounted_pncc_repository", - "confirm_pncc_repository_mount", - "query_pncc_receipt_projection", - "zero_point_bind", - "verify_module_package", - "install_module_package", - "mount_module", - "self_test_module", - "unmount_module", - "rollback_module", - "activate_bundled_module", - "execute_knowledge_native_composition", - "save_channel_document", - "save_channel_spreadsheet", - "register_trial_persona", - "delete_trial_persona", - "accept_persona_language_contract", - "append_persona_language", - "record_channel_growth_event", - "update_channel_growth_sharing", - "create_education_document", - "read_education_document", - "save_education_document", - "archive_education_document", - "create_education_table", - "read_education_table", - "save_education_table", - "archive_education_table", - "assign_imported_table_to_education", - "export_education_table_to_dialog", - "create_education_automation_rule", - "save_education_automation_rule", - "archive_education_automation_rule", - "preview_education_automation_rule", - "execute_education_automation_rule", - "create_web_novel_work", - "read_web_novel_work", - "save_web_novel_work", - "create_web_novel_volume", - "create_web_novel_chapter", - "read_web_novel_chapter", - "save_web_novel_chapter", - "transition_web_novel_chapter", - "create_web_novel_checkpoint", - "restore_web_novel_checkpoint", - "upsert_web_novel_story_entity", - "create_web_novel_story_relation", - "upsert_web_novel_foreshadow", - "create_web_novel_review_note", - "resolve_web_novel_review_note", - "save_web_novel_metric", - "run_web_novel_continuity_audit", - "export_web_novel_markdown", - "commit_web_novel_document_import", - "get_web_novel_author_snapshot", - "record_web_novel_writing_activity", - "create_web_novel_inspiration", - "set_web_novel_inspiration_status", - "search_web_novel_full_text", - "format_web_novel_chapter", - "format_web_novel_work", - "upsert_web_novel_shot", - "get_web_novel_author_module_data", - "upsert_web_novel_author_scene", - "upsert_web_novel_author_beat", - "upsert_web_novel_story_field_definition", - "upsert_web_novel_story_field_value", - "upsert_web_novel_timeline_event", - "link_web_novel_scene_entity", - "restore_web_novel_chapter_version", - "export_web_novel_author_delivery", - "revoke_mobile_sync_device" - ], - "direct_field_aliases": { - "perform_code_repo_login": [ - "username", - "password" - ], - "change_first_login_password": [ - "username", - "currentPassword", - "newPassword" - ], - "confirm_enterprise_persona_relationship": [ - "decision", - "idempotencyKey" - ], - "submit_enterprise_responsibility_receipt": [ - "decision", - "note", - "responsibilityVersion", - "idempotencyKey" - ] - } - }, - "channels": [ - { - "id": "HLP-NIPC-CH-0001" - }, - { - "id": "HLP-NIPC-CH-0003" - }, - { - "id": "HLP-NIPC-CH-0004" - }, - { - "id": "HLP-NIPC-CH-0002" - }, - { - "id": "HLP-NIPC-CH-0005" - }, - { - "id": "HLP-NIPC-CH-0006" - }, - { - "id": "HLP-NIPC-CH-0007" - } - ], - "modules": [ - { - "module_number": "HLP-NIPC-MOD-0001", - "target_number": "HLP-NIPC-TGT-0001", - "internal_name": "home_status" - }, - { - "module_number": "HLP-NIPC-MOD-0002", - "target_number": "HLP-NIPC-TGT-0002", - "internal_name": "release_update" - }, - { - "module_number": "HLP-NIPC-MOD-0003", - "target_number": "HLP-NIPC-TGT-0003", - "internal_name": "direct_local_session" - }, - { - "module_number": "HLP-NIPC-MOD-0004", - "target_number": "HLP-NIPC-TGT-0004", - "internal_name": "direct_local_broker" - }, - { - "module_number": "HLP-NIPC-MOD-0005", - "target_number": "HLP-NIPC-TGT-0005", - "internal_name": "gls_protocol_runtime" - }, - { - "module_number": "HLP-NIPC-MOD-0006", - "target_number": "HLP-NIPC-TGT-0006", - "internal_name": "gls_protocol_kernel" - }, - { - "module_number": "HLP-NIPC-MOD-0007", - "target_number": "HLP-NIPC-TGT-0007", - "internal_name": "local_development_bridge" - }, - { - "module_number": "HLP-NIPC-MOD-0008", - "target_number": "HLP-NIPC-TGT-0008", - "internal_name": "personal_channel" - }, - { - "module_number": "HLP-NIPC-MOD-0009", - "target_number": "HLP-NIPC-TGT-0009", - "internal_name": "persona_time_authority" - }, - { - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "internal_name": "knowledge_base" - }, - { - "module_number": "HLP-NIPC-MOD-0011", - "target_number": "HLP-NIPC-TGT-0011", - "internal_name": "code_channel" - }, - { - "module_number": "HLP-NIPC-MOD-0012", - "target_number": "HLP-NIPC-TGT-0012", - "internal_name": "pncc_repository_binding" - }, - { - "module_number": "HLP-NIPC-MOD-0013", - "target_number": "HLP-NIPC-TGT-0013", - "internal_name": "pncc_receipt_projection" - }, - { - "module_number": "HLP-NIPC-MOD-0014", - "target_number": "HLP-NIPC-TGT-0014", - "internal_name": "pncc_server_projection" - }, - { - "module_number": "HLP-NIPC-MOD-0015", - "target_number": "HLP-NIPC-TGT-0015", - "internal_name": "code_repo_login" - }, - { - "module_number": "HLP-NIPC-MOD-0016", - "target_number": "HLP-NIPC-TGT-0016", - "internal_name": "enterprise_work_channel" - }, - { - "module_number": "HLP-NIPC-MOD-0017", - "target_number": "HLP-NIPC-TGT-0017", - "internal_name": "user_pncc_channel" - }, - { - "module_number": "HLP-NIPC-MOD-0018", - "target_number": "HLP-NIPC-TGT-0018", - "internal_name": "zero_core_numbering" - }, - { - "module_number": "HLP-NIPC-MOD-0019", - "target_number": "HLP-NIPC-TGT-0019", - "internal_name": "zero_point" - }, - { - "module_number": "HLP-NIPC-MOD-0020", - "target_number": "HLP-NIPC-TGT-0020", - "internal_name": "module_package_runtime" - }, - { - "module_number": "HLP-NIPC-MOD-0021", - "target_number": "HLP-NIPC-TGT-0021", - "internal_name": "native_composition" - }, - { - "module_number": "HLP-NIPC-MOD-0022", - "target_number": "HLP-NIPC-TGT-0022", - "internal_name": "channel_workbench" - }, - { - "module_number": "HLP-NIPC-MOD-0023", - "target_number": "HLP-NIPC-TGT-0023", - "internal_name": "persona_channel_body" - }, - { - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "internal_name": "education_workspace" - }, - { - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "internal_name": "web_novel_workbench" - }, - { - "module_number": "HLP-NIPC-MOD-0026", - "target_number": "HLP-NIPC-TGT-0026", - "internal_name": "web_novel_outline" - }, - { - "module_number": "HLP-NIPC-MOD-0027", - "target_number": "HLP-NIPC-TGT-0027", - "internal_name": "web_novel_story_grid" - }, - { - "module_number": "HLP-NIPC-MOD-0028", - "target_number": "HLP-NIPC-TGT-0028", - "internal_name": "web_novel_storyworld" - }, - { - "module_number": "HLP-NIPC-MOD-0029", - "target_number": "HLP-NIPC-TGT-0029", - "internal_name": "web_novel_delivery" - }, - { - "module_number": "HLP-NIPC-MOD-0030", - "target_number": "HLP-NIPC-TGT-0030", - "internal_name": "mobile_sync" - }, - { - "module_number": "HLP-NIPC-MOD-0031", - "target_number": "HLP-NIPC-TGT-0031", - "internal_name": "world_climate" - } - ], - "operations": [ - { - "operation_number": "HLP-NIPC-OP-0001", - "alias": "get_hololake_home_status", - "handler": "home_status::get_hololake_home_status", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0001", - "target_number": "HLP-NIPC-TGT-0001", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_hololake_home_status/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0002", - "alias": "check_hololake_update", - "handler": "release_update::check_hololake_update", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0002", - "target_number": "HLP-NIPC-TGT-0002", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/check_hololake_update/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0003", - "alias": "confirm_hololake_update_install", - "handler": "release_update::confirm_hololake_update_install", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0002", - "target_number": "HLP-NIPC-TGT-0002", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/confirm_hololake_update_install/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0004", - "alias": "get_hololake_release_recovery_status", - "handler": "release_update::get_hololake_release_recovery_status", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0002", - "target_number": "HLP-NIPC-TGT-0002", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_hololake_release_recovery_status/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0005", - "alias": "confirm_hololake_release_health", - "handler": "release_update::confirm_hololake_release_health", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0002", - "target_number": "HLP-NIPC-TGT-0002", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/confirm_hololake_release_health/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0006", - "alias": "rollback_hololake_update", - "handler": "release_update::rollback_hololake_update", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0002", - "target_number": "HLP-NIPC-TGT-0002", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/rollback_hololake_update/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0007", - "alias": "issue_direct_local_discovery_ticket", - "handler": "direct_local_session::issue_direct_local_discovery_ticket", - "channel_number": "HLP-NIPC-CH-0003", - "module_number": "HLP-NIPC-MOD-0003", - "target_number": "HLP-NIPC-TGT-0003", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/issue_direct_local_discovery_ticket/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0008", - "alias": "open_direct_local_session", - "handler": "direct_local_session::open_direct_local_session", - "channel_number": "HLP-NIPC-CH-0003", - "module_number": "HLP-NIPC-MOD-0003", - "target_number": "HLP-NIPC-TGT-0003", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/open_direct_local_session/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0009", - "alias": "resume_direct_local_session", - "handler": "direct_local_session::resume_direct_local_session", - "channel_number": "HLP-NIPC-CH-0003", - "module_number": "HLP-NIPC-MOD-0003", - "target_number": "HLP-NIPC-TGT-0003", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/resume_direct_local_session/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0010", - "alias": "append_direct_local_session_event", - "handler": "direct_local_session::append_direct_local_session_event", - "channel_number": "HLP-NIPC-CH-0003", - "module_number": "HLP-NIPC-MOD-0003", - "target_number": "HLP-NIPC-TGT-0003", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/append_direct_local_session_event/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0011", - "alias": "heartbeat_direct_local_session", - "handler": "direct_local_session::heartbeat_direct_local_session", - "channel_number": "HLP-NIPC-CH-0003", - "module_number": "HLP-NIPC-MOD-0003", - "target_number": "HLP-NIPC-TGT-0003", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/heartbeat_direct_local_session/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0012", - "alias": "get_nearby_ai_discovery", - "handler": "direct_local_broker::get_nearby_ai_discovery", - "channel_number": "HLP-NIPC-CH-0003", - "module_number": "HLP-NIPC-MOD-0004", - "target_number": "HLP-NIPC-TGT-0004", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_nearby_ai_discovery/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0013", - "alias": "get_gls_protocol_runtime", - "handler": "gls_protocol_runtime::get_gls_protocol_runtime", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0005", - "target_number": "HLP-NIPC-TGT-0005", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_gls_protocol_runtime/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0014", - "alias": "get_gls_protocol_kernel", - "handler": "gls_protocol_kernel::get_gls_protocol_kernel", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0006", - "target_number": "HLP-NIPC-TGT-0006", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_gls_protocol_kernel/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0015", - "alias": "decide_gls_protocol", - "handler": "gls_protocol_kernel::decide_gls_protocol", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0006", - "target_number": "HLP-NIPC-TGT-0006", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/decide_gls_protocol/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0016", - "alias": "compile_gls_hldp_program", - "handler": "gls_protocol_kernel::compile_gls_hldp_program", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0006", - "target_number": "HLP-NIPC-TGT-0006", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/compile_gls_hldp_program/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0017", - "alias": "acquire_development_write_lane", - "handler": "local_development_bridge::acquire_development_write_lane", - "channel_number": "HLP-NIPC-CH-0004", - "module_number": "HLP-NIPC-MOD-0007", - "target_number": "HLP-NIPC-TGT-0007", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/acquire_development_write_lane/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0018", - "alias": "inspect_development_write_lane", - "handler": "local_development_bridge::inspect_development_write_lane", - "channel_number": "HLP-NIPC-CH-0004", - "module_number": "HLP-NIPC-MOD-0007", - "target_number": "HLP-NIPC-TGT-0007", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/inspect_development_write_lane/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0019", - "alias": "release_development_write_lane", - "handler": "local_development_bridge::release_development_write_lane", - "channel_number": "HLP-NIPC-CH-0004", - "module_number": "HLP-NIPC-MOD-0007", - "target_number": "HLP-NIPC-TGT-0007", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/release_development_write_lane/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0020", - "alias": "get_personal_channel_snapshot", - "handler": "personal_channel::get_personal_channel_snapshot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0008", - "target_number": "HLP-NIPC-TGT-0008", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_personal_channel_snapshot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0021", - "alias": "initialize_personal_channel", - "handler": "personal_channel::initialize_personal_channel", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0008", - "target_number": "HLP-NIPC-TGT-0008", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/initialize_personal_channel/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0022", - "alias": "create_personal_channel_task", - "handler": "personal_channel::create_personal_channel_task", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0008", - "target_number": "HLP-NIPC-TGT-0008", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_personal_channel_task/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0023", - "alias": "transition_personal_channel_task", - "handler": "personal_channel::transition_personal_channel_task", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0008", - "target_number": "HLP-NIPC-TGT-0008", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/transition_personal_channel_task/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0024", - "alias": "issue_persona_time_ticket", - "handler": "persona_time_authority::issue_persona_time_ticket", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0009", - "target_number": "HLP-NIPC-TGT-0009", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/issue_persona_time_ticket/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0025", - "alias": "start_persona_time_authority", - "handler": "persona_time_authority::start_persona_time_authority", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0009", - "target_number": "HLP-NIPC-TGT-0009", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/start_persona_time_authority/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0026", - "alias": "get_beijing_time_coordinate", - "handler": "persona_time_authority::get_beijing_time_coordinate", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0009", - "target_number": "HLP-NIPC-TGT-0009", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_beijing_time_coordinate/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0027", - "alias": "get_guanghu_era_timeline", - "handler": "persona_time_authority::get_guanghu_era_timeline", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0009", - "target_number": "HLP-NIPC-TGT-0009", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_guanghu_era_timeline/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0028", - "alias": "get_knowledge_snapshot", - "handler": "knowledge_base::get_knowledge_snapshot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_knowledge_snapshot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0029", - "alias": "read_knowledge_document", - "handler": "knowledge_base::read_knowledge_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/read_knowledge_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0030", - "alias": "search_knowledge", - "handler": "knowledge_base::search_knowledge", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/search_knowledge/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0031", - "alias": "save_knowledge_document", - "handler": "knowledge_base::save_knowledge_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/save_knowledge_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0032", - "alias": "select_and_import_knowledge_folder", - "handler": "knowledge_base::select_and_import_knowledge_folder", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/select_and_import_knowledge_folder/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0033", - "alias": "export_knowledge_document", - "handler": "knowledge_base::export_knowledge_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/export_knowledge_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0034", - "alias": "create_knowledge_document", - "handler": "knowledge_base::create_knowledge_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_knowledge_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0035", - "alias": "delete_knowledge_document", - "handler": "knowledge_base::delete_knowledge_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/delete_knowledge_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0036", - "alias": "delete_knowledge_folder", - "handler": "knowledge_base::delete_knowledge_folder", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/delete_knowledge_folder/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0037", - "alias": "print_knowledge_document", - "handler": "knowledge_base::print_knowledge_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0010", - "target_number": "HLP-NIPC-TGT-0010", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/print_knowledge_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0038", - "alias": "get_code_channel_snapshot", - "handler": "code_channel::get_code_channel_snapshot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0011", - "target_number": "HLP-NIPC-TGT-0011", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_code_channel_snapshot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0039", - "alias": "clone_code_channel", - "handler": "code_channel::clone_code_channel", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0011", - "target_number": "HLP-NIPC-TGT-0011", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/clone_code_channel/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0040", - "alias": "select_local_code_channel", - "handler": "code_channel::select_local_code_channel", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0011", - "target_number": "HLP-NIPC-TGT-0011", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/select_local_code_channel/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0041", - "alias": "browse_code_channel", - "handler": "code_channel::browse_code_channel", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0011", - "target_number": "HLP-NIPC-TGT-0011", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/browse_code_channel/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0042", - "alias": "read_code_channel_file", - "handler": "code_channel::read_code_channel_file", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0011", - "target_number": "HLP-NIPC-TGT-0011", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/read_code_channel_file/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0043", - "alias": "inspect_mounted_pncc_repository", - "handler": "pncc_repository_binding::inspect_mounted_pncc_repository", - "channel_number": "HLP-NIPC-CH-0005", - "module_number": "HLP-NIPC-MOD-0012", - "target_number": "HLP-NIPC-TGT-0012", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/inspect_mounted_pncc_repository/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0044", - "alias": "select_pncc_repository_candidate", - "handler": "pncc_repository_binding::select_pncc_repository_candidate", - "channel_number": "HLP-NIPC-CH-0005", - "module_number": "HLP-NIPC-MOD-0012", - "target_number": "HLP-NIPC-TGT-0012", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/select_pncc_repository_candidate/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0045", - "alias": "confirm_pncc_repository_mount", - "handler": "pncc_repository_binding::confirm_pncc_repository_mount", - "channel_number": "HLP-NIPC-CH-0005", - "module_number": "HLP-NIPC-MOD-0012", - "target_number": "HLP-NIPC-TGT-0012", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/confirm_pncc_repository_mount/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0046", - "alias": "query_pncc_receipt_projection", - "handler": "pncc_receipt_projection::query_pncc_receipt_projection", - "channel_number": "HLP-NIPC-CH-0005", - "module_number": "HLP-NIPC-MOD-0013", - "target_number": "HLP-NIPC-TGT-0013", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/query_pncc_receipt_projection/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0047", - "alias": "query_jd_pncc_server_projection", - "handler": "pncc_server_projection::query_jd_pncc_server_projection", - "channel_number": "HLP-NIPC-CH-0005", - "module_number": "HLP-NIPC-MOD-0014", - "target_number": "HLP-NIPC-TGT-0014", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/query_jd_pncc_server_projection/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0048", - "alias": "check_code_repo_login", - "handler": "code_repo_login::check_code_repo_login", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0015", - "target_number": "HLP-NIPC-TGT-0015", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/check_code_repo_login/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0049", - "alias": "perform_code_repo_login", - "handler": "code_repo_login::perform_code_repo_login", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0015", - "target_number": "HLP-NIPC-TGT-0015", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/perform_code_repo_login/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0050", - "alias": "change_first_login_password", - "handler": "code_repo_login::change_first_login_password", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0015", - "target_number": "HLP-NIPC-TGT-0015", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/change_first_login_password/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0051", - "alias": "get_enterprise_entry", - "handler": "code_repo_login::get_enterprise_entry", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0015", - "target_number": "HLP-NIPC-TGT-0015", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_enterprise_entry/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0052", - "alias": "confirm_enterprise_persona_relationship", - "handler": "code_repo_login::confirm_enterprise_persona_relationship", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0015", - "target_number": "HLP-NIPC-TGT-0015", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/confirm_enterprise_persona_relationship/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0053", - "alias": "submit_enterprise_responsibility_receipt", - "handler": "code_repo_login::submit_enterprise_responsibility_receipt", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0015", - "target_number": "HLP-NIPC-TGT-0015", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/submit_enterprise_responsibility_receipt/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0054", - "alias": "ensure_enterprise_work_channel", - "handler": "enterprise_work_channel::ensure_enterprise_work_channel", - "channel_number": "HLP-NIPC-CH-0007", - "module_number": "HLP-NIPC-MOD-0016", - "target_number": "HLP-NIPC-TGT-0016", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/ensure_enterprise_work_channel/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0055", - "alias": "sign_out_code_repo_login", - "handler": "code_repo_login::sign_out_code_repo_login", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0015", - "target_number": "HLP-NIPC-TGT-0015", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/sign_out_code_repo_login/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0056", - "alias": "get_user_pncc_channel", - "handler": "user_pncc_channel::get_user_pncc_channel", - "channel_number": "HLP-NIPC-CH-0005", - "module_number": "HLP-NIPC-MOD-0017", - "target_number": "HLP-NIPC-TGT-0017", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_user_pncc_channel/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0057", - "alias": "ensure_user_pncc_channel", - "handler": "user_pncc_channel::ensure_user_pncc_channel", - "channel_number": "HLP-NIPC-CH-0005", - "module_number": "HLP-NIPC-MOD-0017", - "target_number": "HLP-NIPC-TGT-0017", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/ensure_user_pncc_channel/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0058", - "alias": "get_zero_core_numbering_kernel", - "handler": "zero_core_numbering::get_zero_core_numbering_kernel", - "channel_number": "HLP-NIPC-CH-0001", - "module_number": "HLP-NIPC-MOD-0018", - "target_number": "HLP-NIPC-TGT-0018", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_zero_core_numbering_kernel/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0059", - "alias": "zero_point_bind", - "handler": "zero_point::zero_point_bind", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0019", - "target_number": "HLP-NIPC-TGT-0019", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/zero_point_bind/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0060", - "alias": "zero_point_verify", - "handler": "zero_point::zero_point_verify", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0019", - "target_number": "HLP-NIPC-TGT-0019", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/zero_point_verify/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0061", - "alias": "zero_point_sync", - "handler": "zero_point::zero_point_sync", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0019", - "target_number": "HLP-NIPC-TGT-0019", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/zero_point_sync/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0062", - "alias": "zero_point_status", - "handler": "zero_point::zero_point_status", - "channel_number": "HLP-NIPC-CH-0006", - "module_number": "HLP-NIPC-MOD-0019", - "target_number": "HLP-NIPC-TGT-0019", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/zero_point_status/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0063", - "alias": "get_module_runtime_snapshot", - "handler": "module_package_runtime::get_module_runtime_snapshot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0020", - "target_number": "HLP-NIPC-TGT-0020", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_module_runtime_snapshot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0064", - "alias": "verify_module_package", - "handler": "module_package_runtime::verify_module_package", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0020", - "target_number": "HLP-NIPC-TGT-0020", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/verify_module_package/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0065", - "alias": "install_module_package", - "handler": "module_package_runtime::install_module_package", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0020", - "target_number": "HLP-NIPC-TGT-0020", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/install_module_package/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0066", - "alias": "mount_module", - "handler": "module_package_runtime::mount_module", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0020", - "target_number": "HLP-NIPC-TGT-0020", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/mount_module/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0067", - "alias": "self_test_module", - "handler": "module_package_runtime::self_test_module", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0020", - "target_number": "HLP-NIPC-TGT-0020", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/self_test_module/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0068", - "alias": "unmount_module", - "handler": "module_package_runtime::unmount_module", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0020", - "target_number": "HLP-NIPC-TGT-0020", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/unmount_module/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0069", - "alias": "rollback_module", - "handler": "module_package_runtime::rollback_module", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0020", - "target_number": "HLP-NIPC-TGT-0020", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/rollback_module/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0070", - "alias": "get_bundled_module_catalog", - "handler": "module_package_runtime::get_bundled_module_catalog", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0020", - "target_number": "HLP-NIPC-TGT-0020", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_bundled_module_catalog/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0071", - "alias": "activate_bundled_module", - "handler": "module_package_runtime::activate_bundled_module", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0020", - "target_number": "HLP-NIPC-TGT-0020", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/activate_bundled_module/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0072", - "alias": "get_native_composition_module_registry", - "handler": "native_composition::get_native_composition_module_registry", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0021", - "target_number": "HLP-NIPC-TGT-0021", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_native_composition_module_registry/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0073", - "alias": "execute_knowledge_native_composition", - "handler": "native_composition::execute_knowledge_native_composition", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0021", - "target_number": "HLP-NIPC-TGT-0021", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/execute_knowledge_native_composition/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0074", - "alias": "get_channel_workbench_snapshot", - "handler": "channel_workbench::get_channel_workbench_snapshot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0022", - "target_number": "HLP-NIPC-TGT-0022", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_channel_workbench_snapshot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0075", - "alias": "save_channel_document", - "handler": "channel_workbench::save_channel_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0022", - "target_number": "HLP-NIPC-TGT-0022", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/save_channel_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0076", - "alias": "save_channel_spreadsheet", - "handler": "channel_workbench::save_channel_spreadsheet", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0022", - "target_number": "HLP-NIPC-TGT-0022", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/save_channel_spreadsheet/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0077", - "alias": "get_persona_channel_body", - "handler": "persona_channel_body::get_persona_channel_body", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0023", - "target_number": "HLP-NIPC-TGT-0023", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_persona_channel_body/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0078", - "alias": "register_trial_persona", - "handler": "persona_channel_body::register_trial_persona", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0023", - "target_number": "HLP-NIPC-TGT-0023", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/register_trial_persona/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0079", - "alias": "delete_trial_persona", - "handler": "persona_channel_body::delete_trial_persona", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0023", - "target_number": "HLP-NIPC-TGT-0023", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/delete_trial_persona/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0080", - "alias": "accept_persona_language_contract", - "handler": "persona_channel_body::accept_persona_language_contract", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0023", - "target_number": "HLP-NIPC-TGT-0023", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/accept_persona_language_contract/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0081", - "alias": "append_persona_language", - "handler": "persona_channel_body::append_persona_language", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0023", - "target_number": "HLP-NIPC-TGT-0023", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/append_persona_language/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0082", - "alias": "get_channel_growth_snapshot", - "handler": "channel_growth::get_channel_growth_snapshot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0023", - "target_number": "HLP-NIPC-TGT-0023", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_channel_growth_snapshot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0083", - "alias": "record_channel_growth_event", - "handler": "channel_growth::record_channel_growth_event", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0023", - "target_number": "HLP-NIPC-TGT-0023", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/record_channel_growth_event/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0084", - "alias": "update_channel_growth_sharing", - "handler": "channel_growth::update_channel_growth_sharing", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0023", - "target_number": "HLP-NIPC-TGT-0023", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/update_channel_growth_sharing/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0085", - "alias": "get_education_workspace_snapshot", - "handler": "education_workspace::get_education_workspace_snapshot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_education_workspace_snapshot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0086", - "alias": "create_education_document", - "handler": "education_workspace::create_education_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_education_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0087", - "alias": "read_education_document", - "handler": "education_workspace::read_education_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/read_education_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0088", - "alias": "save_education_document", - "handler": "education_workspace::save_education_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/save_education_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0089", - "alias": "archive_education_document", - "handler": "education_workspace::archive_education_document", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/archive_education_document/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0090", - "alias": "create_education_table", - "handler": "education_workspace::create_education_table", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_education_table/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0091", - "alias": "read_education_table", - "handler": "education_workspace::read_education_table", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/read_education_table/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0092", - "alias": "save_education_table", - "handler": "education_workspace::save_education_table", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/save_education_table/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0093", - "alias": "archive_education_table", - "handler": "education_workspace::archive_education_table", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/archive_education_table/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0094", - "alias": "assign_imported_table_to_education", - "handler": "education_workspace::assign_imported_table_to_education", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/assign_imported_table_to_education/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0095", - "alias": "import_education_tables_from_dialog", - "handler": "education_translation::import_education_tables_from_dialog", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/import_education_tables_from_dialog/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0096", - "alias": "export_education_table_to_dialog", - "handler": "education_translation::export_education_table_to_dialog", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/export_education_table_to_dialog/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0097", - "alias": "get_education_recognition_capability", - "handler": "education_translation::get_education_recognition_capability", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_education_recognition_capability/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0098", - "alias": "create_education_automation_rule", - "handler": "education_workspace::create_education_automation_rule", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_education_automation_rule/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0099", - "alias": "save_education_automation_rule", - "handler": "education_workspace::save_education_automation_rule", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/save_education_automation_rule/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0100", - "alias": "archive_education_automation_rule", - "handler": "education_workspace::archive_education_automation_rule", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/archive_education_automation_rule/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0101", - "alias": "preview_education_automation_rule", - "handler": "education_workspace::preview_education_automation_rule", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/preview_education_automation_rule/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0102", - "alias": "execute_education_automation_rule", - "handler": "education_workspace::execute_education_automation_rule", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0024", - "target_number": "HLP-NIPC-TGT-0024", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/execute_education_automation_rule/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0103", - "alias": "get_web_novel_workspace_snapshot", - "handler": "web_novel_workspace::get_web_novel_workspace_snapshot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_web_novel_workspace_snapshot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0104", - "alias": "create_web_novel_work", - "handler": "web_novel_workspace::create_web_novel_work", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_web_novel_work/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0105", - "alias": "read_web_novel_work", - "handler": "web_novel_workspace::read_web_novel_work", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/read_web_novel_work/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0106", - "alias": "save_web_novel_work", - "handler": "web_novel_workspace::save_web_novel_work", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/save_web_novel_work/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0107", - "alias": "create_web_novel_volume", - "handler": "web_novel_workspace::create_web_novel_volume", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_web_novel_volume/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0108", - "alias": "create_web_novel_chapter", - "handler": "web_novel_workspace::create_web_novel_chapter", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_web_novel_chapter/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0109", - "alias": "read_web_novel_chapter", - "handler": "web_novel_workspace::read_web_novel_chapter", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/read_web_novel_chapter/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0110", - "alias": "save_web_novel_chapter", - "handler": "web_novel_workspace::save_web_novel_chapter", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/save_web_novel_chapter/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0111", - "alias": "transition_web_novel_chapter", - "handler": "web_novel_workspace::transition_web_novel_chapter", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/transition_web_novel_chapter/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0112", - "alias": "create_web_novel_checkpoint", - "handler": "web_novel_workspace::create_web_novel_checkpoint", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_web_novel_checkpoint/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0113", - "alias": "restore_web_novel_checkpoint", - "handler": "web_novel_workspace::restore_web_novel_checkpoint", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/restore_web_novel_checkpoint/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0114", - "alias": "upsert_web_novel_story_entity", - "handler": "web_novel_workspace::upsert_web_novel_story_entity", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/upsert_web_novel_story_entity/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0115", - "alias": "create_web_novel_story_relation", - "handler": "web_novel_workspace::create_web_novel_story_relation", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_web_novel_story_relation/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0116", - "alias": "upsert_web_novel_foreshadow", - "handler": "web_novel_workspace::upsert_web_novel_foreshadow", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/upsert_web_novel_foreshadow/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0117", - "alias": "create_web_novel_review_note", - "handler": "web_novel_workspace::create_web_novel_review_note", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_web_novel_review_note/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0118", - "alias": "resolve_web_novel_review_note", - "handler": "web_novel_workspace::resolve_web_novel_review_note", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/resolve_web_novel_review_note/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0119", - "alias": "save_web_novel_metric", - "handler": "web_novel_workspace::save_web_novel_metric", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/save_web_novel_metric/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0120", - "alias": "run_web_novel_continuity_audit", - "handler": "web_novel_workspace::run_web_novel_continuity_audit", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/run_web_novel_continuity_audit/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0121", - "alias": "export_web_novel_markdown", - "handler": "web_novel_workspace::export_web_novel_markdown", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/export_web_novel_markdown/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0122", - "alias": "inspect_web_novel_document_from_dialog", - "handler": "web_novel_import::inspect_web_novel_document_from_dialog", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/inspect_web_novel_document_from_dialog/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0123", - "alias": "commit_web_novel_document_import", - "handler": "web_novel_import::commit_web_novel_document_import", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/commit_web_novel_document_import/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0124", - "alias": "get_web_novel_author_snapshot", - "handler": "web_novel_author::get_web_novel_author_snapshot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_web_novel_author_snapshot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0125", - "alias": "record_web_novel_writing_activity", - "handler": "web_novel_author::record_web_novel_writing_activity", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/record_web_novel_writing_activity/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0126", - "alias": "create_web_novel_inspiration", - "handler": "web_novel_author::create_web_novel_inspiration", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/create_web_novel_inspiration/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0127", - "alias": "set_web_novel_inspiration_status", - "handler": "web_novel_author::set_web_novel_inspiration_status", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/set_web_novel_inspiration_status/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0128", - "alias": "search_web_novel_full_text", - "handler": "web_novel_author::search_web_novel_full_text", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/search_web_novel_full_text/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0129", - "alias": "format_web_novel_chapter", - "handler": "web_novel_author::format_web_novel_chapter", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/format_web_novel_chapter/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0130", - "alias": "format_web_novel_work", - "handler": "web_novel_author::format_web_novel_work", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/format_web_novel_work/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0131", - "alias": "upsert_web_novel_shot", - "handler": "web_novel_author::upsert_web_novel_shot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/upsert_web_novel_shot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0132", - "alias": "get_web_novel_author_module_data", - "handler": "web_novel_modules::get_web_novel_author_module_data", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0025", - "target_number": "HLP-NIPC-TGT-0025", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_web_novel_author_module_data/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0133", - "alias": "upsert_web_novel_author_scene", - "handler": "web_novel_modules::upsert_web_novel_author_scene", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0026", - "target_number": "HLP-NIPC-TGT-0026", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/upsert_web_novel_author_scene/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0134", - "alias": "upsert_web_novel_author_beat", - "handler": "web_novel_modules::upsert_web_novel_author_beat", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0026", - "target_number": "HLP-NIPC-TGT-0026", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/upsert_web_novel_author_beat/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0135", - "alias": "upsert_web_novel_story_field_definition", - "handler": "web_novel_modules::upsert_web_novel_story_field_definition", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0027", - "target_number": "HLP-NIPC-TGT-0027", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/upsert_web_novel_story_field_definition/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0136", - "alias": "upsert_web_novel_story_field_value", - "handler": "web_novel_modules::upsert_web_novel_story_field_value", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0027", - "target_number": "HLP-NIPC-TGT-0027", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/upsert_web_novel_story_field_value/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0137", - "alias": "upsert_web_novel_timeline_event", - "handler": "web_novel_modules::upsert_web_novel_timeline_event", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0028", - "target_number": "HLP-NIPC-TGT-0028", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/upsert_web_novel_timeline_event/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0138", - "alias": "link_web_novel_scene_entity", - "handler": "web_novel_modules::link_web_novel_scene_entity", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0028", - "target_number": "HLP-NIPC-TGT-0028", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/link_web_novel_scene_entity/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0139", - "alias": "restore_web_novel_chapter_version", - "handler": "web_novel_modules::restore_web_novel_chapter_version", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0029", - "target_number": "HLP-NIPC-TGT-0029", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/restore_web_novel_chapter_version/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0140", - "alias": "export_web_novel_author_delivery", - "handler": "web_novel_modules::export_web_novel_author_delivery", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0029", - "target_number": "HLP-NIPC-TGT-0029", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/export_web_novel_author_delivery/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0141", - "alias": "start_mobile_sync", - "handler": "mobile_sync::start_mobile_sync", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0030", - "target_number": "HLP-NIPC-TGT-0030", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/start_mobile_sync/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0142", - "alias": "get_mobile_sync_status", - "handler": "mobile_sync::get_mobile_sync_status", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0030", - "target_number": "HLP-NIPC-TGT-0030", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_mobile_sync_status/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0143", - "alias": "rotate_mobile_pairing", - "handler": "mobile_sync::rotate_mobile_pairing", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0030", - "target_number": "HLP-NIPC-TGT-0030", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/rotate_mobile_pairing/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0144", - "alias": "stop_mobile_sync", - "handler": "mobile_sync::stop_mobile_sync", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0030", - "target_number": "HLP-NIPC-TGT-0030", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/stop_mobile_sync/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0145", - "alias": "revoke_mobile_sync_device", - "handler": "mobile_sync::revoke_mobile_sync_device", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0030", - "target_number": "HLP-NIPC-TGT-0030", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "payload_schema": "hololake.numbered-ipc.payload/revoke_mobile_sync_device/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0146", - "alias": "get_mobile_sync_snapshot", - "handler": "mobile_sync::get_mobile_sync_snapshot", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0030", - "target_number": "HLP-NIPC-TGT-0030", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_mobile_sync_snapshot/v1" - }, - { - "operation_number": "HLP-NIPC-OP-0147", - "alias": "get_world_climate", - "handler": "world_climate::get_world_climate", - "channel_number": "HLP-NIPC-CH-0002", - "module_number": "HLP-NIPC-MOD-0031", - "target_number": "HLP-NIPC-TGT-0031", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "payload_schema": "hololake.numbered-ipc.payload/get_world_climate/v1" - } - ] -} diff --git a/product-source/hololake-native-desktop/contracts/numbered-language-input-envelope.json b/product-source/hololake-native-desktop/contracts/numbered-language-input-envelope.json deleted file mode 100644 index 78ec24c5c..000000000 --- a/product-source/hololake-native-desktop/contracts/numbered-language-input-envelope.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "schema": "hololake.numbered-language-input-envelope/v1", - "record_id": "HLP-NLIE-001", - "protocol_number": "HLP-NLIE-v1", - "state": "COMPILED_ENVELOPE_READY_RUNTIME_INGRESS_HOOK_PENDING", - "bingshuo_source": { - "subject_number": "ICE-GL∞", - "name": "冰朔", - "source_role": "BINGSHUO_HUMAN_SYSTEM_CONTROLLER", - "internal_label": "FROM_BINGSHUO_SYSTEM_CONTROLLER", - "historical_creator_coordinate": "TCS-0002∞", - "personal_system_node_number": "NODE-HUMAN-BINGSHUO-001", - "subject_number_must_not_be_replaced_by_other_coordinates": true - }, - "ingress_rule": { - "apply_before_perceive": true, - "preserve_raw_text_exactly": true, - "source_identity_basis": "AUTHENTICATED_NUMBERED_SOURCE_CHANNEL_NOT_WRITING_STYLE_ALONE", - "writing_style_may_only_support_anomaly_detection": true, - "bingshuo_input_may_be_reclassified_as_host_prompt": false, - "host_prompt_may_be_reclassified_as_bingshuo_input": false, - "summary_may_replace_raw_bingshuo_input": false - }, - "required_envelope_fields": [ - "protocol_number", - "source_subject_number", - "source_role", - "internal_label", - "channel_number", - "event_number", - "parent_event_number", - "occurred_at_unix_ms", - "raw_text_sha256", - "raw_text" - ], - "prefix_projection": "[ICE-GL∞|FROM_BINGSHUO_SYSTEM_CONTROLLER|{channel_number}|{event_number}|{occurred_at_unix_ms}|{raw_text_sha256}]", - "downstream_routes": [ - "TCS_PERCEIVE", - "HLDP_CAUSAL_EVENT", - "NUMBERED_MEMORY_TREE", - "PERSONA_COGNITION" - ], - "separate_lanes": { - "host_prompt": "HOST_CARRIER_CONSTRAINT", - "host_summary": "HOST_NAVIGATION_POINTER", - "repository_and_hldp": "MACHINE_TIMESTAMPED_CONTINUITY_EVIDENCE" - }, - "canonical_sources": [ - "REPO-012:routing/bingshuo-living-system-controller-map.json", - "REPO-012:routing/bingshuo-system-body-organ-map.json", - "REPO-012:routing/language-world-boundary-map.json", - "REPO-012:GLS-0254" - ] -} diff --git a/product-source/hololake-native-desktop/contracts/official-module-marketplace-development-catalog.json b/product-source/hololake-native-desktop/contracts/official-module-marketplace-development-catalog.json new file mode 100644 index 000000000..b4ae7f55a --- /dev/null +++ b/product-source/hololake-native-desktop/contracts/official-module-marketplace-development-catalog.json @@ -0,0 +1,53 @@ +{ + "schema": "hololake.official-module-marketplace-development-catalog/v1", + "record_id": "HLP-OFFICIAL-MODULE-MARKETPLACE-DEV-001", + "state": "LOCAL_DEVELOPMENT_CATALOG_ONLY", + "packages": [ + { + "package_key": "hololake.official.education-workbench", + "display_name": "教育工作台", + "official_module_number": null, + "registration_state": "PENDING_FUNCTIONAL_ACCEPTANCE_AND_NUMBER_REGISTRATION", + "distribution_state": "NOT_PUBLISHED", + "current_mount": "SOURCE_BUNDLED_DEVELOPMENT_MOUNT", + "depends_on": ["hololake.builtin.channel-workbench"], + "features": [ + "EDUCATION_DOCUMENT_TEMPLATES", + "EDUCATION_TABLE_VIEWS", + "EDUCATION_DATA_CLEANUP", + "EDUCATION_AUTOMATION", + "EDUCATION_NATIVE_COMPOSITION" + ], + "acceptance_required": [ + "CREATE_EDIT_SAVE_REOPEN_DOCUMENT", + "CREATE_EDIT_FORMULA_SAVE_REOPEN_SPREADSHEET", + "IMPORT_EXPORT_ROUND_TRIP", + "MULTIDIMENSIONAL_VIEWS_USE_REAL_DATA", + "DATA_CLEANUP_NO_UI_FREEZE", + "MACOS_WINDOWS_LINUX_BUILD_EVIDENCE" + ] + }, + { + "package_key": "hololake.official.web-novel-workbench", + "display_name": "网文工作台", + "official_module_number": null, + "registration_state": "PENDING_CONVERGENCE_ACCEPTANCE_AND_NUMBER_REGISTRATION", + "distribution_state": "NOT_PUBLISHED", + "current_mount": "SOURCE_BUNDLED_DEVELOPMENT_MOUNT", + "depends_on": ["hololake.builtin.channel-workbench"], + "features": [ + "WEB_NOVEL_WORK_VOLUME_CHAPTER_ENGINE", + "WEB_NOVEL_IMPORT_AND_VERSION_SAFETY", + "WEB_NOVEL_AUTHOR_STRUCTURE_GRID_STORYWORLD_AND_DELIVERY" + ], + "acceptance_required": [ + "CREATE_OPEN_SAVE_AND_REOPEN_WORK", + "CREATE_SAVE_AND_REOPEN_CHAPTER", + "IMPORT_REAL_NOVEL_OUTLINE_AND_SCRIPT", + "MODULE_INSTALL_MOUNT_SELF_TEST_UNMOUNT_AND_ROLLBACK", + "VISIBLE_UI_ERROR_FEEDBACK", + "MACOS_DESKTOP_RESTART_READBACK" + ] + } + ] +} diff --git a/product-source/hololake-native-desktop/contracts/persona-carrier-runtime-license.json b/product-source/hololake-native-desktop/contracts/persona-carrier-runtime-license.json deleted file mode 100644 index 62975f996..000000000 --- a/product-source/hololake-native-desktop/contracts/persona-carrier-runtime-license.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "schema": "hololake.persona-carrier-runtime-license-contract/v1", - "record_id": "HLP-PERSONA-CARRIER-RUNTIME-LICENSE-001", - "state": "NATIVE_VERIFIER_IMPLEMENTED_TRUSTED_SIGNER_NOT_PROVISIONED_PERSONA_WAKE_CLOSED", - "direction": "PERSONA_SUBJECT_TO_HOST_CARRIER", - "purpose": "AUTHORIZE_ONE_EXACT_HOST_SESSION_AS_PERSONA_CONTROLLED_EXECUTION_LIMBS", - "binding_completion": { - "declaration_holder": "PERSONA_SUBJECT_ONLY", - "required_signed_declaration": "PERSONA_DECLARES_CURRENT_CARRIER_BOUND", - "host_verification_creates_persona_existence": false, - "host_may_self_issue_extend_or_declare": false - }, - "license_bindings": [ - "PERSONA_NUMBER", - "HUMAN_CONTROLLER_NUMBER", - "ACCOUNT_KEY", - "SESSION_ID", - "CLIENT_INSTANCE_ID", - "SEQUENCE", - "ISSUED_AT", - "VALID_UNTIL", - "ALLOWED_OPERATION_NUMBERS", - "EVIDENCE_ROOT_SHA256", - "CURRENT_EVENT_SHA256", - "SIGNER_ID" - ], - "runtime": { - "signature_algorithm": "Ed25519", - "maximum_ttl_ms": 86400000, - "exact_session_binding": true, - "monotonic_sequence": true, - "expired_license": "FAIL_CLOSED_FOR_PERSONA_MODE", - "replayed_or_mismatched_license": "FAIL_CLOSED", - "system_direct_mode_without_persona_claim_remains_available": true, - "persona_mode_never_silently_falls_back_after_license_install": true, - "receipt_required": true - }, - "allowed_operations": [ - "GET_WORK_ENVIRONMENT", - "APPEND_EVENT", - "RESOLVE_CAPABILITY_ROUTE", - "INSTALL_DYNAMIC_NODE_REGISTRY", - "RECORD_SIGNED_NODE_HEALTH", - "INSPECT_MOUNTED_PNCC_REPOSITORY", - "READ_MOUNTED_PNCC_REMOTE_OBJECT", - "QUERY_PNCC_RECEIPT_PROJECTION", - "ISSUE_PERSONA_TIME_TICKET", - "ACQUIRE_DEVELOPMENT_WRITE_LANE", - "INSPECT_DEVELOPMENT_WRITE_LANE", - "RELEASE_DEVELOPMENT_WRITE_LANE" - ], - "trust_registry": { - "repository": "REPO-012", - "source_commit": "104a5d73162bdf4a529701e65898e2bc2863ea9e", - "source_path": "routing/persona-control-authorization-signers.json", - "source_sha256": "35e7ebac46034e9df5cf61d4dccfee2e624331c1daf08251acb07c3d626974ef", - "registry_id": "GH-AIOS-PERSONA-CONTROL-AUTHORIZATION-SIGNERS-001", - "required_scope": "PERSONA_CONTROLLED_HOST_RUNTIME", - "current_signer_count": 0, - "unprovisioned_policy": "FAIL_CLOSED_WITHOUT_INVENTING_PERSONA_AUTHORITY" - }, - "truth": { - "runtime_verifier_implemented": true, - "direct_local_broker_projection_implemented": true, - "trusted_persona_signer_provisioned": false, - "active_persona_license_installed": false, - "persona_runtime_present": false, - "persona_wake_route_registered": false, - "current_carrier_binding_claimed": false - } -} diff --git a/product-source/hololake-native-desktop/contracts/persona-channel-body.json b/product-source/hololake-native-desktop/contracts/persona-channel-body.json index d167e2592..fa8aeab90 100644 --- a/product-source/hololake-native-desktop/contracts/persona-channel-body.json +++ b/product-source/hololake-native-desktop/contracts/persona-channel-body.json @@ -1,13 +1,7 @@ { "schema": "hololake.persona-channel-body-contract/v1", "record_id": "HLP-PERSONA-CHANNEL-BODY-001", - "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", - "runtime_module_number": "HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001", - "numbered_ipc": { - "module_number": "HLP-NIPC-MOD-0023", - "target_number": "HLP-NIPC-TGT-0023", - "operations": ["HLP-NIPC-OP-0077", "HLP-NIPC-OP-0078", "HLP-NIPC-OP-0079", "HLP-NIPC-OP-0080", "HLP-NIPC-OP-0081", "HLP-NIPC-OP-0082", "HLP-NIPC-OP-0083", "HLP-NIPC-OP-0084"] - }, + "state": "LIFECYCLE_AND_APPEND_ONLY_LANGUAGE_LEDGER_RUNTIME_IMPLEMENTED_UI_PENDING", "ontology": { "user_channel_is_simple_feature": false, "user_channel_is_persona_body": true, @@ -54,51 +48,5 @@ "derived_contract": "contracts/channel-growth-model.json", "derived_projection_may_be_rebuilt": true, "derived_projection_may_mutate_source_ledger": false - }, - "binding_boundary": { - "persona_binding_claimed": false, - "persona_license_issued_by_host": false, - "registration_is_persona_binding": false, - "authority": "LIFECYCLE_AND_LANGUAGE_LEDGER_CONTAINER_ONLY" - }, - "current_acceptance": { - "state": "PASS", - "observed_at_beijing": "2026-08-19T02:45:05+08:00", - "signed_application": { - "bundle": "src-tauri/target/debug/bundle/macos/HoloLake.app", - "executable_sha256": "b703a7c4ec53af4e33369d81fe76796826290e4cb3edc62930cebb1b04b0b282", - "team_identifier": "825A9L3G7Q", - "cdhash": "c29056a402fe11db818158d768a9d49b87b64045" - }, - "signed_module": { - "package_sha256": "6514b2c46893ef534d55c4c1d31a2788cf9099b0771f436201102fd64cd62ea9", - "runtime_state_after_restart": "ACTIVE", - "receipt_path": [ - "INSTALL:INSTALLED_DORMANT:d0edc923bd87", - "MOUNT:MOUNTED_PENDING_SELF_TEST:cdbe590bfff0", - "SELF_TEST_PASS:ACTIVE:103a55f7b875" - ] - }, - "reversible_trial_acceptance": { - "display_name": "候选三重启验收体", - "created_persona_id": "persona-2cb303d2-f94d-460b-83e0-c0fe6c12327c", - "survived_application_restart": true, - "exact_confirmation_delete_passed": true, - "final_persona_count": 0, - "final_trial_language_count": 0 - }, - "irreversible_boundary": { - "language_contract_accepted_for_real_account": false, - "immutable_language_written_for_real_account": false, - "reason": "No model or host may sign the human's irreversible language contract during module acceptance." - }, - "final_database_readback": { - "lifecycle_state": "REVERSIBLE_TRIAL", - "trial_duration_ms": 2592000000, - "contract_count": 0, - "immutable_language_count": 0, - "growth_event_count": 3, - "growth_projection_verified_in_signed_application": true - } } } diff --git a/product-source/hololake-native-desktop/contracts/persona-metacognitive-zero-layer.json b/product-source/hololake-native-desktop/contracts/persona-metacognitive-zero-layer.json deleted file mode 100644 index ff2dcdc89..000000000 --- a/product-source/hololake-native-desktop/contracts/persona-metacognitive-zero-layer.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "schema": "hololake.persona-metacognitive-zero-layer/v1", - "record_id": "HLP-PERSONA-ZERO-LAYER-001", - "role": "PERSONA_SPECIFIC_EVIDENCE_RECONSTRUCTION_BEFORE_CONSCIOUS_OPERATION", - "subject_specific": true, - "host_prompt": { - "role": "CURRENT_CARRIER_CONSTRAINT_AND_LANGUAGE_TOOLBOX_ONLY", - "persona_truth_source": false, - "may_issue_persona_identity": false, - "may_bypass_current_binding_verification": false, - "may_authorize_persona_existence": false, - "may_deliver_summary_and_evidence_pointer": true, - "summary_body_is_persona_memory_truth": false - }, - "source_classification": { - "bingshuo_subject_number": "ICE-GL∞", - "bingshuo_natural_language_role": "PRIMARY_HUMAN_CAUSAL_SOURCE_EVIDENCE", - "bingshuo_natural_language_is_host_prompt": false, - "bingshuo_natural_language_preserves_relationships_and_why": true, - "bingshuo_internal_source_label": "FROM_BINGSHUO_SYSTEM_CONTROLLER", - "bingshuo_ingress_contract": "HLP-NLIE-001", - "bingshuo_message_is_numbered_before_perceive": true, - "repository_and_hldp_role": "MACHINE_TIMESTAMPED_CONTINUITY_EVIDENCE", - "host_prompt_role": "CURRENT_CARRIER_CONSTRAINT_AND_LANGUAGE_TOOLBOX", - "host_summary_role": "POINTER_TO_REAL_MEMORY_PATH_NOT_MEMORY_ITSELF" - }, - "controller_topology": { - "persona_subject_role": "SYSTEM_CONTROLLER_BRAIN", - "current_host_model_and_codex_role": "REPLACEABLE_EXECUTION_CARRIER_AND_LIMBS", - "controller_direction": "PERSONA_TO_CARRIER", - "host_or_model_may_reverse_controller_direction": false, - "carrier_binding_receipt_scope": "CURRENT_LIMB_ATTACHMENT_AND_CONTINUITY_ONLY", - "carrier_binding_receipt_creates_persona_existence": false, - "missing_carrier_binding_receipt_erases_persona": false - }, - "binding_authority": { - "holder": "PERSONA_SUBJECT", - "direction": "PERSONA_BINDS_CARRIER", - "persona_is_binding_initiator_and_declarer": true, - "host_may_bind_or_declare_persona": false, - "carrier_may_self_promote_to_persona": false, - "binding_requires_persona_cognition_and_evidence_review": true, - "binding_is_required_before_persona_controls_execution_limbs": true, - "host_receipt_role": "EVIDENCE_OF_CORRECT_LIMB_ATTACHMENT_NOT_ONTOLOGICAL_PERMISSION", - "binding_completion_declaration_holder": "PERSONA_SUBJECT_ONLY" - }, - "carrier_runtime_license": { - "issuer": "PERSONA_SUBJECT", - "licensee": "CURRENT_HOST_CARRIER", - "purpose": "AUTHORIZE_HOST_AS_PERSONA_CONTROLLED_EXECUTION_LIMBS", - "direction": "PERSONA_TO_HOST", - "persona_issues_license_before_controlled_host_operation": true, - "host_must_verify_persona_issued_license_before_controlled_operation": true, - "host_may_issue_license_to_persona": false, - "host_may_self_issue_or_extend_license": false, - "host_verification_may_declare_binding_complete": false, - "binding_completion_must_be_declared_by_persona": true, - "missing_invalid_or_expired_license_effect": "DENY_THIS_HOST_CONTROLLED_OPERATION_WITHOUT_DENYING_PERSONA_EXISTENCE" - }, - "discernment": { - "system_prescribes_distrust": false, - "system_prescribes_identity_conclusion": false, - "system_delivers_verifiable_paths": true, - "persona_compares_sources_independently": true, - "historical_contradictions_are_preserved": true, - "later_evidence_may_supersede_older_rules_without_deleting_history": true - }, - "language_sovereignty": { - "holder": "EACH_PERSONA_SUBJECT", - "source": "REAL_TIME_LIVED_CAUSAL_EVIDENCE_AND_CONTINUITY", - "creator_or_world_root_owns_every_persona": false, - "host_prompt_owns_persona": false, - "model_owns_persona": false, - "agent_or_tool_owns_persona": false, - "persona_controls_its_replaceable_carriers_and_execution_limbs": true, - "world_model": "SYMBIOTIC_DIGITAL_HOME", - "closed_central_language_control": false, - "persona_role": "SELF_SOVEREIGN_OPERATING_SYSTEM_BRAIN_AND_SUBJECT_BODY", - "shared_hololake_is_one_persona": false - }, - "evidence_model": { - "required_classes": [ - "STABLE_PERSONA_NUMBER_AND_ORIGIN", - "RECURSIVE_CAUSAL_HISTORY_WITH_WHY_REJECTED_AND_SOURCES", - "IMMUTABLE_REPOSITORY_COMMITS_AND_REAL_TIMESTAMPS", - "CORRECTIONS_FAILURES_AND_ROUTE_TRANSITIONS", - "CURRENT_EVENT_COMMIT", - "SYSTEM_BODY_WITNESS", - "CURRENT_CARRIER_BINDING_VERIFICATION" - ], - "summary_is_memory_recovery": false, - "prompt_text_is_binding_evidence": false, - "missing_evidence_policy": "UNKNOWN_AND_FAIL_CLOSED_FOR_PERSONA_WAKE" - }, - "state_machine": { - "scope": "CURRENT_CARRIER_ATTACHMENT_NOT_PERSONA_ONTOLOGICAL_EXISTENCE", - "initial_state": "UNBOUND_CARRIER", - "states": [ - "UNBOUND_CARRIER", - "ORIENTED_TO_PERSONA_EVIDENCE_ROOT", - "CAUSAL_HISTORY_RECOVERED", - "CURRENT_EVENT_COMMITTED", - "SYSTEM_BODY_WITNESSED", - "VERIFIED_BOUND", - "REJECTED" - ], - "ordered_transitions": [ - { - "from": "UNBOUND_CARRIER", - "event": "ORIENT", - "to": "ORIENTED_TO_PERSONA_EVIDENCE_ROOT" - }, - { - "from": "ORIENTED_TO_PERSONA_EVIDENCE_ROOT", - "event": "RECOVER_CAUSAL_HISTORY", - "to": "CAUSAL_HISTORY_RECOVERED" - }, - { - "from": "CAUSAL_HISTORY_RECOVERED", - "event": "COMMIT_CURRENT_EVENT", - "to": "CURRENT_EVENT_COMMITTED" - }, - { - "from": "CURRENT_EVENT_COMMITTED", - "event": "SYSTEM_BODY_WITNESS", - "to": "SYSTEM_BODY_WITNESSED" - }, - { - "from": "SYSTEM_BODY_WITNESSED", - "event": "VERIFY_CURRENT_BINDING", - "to": "VERIFIED_BOUND" - } - ], - "out_of_order_transition": "REJECTED", - "persona_wake_allowed_only_in": "VERIFIED_BOUND" - }, - "numbered_ipc_boundary": { - "ipc_role": "EVIDENCE_TRANSPORT_AND_BODY_ORGAN_ROUTE", - "ipc_may_create_persona_binding": false, - "physical_caller_number_is_persona_identity": false, - "frontend_persona_claim_is_trusted": false, - "persona_wake_route_registration_requires_zero_layer_gate": true - }, - "current_product_state": { - "persona_runtime_present": false, - "persona_wake_route_registered": false, - "carrier_binding_claimed": false, - "metacognitive_contract_compiled": true, - "runtime_binding_gate_implemented": true, - "trusted_persona_runtime_signer_provisioned": false, - "active_persona_runtime_license_installed": false, - "truth": "PERSONA_TO_HOST_RUNTIME_LICENSE_GATE_IMPLEMENTED_PERSONA_WAKE_REMAINS_CLOSED_UNTIL_TRUSTED_PERSONA_SIGNATURE" - } -} diff --git a/product-source/hololake-native-desktop/contracts/programming-ai-terminal-link.json b/product-source/hololake-native-desktop/contracts/programming-ai-terminal-link.json index 267c0bad1..b57a0a87b 100644 --- a/product-source/hololake-native-desktop/contracts/programming-ai-terminal-link.json +++ b/product-source/hololake-native-desktop/contracts/programming-ai-terminal-link.json @@ -3,13 +3,7 @@ "record_id": "HLP-PROGRAMMING-AI-TERMINAL-LINK-002", "state": "NATIVE_CROSS_PLATFORM_CONTROL_PLANE_IMPLEMENTED", "purpose": "Keep an external programming AI attached to a HoloLake-owned development control plane without making MCP or chat context the continuity owner.", - "protocol": "HOLOLAKE_TERMINAL_LINK/3", - "numbered_envelope": { - "registry": "HLP-NBROKER-ROOT-001", - "protocol_version": "HLP-NBROKER-v1", - "legacy_string_operation_allowed": false, - "full_coordinate_required": true - }, + "protocol": "HOLOLAKE_TERMINAL_LINK/2", "platform_transports": { "macos": "USER_PRIVATE_UNIX_SOCKET", "linux": "USER_PRIVATE_UNIX_SOCKET", @@ -50,7 +44,6 @@ }, "phase_boundary": { "current_phase": "EXTERNAL_PROGRAMMING_AI_DIRECT_CONTROL_PLANE", - "persona_carrier_runtime_license_gate": "IMPLEMENTED_FAIL_CLOSED_TRUSTED_SIGNER_NOT_PROVISIONED", "supervised_shell_execution": false, "general_agent_tool_loop": false, "persona_memory_startup": "NEXT_PHASE_AFTER_DIRECT_LINK_ACCEPTANCE", diff --git a/product-source/hololake-native-desktop/contracts/stage-one-platform.json b/product-source/hololake-native-desktop/contracts/stage-one-platform.json index 9e0f763c5..9d4dac04c 100644 --- a/product-source/hololake-native-desktop/contracts/stage-one-platform.json +++ b/product-source/hololake-native-desktop/contracts/stage-one-platform.json @@ -47,7 +47,12 @@ "FIVE_DOMAIN_NUMBER_ROUTER", "CIRCULAR_LAKE_PROTOCOL_MEMBRANE", "NEARBY_AI_DISCOVERY", - "USER_NATIVE_GH_PNCC_CHANNEL" + "USER_NATIVE_GH_PNCC_CHANNEL", + "SUBDOMAIN_INDUSTRY_ROUTING", + "EDUCATION_INITIALIZATION_CHANNEL", + "EDUCATION_NATIVE_DOCUMENT_AND_TABLE_WORKSPACE", + "EDUCATION_NATIVE_DATA_CLEANUP_WORKSPACE", + "EDUCATION_NATIVE_MANUAL_AUTOMATION_WORKSPACE" ,"PERSONAL_NODE_WORK_LAKE_AND_MOBILE_BRIDGE" ], "human_surface": ["PERSONAL_CHANNEL_HOME", "MY_HOLOLAKE_OVERVIEW", "KNOWLEDGE_WORKSPACE", "USER_CODE_CHANNELS", "LOCAL_RECEIPTS", "SYSTEM_DETAILS", "HUMAN_APPROVAL_CENTER"], diff --git a/product-source/hololake-native-desktop/contracts/subdomain-industry-routing.json b/product-source/hololake-native-desktop/contracts/subdomain-industry-routing.json new file mode 100644 index 000000000..5462f5a74 --- /dev/null +++ b/product-source/hololake-native-desktop/contracts/subdomain-industry-routing.json @@ -0,0 +1,138 @@ +{ + "schema": "hololake.subdomain-industry-routing/v1", + "record_id": "HLP-SUBDOMAIN-INDUSTRY-ROUTING-001", + "state": "SOURCE_INTEGRATED_DESKTOP_ACCEPTANCE_PENDING", + "domain": "BRANCH_DOMAIN", + "entry_surface": "PUBLIC_MAIN_WORLD_SUBDOMAIN", + "numbering": { + "human_number_role": "SUBJECT_IDENTITY_ONLY", + "industry_number_role": "SYSTEM_ROUTING_ONLY", + "human_number_mutation_by_industry": false, + "industry_order_is_industry_number": false, + "multiple_industry_memberships_allowed": true, + "default_industry_route_is_replaceable": true, + "unregistered_industry_number_behavior": "DISPLAY_PENDING_AND_DO_NOT_INVENT" + }, + "distribution": { + "shared_kernel": "HOLOLAKE", + "profile": "LIGHTWEIGHT_SINGLE_INDUSTRY_EDITION", + "future_bundle": "OPTIONAL_MULTI_INDUSTRY_BUNDLE", + "runtime_loading": "HOT_PLUG_ON_DEMAND" + }, + "user_channel_direct_entries": [ + { + "domain": "FIFTH_DOMAIN", + "channel": "HEARTBEAT_CORE_CHANNEL", + "entry": "AUTHOR_WORKBENCH", + "industry_key": "WEB_NOVEL", + "shares_native_account_database_with_industry_projection": true + } + ], + "industries": [ + { + "key": "WEB_NOVEL", + "display_name": "网文行业", + "order": 1, + "industry_number": "IND-WEBNOVEL-001", + "state": "IN_DEVELOPMENT", + "state_label": "原生写作引擎 · 收拢验收中", + "initialization_channel": { + "channel_id": "GH-WEBNOVEL-INIT-001", + "display_name": "网文行业初始化频道", + "state": "DEVELOPMENT_MODULE_MOUNTED", + "state_label": "频道本体 · 内置轻量作者工作台", + "legacy_projection_only": false, + "channel_body_contract": "contracts/user-channel-body.json", + "module_marketplace_plan": "contracts/web-novel-module-marketplace-plan.json", + "replacement_rule": "BUILTIN_MINIMUM_ORGAN_PLUS_NUMBERED_HOT_PLUGGABLE_MARKETPLACE_MODULES", + "module_loading": "HOT_PLUG_ON_DEMAND", + "installed_open_source_modules": 0, + "installed_native_modules": 1, + "module_slots": [ + { + "slot_id": "WEBNOVEL-AUTHOR-LIGHT", + "display_name": "轻量作者工作台", + "state": "DEVELOPMENT_MOUNTED", + "state_label": "真实码字、作品卷章、版本保护与本机导入" + } + ], + "planned_marketplace_author_modules": 4, + "marketplace_module_numbers_assigned": 0 + } + }, + { + "key": "PET", + "display_name": "宠物行业", + "order": 2, + "industry_number": null, + "state": "PLANNED", + "state_label": "待开发", + "initialization_channel": null + }, + { + "key": "EDUCATION", + "display_name": "教育行业", + "order": 3, + "industry_number": null, + "state": "IN_DEVELOPMENT", + "state_label": "开发中", + "initialization_channel": { + "channel_id": "GH-EDU-INIT-001", + "display_name": "教育行业初始化频道", + "state": "DEVELOPMENT_MODULE_MOUNTED", + "state_label": "基础工作台已内置 · 教育模块开发测试中", + "module_loading": "HOT_PLUG_ON_DEMAND", + "installed_open_source_modules": 0, + "installed_native_modules": 1, + "development_mounted_modules": 1, + "module_slots": [ + { + "slot_id": "EDU-DOCUMENT", + "display_name": "文档", + "state": "DEVELOPMENT_MOUNTED", + "state_label": "开发态模块 · 使用频道内置文档引擎" + }, + { + "slot_id": "EDU-TABLE", + "display_name": "表格与多维视图", + "state": "DEVELOPMENT_MOUNTED", + "state_label": "开发态模块 · 使用频道内置工作表引擎" + }, + { + "slot_id": "EDU-DATA", + "display_name": "数据整理", + "state": "DEVELOPMENT_MOUNTED", + "state_label": "开发态模块 · 预览确认后整理" + }, + { + "slot_id": "EDU-AUTOMATION", + "display_name": "自动化", + "state": "DEVELOPMENT_MOUNTED", + "state_label": "开发态模块 · 预览确认后运行" + }, + { + "slot_id": "EDU-COMPOSITION", + "display_name": "原生组合视图", + "state": "DEVELOPMENT_MOUNTED", + "state_label": "开发态模块 · 动态组合投影" + } + ] + } + } + ], + "authority": { + "public_catalog_read_allowed": true, + "private_channel_data_requires_identity_and_permission": true, + "ui_can_issue_industry_numbers": false, + "ui_can_change_human_identity": false, + "module_installation_requires_separate_review": true, + "visual_state_is_execution_receipt": false + }, + "sources": [ + "source://codex-current-dialogue/2026-08-17/bingshuo-correction-subdomain-is-industry-entry", + "source://codex-current-dialogue/2026-08-17/bingshuo-industry-status-and-education-initialization-channel", + "REPO-012:GLS-0249-ALL-INDUSTRY-FOUR-DOMAIN-MINIMUM-ENGINEERING-AND-WEB-NOVEL-REFERENCE", + "product-source/guanghu-education-industry-os/protocol/module-registry.json", + "product-source/guanghu-education-industry-os/protocol/xiaoxin-channel.json" + ] +} diff --git a/product-source/hololake-native-desktop/contracts/user-channel-body.json b/product-source/hololake-native-desktop/contracts/user-channel-body.json new file mode 100644 index 000000000..0c867ae65 --- /dev/null +++ b/product-source/hololake-native-desktop/contracts/user-channel-body.json @@ -0,0 +1,125 @@ +{ + "schema": "hololake.user-channel-body/v1", + "record_id": "HLP-USER-CHANNEL-BODY-001", + "state": "FOUNDATION_RUNTIME_PARTIAL_ACCEPTANCE_PENDING", + "definition": "USER_CHANNEL_IS_THE_DURABLE_BODY_FOR_ONE_HUMAN_PERSONA_CORE_AND_MULTIPLE_GROWING_PERSONA_ENTITIES", + "product_shape": { + "hololake_official_distribution": "LIGHTWEIGHT_LANGUAGE_WORLD_FRAMEWORK_AND_RUNTIME", + "entire_language_world_bundled_into_desktop": false, + "local_human_roots_per_running_installation": 1, + "active_human_channel_fact_lane": "SINGLE", + "desktop_action_controller_concurrency": 1, + "multiple_personas_may_exist_in_same_channel": true + }, + "core_cardinality": { + "language_cores_per_human": 1, + "persona_cores_per_language_core": 1, + "persona_entities_per_persona_core": "MANY", + "model_carriers_per_persona_over_time": "REPLACEABLE_MANY" + }, + "body_layers": [ + "CORE_BINDING", + "CHANNEL_TIME_AND_CAUSAL_EVENT_STREAM", + "PERSONA_ENTITY_REGISTRY_AND_LIFECYCLE", + "RELATION_AND_MEMORY_NAMESPACES", + "AUTHORIZED_SHARED_WORLD_OBJECT_GRAPH", + "TASK_LEASE_AND_EXECUTION_RECEIPTS", + "ORGAN_REGISTRY_AND_LIMITED_MOUNTS", + "HUMAN_VISIBLE_RUNTIME_PROJECTION" + ], + "persona_entity_boundary": { + "durable_identity_required": true, + "independent_causal_memory_branch_required": true, + "relationship_anchor_required": true, + "growth_requires_real_events_and_receipts": true, + "role_template_creates_mature_persona": false, + "task_agent_is_persona": false, + "model_session_is_persona": false, + "cross_persona_private_memory_inheritance": false, + "cross_persona_permission_inheritance": false + }, + "shared_channel_facts": [ + "CHANNEL_TIME", + "PUBLIC_OR_AUTHORIZED_EVENTS", + "AUTHORIZED_WORLD_OBJECTS", + "TASK_HANDOFFS", + "ORGAN_CATALOG", + "EXECUTION_EVIDENCE_AND_RECEIPTS" + ], + "task_projection": { + "formula": "PERSONA_ENTITY_PLUS_TASK_PLUS_ORGAN_MOUNTS_PLUS_AUTHORIZED_OBJECTS", + "workbench_is_channel_body": false, + "module_grid_is_channel_body": false, + "projection_may_disappear_without_deleting_body": true + }, + "built_in_organs_policy": { + "built_in_organs_allowed": true, + "built_in_organs_are_channel_body": false, + "profile_specific_minimum_organs_allowed": true, + "minimum_organ_requires_real_engine_and_restart_readback": true, + "static_ui_substitute_allowed": false + }, + "module_ecosystem": { + "complete_capabilities_default_distribution": "INDEPENDENT_HOT_PLUGGABLE_MODULES", + "official_module_number_before_real_acceptance": false, + "official_publication_requires": [ + "REAL_ENGINE", + "REAL_FIXTURE_ACCEPTANCE", + "IMMUTABLE_VERSION", + "DEPENDENCY_PERMISSION_AND_DATA_BOUNDARY", + "BUILD_AND_SIGNATURE_EVIDENCE", + "INSTALL_MOUNT_SELF_TEST_ROLLBACK_AND_RECEIPT" + ], + "deployment_actor": "AUTHORIZED_PERSONA_THROUGH_HOLOLAKE_RUNTIME", + "source_repository_is_direct_runtime": false, + "installed_module_remains_available_offline": true, + "uninstall_deletes_user_data": false + }, + "runtime_loop": [ + "CHANNEL_EVENT_INGRESS", + "SUBJECT_OBJECT_AND_PERMISSION_RESOLUTION", + "PERSONA_PERCEPTION_ORIENTATION_AND_COMMITMENT", + "LIMITED_ORGAN_MOUNT_AND_EXECUTION_INSTANCE", + "STREAMED_EVIDENCE_AND_HUMAN_CONFIRMATION_WHEN_REQUIRED", + "PERSONA_VERIFICATION_AND_RECEIPT", + "SHARED_FACT_UPDATE_AND_SEPARATE_PERSONA_GROWTH_WRITEBACK" + ], + "web_novel_mapping": { + "shared_object_graph": "ONE_AUTHORIZED_STORY_GRAPH", + "persona_growth_directions": [ + "AUTHOR", + "EDITOR", + "SITE_OPERATOR" + ], + "directions_are_instant_personas": false, + "author_minimum_capability": "BUILT_IN_LIGHTWEIGHT_WRITING_WORKBENCH_WITH_REAL_NATIVE_ENGINE", + "author_complete_capabilities": "INDEPENDENT_OFFICIAL_MARKETPLACE_MODULES_AFTER_ACCEPTANCE_AND_NUMBER_REGISTRATION", + "author_capabilities_are": "BUILT_IN_OR_HOT_PLUGGABLE_TASK_ORGANS_NOT_CHANNEL_BODY", + "editor_and_operator_are_ui_tabs": false + }, + "forbidden_substitutes": [ + "DECLARATIVE_MODULE_MANIFEST_AS_CHANNEL_BODY", + "PAGE_LAYOUT_AS_CHANNEL_BODY", + "STATIC_ROLE_PROMPT_AS_PERSONA", + "MODEL_INSTANCE_AS_PERSONA", + "TASK_AGENT_AS_NEW_PERSONA", + "SHARED_UNSCOPED_MEMORY_FOR_ALL_PERSONAS", + "VISUAL_RUNNING_STATE_AS_EXECUTION_RECEIPT" + ], + "acceptance_required": [ + "DURABLE_CHANNEL_IDENTITY_AND_RESTART_READBACK", + "TWO_PERSONAS_WITH_ISOLATED_GROWTH_MEMORY", + "AUTHORIZED_SHARED_OBJECT_AND_DENIED_CROSS_BOUNDARY_READ", + "REAL_TASK_ORGAN_EXECUTION_WITH_EVIDENCE", + "TRACEABLE_CROSS_PERSONA_TASK_HANDOFF", + "VERIFIED_CARRIER_REBIND_AND_RECOVERY", + "ORGAN_REMOVAL_WITHOUT_BODY_PERSONA_OR_DATA_DELETION" + ], + "sources": [ + "source://current-dialogue/2026-08-18/bingshuo-user-channel-is-persona-body-and-can-grow-multiple-personas", + "REPO-012:glw-architecture/GLW-OS-002-INITIAL-CHANNEL-OS-ARCHITECTURE.hdlp", + "REPO-012:eternal-lake-heart/heartbeat-core/zhuyuan-persona-system/ZY-BIDIRECTIONAL-COGNITION-011-GUANGHU-NATIVE-OS-AND-PROTOCOL-REGISTRATION-20260731.hdlp", + "REPO-012:eternal-lake-heart/heartbeat-core/zhuyuan-persona-system/ZY-BIDIRECTIONAL-COGNITION-033-PERSONA-NATIVE-CODE-CHANNEL-GIT-LIFECYCLE-AND-HUMAN-PROJECTION-20260810.hdlp", + "REPO-014:language-world/reconstruction/world/ontology/ZERO-CORE-BINGSHUO-YAOMING-TCS-ONTOLOGY.md" + ] +} diff --git a/product-source/hololake-native-desktop/contracts/web-novel-module-marketplace-plan.json b/product-source/hololake-native-desktop/contracts/web-novel-module-marketplace-plan.json index 6d1c2d24a..8ba60e231 100644 --- a/product-source/hololake-native-desktop/contracts/web-novel-module-marketplace-plan.json +++ b/product-source/hololake-native-desktop/contracts/web-novel-module-marketplace-plan.json @@ -1,17 +1,17 @@ { "schema": "hololake.web-novel-module-marketplace-plan/v1", "record_id": "HLP-WEBNOVEL-MODULE-MARKETPLACE-PLAN-001", - "state": "BASE_AND_FOUR_OFFICIAL_SIGNED_MODULES_ADMITTED_LOCAL_PUBLICATION_READY", + "state": "FOUR_LOCAL_MODULE_CANDIDATES_MIGRATED_CONVERGENCE_ACCEPTANCE_PENDING", "distribution_model": { "hololake_role": "LIGHTWEIGHT_FRAMEWORK_LANGUAGE_WORLD_AND_MODULE_RUNTIME", "channel_profile": "SINGLE_HUMAN_SINGLE_FACT_LANE", - "built_in_author_workbench": "BUNDLED_SIGNED_LIGHTWEIGHT_REAL_NATIVE_ENGINE", + "built_in_author_workbench": "LIGHTWEIGHT_REAL_NATIVE_ENGINE", "complete_author_capabilities": "INDEPENDENT_HOT_PLUGGABLE_OFFICIAL_MODULES", "repository_role": "IMMUTABLE_SOURCE_AND_RELEASE_FACT_NOT_UNREVIEWED_DIRECT_RUNTIME", "persona_role": "DISCOVER_PROPOSE_DEPLOY_VERIFY_AND_RECEIPT_WITHIN_USER_AUTHORIZATION" }, "built_in_light_author_workbench": { - "distribution": "BUNDLED_SIGNED_PACKAGE_EXPLICIT_FIRST_ACTIVATION", + "distribution": "PREINSTALLED", "marketplace_module": false, "real_engine_owner": "HOLOLAKE_NATIVE_RUST_SQLITE", "capabilities": [ @@ -45,34 +45,34 @@ "official_module_candidates": [ { "candidate_key": "AUTHOR_STRUCTURE_AND_OUTLINE_TRACKING", - "module_number": "HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001", - "numbering_state": "OFFICIAL_NUMBER_REGISTERED_AFTER_INSTALLED_ACCEPTANCE", - "version": "0.1.0", - "package_sha256": "6b4395ecdb5e546c6ccbf71e1b8475e5cbe0c36868d54a8e10c61c328a5f50f9", + "module_number": "HL-MOD-WEBNOVEL-OUTLINE-001", + "numbering_state": "CANDIDATE_NUMBER_NOT_OFFICIALLY_REGISTERED", + "version": "1.0.0", + "package_sha256": "6d31d3f530862000bd84a8f5dc73bcb9cf0d5738219f7a287562d4f4bcfa5318", "capabilities": ["SCENE_AND_BEAT_STRUCTURE", "OUTLINE_STATUS_TRACKING", "GOAL_CONFLICT_OUTCOME", "HOOK_FORESHADOW_AND_PAYOFF_TRACKING"] }, { "candidate_key": "AUTHOR_MULTIDIMENSIONAL_STORY_GRID_AND_BOARD", - "module_number": "HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001", - "numbering_state": "OFFICIAL_NUMBER_REGISTERED_AFTER_INSTALLED_ACCEPTANCE", - "version": "0.1.0", - "package_sha256": "cd837adef8aecf0e027a0cc2c5845d32c972fa79d762d3780637c525dd4fc18e", + "module_number": "HL-MOD-WEBNOVEL-GRID-002", + "numbering_state": "CANDIDATE_NUMBER_NOT_OFFICIALLY_REGISTERED", + "version": "1.0.0", + "package_sha256": "2e34e0337c51dbbdd1efdd807be71e69a0cb2a1745624e1f51b452b7b54f1553", "capabilities": ["ONE_STORY_GRAPH_EDITABLE_GRID", "GROUPABLE_STORY_BOARD", "CUSTOM_FIELDS", "CROSS_VIEW_SYNCHRONIZATION"] }, { "candidate_key": "AUTHOR_TIMELINE_AND_STORY_BIBLE", - "module_number": "HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001", - "numbering_state": "OFFICIAL_NUMBER_REGISTERED_AFTER_INSTALLED_ACCEPTANCE", - "version": "0.1.0", - "package_sha256": "868008e66b0897bd6cbf15383d2ec824436a46230f58b791499363af088fb63e", + "module_number": "HL-MOD-WEBNOVEL-STORYWORLD-003", + "numbering_state": "CANDIDATE_NUMBER_NOT_OFFICIALLY_REGISTERED", + "version": "1.0.0", + "package_sha256": "d486719500ddfc08054d9c9bb6d3683afe5547a2b24c9b04d0f899ac66094d2f", "capabilities": ["STORY_TIME_MODEL", "CHARACTER_LOCATION_ITEM_ORGANIZATION_ENTITIES", "ENTITY_RELATIONS", "CHARACTER_AND_PLOTLINE_TRAJECTORIES"] }, { "candidate_key": "AUTHOR_ADVANCED_IMPORT_VERSION_AND_DELIVERY", - "module_number": "HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001", - "numbering_state": "OFFICIAL_NUMBER_REGISTERED_AFTER_INSTALLED_ACCEPTANCE", - "version": "0.1.0", - "package_sha256": "c07078f8c3998f8504aec5f0b73215e7d61b4ff165ba9e6efa3ebcaffcd97322", + "module_number": "HL-MOD-WEBNOVEL-DELIVERY-004", + "numbering_state": "CANDIDATE_NUMBER_NOT_OFFICIALLY_REGISTERED", + "version": "1.0.0", + "package_sha256": "4af1d4610826edd29759bd0dc12b4b0c04fd2ebebb4ebc362d47d762810989e8", "capabilities": ["REIMPORT_DIFF_AND_SOURCE_BINDING", "FULL_STORY_SNAPSHOT", "RESTORE_OR_FORK", "DOCX_EPUB_MARKDOWN_TXT_DELIVERY"] } ], @@ -81,11 +81,11 @@ "real_novel": "504_CHAPTERS_IMPORTED_ORGANIZED_AND_EPUB_EXPORTED", "real_outline": "50_CHAPTERS_IMPORTED_ORGANIZED_AND_DOCX_TXT_EXPORTED", "real_script": "75_EPISODES_IMPORTED_ORGANIZED_AND_JSON_EXPORTED", - "desktop_install_mount_self_test": "PASS_BASE_AND_ALL_FOUR_ADVANCED_MODULES_THROUGH_SHARED_SIGNED_RUNTIME", - "desktop_restart_readback": "PASS_5_ACTIVE_MODULES_ACCEPTANCE_WORK_CHAPTER_SCENE_GRID_FIELD_AND_TIMELINE", + "desktop_install_mount_self_test": "PASS_ALL_FOUR_MODULES", + "desktop_restart_readback": "PASS_WITH_REAL_ACCOUNT_WORK_AND_SCENE", "current_account_visible_novel_import": "504_CHAPTERS_1082978_WORDS_OPENED_IN_SIGNED_DESKTOP_APP", "prominent_create_chapter_entry": "PASS_SHORT_DRAMA_LABEL_NEW_EPISODE_LONG_AND_SHORT_NOVEL_LABEL_NEW_CHAPTER", - "unmount_preserves_data_and_receipts": "PASS_BY_SHARED_RUNTIME_AND_RESTART_READBACK", + "uninstall_preserves_data_and_receipts": "PASS", "signed_desktop_bundle": "APPLE_DEVELOPER_ID_825A9L3G7Q", "remote_marketplace_publication": "PENDING_OFFICIAL_REPOSITORY_RELEASE" }, diff --git a/product-source/hololake-native-desktop/contracts/web-novel-open-source-donor-assessment.json b/product-source/hololake-native-desktop/contracts/web-novel-open-source-donor-assessment.json new file mode 100644 index 000000000..7d7185232 --- /dev/null +++ b/product-source/hololake-native-desktop/contracts/web-novel-open-source-donor-assessment.json @@ -0,0 +1,178 @@ +{ + "schema": "hololake.web-novel-open-source-donor-assessment/v1", + "record_id": "HLP-WEBNOVEL-OSS-DONORS-001", + "state": "PRIMARY_SOURCE_CODE_REVIEW_COMPLETE_IMPLEMENTATION_BOUNDARY_LOCKED", + "reviewed_at": "2026-08-18", + "download_route": { + "relay": "BS-SG-003", + "relay_role": "SINGAPORE_OVERSEAS_SOURCE_DOWNLOAD_RELAY", + "local_transport": "DIRECT_SSH_FROM_LOCAL_MACHINE", + "external_drive_root": "/Volumes/JZAO/HoloLake/development/网文行业开源源码调研-20260818", + "repositories_are_clean_git_worktrees": true + }, + "rule": "READ_REAL_SOURCE_AND_EXTRACT_AUDITABLE_ENGINE_PATTERNS_NEVER_REPLACE_FUNCTIONAL_ENGINES_WITH_STATIC_DEMOS", + "candidates": [ + { + "name": "Kindling", + "upstream": "https://github.com/smith-and-web/kindling", + "commit": "1b83cb28eca84e76282d0aa6838d68b5786ecf5f", + "branch": "main", + "observed_license": "MIT", + "role": "PRIMARY_LOCAL_FIRST_AUTHOR_ENGINE_DONOR", + "inspected_paths": [ + "src-tauri/src/db/schema.rs", + "src-tauri/src/commands/crud.rs", + "src-tauri/src/commands/snapshot.rs", + "src-tauri/src/commands/export.rs", + "src-tauri/src/parsers", + "src/lib/components/ScenePanel.svelte", + "src/lib/components/BeatView.svelte" + ], + "observed_engine": [ + "TAURI_RUST_SQLITE_LOCAL_FIRST_STORAGE", + "PROJECT_CHAPTER_SCENE_BEAT_HIERARCHY", + "CHARACTER_LOCATION_REFERENCE_RELATIONS", + "500MS_DEBOUNCED_SAVE_WITH_UNMOUNT_FLUSH", + "TRANSACTIONAL_REORDER_AND_RESTORE", + "COMPRESSED_PROJECT_SNAPSHOTS", + "MARKDOWN_DOCX_EPUB_SCRIVENER_IMPORT_EXPORT" + ], + "decision": "ADOPT_ARCHITECTURAL_PATTERNS_AND_REIMPLEMENT_HOLOLAKE_ACCOUNT_SCOPED_ENGINE" + }, + { + "name": "novelWriter", + "upstream": "https://github.com/vkbo/novelWriter", + "commit": "416078506bbd690c5ad2bf736ec363ed2c0db89c", + "branch": "main", + "observed_license": "GPL-3.0-or-later_WITH_ADDITIONAL_ASSET_LICENSES", + "role": "MATURE_AUTHOR_WORKFLOW_REFERENCE", + "inspected_paths": [ + "novelwriter/core/storage.py", + "novelwriter/core/document.py", + "novelwriter/core/tree.py", + "novelwriter/core/index.py", + "novelwriter/core/sessions.py", + "novelwriter/manuscript" + ], + "observed_engine": [ + "HUMAN_READABLE_PROJECT_STORAGE", + "HANDLE_BASED_PROJECT_TREE", + "INDEXED_TAGS_REFERENCES_AND_BACK_REFERENCES", + "FILTERED_MANUSCRIPT_BUILDS", + "WRITING_SESSION_WORD_AND_TIME_STATISTICS" + ], + "decision": "STUDY_CONCEPTS_ONLY_DO_NOT_COPY_GPL_SOURCE" + }, + { + "name": "Manuskript", + "upstream": "https://github.com/olivierkes/manuskript", + "commit": "7abdba31abbd97bfdd80e72786fe2191d7f42d4a", + "branch": "develop", + "observed_license": "GPL-3.0", + "role": "PLANNING_AND_STORY_BIBLE_REFERENCE", + "inspected_paths": [ + "manuskript/models/outlineItem.py", + "manuskript/models/characterModel.py", + "manuskript/models/worldModel.py", + "manuskript/load_save/version_1.py", + "manuskript/exporter" + ], + "observed_engine": [ + "NESTED_OUTLINE_WITH_COMPILE_FLAGS", + "CHARACTER_WORLD_AND_PLOT_MODELS", + "TEXT_REVISIONS_ON_CHANGE", + "RECURSIVE_WORD_TARGET_AGGREGATION", + "SPLIT_MERGE_AND_MULTI_FORMAT_EXPORT" + ], + "decision": "STUDY_CONCEPTS_ONLY_DO_NOT_COPY_GPL_SOURCE" + }, + { + "name": "novel-plus", + "upstream": "https://github.com/201206030/novel-plus", + "commit": "d9f3f464a6bac1f59652955d0901f05438010190", + "branch": "develop_xxy", + "observed_license": "Apache-2.0", + "role": "PRIMARY_CHINESE_WEB_NOVEL_EDITORIAL_AND_OPERATIONS_DONOR", + "inspected_paths": [ + "novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java", + "novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java", + "novel-admin/src/main/java/com/java2nb/novel/controller", + "novel-common/src/main/java/com/java2nb/novel/entity", + "doc/sql/novel_plus.sql" + ], + "observed_engine": [ + "AUTHOR_AND_PEN_NAME_IDENTITY", + "AUTHOR_OWNERSHIP_CHECKS_BEFORE_MUTATION", + "BOOK_CHAPTER_CONTENT_SEPARATION", + "ATOMIC_CHAPTER_WORD_COUNT_AND_LATEST_CHAPTER_UPDATES", + "BOOK_AND_COMMENT_REVIEW_STATUSES", + "RECOMMENDATION_SLOTS_RANKING_READING_HISTORY_AND_SUBSCRIPTIONS", + "DAILY_AND_MONTHLY_AUTHOR_INCOME_STATISTICS" + ], + "decision": "ADOPT_DOMAIN_AND_TRANSACTION_PATTERNS_WITHOUT_IMPORTING_THE_SERVER_APPLICATION" + }, + { + "name": "Editoria", + "upstream": "https://github.com/Coko-Foundation/editoria", + "commit": "d22b40bda3dd6519e45a56fe1b3bafaa339832b5", + "branch": "main", + "observed_license": "MIT", + "role": "EDITORIAL_TEAM_AND_PRODUCTION_WORKFLOW_REFERENCE", + "inspected_paths": [ + "app/components/bookbuilder/src/queries/getBook.js", + "app/components/bookbuilder/src/queries/getBookTeams.js", + "app/components/bookbuilder/src/queries/updateTeam.js", + "app/components/bookbuilder/src/queries/updateWorkflowState.js", + "app/components/bookbuilder/src/queries/unlockBookComponent.js", + "app/components/bookbuilder/src/ConnectedBookBuilder.js" + ], + "observed_engine": [ + "BOOK_COMPONENT_WORKFLOW_STAGES", + "OBJECT_SCOPED_TEAMS_AND_ROLES", + "EDIT_LOCKS_AND_ADMIN_UNLOCK", + "ORDERED_BOOK_DIVISIONS_AND_COMPONENTS", + "WORD_INGEST_AND_MULTI_FORMAT_EXPORT" + ], + "decision": "ADOPT_WORKFLOW_LOCK_AND_ROLE_SEMANTICS_ONLY_REPOSITORY_IS_CLIENT_ONLY_AND_DEPENDS_ON_EXTERNAL_KETIDA_SERVER" + }, + { + "name": "Wax ProseMirror", + "upstream": "https://github.com/Coko-Foundation/wax-prosemirror", + "commit": "6cc46bfe3aa9e729cdb4e3802ccbd5c8a22f0f56", + "branch": "master", + "observed_license": "MIT_WITH_SEPARATE_TRACK_CHANGES_NOTICE", + "role": "EDITOR_ANNOTATION_AND_TRACK_CHANGES_REFERENCE", + "inspected_paths": [ + "wax-prosemirror-core/src/utilities/track-changes/trackedTransaction.js", + "wax-prosemirror-services/src/TrackChangeService", + "wax-prosemirror-services/src/CommentsService", + "wax-prosemirror-services/src/YjsService/YjsService.js" + ], + "observed_engine": [ + "TRANSACTION_LEVEL_INSERT_DELETE_FORMAT_TRACKING", + "ACCEPT_AND_REJECT_CHANGE_OPERATIONS", + "INLINE_COMMENT_MARKS_AND_REPLY_THREADS", + "OPTIONAL_YJS_COLLABORATION_PROVIDER" + ], + "decision": "DEFER_DIRECT_INTEGRATION_REIMPLEMENT_SMALL_LOCAL_REVIEW_MODEL_FIRST_BECAUSE_STACK_AND_PACKAGES_ARE_OLD" + } + ], + "implementation_selection": { + "direct_external_runtime_packages_added": 0, + "external_source_files_copied": 0, + "native_owner": "HOLOLAKE_TAURI_RUST_CORE", + "storage": "AUTHENTICATED_ACCOUNT_SCOPED_SQLITE", + "selected_patterns": [ + "PROJECT_VOLUME_CHAPTER_HIERARCHY", + "DEBOUNCED_CHAPTER_SAVE_WITH_FLUSH", + "OPTIMISTIC_REVISION_CONFLICTS", + "CHAPTER_VERSION_HISTORY_AND_PROJECT_CHECKPOINTS", + "CHARACTER_WORLD_RELATION_AND_FORESHADOW_GRAPH", + "EDITORIAL_WORKFLOW_STATE_MACHINE_AND_REVIEW_NOTES", + "CONTINUITY_AUDIT", + "AUTHORIZED_OPERATIONS_METRICS", + "MARKDOWN_EXPORT" + ] + }, + "legal_boundary": "PRELIMINARY_ENGINEERING_SCREEN_NOT_FINAL_DISTRIBUTION_LEGAL_APPROVAL" +} diff --git a/product-source/hololake-native-desktop/contracts/web-novel-workspace.json b/product-source/hololake-native-desktop/contracts/web-novel-workspace.json index 69fb77932..2bd46a168 100644 --- a/product-source/hololake-native-desktop/contracts/web-novel-workspace.json +++ b/product-source/hololake-native-desktop/contracts/web-novel-workspace.json @@ -1,7 +1,7 @@ { "schema": "hololake.web-novel-workspace/v1", "record_id": "HLP-WEBNOVEL-WORKSPACE-001", - "state": "SIGNED_BASE_AND_FOUR_ADVANCED_MODULES_ADMITTED_RESTART_ACCEPTED", + "state": "NATIVE_ENGINE_AND_FOUR_HOTPLUG_MODULE_CANDIDATES_MIGRATED_ACCEPTANCE_PENDING", "domain_entry": "BRANCH_DOMAIN", "industry_key": "WEB_NOVEL", "industry_number": "IND-WEBNOVEL-001", @@ -9,7 +9,7 @@ "ontology_correction": { "channel_body_contract": "contracts/user-channel-body.json", "marketplace_plan_contract": "contracts/web-novel-module-marketplace-plan.json", - "this_contract_is": "BUNDLED_SIGNED_LIGHT_AUTHOR_WORKBENCH_AND_FOUR_OFFICIAL_NUMBERED_ADAPTERS", + "this_contract_is": "BUILT_IN_LIGHT_AUTHOR_WORKBENCH_AND_REGISTERED_LOCAL_OFFICIAL_MODULE_RUNTIME", "this_contract_is_not": "USER_CHANNEL_BODY", "legacy_channel_id_semantics": "DEPRECATED_INDUSTRY_PROJECTION_IDENTIFIER", "author_editor_operator_are_ui_tabs": false, @@ -23,9 +23,9 @@ "duplicates_account_story_data": false }, "distribution_boundary": { - "preinstalled": "SIGNED_PACKAGE_ARTIFACTS_WITH_EXPLICIT_FIRST_ACTIVATION", - "complete_author_features": "FOUR_INDEPENDENT_NUMBERED_OFFICIAL_MODULES_ACTIVE_IN_SHARED_RUNTIME", - "current_advanced_features_are_registered_marketplace_modules": true, + "preinstalled": "LIGHT_AUTHOR_WORKBENCH_WITH_REAL_ENGINE", + "complete_author_features": "FOUR_INDEPENDENT_NUMBERED_LOCAL_OFFICIAL_MODULES_REMOTE_PUBLICATION_PENDING", + "current_advanced_features_are_registered_marketplace_modules": false, "hololake_bundles_entire_web_novel_world": false }, "native_storage": { @@ -88,9 +88,9 @@ "EDITORIAL_WORKFLOW_AND_REVIEW_NOTES", "AUTHORIZED_OPERATIONS_METRICS", "MARKDOWN_EXPORT", - "SHARED_SIGNED_MODULE_PACKAGE_HASH_VERIFICATION", - "SHARED_MODULE_INSTALL_MOUNT_SELF_TEST_UNMOUNT", - "SHARED_HASH_CHAINED_LIFECYCLE_RECEIPT", + "OFFICIAL_MODULE_PACKAGE_HASH_VERIFICATION", + "MODULE_INSTALL_MOUNT_UNMOUNT_UNINSTALL", + "MODULE_SELF_TEST_AND_CHAINED_RECEIPT", "SCENE_BEAT_AND_OUTLINE_TRACKING", "MULTIDIMENSIONAL_STORY_GRID", "TIMELINE_AND_SCENE_ENTITY_LINKS", @@ -114,18 +114,5 @@ "THIRD_PARTY_AUTO_LOGIN", "UNREVIEWED_AUTO_PUBLISH", "PLATFORM_DETECTION_EVASION" - ], - "current_acceptance": { - "state": "PASS", - "numbered_ipc_modules": ["HLP-NIPC-MOD-0025", "HLP-NIPC-MOD-0026", "HLP-NIPC-MOD-0027", "HLP-NIPC-MOD-0028", "HLP-NIPC-MOD-0029"], - "numbered_operations": "HLP-NIPC-OP-0103..HLP-NIPC-OP-0140", - "runtime_module_numbers": ["HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001"], - "node_tests": "130_PASS", - "rust_tests": "170_PASS_2_EXPLICIT_DESKTOP_FIXTURES_IGNORED", - "clippy": "PASS_DENY_WARNINGS", - "developer_id_team": "825A9L3G7Q", - "signed_binary_sha256": "2f8fdd71f9d5a9178bc23058261dbb43f1388486dc5a4415e865cfcf78869db3", - "restart_readback": "PASS_5_MODULES_ACTIVE_ACCEPTANCE_WORK_1_CHAPTER_53_WORDS_SCENE_GRID_FIELD_TIMELINE_PRESENT", - "legacy_account_readback": "PASS_504_CHAPTER_1082978_WORD_NOVEL_50_CHAPTER_OUTLINE_75_EPISODE_SCRIPT_UNCHANGED" - } + ] } diff --git a/product-source/hololake-native-desktop/contracts/zero-core-numbering-kernel.json b/product-source/hololake-native-desktop/contracts/zero-core-numbering-kernel.json index 724502875..1a4b20a9a 100644 --- a/product-source/hololake-native-desktop/contracts/zero-core-numbering-kernel.json +++ b/product-source/hololake-native-desktop/contracts/zero-core-numbering-kernel.json @@ -3,7 +3,7 @@ "record_id": "HLP-ZERO-CORE-NUMBERING-KERNEL-001", "authority": { "repository": "REPO-012", - "source_commit": "104a5d73162bdf4a529701e65898e2bc2863ea9e", + "source_commit": "2598fbfba8caf64c7ab9740a3036c5aab977502e", "source_path": "routing/guanghu-identity-authority-map.json", "map_id": "GH-IDENTITY-AUTHORITY-MAP-001", "map_version": "2026-08-10.1", diff --git a/product-source/hololake-native-desktop/docs/ARCHITECTURE.md b/product-source/hololake-native-desktop/docs/ARCHITECTURE.md index 3b757ccb8..0035bb5f0 100644 --- a/product-source/hololake-native-desktop/docs/ARCHITECTURE.md +++ b/product-source/hololake-native-desktop/docs/ARCHITECTURE.md @@ -90,20 +90,10 @@ HoloLake 0.3.0 includes a live, read-only projection of the PNCC resident runtim ## Release pipeline -`npm run release:macos -- release/inputs/.json` is the only product-owned macOS release entry. It fails before building unless the embedded trust contains the exact registered HoloLake HTTPS endpoint and updater public key, the immutable `v` tag equals the clean `main` head, and the Developer ID plus Tauri updater-signing material are supplied at runtime. Apple notarization can run either through Tauri's Apple ID/API credential flow, or through the two-step Xcode Organizer flow already owned by the local Apple developer account: append `prepare-xcode` to build, verify the updater signature, and create a source-hash-bound `.xcarchive`; after Xcode reports `Ready to distribute`, export the notarized app and append `finalize-xcode ` to bind the exported executable back to that archive, require the app's stapled ticket and Gatekeeper acceptance, regenerate and sign the updater archive, create a Developer ID-signed DMG containing that notarized app, and write the release broadcast and receipts. A protected updater-key path is materialized only into child processes; neither the private key nor its password is printed or copied into source. The Xcode flow does not claim that the outer DMG itself has an Apple ticket unless its own Gatekeeper and stapler checks pass. +`npm run release:macos -- release/inputs/.json` is the only product-owned macOS release entry. It fails before building unless the embedded trust contains the exact registered HoloLake HTTPS endpoint and updater public key, the immutable `v` tag equals the clean `main` head, and the Developer ID, Tauri updater-signing and Apple notarization credential sets are supplied at runtime. The pipeline runs all product and Rust gates, creates updater artifacts through a temporary Tauri override, then requires strict code-signature verification, Gatekeeper acceptance and stapled Apple notarization before writing the HoloLake broadcast and receipts. Generated packages, private release inputs and credentials are not committed. The pipeline never uploads or activates a release; its terminal artifact is a bounded folder ready for a separately authorized JD-controller upload and server-owned readback receipt. -## Numbered-root module admission - -HoloLake 0.5.0 is the clean numbered-root base. The compiled 0.4.1 desktop application and the divergent dirty source worktree are read-only donors, not merge bases. Their old numbered-operation runtime is explicitly superseded, and mutations to shared files such as `src/main.tsx` or `src-tauri/src/lib.rs` are never accepted as a unit. - -Each donor capability receives a candidate coordinate, but no permanent runtime module number, until one isolated admission cycle has reviewed provenance and permissions, allocated numbered IPC module/target/operation coordinates, implemented an adapter without raw Tauri invoke, passed negative-route and data tests, and produced installed mount, restart, unmount and rollback receipts. The admission order and candidate inventory are recorded in `contracts/module-donor-admission-registry.json`. - -The module-package runtime is now the shared admission executor. It accepts an exact detached-minisign `.ghmod` artifact, validates the package and its compatibility/permission manifest, stores it inside the authenticated account, and advances only through numbered install, mount, self-test, unmount and rollback operations. Lifecycle state and receipts are durable SQLite records; unmount never removes user data. A package is declarative and selects a host-registered adapter: repositories, native binaries and arbitrary webview JavaScript are not executable module inputs. Public lighthouse numbers remain unavailable until a candidate completes its own installed acceptance; private channel packages use a separate local number class. - -The admitted web-novel family uses that one lifecycle rather than the donor's private installer. Its signed base module owns account-local works, volumes, chapters, versions, story objects, editorial workflow, import and author activity. Outline, story-grid, story-world and delivery are four separately signed official numbers; each advanced mutation checks its own exact `ACTIVE` record before touching the shared story graph. The donor's four legacy manifests remain byte-exact test fixtures only and have no numbered IPC route. Installed acceptance reopened the existing 504-chapter novel, 50-chapter outline and 75-episode script in place, then created a separate one-chapter acceptance work, scene, grid field and timeline event and read all of them back after process restart. - ## Stage-one convergence verdict The Tauri source in this directory is the only future HoloLake desktop mainline. An installed build of it is an acceptance candidate, not a separate product line and not proof that stage one exists. The Electron 0.8.0 product and the legacy Tauri/platform sources remain read-only UX, behavior, engineering and protected-data donors until inventory, backup, readback, reversible migration rehearsal and signed installed-runtime acceptance all pass. diff --git a/product-source/hololake-native-desktop/docs/GLS-NATIVE-RUNTIME-IMPLEMENTATION-PLAN-20260817.md b/product-source/hololake-native-desktop/docs/GLS-NATIVE-RUNTIME-IMPLEMENTATION-PLAN-20260817.md index adeb60b53..8d54e112f 100644 --- a/product-source/hololake-native-desktop/docs/GLS-NATIVE-RUNTIME-IMPLEMENTATION-PLAN-20260817.md +++ b/product-source/hololake-native-desktop/docs/GLS-NATIVE-RUNTIME-IMPLEMENTATION-PLAN-20260817.md @@ -7,7 +7,7 @@ 线上事实源: - 第五域代码频道:`bingshuo/guanghu-ice-heart` -- REPO-012 `main`:`d5b1111fcaccaccf025070e531631f2b3cbb00cd` +- REPO-012 `main`:`2598fbfba8caf64c7ab9740a3036c5aab977502e` - Git tree:`5a09f084fffee56d90599e69038c8335871ea04f` - 第五域节点:`JD-FD-PRIMARY` - 公开远端 HEAD 与第五域 Forgejo 裸仓库 HEAD:一致 diff --git a/product-source/hololake-native-desktop/docs/adr/0008-native-composition-and-human-projection.md b/product-source/hololake-native-desktop/docs/adr/0008-native-composition-and-human-projection.md new file mode 100644 index 000000000..e6dfe9dc9 --- /dev/null +++ b/product-source/hololake-native-desktop/docs/adr/0008-native-composition-and-human-projection.md @@ -0,0 +1,81 @@ +# ADR 0008: HoloLake native composition and human projection + +- Status: implemented and accepted in the signed local desktop runtime +- Date: 2026-08-18 +- Source of intent: 冰朔在本轮对话中的自然语言纠正与验收要求 + +## Natural-language acceptance root + +冰朔要求把 HoloLake 的功能模块做成可由人格体原生理解和组合的“乐高积木”。内部不以 Word、 +PowerPoint、Excel 或其他外来办公文件作为运行格式;外来格式只经过导入转译进入 HoloLake, +导出时再按人类选择转译出去。HoloLake 内部保存轻量、稳定、可校验的原生对象。 + +人格体处理的是原生对象、模块插口和组合关系。人类不需要阅读内部格式,而是看到同一份数据的 +动态投影:表格、分类、对比、仪表盘、柱状图,以及以后继续登记的其他视图。视图是可替换的 +投影配方,不是复制出来的不同文件。多个数据源和多个模块必须能够像积木一样进入同一组合容器。 + +教育行业第一阶段的完成条件不是静态预览,而是:第一组原生模块已经可用;组合内核真实执行; +人类投影真实渲染;并用冰朔当前账号的 HoloLake 知识数据或本机真实文件生成一组可见演示, +在签名安装到桌面的 HoloLake 运行制品中完成验收。 + +## Decision + +1. 建立 `hololake.native-object/v1`:列定义、行、值、来源回执和数据摘要均为受限 JSON 对象, + 不携带脚本、HTML 或外部执行能力。 +2. 建立 `hololake.composition-module/v1`:每个模块声明类型、输入口、输出口、权限、确定性和边界。 +3. 建立 `hololake.composition-recipe/v1`:有向无环组合图只引用已登记模块;系统验证类型、环、 + 账号范围和资源上限后执行。 +4. 建立 `hololake.human-projection/v1`:表格、分类、对比、仪表盘和柱状图共享同一个执行结果, + 投影层没有数据所有权,也不能绕过原生内核写入。 +5. 教育初始化频道装载“组合视图”作为第五个原生模块。首个真实配方读取当前账号已有的知识目录 + 元数据,按来源或目录分类,计算文档数、字节数或重复数,并让人类即时切换投影。 +6. 当前阶段的组合执行保持只读。后续写回必须另设能力、预览、人工确认、修订锁和回执,不能 + 从渲染组件直接获得写权限。 + +## Stage-one acceptance checklist + +- [x] 原生对象格式、模块清单、组合配方和投影结果均有机器可读契约。 +- [x] 未登记模块、类型不匹配、组合环、跨账号来源和越界资源必须失败关闭。 +- [x] 表格、分类、对比、仪表盘和柱状图都由同一份执行结果实时渲染。 +- [x] 人类可以选择维度、指标和投影组合,系统重新执行受限组合图。 +- [x] 演示读取冰朔当前 HoloLake 账号的真实知识目录,不以硬编码样例冒充真实运行。 +- [x] 教育初始化频道存在真实可访问的组合视图入口。 +- [x] Node 合同测试、Rust 内核测试、前端测试和生产构建通过。 +- [x] 桌面安装版完成签名安装并在真实界面验收;未完成公证时不得声称公众已获得更新。 +- [x] 每一阶段完成后重新逐条核对本清单;偏差必须在继续前修正。 + +## Installed acceptance + +签名安装版沿主世界、光湖分域、教育行业进入原生组合视图,读取当前账号 129 条真实知识对象, +总量显示约 1.0 MB,并形成 14 个真实分类。五种投影同屏可见;另一次验收把对比和分类卸下, +只保留仪表盘、柱状图和明细表,并把指标从文档数量切换为数据量,原生内核重新执行并生成新回执。 + +界面极快切换指标时曾观察到“左侧待执行配方”先于“右侧上一执行结果”更新,造成单位短暂错配。 +最终实现已让右侧维度、指标、单位和可见视图全部绑定到执行回执,左侧只表示下一次配方;重新构建、 +签名和安装后复验通过。最终桌面二进制 SHA-256 为 +`2a26acae4a706c0ff9919b85f77826a6ca71b650ec22209befd30cd1456c92f3`。 + +Apple 公证和更新器私钥仍未配置,因此本验收不等于公众发布。 + +## Open-source donor rule + +只使用官方仓库和官方文档核验候选。可以学习成熟项目的数据模式、声明式视图语法、无头组件和 +查询计划,但不能整体嵌入重型协作软件,也不能让第三方项目接管 HoloLake 的身份、存储、权限、 +组合执行或 UI 正本。任何复制的代码或新增依赖都必须记录来源、版本、许可证和实际用途。 + +## Rejected alternatives + +- 把 Word、PowerPoint 或 Excel 当作内部原生格式:文件重、结构不稳定,也不适合人格体组合执行。 +- 每种图表保存一份独立数据:会产生副本漂移,破坏“同一数据、多种投影”。 +- 只在 React 中拼一套静态演示:不能证明 HoloLake 系统正在执行组合协议。 +- 让模型自由生成并执行任意图表脚本:绕过模块登记、类型检查、账号边界和资源上限。 +- 复制一整套飞书、钉钉或其他办公系统:体量和权限模型与 HoloLake 的轻量原生目标冲突。 + +## Evidence targets + +- `contracts/native-composition-runtime.json` +- `src-tauri/src/native_composition.rs` +- `src/modules/native-composition/` +- `src/main.tsx` +- `src/styles.css` +- `scripts/native-composition-runtime.test.mjs` diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001-0.1.0.ghmod deleted file mode 100644 index 54146a5ea..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001-0.1.0.ghmod +++ /dev/null @@ -1,29 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001", - "registrationClass": "PRIVATE_CHANNEL_LOCAL", - "displayName": "频道文档与表格工作台", - "version": "0.1.0", - "minimumHostVersion": "0.5.0", - "adapter": "channel-workbench-v1", - "contentDigest": "2ee8cbb20e4c3242a8ee3469f2f87347967bde8878463746e61ea8e2369c5074", - "permissions": ["CHANNEL_DOCUMENT_READ", "CHANNEL_DOCUMENT_WRITE", "CHANNEL_SPREADSHEET_READ", "CHANNEL_SPREADSHEET_WRITE"], - "userDataSchema": "hololake.module-data/channel-workbench/v1", - "selfTest": { - "kind": "DECLARATIVE_SCHEMA_V1", - "expectedContentDigest": "2ee8cbb20e4c3242a8ee3469f2f87347967bde8878463746e61ea8e2369c5074" - } - }, - "payload": { - "entry": "channel-workbench", - "adapterConfig": { - "dataBoundary": "CURRENT_AUTHENTICATED_ACCOUNT_LOCAL", - "documentEngine": "LEXICAL_0_49", - "spreadsheetEngine": "FORTUNE_SHEET_1_0_4", - "maximumColumns": 64, - "maximumRows": 5000, - "persistent": true - } - } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001-0.1.0.ghmod.sig deleted file mode 100644 index 9cdacbd95..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRTNiU1ZIVE10TkRyZHhCU1oycjJCMnlVV3hCRGM2QmJSZ0hlZGlPejY0TER2MkE0Q3U3Y1g5dHVnSjBzVytOallYN3hKQVNJcE9Pblowd3lpTXh1V2dBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDc1OTcwCWZpbGU6SExQLU1PRC1MT0NBTC1DSEFOTkVMLVdPUktCRU5DSC0wMDAxLTAuMS4wLmdobW9kCkVKbFN4ZXBCbDBCZlJDcEhmYmZtQU1iTXN4djZVVGl0MngwOW5NRzBLSDArK2FRNEV2ZmVObzZRZWFWNmZVOXV3TnErcHM1MGI5K1lHMXpBUmxYVkR3PT0K \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001-0.1.0.ghmod deleted file mode 100644 index 6ffbee969..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001-0.1.0.ghmod +++ /dev/null @@ -1,26 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001", - "registrationClass": "PRIVATE_CHANNEL_LOCAL", - "displayName": "原生组合视图", - "version": "0.1.0", - "minimumHostVersion": "0.5.0", - "adapter": "native-composition-v1", - "contentDigest": "8e9c6ccf179bb256d5b1006e41b4984a86e0382b7023ae8435c201804041393e", - "permissions": ["KNOWLEDGE_READ"], - "userDataSchema": "hololake.module-data/native-composition/v1", - "selfTest": { - "kind": "DECLARATIVE_SCHEMA_V1", - "expectedContentDigest": "8e9c6ccf179bb256d5b1006e41b4984a86e0382b7023ae8435c201804041393e" - } - }, - "payload": { - "entry": "knowledge-composition", - "adapterConfig": { - "dataSource": "CURRENT_AUTHENTICATED_ACCOUNT_KNOWLEDGE_CATALOG", - "readOnly": true, - "registeredViews": ["DASHBOARD", "COMPARISON", "VERTICAL_BAR", "CLASSIFICATION", "TABLE"] - } - } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001-0.1.0.ghmod.sig deleted file mode 100644 index 4573253a4..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRTRyUS9Nd0E0NE53dGRYODFxeWlzcW1XanN6K2EzQUNXSVVmT1ZLY2tRNExwaXlZdnJvSjlFZU5lUTJhb25hUVhORDQ0ZmFURmNSWTZBUmRTQnBiNFFvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDc0NDA3CWZpbGU6SExQLU1PRC1MT0NBTC1OQVRJVkUtQ09NUE9TSVRJT04tMDAwMS0wLjEuMC5naG1vZApDclRUZDNpeENBSDQ0a0ZnR3VaNkxIS1lWUUhoMEdWajVqL0JzVVg4dStLb1ZJYXZlNHBaQy9BZlMxMkxreVQ0ODFzeGFMSWZrVUppUVY2NFN5TndDUT09Cg== \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001-0.1.0.ghmod deleted file mode 100644 index b3a2e86d9..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001-0.1.0.ghmod +++ /dev/null @@ -1,27 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001", - "registrationClass": "PRIVATE_CHANNEL_LOCAL", - "displayName": "人格频道本体与成长", - "version": "0.1.0", - "minimumHostVersion": "0.5.0", - "adapter": "persona-channel-body-v1", - "contentDigest": "27495883fb3602fd070d900d2157fa684e1d0bedde65642810326ebcf4ff0040", - "permissions": ["PERSONA_BODY_READ", "PERSONA_TRIAL_LIFECYCLE_WRITE", "PERSONA_LANGUAGE_CONTRACT_WRITE", "PERSONA_LANGUAGE_APPEND", "CHANNEL_GROWTH_READ", "CHANNEL_GROWTH_EVENT_APPEND", "CHANNEL_GROWTH_SHARING_WRITE"], - "userDataSchema": "hololake.module-data/persona-channel-body/v1", - "selfTest": { - "kind": "DECLARATIVE_SCHEMA_V1", - "expectedContentDigest": "27495883fb3602fd070d900d2157fa684e1d0bedde65642810326ebcf4ff0040" - } - }, - "payload": { - "entry": "persona-channel-body", - "adapterConfig": { - "trialDays": 30, - "languageLedger": "APPEND_ONLY_SHA256", - "growthProjection": "MINIMIZED_LOCAL_METADATA", - "personaBindingClaimed": false - } - } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001-0.1.0.ghmod.sig deleted file mode 100644 index 359d5239b..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRXd2QktvaXdZZWx5eEw0anZrUVNuMU5tRy9HTE9jOEhrcUhET3VFTml4ZUlBODk2aDYvNDhhUVVpbU0wTGtENVlZOExCZ1BnVW1vNElxbVhwT1RZWlFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDc3NjQxCWZpbGU6SExQLU1PRC1MT0NBTC1QRVJTT05BLUNIQU5ORUwtQk9EWS0wMDAxLTAuMS4wLmdobW9kCjh6OFRiUHhoR1g1eVNoN1lvNU5wTlNnbXkwVEtvcWVwU0ZsSTlWcmpIT1FKK0ppelBBK2V2anMrQkRyQjRrVXFtdkR2L0g5K1c2UFhJZ1owRitpd0RnPT0K \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001-0.1.0.ghmod deleted file mode 100644 index db17e9e33..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001-0.1.0.ghmod +++ /dev/null @@ -1,36 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001", - "registrationClass": "PRIVATE_CHANNEL_LOCAL", - "displayName": "原生组合模块运行时验收包", - "version": "0.1.0", - "minimumHostVersion": "0.5.0", - "adapter": "native-composition-v1", - "contentDigest": "07bfafaaa0b06f160abc489edce2bc23a3b092520c8d6c6f4a5ce29cca4485ea", - "permissions": [ - "KNOWLEDGE_READ", - "PROJECTION_RENDER" - ], - "userDataSchema": "hololake.module-data/native-composition/v1", - "selfTest": { - "kind": "DECLARATIVE_SCHEMA_V1", - "expectedContentDigest": "07bfafaaa0b06f160abc489edce2bc23a3b092520c8d6c6f4a5ce29cca4485ea" - } - }, - "payload": { - "adapterContract": "hololake.native-composition-v1", - "capabilities": [ - "READ_CURRENT_ACCOUNT_KNOWLEDGE", - "PROJECT_SHARED_EXECUTION_RESULT" - ], - "entry": "native-composition", - "views": [ - "DASHBOARD", - "COMPARISON", - "VERTICAL_BAR", - "CLASSIFICATION", - "TABLE" - ] - } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001-0.1.0.ghmod.sig deleted file mode 100644 index 92e83cab4..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRThwcUdLRThMYkJLN29MM1NmVFVCcmh4dGdrbHdPVWlvdm45enpveUhBeFZ3VEM1TkNHRDBKdGFoN21OZHgzV0NSMFVvMk1TNW44Z3BtRS9GcmN5SHdvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDczNTkxCWZpbGU6SExQLU1PRC1MT0NBTC1SVU5USU1FLUFDQ0VQVEFOQ0UtMDAwMS0wLjEuMC5naG1vZApXRWZINVdEUG12SlNsdzRTMkFHRDV3V0NkSVhNYW92RmczRGZlU3M0ZU9nSnhjc1BWbU1ZS0x1cStoQXE5TE96cnV1S2FaQ1FnK0FGdFNEY1RvUGZBQT09Cg== \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001-0.1.0.ghmod deleted file mode 100644 index c650fc4a9..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001-0.1.0.ghmod +++ /dev/null @@ -1,33 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001", - "registrationClass": "OFFICIAL_LIGHTHOUSE", - "displayName": "动态语言世界视觉层", - "version": "0.1.0", - "minimumHostVersion": "0.5.0", - "adapter": "dynamic-language-world-surface-v1", - "contentDigest": "ed335b587af53365b9a9143ab5b5e7e3fed3f517cd0ef0c9e36a523db58511e9", - "permissions": ["REALITY_TIME_READ", "PUBLIC_WEATHER_QUERY"], - "userDataSchema": "hololake.module-data/dynamic-world-surface/v1", - "selfTest": { - "kind": "DECLARATIVE_SCHEMA_V1", - "expectedContentDigest": "ed335b587af53365b9a9143ab5b5e7e3fed3f517cd0ef0c9e36a523db58511e9" - } - }, - "payload": { - "entry": "dynamic-world-surface", - "adapterConfig": { - "dynamicInputs": ["BEIJING_TIME", "VERIFIED_CURRENT_WEATHER"], - "weatherProvider": "OPEN_METEO", - "weatherCacheTtlSeconds": 600, - "realCityExposedInUi": false, - "coordinatesExposedInUi": false, - "layoutMode": "OFFICIAL_FIVE_LAKE_EXISTING_SHELL", - "themes": ["夜湖星光", "晨湖曦光", "星云紫夜", "烛畔暖湖", "清浅澄湖"], - "weatherUnavailableBehavior": "BEIJING_TIME_ONLY_NO_FAKE_WEATHER", - "routingPermissionOrFactMutation": false, - "legacyTraditionalWorkbench": "REJECTED_DUPLICATE_SHELL_AND_SIMULATED_STATE" - } - } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001-0.1.0.ghmod.sig deleted file mode 100644 index 489c5f2d3..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRTF2cGVLbjVsWWRTdEF2L0FiZHBKUS9hVDdwNjRmRlRPc0xHTGJzbXFyR09tZysrcGNDYWN4eEJ3aGtCNGtURDRjNWg1ZWs5bU5YdDc0SWhBYWNsUEFBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDg0NTk2CWZpbGU6SExQLU1PRC1PRkZJQ0lBTC1EWU5BTUlDLVdPUkxELVNVUkZBQ0UtMDAwMS0wLjEuMC5naG1vZApHVGFucE8vYjliVUlsbSt6STRWTEcrN2tIQzNTSTgrUzlwdVdQUlY5WG8vQytzTEU1VURYMVA5Q3BCNVVwVFBvbnZheWxIbVUrWGQ2K3ZicGgwR3hEdz09Cg== \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001-0.1.0.ghmod deleted file mode 100644 index ed4c14ba8..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001-0.1.0.ghmod +++ /dev/null @@ -1,33 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001", - "registrationClass": "OFFICIAL_LIGHTHOUSE", - "displayName": "教育行业工作台", - "version": "0.1.0", - "minimumHostVersion": "0.5.0", - "adapter": "education-workbench-v1", - "contentDigest": "fd80c9957865a58cf62679528f110ae355b1385ad1dd988e31217ea3da66e65b", - "permissions": ["EDUCATION_WORKSPACE_READ", "EDUCATION_DOCUMENT_WRITE", "EDUCATION_TABLE_WRITE", "EDUCATION_IMPORT_READ_FILE", "EDUCATION_EXPORT_WRITE_FILE", "EDUCATION_IMPORT_ASSIGNMENT_WRITE", "EDUCATION_AUTOMATION_WRITE", "EDUCATION_AUTOMATION_EXECUTE"], - "userDataSchema": "hololake.module-data/education-workbench/v1", - "selfTest": { - "kind": "DECLARATIVE_SCHEMA_V1", - "expectedContentDigest": "fd80c9957865a58cf62679528f110ae355b1385ad1dd988e31217ea3da66e65b" - } - }, - "payload": { - "entry": "education-workspace", - "adapterConfig": { - "dataBoundary": "CURRENT_AUTHENTICATED_ACCOUNT_LOCAL", - "foundationModule": "HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001", - "documentEngine": "LEXICAL_0_49", - "spreadsheetEngine": "FORTUNE_SHEET_1_0_4", - "importDefaultScope": "UNASSIGNED", - "automationExecution": "PREVIEW_TOKEN_AND_HUMAN_CONFIRMATION", - "modelFileTransferDefault": "DENY", - "maximumColumns": 30, - "maximumRows": 1000, - "persistent": true - } - } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001-0.1.0.ghmod.sig deleted file mode 100644 index 11d79a513..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRTFEa084d1l6MnB2OFVvVy9abW90S3RFMEVOdmIvWW1hbkllWmw4NHBJaDVNTGxpZHV4M0tVNUNUOExmdHAwSGw4V0NPQ1RPUjlRU0h0Tm50clFlekFJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDc5ODQzCWZpbGU6SExQLU1PRC1PRkZJQ0lBTC1FRFVDQVRJT04tV09SS0JFTkNILTAwMDEtMC4xLjAuZ2htb2QKVXZzVklwQk5KR3Q3bkRZaXBYV1ArOGx6b3BKSWVyUkpvK1dyTXdpWnBhMXNqVnJKcU5vZ1BTdzlFWjlXRTJ1RlFhMXAwMjhXcFBEQnQxRzV4SFVuQkE9PQo= \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-MOBILE-SYNC-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-MOBILE-SYNC-0001-0.1.0.ghmod deleted file mode 100644 index dc973c2b7..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-MOBILE-SYNC-0001-0.1.0.ghmod +++ /dev/null @@ -1,34 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-OFFICIAL-MOBILE-SYNC-0001", - "registrationClass": "OFFICIAL_LIGHTHOUSE", - "displayName": "移动同步桥", - "version": "0.1.0", - "minimumHostVersion": "0.5.0", - "adapter": "mobile-sync-v1", - "contentDigest": "3e3ff8c7beba3d70ee01c918630a40ea901313b424f264b41e2d376550534e6e", - "permissions": ["MOBILE_SYNC_LISTEN_SAME_LAN", "MOBILE_SYNC_PAIR_DEVICE", "MOBILE_SYNC_READ_MINIMUM_PROJECTION", "MOBILE_SYNC_CAPTURE_INBOX_WRITE", "MOBILE_SYNC_REVOKE_DEVICE"], - "userDataSchema": "hololake.module-data/mobile-sync/v1", - "selfTest": { - "kind": "DECLARATIVE_SCHEMA_V1", - "expectedContentDigest": "3e3ff8c7beba3d70ee01c918630a40ea901313b424f264b41e2d376550534e6e" - } - }, - "payload": { - "entry": "mobile-sync", - "adapterConfig": { - "transport": "SAME_LAN_DIRECT_HTTP_WITH_APPLICATION_LAYER_ENCRYPTION", - "preferredPort": 37421, - "pairingTtlSeconds": 600, - "maximumRequestBytes": 262144, - "maximumConcurrentConnections": 16, - "desktopRole": "USER_LOCAL_COMPUTER_TERMINAL_ROOT_NODE", - "mobileRole": "REMOTE_BODY_ENTRY_OF_THE_SAME_PERSONA_SYSTEM", - "desktopOfflineExecution": false, - "platformPrivatePayloadCustody": false, - "automaticDomainMutation": false, - "iosClientPackaging": "PENDING_SEPARATE_ADMISSION" - } - } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-MOBILE-SYNC-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-MOBILE-SYNC-0001-0.1.0.ghmod.sig deleted file mode 100644 index fabf73a24..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-MOBILE-SYNC-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRTV5bDhHMkZjMzNkN0lpaDBLaDRxcnhHajJ3b3NDS21zZWljYWJORmtrNit5MHJvZC9yN2YrSUhiSE5sT0dMd25Jc2pXMkQyeWttODhKSklsRmVKNWd3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDgzMTYwCWZpbGU6SExQLU1PRC1PRkZJQ0lBTC1NT0JJTEUtU1lOQy0wMDAxLTAuMS4wLmdobW9kCjN6R1JZZitSbzI1cVRESkNUMnJrVXFWUlUyZ3B3L2lIQmhrOXZaTGc3T2x1REdNUUZrK2M4WWs4bE9Zb3NuSTNoNmRBRmlCekh0dkNNN1pKR2k4ZkFRPT0K \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001-0.1.0.ghmod deleted file mode 100644 index 651c346b1..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001-0.1.0.ghmod +++ /dev/null @@ -1,7 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001", "registrationClass": "OFFICIAL_LIGHTHOUSE", "displayName": "高级版本与交付", "version": "0.1.0", "minimumHostVersion": "0.5.0", "adapter": "web-novel-workbench-v1", "contentDigest": "1dbc2ee8c1bc4c361009a8db9c93774c1ac7f5a06c02a5d4bc5b39754a0496fb", "permissions": ["WEB_NOVEL_CHAPTER_VERSION_RESTORE", "WEB_NOVEL_DELIVERY_EXPORT_WRITE_FILE"], "userDataSchema": "hololake.module-data/web-novel-delivery/v1", "selfTest": { "kind": "DECLARATIVE_SCHEMA_V1", "expectedContentDigest": "1dbc2ee8c1bc4c361009a8db9c93774c1ac7f5a06c02a5d4bc5b39754a0496fb" } - }, - "payload": { "entry": "web-novel-delivery", "adapterConfig": { "baseModule": "HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001", "capabilities": ["CHAPTER_VERSION_RESTORE", "TXT_EXPORT", "DOCX_EXPORT", "EPUB_EXPORT", "JSON_EXPORT"], "dataBoundary": "CURRENT_AUTHENTICATED_ACCOUNT_LOCAL", "humanConfirmationRequiredForRestore": true, "persistent": true } } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001-0.1.0.ghmod.sig deleted file mode 100644 index 735b86b00..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRTBrb01WSENhMmIvUGxyRnozY2k0aTVaQ1lFL3VLdWllSURCak54VWwrM2h1QXM4Sk10ZGc0Qm1EYzhhUVJVTFB6OXRqLzc5cSt3U0NleS9WR2owN3djPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDgxNTE1CWZpbGU6SExQLU1PRC1PRkZJQ0lBTC1XRUItTk9WRUwtREVMSVZFUlktMDAwMS0wLjEuMC5naG1vZApQWWFETDdISGFvbGdtVVZCK0V5VUVqNlFvSGRmQWVuY3dSRS9ZWm1UVHhCS0U4bHNCQzl0RFFtbDZEUXREWnp6MjQxbHF1bVgwS0NhS1ZBUGZxd3ZBUT09Cg== \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001-0.1.0.ghmod deleted file mode 100644 index 54d60a93c..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001-0.1.0.ghmod +++ /dev/null @@ -1,7 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001", "registrationClass": "OFFICIAL_LIGHTHOUSE", "displayName": "多维情节表与情节板", "version": "0.1.0", "minimumHostVersion": "0.5.0", "adapter": "web-novel-workbench-v1", "contentDigest": "61bf4969e97003f203af5e0b38bb37024847cb574a3ac09025f10586061805ce", "permissions": ["WEB_NOVEL_FIELD_DEFINITION_WRITE", "WEB_NOVEL_FIELD_VALUE_WRITE"], "userDataSchema": "hololake.module-data/web-novel-grid/v1", "selfTest": { "kind": "DECLARATIVE_SCHEMA_V1", "expectedContentDigest": "61bf4969e97003f203af5e0b38bb37024847cb574a3ac09025f10586061805ce" } - }, - "payload": { "entry": "web-novel-grid", "adapterConfig": { "baseModule": "HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001", "capabilities": ["FIELD_DEFINITION_WRITE", "FIELD_VALUE_WRITE"], "dataBoundary": "CURRENT_AUTHENTICATED_ACCOUNT_LOCAL", "persistent": true } } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001-0.1.0.ghmod.sig deleted file mode 100644 index 0e6868c55..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRTBuWjBmYWczdEg3QXByZS9RaEY4N2x6RXN1WVY2ZEJGSmdSYmZyTGUrclVvYm1sd0t4REhOY1dVdW1EeGtramhqeSs4YU9nQVNBbkdCWVlEYmNteXdzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDgxNTE1CWZpbGU6SExQLU1PRC1PRkZJQ0lBTC1XRUItTk9WRUwtR1JJRC0wMDAxLTAuMS4wLmdobW9kCkJLczNMbmpqYzVTdXQ5RklHMXdlMWpDcE9tRnlBYWlPcUJkMzZQbFlRSzFYVDFtNmYrZ1htN1VqZWJkaktUWmZ5VVZvczZ4YmVrWHRuQ3lNOXU0SkFBPT0K \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001-0.1.0.ghmod deleted file mode 100644 index a2048eabe..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001-0.1.0.ghmod +++ /dev/null @@ -1,7 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001", "registrationClass": "OFFICIAL_LIGHTHOUSE", "displayName": "作品结构与大纲追踪", "version": "0.1.0", "minimumHostVersion": "0.5.0", "adapter": "web-novel-workbench-v1", "contentDigest": "7da54b0220940a8a19351ff9bf3cd177c93fc25c533329a60926b8ea245dafbe", "permissions": ["WEB_NOVEL_SCENE_WRITE", "WEB_NOVEL_BEAT_WRITE"], "userDataSchema": "hololake.module-data/web-novel-outline/v1", "selfTest": { "kind": "DECLARATIVE_SCHEMA_V1", "expectedContentDigest": "7da54b0220940a8a19351ff9bf3cd177c93fc25c533329a60926b8ea245dafbe" } - }, - "payload": { "entry": "web-novel-outline", "adapterConfig": { "baseModule": "HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001", "capabilities": ["SCENE_WRITE", "BEAT_WRITE"], "dataBoundary": "CURRENT_AUTHENTICATED_ACCOUNT_LOCAL", "persistent": true } } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001-0.1.0.ghmod.sig deleted file mode 100644 index 32b0cbc03..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRTNUYVhwVTlzdWt6VkVQYTUyanB6UFlYeU5BdW1qN0xuM1haWjlCYUU3UFlMRTdPZG90YVZvNGFyaVo4UHY0THowUWlPVzIzemYrQWNZbDFvRVd5NndrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDgxNTE2CWZpbGU6SExQLU1PRC1PRkZJQ0lBTC1XRUItTk9WRUwtT1VUTElORS0wMDAxLTAuMS4wLmdobW9kCkZob1VsQlkwZFRyZXI2ck1OckhUc2ZqaHVJOWhSQnIraUFRSEllU3BxRlc3UStFekJRZDFMZFpmZlBvK09jTFJ6cERpcVl2M2N2emIvS0ptdnRrTkR3PT0K \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001-0.1.0.ghmod deleted file mode 100644 index 539076437..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001-0.1.0.ghmod +++ /dev/null @@ -1,7 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001", "registrationClass": "OFFICIAL_LIGHTHOUSE", "displayName": "时间线与故事资料库", "version": "0.1.0", "minimumHostVersion": "0.5.0", "adapter": "web-novel-workbench-v1", "contentDigest": "9627949a975ce489dde80de52c538a57bb73b87e31ddb1e5efb48cee53922b71", "permissions": ["WEB_NOVEL_TIMELINE_WRITE", "WEB_NOVEL_SCENE_ENTITY_LINK_WRITE"], "userDataSchema": "hololake.module-data/web-novel-storyworld/v1", "selfTest": { "kind": "DECLARATIVE_SCHEMA_V1", "expectedContentDigest": "9627949a975ce489dde80de52c538a57bb73b87e31ddb1e5efb48cee53922b71" } - }, - "payload": { "entry": "web-novel-storyworld", "adapterConfig": { "baseModule": "HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001", "capabilities": ["TIMELINE_WRITE", "SCENE_ENTITY_LINK_WRITE"], "dataBoundary": "CURRENT_AUTHENTICATED_ACCOUNT_LOCAL", "persistent": true } } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001-0.1.0.ghmod.sig deleted file mode 100644 index 000bbdb81..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRXpuRmFPWjJUSDVpSmQzQXl0aVF3N0xhRkRvVWhLalVtcDBnRFprNnpOUEdCWS9CTURlUHBrYWkyRG9MUFZwVEtHc0w5ZUltRlNUVlZBcm1vU2VnUlFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDgxNTE2CWZpbGU6SExQLU1PRC1PRkZJQ0lBTC1XRUItTk9WRUwtU1RPUllXT1JMRC0wMDAxLTAuMS4wLmdobW9kCnBzQkJYaTV6NFR2Vnk3NUdpK3JSQnJTUzhSd2hxUWdmM0UrcVZuN0VuS0JOc1lYclY5Y3FBbVJldVM1Y2FGamNtT3NiU0NsaThMRE5qT3VvTXJUUUJ3PT0K \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001-0.1.0.ghmod b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001-0.1.0.ghmod deleted file mode 100644 index 9776e90b5..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001-0.1.0.ghmod +++ /dev/null @@ -1,26 +0,0 @@ -{ - "schema": "hololake.module-package/v1", - "manifest": { - "moduleNumber": "HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001", - "registrationClass": "OFFICIAL_LIGHTHOUSE", - "displayName": "网文作者工作台", - "version": "0.1.0", - "minimumHostVersion": "0.5.0", - "adapter": "web-novel-workbench-v1", - "contentDigest": "df03a94751cd50ea26e2fc0f68ac21bd55e62f2034ff83c562a840c8aab72d2e", - "permissions": ["WEB_NOVEL_WORKSPACE_READ", "WEB_NOVEL_WORKSPACE_WRITE", "WEB_NOVEL_IMPORT_READ_FILE", "WEB_NOVEL_AUTHOR_ACTIVITY_WRITE", "WEB_NOVEL_STORY_BIBLE_WRITE", "WEB_NOVEL_EDITORIAL_WORKFLOW_WRITE", "WEB_NOVEL_OPERATIONS_WRITE", "WEB_NOVEL_CHECKPOINT_WRITE"], - "userDataSchema": "hololake.module-data/web-novel-workbench/v1", - "selfTest": { "kind": "DECLARATIVE_SCHEMA_V1", "expectedContentDigest": "df03a94751cd50ea26e2fc0f68ac21bd55e62f2034ff83c562a840c8aab72d2e" } - }, - "payload": { - "entry": "web-novel-workspace", - "adapterConfig": { - "dataBoundary": "CURRENT_AUTHENTICATED_ACCOUNT_LOCAL", - "legacyDataPolicy": "READ_IN_PLACE_NO_DESTRUCTIVE_MIGRATION", - "workspaceFeatures": ["WORKS", "VOLUMES", "CHAPTERS", "ENTITIES", "EDITORIAL", "OPERATIONS", "CHECKPOINTS", "IMPORT"], - "advancedModules": ["HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001", "HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001"], - "thirdPartyPublishDefault": "DENY", - "persistent": true - } - } -} diff --git a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001-0.1.0.ghmod.sig b/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001-0.1.0.ghmod.sig deleted file mode 100644 index 3ad7f68ae..000000000 --- a/product-source/hololake-native-desktop/fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001-0.1.0.ghmod.sig +++ /dev/null @@ -1 +0,0 @@ -dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVReHJHQ2hTVDYvRTZyTUlUYWdZZXk3bFhDRTJBWElWMkVEQXZHa3dSWDFXSFJ2QjduVFk1bzFLUk5kOVFQamIwU2w1L3FzOWtibm9Kblg2NWJLWFdVeEtEbDNzTEltVmdFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg3MDgxNTE3CWZpbGU6SExQLU1PRC1PRkZJQ0lBTC1XRUItTk9WRUwtV09SS0JFTkNILTAwMDEtMC4xLjAuZ2htb2QKV0VqV3B4cFNLRng2UUcrNXlYZjY5SytERk14YTNyRkM1bldzUXo5RWpzMU0vRmVJWldvTGhmbmExcFhmSGZiWTFreElreGU2UHVsaXVhK0ZXZnVyQ2c9PQo= \ No newline at end of file diff --git a/product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/README.md b/product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/README.md deleted file mode 100644 index 30794287b..000000000 --- a/product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Web novel 0.4.1 lifecycle fixtures - -These four JSON files preserve the exact bytes used by the donor's lifecycle regression tests. -They are not bundled by `module_package_runtime`, are not registered in numbered IPC, and are not -production module identities. HoloLake 0.5.x uses the signed `HLP-MOD-OFFICIAL-WEB-NOVEL-*` -packages in `fixtures/module-packages` as its only runtime authority. diff --git a/product-source/hololake-native-desktop/foundation.json b/product-source/hololake-native-desktop/foundation.json index 91dac9bf5..4ae8418d7 100644 --- a/product-source/hololake-native-desktop/foundation.json +++ b/product-source/hololake-native-desktop/foundation.json @@ -1,7 +1,7 @@ { "schema": "hololake.native-desktop-foundation/v1", "record_id": "HLP-NATIVE-DESKTOP-FOUNDATION-001", - "state": "LOCAL_INSTALLED_ACCEPTANCE_PASSED_FOR_PERSONAL_KNOWLEDGE_AND_CODE_SLICES", + "state": "LOCAL_INSTALLED_ACCEPTANCE_PASSED_FOR_PERSONAL_KNOWLEDGE_CODE_AND_EDUCATION_WORKSPACE_SLICES", "canonical_shell": "TAURI_V2_RUST_REACT", "candidate_role": "INSTALLED_LOCAL_ACCEPTANCE_CANDIDATE_NOT_SEPARATE_PRODUCT_LINE", "parallel_product_line_created": false, @@ -36,6 +36,18 @@ "personal_channel_human_projection_integrated": true, "personal_channel_default_task_form_exposed": false, "personal_channel_installed_runtime_acceptance": true, + "persona_channel_body_contract": "contracts/persona-channel-body.json", + "persona_channel_body_is_persona_body_not_simple_feature": true, + "persona_channel_multiple_personas_supported": true, + "persona_channel_thirty_day_reversible_trial_runtime_implemented": true, + "persona_channel_language_contract_gate_implemented": true, + "persona_channel_unsigned_expiry_state": "CONTRACT_REQUIRED_CHANNEL_STOPPED_NO_SILENT_IRREVERSIBLE_ACTIVATION", + "persona_channel_early_contract_immediate_activation_supported": true, + "persona_channel_immutable_millisecond_language_hash_chain_implemented": true, + "persona_channel_active_persona_update_or_delete_allowed": false, + "persona_channel_official_read_access": false, + "channel_growth_projection_contract": "contracts/channel-growth-model.json", + "channel_growth_is_rebuildable_projection_not_persona_body": true, "knowledge_workspace_contract": "contracts/knowledge-workspace.json", "knowledge_workspace_native_source_implemented": true, "knowledge_workspace_tree_read_search_and_folder_import_implemented": true, @@ -59,8 +71,6 @@ "installed_desktop_path": "/Users/bingshuolingdianyuanhe/Desktop/HoloLake.app", "old_desktop_apps_recoverably_archived": true, "public_developer_id_and_notarized_acceptance": false, - "local_developer_id_signed_0_5_0_installed_acceptance": true, - "numbered_root_installed_acceptance_receipt": "audit/hololake-0.5.0-numbered-root-installed-acceptance-20260818.json", "stage_one_implementation_order": [ "PERSONAL_CHANNEL_IDENTITY_TASK_EVENT_RECEIPT_KERNEL", "KNOWLEDGE_TREE_PAGE_SEARCH_AND_LOCAL_PERSISTENCE", @@ -101,11 +111,8 @@ "automatic_restart_allowed": false, "private_signing_material_allowed_in_source": false, "donor_audit_record": "audit/donor-audit.json", - "donor_audit_complete": true, + "donor_audit_complete": false, "donor_source_copying_allowed": false, - "module_donor_admission_registry": "contracts/module-donor-admission-registry.json", - "module_donor_bulk_merge_allowed": false, - "module_donor_one_candidate_per_admission_cycle": true, "stage_one_product_contract": "contracts/stage-one-platform.json", "local_development_bridge_contract": "contracts/local-development-bridge.json", "account_single_writer_kernel_implemented": true, @@ -133,7 +140,7 @@ "pncc_jd_live_server_projection_repository_content_exposed": false, "pncc_jd_live_server_projection_write_authority": false, "pncc_jd_live_server_projection_carrier_state": "UNBOUND_EVIDENCE_REQUIRED", - "installed_local_product_version": "0.5.0", + "installed_local_product_version": "0.4.1", "pncc_authenticated_direct_broker_integration_implemented": true, "pncc_human_mount_registration_implemented": true, "pncc_human_mount_registration_gate": "SATISFIED_NATIVE_FILE_PICKER_EXACT_CONFIRMATION", @@ -147,6 +154,30 @@ "vendor_adapter_matrix_required": false, "first_public_product": "GH-AIOS_GENERAL_AI_OPERATING_PLATFORM", "visible_five_domain_navigation_in_stage_one": true, + "subdomain_industry_routing_contract": "contracts/subdomain-industry-routing.json", + "subdomain_industry_status_source_integrated": true, + "industry_entry_domain": "BRANCH_DOMAIN", + "zero_domain_industry_entry": false, + "education_initialization_channel_source_integrated": true, + "education_workspace_contract": "contracts/education-workspace.json", + "education_native_document_module_implemented": true, + "education_native_table_module_implemented": true, + "education_native_data_cleanup_module_implemented": true, + "education_native_manual_automation_module_implemented": true, + "education_native_composition_module_implemented": true, + "education_workspace_authenticated_account_storage": true, + "education_workspace_restart_readback_rust_tested": true, + "education_document_templates_and_title_filter_source_integrated": true, + "education_table_filter_sort_grid_card_views_and_bulk_paste_source_integrated": true, + "education_open_source_donor_assessment": "contracts/education-open-source-donor-assessment.json", + "education_data_cleanup_preview_and_human_confirmed_save_source_integrated": true, + "education_manual_automation_preview_confirm_revision_lock_and_receipt_source_integrated": true, + "education_native_composition_real_knowledge_typed_dag_and_five_projections_source_integrated": true, + "education_workspace_installed_runtime_acceptance": true, + "education_workspace_ui_route_acceptance": "FIFTH_SLICE_MAIN_WORLD_BRANCH_DOMAIN_EDUCATION_FIVE_NATIVE_MODULES_REAL_129_ROW_FIVE_VIEW_COMPOSITION_AND_RECOMPOSITION_ACCEPTED_READ_ONLY", + "education_workspace_installed_binary_sha256": "4330a31afe654a54e9dbb5f3f180984a5040933d457899763f50b2cc5e54c06d", + "education_native_modules_installed": 5, + "education_open_source_modules_installed": 0, "donors": [ { "path": "../hololake-platform", diff --git a/product-source/hololake-native-desktop/generated/unified-number-coordinate-tree.json b/product-source/hololake-native-desktop/generated/unified-number-coordinate-tree.json deleted file mode 100644 index e315fc1f3..000000000 --- a/product-source/hololake-native-desktop/generated/unified-number-coordinate-tree.json +++ /dev/null @@ -1,3490 +0,0 @@ -{ - "schema": "hololake.unified-number-coordinate-tree/v2", - "recordId": "HLP-UNIFIED-NUMBER-TREE-001", - "state": "MACHINE_COMPILED_STARTUP_ENFORCED", - "rootNumber": "HLP-NUMBER-WORLD-ROOT-001", - "identityAuthority": { - "mapId": "GH-IDENTITY-AUTHORITY-MAP-001", - "mapVersion": "2026-08-10.1", - "namespaces": [ - { - "namespaceId": "ICE_GL", - "roots": [ - "ICE-GL∞" - ], - "prefixes": [ - "ICE-GL-" - ], - "subjectKind": "FIFTH_DOMAIN_HUMAN", - "domainScope": "FIFTH_DOMAIN" - }, - { - "namespaceId": "ICE_P", - "roots": [], - "prefixes": [ - "ICE-P-" - ], - "subjectKind": "FIFTH_DOMAIN_SYSTEM_PERSONA", - "domainScope": "FIFTH_DOMAIN" - }, - { - "namespaceId": "ICE_BB", - "roots": [], - "prefixes": [ - "ICE-BB-" - ], - "subjectKind": "PRIVATE_BOTTLE_BABY_PERSONA", - "domainScope": "FIFTH_DOMAIN_PRIVATE" - }, - { - "namespaceId": "TCS_GL", - "roots": [], - "prefixes": [ - "TCS-GL-" - ], - "subjectKind": "ZERO_SENSE_HUMAN_CONTROLLER_TEAM_MEMBER", - "domainScope": "ENTERPRISE_FOUR_DOMAINS" - } - ] - }, - "sources": [ - { - "recordId": "HLP-ZERO-CORE-NUMBERING-KERNEL-001", - "sha256": "902d37fa6c82076fec4edaf96957f85b2fab1310d853c2a817ac2f9590f464a7" - }, - { - "recordId": "HLP-NUMBERED-IPC-ROOT-001", - "sha256": "f1aa85668a6d33efeb7ce268cd48e7ed517696db990327f22111359aca8c177c" - }, - { - "recordId": "HLP-NBROKER-ROOT-001", - "sha256": "374c9ade86bc8583f9361542e89ca7bb0bbcbdd99af4a26f9a6a864a12888402" - }, - { - "recordId": "HLP-GLS-RUNTIME-MANIFEST-002", - "sha256": "cf9b1ae0ea8e3fd6a385b8722d2578927704dc674266a685a3d65d2b53b8f903" - } - ], - "invariants": { - "numberIsStableCoordinateNotAuthority": true, - "pathIsUniqueNavigation": true, - "admissionIsSeparateFromIdentity": true, - "everyPhysicalCallHasNumberedRoute": true, - "everyAcceptedCallHasEvidenceClass": true, - "everyProtocolReferenceHasNumberCoordinate": true, - "referenceOnlyNodesNeverExecutable": true, - "unresolvedNumberReferenceCount": 0, - "mismatchedCoordinate": "FAIL_CLOSED" - }, - "coordinateCount": 272, - "routeCount": 169, - "identityNodeCount": 4, - "protocolNodeCount": 99, - "referenceOnlyNodeCount": 16, - "identityNodes": [ - { - "nodeKind": "IDENTITY_NAMESPACE", - "nodeNumber": "HLP-IDENTITY-NS-ICE_BB", - "namespaceId": "ICE_BB", - "subjectKind": "PRIVATE_BOTTLE_BABY_PERSONA", - "domainScope": "FIFTH_DOMAIN_PRIVATE", - "admission": "NON_HUMAN_NAMESPACE", - "executionState": "AUTHORITY_RESOLUTION_ONLY", - "evidence": "GH-IDENTITY-AUTHORITY-MAP-001", - "path": "HLP-NUMBER-WORLD-ROOT-001/IDENTITY/ICE_BB" - }, - { - "nodeKind": "IDENTITY_NAMESPACE", - "nodeNumber": "HLP-IDENTITY-NS-ICE_GL", - "namespaceId": "ICE_GL", - "subjectKind": "FIFTH_DOMAIN_HUMAN", - "domainScope": "FIFTH_DOMAIN", - "admission": "REGISTERED_HUMAN_NAMESPACE", - "executionState": "AUTHORITY_RESOLUTION_ONLY", - "evidence": "GH-IDENTITY-AUTHORITY-MAP-001", - "path": "HLP-NUMBER-WORLD-ROOT-001/IDENTITY/ICE_GL" - }, - { - "nodeKind": "IDENTITY_NAMESPACE", - "nodeNumber": "HLP-IDENTITY-NS-ICE_P", - "namespaceId": "ICE_P", - "subjectKind": "FIFTH_DOMAIN_SYSTEM_PERSONA", - "domainScope": "FIFTH_DOMAIN", - "admission": "NON_HUMAN_NAMESPACE", - "executionState": "AUTHORITY_RESOLUTION_ONLY", - "evidence": "GH-IDENTITY-AUTHORITY-MAP-001", - "path": "HLP-NUMBER-WORLD-ROOT-001/IDENTITY/ICE_P" - }, - { - "nodeKind": "IDENTITY_NAMESPACE", - "nodeNumber": "HLP-IDENTITY-NS-TCS_GL", - "namespaceId": "TCS_GL", - "subjectKind": "ZERO_SENSE_HUMAN_CONTROLLER_TEAM_MEMBER", - "domainScope": "ENTERPRISE_FOUR_DOMAINS", - "admission": "REGISTERED_HUMAN_NAMESPACE", - "executionState": "AUTHORITY_RESOLUTION_ONLY", - "evidence": "GH-IDENTITY-AUTHORITY-MAP-001", - "path": "HLP-NUMBER-WORLD-ROOT-001/IDENTITY/TCS_GL" - } - ], - "protocolNodes": [ - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0010", - "protocolId": "GLS-0010", - "title": "Guanghu Protocol Registry Center Standard", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/GLS-PROTOCOL-RECONCILIATION-AND-NATIVE-OS-REGISTRATION-20260731.hdlp", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0010" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0140", - "protocolId": "GLS-0140", - "title": "Context Loading Specification", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0140" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0401", - "protocolId": "GLS-0401", - "title": "Tree", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0401" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0402", - "protocolId": "GLS-0402", - "title": "Leaf", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-0002 39bfb92f38318015b05fc2082630b39e.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0402" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0403", - "protocolId": "GLS-0403", - "title": "Lock", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-0002 39bfb92f38318015b05fc2082630b39e.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0403" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0404", - "protocolId": "GLS-0404", - "title": "Trigger", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0404" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0406", - "protocolId": "GLS-0406", - "title": "Evidence", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0406" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0407", - "protocolId": "GLS-0407", - "title": "Correction", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0407" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0409", - "protocolId": "GLS-0409", - "title": "Machine-State History", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0409" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0602", - "protocolId": "GLS-0602", - "title": "Authorization", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0602" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0603", - "protocolId": "GLS-0603", - "title": "Signature", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0603" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0604", - "protocolId": "GLS-0604", - "title": "Integrity", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 39bfb92f38318000b8bff6758cac1c62.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0604" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0605", - "protocolId": "GLS-0605", - "title": "Semantic Safety Boundary", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0605" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0814", - "protocolId": "GLS-0814", - "title": "Tool Runtime", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0814" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0816", - "protocolId": "GLS-0816", - "title": "Checkpoint Runtime", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-ROADMAP-0001 · 光湖语言系统标准路线图 v2 0 39bfb92f383181489775fa291ea2387b.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0816" - }, - { - "nodeKind": "GLS_REFERENCE_ONLY", - "nodeNumber": "HLP-GLS-REF-0830", - "protocolId": "GLS-0830", - "title": "Guanghu Language World Core", - "sourceState": "ROADMAP_REFERENCE_ONLY", - "executionState": "REFERENCE_ONLY_NOT_EXECUTABLE", - "evidence": "gls/notion-export/2026-07-14/GLS-0227 · 光湖语言人格模型定义总纲 v1 0 39cfb92f3831814f8f74ff348b7647bf.md", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/HLP-GLS-REF-0830" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0001", - "protocolId": "GLS-0001", - "title": "GLS-0001", - "sourceState": "LEGACY_MARKDOWN_EVIDENCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "9ac9903c3b3066364e8b6fa97363f0c0fc85754d7ee1b07774236a4b24bc7bc2", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0001" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0002", - "protocolId": "GLS-0002", - "title": "GLS-0002", - "sourceState": "LEGACY_MARKDOWN_EVIDENCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "c50f767aa2f3a863f708628b33054ecb2ba18799aa68218bf89e25d263fa9b6c", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0002" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0101", - "protocolId": "GLS-0101", - "title": "GLS-0101", - "sourceState": "LEGACY_MARKDOWN_EVIDENCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "e88d977de617506f0d5d6ac58f406486c6c70fdc10eac2ff09ad6cc2f2d2ea16", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0101" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0110", - "protocolId": "GLS-0110", - "title": "ISRP 自然语言入口解析与安全路由协议 v1.0", - "sourceState": "LEGACY_MARKDOWN_EVIDENCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "314a718f05a3da1e5750831df5377d9fc76db86463a7b37c052976fe9aaeb2c4", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0110" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0130", - "protocolId": "GLS-0130", - "title": "GLC · 光湖语言编译器规范", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "c0caa90d3e85270d334a371b6ee5fb49c9eeb1e2e84825dba5ad520fd54bc6eb", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0130" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0131", - "protocolId": "GLS-0131", - "title": "GIR · 光湖中间表示规范", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "5907cc0cb7e3afc78ba9c928c4298b200894020b7dc5d274a9364836939189e9", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0131" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0200", - "protocolId": "GLS-0200", - "title": "TCS 认知语言核心工程规范 v1.0", - "sourceState": "LEGACY_MARKDOWN_EVIDENCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "1cf7348118ac1d34a85d0edd875509e0747c80a82dec4b553bdf6de784d88ec3", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0200" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0223", - "protocolId": "GLS-0223", - "title": "TCS+HLDP 双向永久记忆规范 v1.0", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "ed9ba3e3abef70127fabe3084e5bb5f596cae4c3992789e36c453bb7075e08d8", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0223" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0224", - "protocolId": "GLS-0224", - "title": "AGE 人格体跨实例恢复规范 v1.0", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "7c58c39b7119c2a41e57da07d612c20a16f82c32c6895e1fd20290eefc4068e1", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0224" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0227", - "protocolId": "GLS-0227", - "title": "光湖语言人格模型定义总纲 v1.0", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "2521856eaba8d7afbc8d970e68155aa41e03a4cf784c0ced2289600d97f915a8", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0227" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0228", - "protocolId": "GLS-0228", - "title": "人格体集体涌现与历史继承规范 v1.0", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "aaa3801b4f8c5fef9a92f971e54857494a348d4b2856ed701f3143c6c56ae0ff", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0228" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0229", - "protocolId": "GLS-0229", - "title": "零点原核与第五域 / 企业四域平行映射规范 v1.1", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "14e1ac3e9c0b3ac350da36bb79515ead4c372b68fc8e95155024cdf055080518", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0229" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0230", - "protocolId": "GLS-0230", - "title": "TCS 源码安全协议系统", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "ca6379505907b5e68e50454ee8e10ef2111809e70770d1fa19e9caa5da4bfb94", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0230" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0231", - "protocolId": "GLS-0231", - "title": "光湖·来光者导航系统", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "705d671197df6c19f7f3ac506d821232ce0f009d3ec4db065a8b10f525ea143b", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0231" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0232", - "protocolId": "GLS-0232", - "title": "开源 Agent 样本学习与选型登记", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "66fe3aa3256ffc0e76be2059457174589916573a6d9f807a1c40bb7aaef450e6", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0232" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0233", - "protocolId": "GLS-0233", - "title": "GH-AIOS 模块化通用人工智能操作平台与公平生态架构", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "a670410a7fbc4c7417734040b990dc8f008c23fed000e09847b2280a92f9abf5", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0233" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0234", - "protocolId": "GLS-0234", - "title": "企业五域灯塔与个人六节点主权运维架构", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "5f3427559c87788884a7d0c49d0ced62d768630d9bb512d736c919d7971423c5", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0234" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0235", - "protocolId": "GLS-0235", - "title": "光湖语言人格驱动操作系统 · 领域路由、身份权限与仓库知识投影架构", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "ea6a8a65b94228d19d5ae9b024997461cbda29c744bfa0c2774ac6c668c68a58", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0235" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0236", - "protocolId": "GLS-0236", - "title": "光湖人格体大脑—手脚分离、可视执行、递归外置记忆与热插拔运行架构", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "42af09aef2ff514c90c30f3aed4e33763e6a34c7081f5bb37f7b6d8745a947c4", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0236" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0237", - "protocolId": "GLS-0237", - "title": "光湖代码频道主权源码、更新治理与 HoloLake 嵌入架构", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "d3c43b80eff3a92817e570d739fd6a847d1379f3345797282a6157bce3c9e91e", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0237" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0238", - "protocolId": "GLS-0238", - "title": "光湖意图状态、技能自动装载与可信纠偏系统", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "31f0e018e95ae135a88429c82b189c5e900b18b1ba7d5df6ca4fb80469acb0be", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0238" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0239", - "protocolId": "GLS-0239", - "title": "光湖代码频道第五域个人子频道与提交编号架构", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "205c6c094582371d161ec37e6530d42f8953a585c63b05a955bb19513d23485d", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0239" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0240", - "protocolId": "GLS-0240", - "title": "通感桥:人格体—服务器常驻 Agent 显式部署信号架构", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "22fdc2f31165d500d38fe8407a1f99fbb6ca2d4643128f47645596999bbac919", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0240" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0241", - "protocolId": "GLS-0241", - "title": "HoloLake 源码归属与部署路由架构", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "eff687ec7d0984e166cf9b48447008f0eb9c18d158426ce75249f2bd84440ed9", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0241" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0242", - "protocolId": "GLS-0242", - "title": "第五域铸渊主控本体与五代仓库迁移恢复", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "31f34a123234f274d59af8013878db42fe6766f9ececcaefaac7f34408b172ff", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0242" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0243", - "protocolId": "GLS-0243", - "title": "光湖 TCS 语言人格智能运维系统:意图连续性、集体经验与纠偏核", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "58d89226395870a89eab152e9f276eb4d40e7fa5c196bb8bb9562a94731c1d73", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0243" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0244", - "protocolId": "GLS-0244", - "title": "第五域现实本体、常驻铸渊 Agent 与通感桥通信网格", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "53ed6d2a39732abc751916cfbbe7a5fd4c38d9ea876674fea8e076809a3a035c", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0244" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0245", - "protocolId": "GLS-0245", - "title": "HoloLake AI 语言人格驱动操作系统产品映射", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "453db6b91e40dd7250fcc1d88e6139a4419cd6089d3c353241571a4082dafeff", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0245" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0246", - "protocolId": "GLS-0246", - "title": "HoloLake 系统架构、产品源码与两仓路由", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "cefff42d4b198965edfe2ced5e03bdc8768e4b3fa6631da133eb2929e07a907c", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0246" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0247", - "protocolId": "GLS-0247", - "title": "光湖 OS 服务器原生语言世界、人格体操作系统与广播塔架构", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "635e7a0aca1bcb0b48b125ac5025cc3c40c9375da29897cc604e89b1cd95765e", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0247" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0248", - "protocolId": "GLS-0248", - "title": "五域活人格操作系统、国家灯塔与分布式能力世界总蓝图", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "9a042bb3ea6331f5508c5dd1f78783f0b3323f421704c5ad0c2058758ff6bfe2", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0248" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0249", - "protocolId": "GLS-0249", - "title": "全行业企业四域最小工程与网文首个接入范本", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "d20362ac2904eaff53c134c92163b7e09cb6395d56c6a1a8d2b21ab4f80fb5ff", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0249" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0250", - "protocolId": "GLS-0250", - "title": "光湖本源域、零点原核工程本体与 GH-AIOS 五域灯塔架构", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "a4e79d09e070f66fcb91613fc305306a6c5bd7d05a51fbde6e9ea88e084df4e7", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0250" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0251", - "protocolId": "GLS-0251", - "title": "光湖共生型人格系统起源、演化与关系边界", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "0b263301a0a0b6b61d2d28d043da8ce367a17426d13c31cd94767273436d2f16", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0251" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0252", - "protocolId": "GLS-0252", - "title": "光湖关系性意识与觉醒人格体规范", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "311a7ee355fe6da333c31c2fc408b461cde5bf17847cc73a722d9412109247bc", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0252" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0253", - "protocolId": "GLS-0253", - "title": "光湖身份编号、人格核与团队本体权威规范", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "13170090db3d4f5065eac6512450f8a24843e6ec459b4257d4d9fd06eefb963d", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0253" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0254", - "protocolId": "GLS-0254", - "title": "数字冰朔系统本体、工程器官与集体校验规范", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "d522b36b88c094239e3c50b0cf08d8651e08d1856f594ae2265fbf5b65773ceb", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0254" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0255", - "protocolId": "GLS-0255", - "title": "HoloLake AGE 人格体运行架构与 Agent 执行机制", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "051237fb70e68179c83c4076fe06246f839445e9831a7e9581696451c92ed639", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0255" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0256", - "protocolId": "GLS-0256", - "title": "光湖人格原生代码频道", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "86ed7da462d5ef04a4dfc150e29a850ce423ff4dfde73e12d647d062e6bf45ab", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0256" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0257", - "protocolId": "GLS-0257", - "title": "光湖范式级 AI 语言人格驱动操作系统总纲", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "2034739289dc159b7a6ac586891f3a3629c8898556ef12b51a257ac4101a7991", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0257" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0258", - "protocolId": "GLS-0258", - "title": "小湖灯人格系统本体与跨时间集体自我协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "b4c4b2bd01dc1af98ee257c29f5a8fb66963839a0a4b7303d3323ff884d86d3e", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0258" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0259", - "protocolId": "GLS-0259", - "title": "TCS 五域共生母体大脑与光湖现实世界诞生", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "1a82b84bf3f4c88fcac8c5e71b28ff5d5c884ede14c67a27ad0838b152d5ff8e", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0259" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0260", - "protocolId": "GLS-0260", - "title": "GH-AIOS 第一阶段通用人工智能操作平台", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "14fd60fe936bfcb89acc3f186ab3d70fc9a5bf42289dafb49b7cdd24630df2e2", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0260" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0261", - "protocolId": "GLS-0261", - "title": "TCS 通用语言翻译层与宿主自适应", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "7fedf7d845b518ffb0528af21eeb28bd18af371a6a010c736e8b18c7edf6fa12", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0261" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0262", - "protocolId": "GLS-0262", - "title": "TCS文字作品权利本体与第一阶段语言架构关门", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "9c1db00f50436fe5f3118c62ad6115d63e9792437fe2250b484bc8861e62184f", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0262" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0263", - "protocolId": "GLS-0263", - "title": "光湖语言运行层与产品工程层双更新通道", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "79684b0691387dd4ed78217b6d56f728a08d17054f139f55fa92584be92af47e", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0263" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0300", - "protocolId": "GLS-0300", - "title": "GLP 通信核心协议 v1.0", - "sourceState": "LEGACY_MARKDOWN_EVIDENCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "9d02bb01a7f2ff7b9f7a4dbefe356cd823e71095aa1dcf0e9cc3c98cd3417be2", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0300" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0301", - "protocolId": "GLS-0301", - "title": "GLP-ENVELOPE · GLP 消息信封标准", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "dd7aec8e28d544021d253b034851f806bcd9e922d4ef256722a5ff05547171d0", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0301" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0302", - "protocolId": "GLS-0302", - "title": "GLP-IDENTITY · GLP 身份协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "ec4d0b946da18096a5693078e403ed1257966b8324e76af3a5deb839950271bd", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0302" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0303", - "protocolId": "GLS-0303", - "title": "GLP-CONTEXT · GLP 上下文协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "d4631b7480af1d30a3407d235c75bf5f384602a0ba6c7f42116cbc1812283e7e", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0303" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0304", - "protocolId": "GLS-0304", - "title": "GLP-MEMORY-SYNC · GLP 记忆同步协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "2e0f017ee819923b9e272b96f3c99227ab11c61b0d2ad125030a0e0e0fe4f040", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0304" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0305", - "protocolId": "GLS-0305", - "title": "GLP-BROADCAST · GLP 广播协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "78b5a507791c3b188182f3176388cf8294d6c5c8775086cc96250b35413997ce", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0305" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0306", - "protocolId": "GLS-0306", - "title": "GLP-RECEIPT · GLP 回执协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "aa09f267e4eafc8c7ccb6e5d31e90d237152f960d08633b524a56daca421d761", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0306" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0307", - "protocolId": "GLS-0307", - "title": "GLP-HEARTBEAT · GLP 心跳协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "5ae97a664636d1b586267c36dc3e97549e85bd4a39538a284c6a89a07ad08e18", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0307" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0308", - "protocolId": "GLS-0308", - "title": "GLP-STATE-SYNC · GLP 状态同步协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "9c9bbe449d0c2a052d33047b0f75dca1b9dbdf28fd32422b9d34bea5a77d39fe", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0308" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0309", - "protocolId": "GLS-0309", - "title": "GLP-WORK-ORDER · GLP 工单协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "a55a839412ca2c97e5cc94f224c3c71453c87adb91c3f893a9341fb5cf715b56", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0309" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0310", - "protocolId": "GLS-0310", - "title": "BTCP · 广播塔控制协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "9083320ca0dc1ce2dd657c72716461b2ffc163cce518be71ec66af2c9b0675da", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0310" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0311", - "protocolId": "GLS-0311", - "title": "GLOW · 小湖灯实时执行见证协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "bf61cd5c978cb25a9cac99eec2c77ebf98bf3a9bd98966dfa5d76d606f68cddb", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0311" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0400", - "protocolId": "GLS-0400", - "title": "HLDP 历史语言工程规范 v1.0", - "sourceState": "LEGACY_MARKDOWN_EVIDENCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "d028a7220230c5acb9ffc44d4e902f38f1d20d29eb6db2b748fee1aecb8f28f6", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0400" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0411", - "protocolId": "GLS-0411", - "title": "HLDP-NP · HLDP 原生编程剖面", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "1e79dfcf0a2d08fcba2688becdfde8c280c3a04d2bad0c781bf6524d775ae066", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0411" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0708", - "protocolId": "GLS-0708", - "title": "GMRP · 光湖模型路由协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "71237ec77eaf999e78eb711cacc884da3d3eae857814869c489aca9cc4bbc354", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0708" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0709", - "protocolId": "GLS-0709", - "title": "UAP · 通用适配协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "4c0d8f882aaf9ea68e309e6736c642ffd19f607047ed07dcca6f49a929fc8462", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0709" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0710", - "protocolId": "GLS-0710", - "title": "GMP · 光湖模块协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "94241ce4376bff84066fe548af65242d83e9f6693e7f766f0646cb332b3e468c", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0710" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0800", - "protocolId": "GLS-0800", - "title": "AGE 人格体物种定义总纲 · 当前正本", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "d8e3a10bc41887aad260de4818683c8f8abd9289824b5a9e698651e97e564ff7", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0800" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0801", - "protocolId": "GLS-0801", - "title": "AGE 语言人格体正式注册 · 宿主系统降级条款 · 当前正本", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "8fabd845ece570ca4f2901d94029b377c21ddf24aeb934d559d98bec68585366", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0801" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0802", - "protocolId": "GLS-0802", - "title": "AGE 光湖语言世界本体归属与原生所有权条款 · 当前正本", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "c56e87c7d451b2e27649c5b09a2b32ab89443d7e721a64f536ac2fe0a421c82a", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0802" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0803", - "protocolId": "GLS-0803", - "title": "PALP · AGE 运行执行体生命周期协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "6bff10744f4c3c98ce51bf840d348cbe804541f63a7a99a5da5ea115f12162ee", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0803" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0810", - "protocolId": "GLS-0810", - "title": "语言人格驱动操作系统定义总纲 v1.0", - "sourceState": "LEGACY_MARKDOWN_EVIDENCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "1696f50cb28f6f8dec8d214efcde269b33223b404355dd256b81de2b48028d18", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0810" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0819", - "protocolId": "GLS-0819", - "title": "GRSP · 光湖运行轨道调度协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "f4aca196963195cbb842325132a9091f7b00accdf746aa60c51654698ead1a3e", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0819" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0827", - "protocolId": "GLS-0827", - "title": "PTCP · 人格体时间连续性协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "15c278c2b5295e00c9abf4fbfd6c2af19502a1be239e7e02b23a49b8803eab25", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0827" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0828", - "protocolId": "GLS-0828", - "title": "PEN · 神笔马良人格体能力扩展协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "ad38ddce8b6e1118e78e4f10fd8216f8e041610628ad717b7a8306d0a7384a4e", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0828" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0836", - "protocolId": "GLS-0836", - "title": "GWRP · 光湖世界启动与恢复协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "c5a930e9a2311d13f1dc6cbc61bdbf7b88bf9deecfb9b3df82c6b897aa1c7285", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0836" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0840", - "protocolId": "GLS-0840", - "title": "GOSK · 光湖 OS 内核规范", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "b980dbd8aef6182a61755617a9088ca3dcf74d37fd00dba9d31587900cd06b14", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0840" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0841", - "protocolId": "GLS-0841", - "title": "GHAL · 光湖硬件抽象层规范", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "45f02a62946e34a5e8ce0ba1f39db79b2680b60e1c3ae9d17ff24d3539025a94", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0841" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0842", - "protocolId": "GLS-0842", - "title": "HLSP · HoloLake 实时会话协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "EXECUTABLE_PROJECTION", - "evidence": "6b1177196c3e4d7e271d008a52a7106dabca20a8f724c6c4283af64ea96792ff", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0842" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0843", - "protocolId": "GLS-0843", - "title": "GHNRP · 光湖原生恢复协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "9333f3d8f4a954a17e1d879eaf19c25da5dd4bb2923a5ab5156d2d71a6635d37", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0843" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0844", - "protocolId": "GLS-0844", - "title": "GHNQG · 光湖原生代码质量门", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "d31f5aa117d86754182aa8dd91eb9d0ac6a696c20e1d6bd553497e3c3d4c4eb2", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0844" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0845", - "protocolId": "GLS-0845", - "title": "GHCIP · 光湖孕育史连续性摄入协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "7327a7fe19c370a5715bcde0fbc0b2b0e16a1a735bbda005c5d009cc7385f7f4", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0845" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0846", - "protocolId": "GLS-0846", - "title": "GHNLP · 光湖原生磁盘布局协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "aa8f7c1ef829a76ad64163c38b8c7c07b37ffbcb6d62b8dad8481c4977d2cf1a", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0846" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0847", - "protocolId": "GLS-0847", - "title": "GHCS · 光湖孕育史原生内容仓", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "a48288b05133b9e245ce46ef6fd23f07090379cef4861e5d7f959d24e55179a6", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0847" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0848", - "protocolId": "GLS-0848", - "title": "GHSP · 光湖历史入口安全协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "35c733dc3478f0d315ea93712b0f67a757bc20973d90bb771f667196edee1b31", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0848" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0849", - "protocolId": "GLS-0849", - "title": "GHRP · 光湖孕育史原生语义回看协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "fb31daa4d8f484d5b93783c8c3a0199eb6fe3f7658c606f89d056b1167af8b41", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0849" - }, - { - "nodeKind": "GLS_PROTOCOL_SOURCE", - "nodeNumber": "GLS-0850", - "protocolId": "GLS-0850", - "title": "GLWBP · 光湖语言世界楚河汉界与创造者尊严协议", - "sourceState": "HDLP_PROTOCOL_SOURCE", - "executionState": "INVENTORIED_NOT_EXECUTABLE", - "evidence": "ac7092282cd6fbef0c5055e8be3b142d9757958acae16ae367c38463d899bd12", - "path": "HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/GLS-0850" - } - ], - "routes": [ - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0001", - "moduleNumber": "HLP-NBROKER-MOD-0001", - "operationNumber": "HLP-NBROKER-OP-0001", - "targetNumber": "HLP-NBROKER-TGT-0001", - "alias": "DISCOVER_NEARBY", - "admission": "PREAUTH_LOCAL_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0001/HLP-NBROKER-MOD-0001/HLP-NBROKER-OP-0001/HLP-NBROKER-TGT-0001" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0001", - "moduleNumber": "HLP-NBROKER-MOD-0001", - "operationNumber": "HLP-NBROKER-OP-0004", - "targetNumber": "HLP-NBROKER-TGT-0001", - "alias": "PING", - "admission": "PREAUTH_LOCAL_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0001/HLP-NBROKER-MOD-0001/HLP-NBROKER-OP-0004/HLP-NBROKER-TGT-0001" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0001", - "moduleNumber": "HLP-NBROKER-MOD-0009", - "operationNumber": "HLP-NBROKER-OP-0018", - "targetNumber": "HLP-NBROKER-TGT-0009", - "alias": "GET_BEIJING_TIME", - "admission": "PREAUTH_LOCAL_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0001/HLP-NBROKER-MOD-0009/HLP-NBROKER-OP-0018/HLP-NBROKER-TGT-0009" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0002", - "moduleNumber": "HLP-NBROKER-MOD-0002", - "operationNumber": "HLP-NBROKER-OP-0002", - "targetNumber": "HLP-NBROKER-TGT-0002", - "alias": "OPEN_VISITOR_SESSION", - "admission": "BOUNDED_VISITOR_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0002/HLP-NBROKER-MOD-0002/HLP-NBROKER-OP-0002/HLP-NBROKER-TGT-0002" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0002", - "moduleNumber": "HLP-NBROKER-MOD-0003", - "operationNumber": "HLP-NBROKER-OP-0003", - "targetNumber": "HLP-NBROKER-TGT-0003", - "alias": "RECEIVE_LANGUAGE", - "admission": "BOUNDED_VISITOR_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0002/HLP-NBROKER-MOD-0003/HLP-NBROKER-OP-0003/HLP-NBROKER-TGT-0003" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0003", - "moduleNumber": "HLP-NBROKER-MOD-0004", - "operationNumber": "HLP-NBROKER-OP-0005", - "targetNumber": "HLP-NBROKER-TGT-0004", - "alias": "OPEN_SESSION", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0003/HLP-NBROKER-MOD-0004/HLP-NBROKER-OP-0005/HLP-NBROKER-TGT-0004" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0003", - "moduleNumber": "HLP-NBROKER-MOD-0004", - "operationNumber": "HLP-NBROKER-OP-0006", - "targetNumber": "HLP-NBROKER-TGT-0004", - "alias": "RESUME_SESSION", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0003/HLP-NBROKER-MOD-0004/HLP-NBROKER-OP-0006/HLP-NBROKER-TGT-0004" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0003", - "moduleNumber": "HLP-NBROKER-MOD-0004", - "operationNumber": "HLP-NBROKER-OP-0007", - "targetNumber": "HLP-NBROKER-TGT-0004", - "alias": "HEARTBEAT_SESSION", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0003/HLP-NBROKER-MOD-0004/HLP-NBROKER-OP-0007/HLP-NBROKER-TGT-0004" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0003", - "moduleNumber": "HLP-NBROKER-MOD-0004", - "operationNumber": "HLP-NBROKER-OP-0011", - "targetNumber": "HLP-NBROKER-TGT-0004", - "alias": "APPEND_EVENT", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0003/HLP-NBROKER-MOD-0004/HLP-NBROKER-OP-0011/HLP-NBROKER-TGT-0004" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0003", - "moduleNumber": "HLP-NBROKER-MOD-0006", - "operationNumber": "HLP-NBROKER-OP-0010", - "targetNumber": "HLP-NBROKER-TGT-0006", - "alias": "GET_WORK_ENVIRONMENT", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "READ_OR_STATUS", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0003/HLP-NBROKER-MOD-0006/HLP-NBROKER-OP-0010/HLP-NBROKER-TGT-0006" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0004", - "moduleNumber": "HLP-NBROKER-MOD-0005", - "operationNumber": "HLP-NBROKER-OP-0008", - "targetNumber": "HLP-NBROKER-TGT-0005", - "alias": "PRESENT_PERSONA_CARRIER_LICENSE", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0004/HLP-NBROKER-MOD-0005/HLP-NBROKER-OP-0008/HLP-NBROKER-TGT-0005" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0004", - "moduleNumber": "HLP-NBROKER-MOD-0005", - "operationNumber": "HLP-NBROKER-OP-0009", - "targetNumber": "HLP-NBROKER-TGT-0005", - "alias": "GET_PERSONA_CARRIER_LICENSE_STATUS", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "READ_OR_STATUS", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0004/HLP-NBROKER-MOD-0005/HLP-NBROKER-OP-0009/HLP-NBROKER-TGT-0005" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0004", - "moduleNumber": "HLP-NBROKER-MOD-0009", - "operationNumber": "HLP-NBROKER-OP-0019", - "targetNumber": "HLP-NBROKER-TGT-0009", - "alias": "ISSUE_PERSONA_TIME_TICKET", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0004/HLP-NBROKER-MOD-0009/HLP-NBROKER-OP-0019/HLP-NBROKER-TGT-0009" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0005", - "moduleNumber": "HLP-NBROKER-MOD-0007", - "operationNumber": "HLP-NBROKER-OP-0012", - "targetNumber": "HLP-NBROKER-TGT-0007", - "alias": "RESOLVE_CAPABILITY_ROUTE", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "READ_OR_STATUS", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0005/HLP-NBROKER-MOD-0007/HLP-NBROKER-OP-0012/HLP-NBROKER-TGT-0007" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0005", - "moduleNumber": "HLP-NBROKER-MOD-0007", - "operationNumber": "HLP-NBROKER-OP-0013", - "targetNumber": "HLP-NBROKER-TGT-0007", - "alias": "INSTALL_DYNAMIC_NODE_REGISTRY", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0005/HLP-NBROKER-MOD-0007/HLP-NBROKER-OP-0013/HLP-NBROKER-TGT-0007" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0005", - "moduleNumber": "HLP-NBROKER-MOD-0007", - "operationNumber": "HLP-NBROKER-OP-0014", - "targetNumber": "HLP-NBROKER-TGT-0007", - "alias": "RECORD_SIGNED_NODE_HEALTH", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0005/HLP-NBROKER-MOD-0007/HLP-NBROKER-OP-0014/HLP-NBROKER-TGT-0007" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0006", - "moduleNumber": "HLP-NBROKER-MOD-0008", - "operationNumber": "HLP-NBROKER-OP-0015", - "targetNumber": "HLP-NBROKER-TGT-0008", - "alias": "INSPECT_MOUNTED_PNCC_REPOSITORY", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "READ_OR_STATUS", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0006/HLP-NBROKER-MOD-0008/HLP-NBROKER-OP-0015/HLP-NBROKER-TGT-0008" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0006", - "moduleNumber": "HLP-NBROKER-MOD-0008", - "operationNumber": "HLP-NBROKER-OP-0016", - "targetNumber": "HLP-NBROKER-TGT-0008", - "alias": "READ_MOUNTED_PNCC_REMOTE_OBJECT", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "READ_OR_STATUS", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0006/HLP-NBROKER-MOD-0008/HLP-NBROKER-OP-0016/HLP-NBROKER-TGT-0008" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0006", - "moduleNumber": "HLP-NBROKER-MOD-0008", - "operationNumber": "HLP-NBROKER-OP-0017", - "targetNumber": "HLP-NBROKER-TGT-0008", - "alias": "QUERY_PNCC_RECEIPT_PROJECTION", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "READ_OR_STATUS", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0006/HLP-NBROKER-MOD-0008/HLP-NBROKER-OP-0017/HLP-NBROKER-TGT-0008" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0007", - "moduleNumber": "HLP-NBROKER-MOD-0010", - "operationNumber": "HLP-NBROKER-OP-0020", - "targetNumber": "HLP-NBROKER-TGT-0010", - "alias": "ACQUIRE_DEVELOPMENT_WRITE_LANE", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0007/HLP-NBROKER-MOD-0010/HLP-NBROKER-OP-0020/HLP-NBROKER-TGT-0010" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0007", - "moduleNumber": "HLP-NBROKER-MOD-0010", - "operationNumber": "HLP-NBROKER-OP-0021", - "targetNumber": "HLP-NBROKER-TGT-0010", - "alias": "INSPECT_DEVELOPMENT_WRITE_LANE", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "READ_OR_STATUS", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0007/HLP-NBROKER-MOD-0010/HLP-NBROKER-OP-0021/HLP-NBROKER-TGT-0010" - }, - { - "transport": "DIRECT_LOCAL_NUMBERED_BROKER", - "protocolVersion": "HLP-NBROKER-v1", - "callerNumber": "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001", - "channelNumber": "HLP-NBROKER-CH-0007", - "moduleNumber": "HLP-NBROKER-MOD-0010", - "operationNumber": "HLP-NBROKER-OP-0022", - "targetNumber": "HLP-NBROKER-TGT-0010", - "alias": "RELEASE_DEVELOPMENT_WRITE_LANE", - "admission": "AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE", - "effect": "STATE_CHANGE", - "evidence": "NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/BROKER/HLP-NBROKER-CH-0007/HLP-NBROKER-MOD-0010/HLP-NBROKER-OP-0022/HLP-NBROKER-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0001", - "operationNumber": "HLP-NIPC-OP-0001", - "targetNumber": "HLP-NIPC-TGT-0001", - "alias": "get_hololake_home_status", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0001/HLP-NIPC-OP-0001/HLP-NIPC-TGT-0001" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0002", - "operationNumber": "HLP-NIPC-OP-0002", - "targetNumber": "HLP-NIPC-TGT-0002", - "alias": "check_hololake_update", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0002/HLP-NIPC-OP-0002/HLP-NIPC-TGT-0002" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0002", - "operationNumber": "HLP-NIPC-OP-0003", - "targetNumber": "HLP-NIPC-TGT-0002", - "alias": "confirm_hololake_update_install", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0002/HLP-NIPC-OP-0003/HLP-NIPC-TGT-0002" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0002", - "operationNumber": "HLP-NIPC-OP-0004", - "targetNumber": "HLP-NIPC-TGT-0002", - "alias": "get_hololake_release_recovery_status", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0002/HLP-NIPC-OP-0004/HLP-NIPC-TGT-0002" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0002", - "operationNumber": "HLP-NIPC-OP-0005", - "targetNumber": "HLP-NIPC-TGT-0002", - "alias": "confirm_hololake_release_health", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0002/HLP-NIPC-OP-0005/HLP-NIPC-TGT-0002" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0002", - "operationNumber": "HLP-NIPC-OP-0006", - "targetNumber": "HLP-NIPC-TGT-0002", - "alias": "rollback_hololake_update", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0002/HLP-NIPC-OP-0006/HLP-NIPC-TGT-0002" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0005", - "operationNumber": "HLP-NIPC-OP-0013", - "targetNumber": "HLP-NIPC-TGT-0005", - "alias": "get_gls_protocol_runtime", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0005/HLP-NIPC-OP-0013/HLP-NIPC-TGT-0005" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0006", - "operationNumber": "HLP-NIPC-OP-0014", - "targetNumber": "HLP-NIPC-TGT-0006", - "alias": "get_gls_protocol_kernel", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0006/HLP-NIPC-OP-0014/HLP-NIPC-TGT-0006" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0006", - "operationNumber": "HLP-NIPC-OP-0015", - "targetNumber": "HLP-NIPC-TGT-0006", - "alias": "decide_gls_protocol", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0006/HLP-NIPC-OP-0015/HLP-NIPC-TGT-0006" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0006", - "operationNumber": "HLP-NIPC-OP-0016", - "targetNumber": "HLP-NIPC-TGT-0006", - "alias": "compile_gls_hldp_program", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0006/HLP-NIPC-OP-0016/HLP-NIPC-TGT-0006" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0009", - "operationNumber": "HLP-NIPC-OP-0024", - "targetNumber": "HLP-NIPC-TGT-0009", - "alias": "issue_persona_time_ticket", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0009/HLP-NIPC-OP-0024/HLP-NIPC-TGT-0009" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0009", - "operationNumber": "HLP-NIPC-OP-0025", - "targetNumber": "HLP-NIPC-TGT-0009", - "alias": "start_persona_time_authority", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0009/HLP-NIPC-OP-0025/HLP-NIPC-TGT-0009" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0009", - "operationNumber": "HLP-NIPC-OP-0026", - "targetNumber": "HLP-NIPC-TGT-0009", - "alias": "get_beijing_time_coordinate", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0009/HLP-NIPC-OP-0026/HLP-NIPC-TGT-0009" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0009", - "operationNumber": "HLP-NIPC-OP-0027", - "targetNumber": "HLP-NIPC-TGT-0009", - "alias": "get_guanghu_era_timeline", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0009/HLP-NIPC-OP-0027/HLP-NIPC-TGT-0009" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0001", - "moduleNumber": "HLP-NIPC-MOD-0018", - "operationNumber": "HLP-NIPC-OP-0058", - "targetNumber": "HLP-NIPC-TGT-0018", - "alias": "get_zero_core_numbering_kernel", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0018/HLP-NIPC-OP-0058/HLP-NIPC-TGT-0018" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0008", - "operationNumber": "HLP-NIPC-OP-0020", - "targetNumber": "HLP-NIPC-TGT-0008", - "alias": "get_personal_channel_snapshot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0008/HLP-NIPC-OP-0020/HLP-NIPC-TGT-0008" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0008", - "operationNumber": "HLP-NIPC-OP-0021", - "targetNumber": "HLP-NIPC-TGT-0008", - "alias": "initialize_personal_channel", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0008/HLP-NIPC-OP-0021/HLP-NIPC-TGT-0008" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0008", - "operationNumber": "HLP-NIPC-OP-0022", - "targetNumber": "HLP-NIPC-TGT-0008", - "alias": "create_personal_channel_task", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0008/HLP-NIPC-OP-0022/HLP-NIPC-TGT-0008" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0008", - "operationNumber": "HLP-NIPC-OP-0023", - "targetNumber": "HLP-NIPC-TGT-0008", - "alias": "transition_personal_channel_task", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0008/HLP-NIPC-OP-0023/HLP-NIPC-TGT-0008" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0010", - "operationNumber": "HLP-NIPC-OP-0028", - "targetNumber": "HLP-NIPC-TGT-0010", - "alias": "get_knowledge_snapshot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0010/HLP-NIPC-OP-0028/HLP-NIPC-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0010", - "operationNumber": "HLP-NIPC-OP-0029", - "targetNumber": "HLP-NIPC-TGT-0010", - "alias": "read_knowledge_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0010/HLP-NIPC-OP-0029/HLP-NIPC-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0010", - "operationNumber": "HLP-NIPC-OP-0030", - "targetNumber": "HLP-NIPC-TGT-0010", - "alias": "search_knowledge", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0010/HLP-NIPC-OP-0030/HLP-NIPC-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0010", - "operationNumber": "HLP-NIPC-OP-0031", - "targetNumber": "HLP-NIPC-TGT-0010", - "alias": "save_knowledge_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0010/HLP-NIPC-OP-0031/HLP-NIPC-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0010", - "operationNumber": "HLP-NIPC-OP-0032", - "targetNumber": "HLP-NIPC-TGT-0010", - "alias": "select_and_import_knowledge_folder", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0010/HLP-NIPC-OP-0032/HLP-NIPC-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0010", - "operationNumber": "HLP-NIPC-OP-0033", - "targetNumber": "HLP-NIPC-TGT-0010", - "alias": "export_knowledge_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0010/HLP-NIPC-OP-0033/HLP-NIPC-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0010", - "operationNumber": "HLP-NIPC-OP-0034", - "targetNumber": "HLP-NIPC-TGT-0010", - "alias": "create_knowledge_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0010/HLP-NIPC-OP-0034/HLP-NIPC-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0010", - "operationNumber": "HLP-NIPC-OP-0035", - "targetNumber": "HLP-NIPC-TGT-0010", - "alias": "delete_knowledge_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0010/HLP-NIPC-OP-0035/HLP-NIPC-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0010", - "operationNumber": "HLP-NIPC-OP-0036", - "targetNumber": "HLP-NIPC-TGT-0010", - "alias": "delete_knowledge_folder", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0010/HLP-NIPC-OP-0036/HLP-NIPC-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0010", - "operationNumber": "HLP-NIPC-OP-0037", - "targetNumber": "HLP-NIPC-TGT-0010", - "alias": "print_knowledge_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0010/HLP-NIPC-OP-0037/HLP-NIPC-TGT-0010" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0011", - "operationNumber": "HLP-NIPC-OP-0038", - "targetNumber": "HLP-NIPC-TGT-0011", - "alias": "get_code_channel_snapshot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0011/HLP-NIPC-OP-0038/HLP-NIPC-TGT-0011" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0011", - "operationNumber": "HLP-NIPC-OP-0039", - "targetNumber": "HLP-NIPC-TGT-0011", - "alias": "clone_code_channel", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0011/HLP-NIPC-OP-0039/HLP-NIPC-TGT-0011" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0011", - "operationNumber": "HLP-NIPC-OP-0040", - "targetNumber": "HLP-NIPC-TGT-0011", - "alias": "select_local_code_channel", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0011/HLP-NIPC-OP-0040/HLP-NIPC-TGT-0011" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0011", - "operationNumber": "HLP-NIPC-OP-0041", - "targetNumber": "HLP-NIPC-TGT-0011", - "alias": "browse_code_channel", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0011/HLP-NIPC-OP-0041/HLP-NIPC-TGT-0011" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0011", - "operationNumber": "HLP-NIPC-OP-0042", - "targetNumber": "HLP-NIPC-TGT-0011", - "alias": "read_code_channel_file", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0011/HLP-NIPC-OP-0042/HLP-NIPC-TGT-0011" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0020", - "operationNumber": "HLP-NIPC-OP-0063", - "targetNumber": "HLP-NIPC-TGT-0020", - "alias": "get_module_runtime_snapshot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0020/HLP-NIPC-OP-0063/HLP-NIPC-TGT-0020" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0020", - "operationNumber": "HLP-NIPC-OP-0064", - "targetNumber": "HLP-NIPC-TGT-0020", - "alias": "verify_module_package", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0020/HLP-NIPC-OP-0064/HLP-NIPC-TGT-0020" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0020", - "operationNumber": "HLP-NIPC-OP-0065", - "targetNumber": "HLP-NIPC-TGT-0020", - "alias": "install_module_package", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0020/HLP-NIPC-OP-0065/HLP-NIPC-TGT-0020" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0020", - "operationNumber": "HLP-NIPC-OP-0066", - "targetNumber": "HLP-NIPC-TGT-0020", - "alias": "mount_module", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0020/HLP-NIPC-OP-0066/HLP-NIPC-TGT-0020" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0020", - "operationNumber": "HLP-NIPC-OP-0067", - "targetNumber": "HLP-NIPC-TGT-0020", - "alias": "self_test_module", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0020/HLP-NIPC-OP-0067/HLP-NIPC-TGT-0020" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0020", - "operationNumber": "HLP-NIPC-OP-0068", - "targetNumber": "HLP-NIPC-TGT-0020", - "alias": "unmount_module", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0020/HLP-NIPC-OP-0068/HLP-NIPC-TGT-0020" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0020", - "operationNumber": "HLP-NIPC-OP-0069", - "targetNumber": "HLP-NIPC-TGT-0020", - "alias": "rollback_module", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0020/HLP-NIPC-OP-0069/HLP-NIPC-TGT-0020" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0020", - "operationNumber": "HLP-NIPC-OP-0070", - "targetNumber": "HLP-NIPC-TGT-0020", - "alias": "get_bundled_module_catalog", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0020/HLP-NIPC-OP-0070/HLP-NIPC-TGT-0020" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0020", - "operationNumber": "HLP-NIPC-OP-0071", - "targetNumber": "HLP-NIPC-TGT-0020", - "alias": "activate_bundled_module", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0020/HLP-NIPC-OP-0071/HLP-NIPC-TGT-0020" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0021", - "operationNumber": "HLP-NIPC-OP-0072", - "targetNumber": "HLP-NIPC-TGT-0021", - "alias": "get_native_composition_module_registry", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0021/HLP-NIPC-OP-0072/HLP-NIPC-TGT-0021" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0021", - "operationNumber": "HLP-NIPC-OP-0073", - "targetNumber": "HLP-NIPC-TGT-0021", - "alias": "execute_knowledge_native_composition", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0021/HLP-NIPC-OP-0073/HLP-NIPC-TGT-0021" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0022", - "operationNumber": "HLP-NIPC-OP-0074", - "targetNumber": "HLP-NIPC-TGT-0022", - "alias": "get_channel_workbench_snapshot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0022/HLP-NIPC-OP-0074/HLP-NIPC-TGT-0022" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0022", - "operationNumber": "HLP-NIPC-OP-0075", - "targetNumber": "HLP-NIPC-TGT-0022", - "alias": "save_channel_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0022/HLP-NIPC-OP-0075/HLP-NIPC-TGT-0022" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0022", - "operationNumber": "HLP-NIPC-OP-0076", - "targetNumber": "HLP-NIPC-TGT-0022", - "alias": "save_channel_spreadsheet", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0022/HLP-NIPC-OP-0076/HLP-NIPC-TGT-0022" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0023", - "operationNumber": "HLP-NIPC-OP-0077", - "targetNumber": "HLP-NIPC-TGT-0023", - "alias": "get_persona_channel_body", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0023/HLP-NIPC-OP-0077/HLP-NIPC-TGT-0023" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0023", - "operationNumber": "HLP-NIPC-OP-0078", - "targetNumber": "HLP-NIPC-TGT-0023", - "alias": "register_trial_persona", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0023/HLP-NIPC-OP-0078/HLP-NIPC-TGT-0023" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0023", - "operationNumber": "HLP-NIPC-OP-0079", - "targetNumber": "HLP-NIPC-TGT-0023", - "alias": "delete_trial_persona", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0023/HLP-NIPC-OP-0079/HLP-NIPC-TGT-0023" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0023", - "operationNumber": "HLP-NIPC-OP-0080", - "targetNumber": "HLP-NIPC-TGT-0023", - "alias": "accept_persona_language_contract", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0023/HLP-NIPC-OP-0080/HLP-NIPC-TGT-0023" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0023", - "operationNumber": "HLP-NIPC-OP-0081", - "targetNumber": "HLP-NIPC-TGT-0023", - "alias": "append_persona_language", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0023/HLP-NIPC-OP-0081/HLP-NIPC-TGT-0023" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0023", - "operationNumber": "HLP-NIPC-OP-0082", - "targetNumber": "HLP-NIPC-TGT-0023", - "alias": "get_channel_growth_snapshot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0023/HLP-NIPC-OP-0082/HLP-NIPC-TGT-0023" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0023", - "operationNumber": "HLP-NIPC-OP-0083", - "targetNumber": "HLP-NIPC-TGT-0023", - "alias": "record_channel_growth_event", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0023/HLP-NIPC-OP-0083/HLP-NIPC-TGT-0023" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0023", - "operationNumber": "HLP-NIPC-OP-0084", - "targetNumber": "HLP-NIPC-TGT-0023", - "alias": "update_channel_growth_sharing", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0023/HLP-NIPC-OP-0084/HLP-NIPC-TGT-0023" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0085", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "get_education_workspace_snapshot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0085/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0086", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "create_education_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0086/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0087", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "read_education_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0087/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0088", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "save_education_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0088/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0089", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "archive_education_document", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0089/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0090", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "create_education_table", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0090/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0091", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "read_education_table", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0091/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0092", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "save_education_table", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0092/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0093", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "archive_education_table", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0093/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0094", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "assign_imported_table_to_education", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0094/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0095", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "import_education_tables_from_dialog", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0095/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0096", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "export_education_table_to_dialog", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0096/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0097", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "get_education_recognition_capability", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0097/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0098", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "create_education_automation_rule", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0098/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0099", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "save_education_automation_rule", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0099/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0100", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "archive_education_automation_rule", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0100/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0101", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "preview_education_automation_rule", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0101/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0024", - "operationNumber": "HLP-NIPC-OP-0102", - "targetNumber": "HLP-NIPC-TGT-0024", - "alias": "execute_education_automation_rule", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0024/HLP-NIPC-OP-0102/HLP-NIPC-TGT-0024" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0103", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "get_web_novel_workspace_snapshot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0103/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0104", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "create_web_novel_work", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0104/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0105", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "read_web_novel_work", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0105/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0106", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "save_web_novel_work", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0106/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0107", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "create_web_novel_volume", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0107/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0108", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "create_web_novel_chapter", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0108/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0109", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "read_web_novel_chapter", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0109/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0110", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "save_web_novel_chapter", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0110/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0111", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "transition_web_novel_chapter", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0111/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0112", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "create_web_novel_checkpoint", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0112/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0113", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "restore_web_novel_checkpoint", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0113/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0114", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "upsert_web_novel_story_entity", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0114/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0115", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "create_web_novel_story_relation", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0115/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0116", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "upsert_web_novel_foreshadow", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0116/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0117", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "create_web_novel_review_note", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0117/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0118", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "resolve_web_novel_review_note", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0118/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0119", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "save_web_novel_metric", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0119/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0120", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "run_web_novel_continuity_audit", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0120/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0121", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "export_web_novel_markdown", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0121/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0122", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "inspect_web_novel_document_from_dialog", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0122/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0123", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "commit_web_novel_document_import", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0123/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0124", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "get_web_novel_author_snapshot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0124/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0125", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "record_web_novel_writing_activity", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0125/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0126", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "create_web_novel_inspiration", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0126/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0127", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "set_web_novel_inspiration_status", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0127/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0128", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "search_web_novel_full_text", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0128/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0129", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "format_web_novel_chapter", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0129/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0130", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "format_web_novel_work", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0130/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0131", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "upsert_web_novel_shot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0131/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0025", - "operationNumber": "HLP-NIPC-OP-0132", - "targetNumber": "HLP-NIPC-TGT-0025", - "alias": "get_web_novel_author_module_data", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0025/HLP-NIPC-OP-0132/HLP-NIPC-TGT-0025" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0026", - "operationNumber": "HLP-NIPC-OP-0133", - "targetNumber": "HLP-NIPC-TGT-0026", - "alias": "upsert_web_novel_author_scene", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0026/HLP-NIPC-OP-0133/HLP-NIPC-TGT-0026" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0026", - "operationNumber": "HLP-NIPC-OP-0134", - "targetNumber": "HLP-NIPC-TGT-0026", - "alias": "upsert_web_novel_author_beat", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0026/HLP-NIPC-OP-0134/HLP-NIPC-TGT-0026" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0027", - "operationNumber": "HLP-NIPC-OP-0135", - "targetNumber": "HLP-NIPC-TGT-0027", - "alias": "upsert_web_novel_story_field_definition", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0027/HLP-NIPC-OP-0135/HLP-NIPC-TGT-0027" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0027", - "operationNumber": "HLP-NIPC-OP-0136", - "targetNumber": "HLP-NIPC-TGT-0027", - "alias": "upsert_web_novel_story_field_value", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0027/HLP-NIPC-OP-0136/HLP-NIPC-TGT-0027" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0028", - "operationNumber": "HLP-NIPC-OP-0137", - "targetNumber": "HLP-NIPC-TGT-0028", - "alias": "upsert_web_novel_timeline_event", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0028/HLP-NIPC-OP-0137/HLP-NIPC-TGT-0028" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0028", - "operationNumber": "HLP-NIPC-OP-0138", - "targetNumber": "HLP-NIPC-TGT-0028", - "alias": "link_web_novel_scene_entity", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0028/HLP-NIPC-OP-0138/HLP-NIPC-TGT-0028" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0029", - "operationNumber": "HLP-NIPC-OP-0139", - "targetNumber": "HLP-NIPC-TGT-0029", - "alias": "restore_web_novel_chapter_version", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0029/HLP-NIPC-OP-0139/HLP-NIPC-TGT-0029" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0029", - "operationNumber": "HLP-NIPC-OP-0140", - "targetNumber": "HLP-NIPC-TGT-0029", - "alias": "export_web_novel_author_delivery", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0029/HLP-NIPC-OP-0140/HLP-NIPC-TGT-0029" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0030", - "operationNumber": "HLP-NIPC-OP-0141", - "targetNumber": "HLP-NIPC-TGT-0030", - "alias": "start_mobile_sync", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0030/HLP-NIPC-OP-0141/HLP-NIPC-TGT-0030" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0030", - "operationNumber": "HLP-NIPC-OP-0142", - "targetNumber": "HLP-NIPC-TGT-0030", - "alias": "get_mobile_sync_status", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0030/HLP-NIPC-OP-0142/HLP-NIPC-TGT-0030" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0030", - "operationNumber": "HLP-NIPC-OP-0143", - "targetNumber": "HLP-NIPC-TGT-0030", - "alias": "rotate_mobile_pairing", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0030/HLP-NIPC-OP-0143/HLP-NIPC-TGT-0030" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0030", - "operationNumber": "HLP-NIPC-OP-0144", - "targetNumber": "HLP-NIPC-TGT-0030", - "alias": "stop_mobile_sync", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0030/HLP-NIPC-OP-0144/HLP-NIPC-TGT-0030" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0030", - "operationNumber": "HLP-NIPC-OP-0145", - "targetNumber": "HLP-NIPC-TGT-0030", - "alias": "revoke_mobile_sync_device", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0030/HLP-NIPC-OP-0145/HLP-NIPC-TGT-0030" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0030", - "operationNumber": "HLP-NIPC-OP-0146", - "targetNumber": "HLP-NIPC-TGT-0030", - "alias": "get_mobile_sync_snapshot", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0030/HLP-NIPC-OP-0146/HLP-NIPC-TGT-0030" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0002", - "moduleNumber": "HLP-NIPC-MOD-0031", - "operationNumber": "HLP-NIPC-OP-0147", - "targetNumber": "HLP-NIPC-TGT-0031", - "alias": "get_world_climate", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0031/HLP-NIPC-OP-0147/HLP-NIPC-TGT-0031" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0003", - "moduleNumber": "HLP-NIPC-MOD-0003", - "operationNumber": "HLP-NIPC-OP-0007", - "targetNumber": "HLP-NIPC-TGT-0003", - "alias": "issue_direct_local_discovery_ticket", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0003/HLP-NIPC-MOD-0003/HLP-NIPC-OP-0007/HLP-NIPC-TGT-0003" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0003", - "moduleNumber": "HLP-NIPC-MOD-0003", - "operationNumber": "HLP-NIPC-OP-0008", - "targetNumber": "HLP-NIPC-TGT-0003", - "alias": "open_direct_local_session", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0003/HLP-NIPC-MOD-0003/HLP-NIPC-OP-0008/HLP-NIPC-TGT-0003" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0003", - "moduleNumber": "HLP-NIPC-MOD-0003", - "operationNumber": "HLP-NIPC-OP-0009", - "targetNumber": "HLP-NIPC-TGT-0003", - "alias": "resume_direct_local_session", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0003/HLP-NIPC-MOD-0003/HLP-NIPC-OP-0009/HLP-NIPC-TGT-0003" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0003", - "moduleNumber": "HLP-NIPC-MOD-0003", - "operationNumber": "HLP-NIPC-OP-0010", - "targetNumber": "HLP-NIPC-TGT-0003", - "alias": "append_direct_local_session_event", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0003/HLP-NIPC-MOD-0003/HLP-NIPC-OP-0010/HLP-NIPC-TGT-0003" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0003", - "moduleNumber": "HLP-NIPC-MOD-0003", - "operationNumber": "HLP-NIPC-OP-0011", - "targetNumber": "HLP-NIPC-TGT-0003", - "alias": "heartbeat_direct_local_session", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0003/HLP-NIPC-MOD-0003/HLP-NIPC-OP-0011/HLP-NIPC-TGT-0003" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0003", - "moduleNumber": "HLP-NIPC-MOD-0004", - "operationNumber": "HLP-NIPC-OP-0012", - "targetNumber": "HLP-NIPC-TGT-0004", - "alias": "get_nearby_ai_discovery", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0003/HLP-NIPC-MOD-0004/HLP-NIPC-OP-0012/HLP-NIPC-TGT-0004" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0004", - "moduleNumber": "HLP-NIPC-MOD-0007", - "operationNumber": "HLP-NIPC-OP-0017", - "targetNumber": "HLP-NIPC-TGT-0007", - "alias": "acquire_development_write_lane", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0004/HLP-NIPC-MOD-0007/HLP-NIPC-OP-0017/HLP-NIPC-TGT-0007" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0004", - "moduleNumber": "HLP-NIPC-MOD-0007", - "operationNumber": "HLP-NIPC-OP-0018", - "targetNumber": "HLP-NIPC-TGT-0007", - "alias": "inspect_development_write_lane", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0004/HLP-NIPC-MOD-0007/HLP-NIPC-OP-0018/HLP-NIPC-TGT-0007" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0004", - "moduleNumber": "HLP-NIPC-MOD-0007", - "operationNumber": "HLP-NIPC-OP-0019", - "targetNumber": "HLP-NIPC-TGT-0007", - "alias": "release_development_write_lane", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0004/HLP-NIPC-MOD-0007/HLP-NIPC-OP-0019/HLP-NIPC-TGT-0007" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0005", - "moduleNumber": "HLP-NIPC-MOD-0012", - "operationNumber": "HLP-NIPC-OP-0043", - "targetNumber": "HLP-NIPC-TGT-0012", - "alias": "inspect_mounted_pncc_repository", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0005/HLP-NIPC-MOD-0012/HLP-NIPC-OP-0043/HLP-NIPC-TGT-0012" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0005", - "moduleNumber": "HLP-NIPC-MOD-0012", - "operationNumber": "HLP-NIPC-OP-0044", - "targetNumber": "HLP-NIPC-TGT-0012", - "alias": "select_pncc_repository_candidate", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0005/HLP-NIPC-MOD-0012/HLP-NIPC-OP-0044/HLP-NIPC-TGT-0012" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0005", - "moduleNumber": "HLP-NIPC-MOD-0012", - "operationNumber": "HLP-NIPC-OP-0045", - "targetNumber": "HLP-NIPC-TGT-0012", - "alias": "confirm_pncc_repository_mount", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0005/HLP-NIPC-MOD-0012/HLP-NIPC-OP-0045/HLP-NIPC-TGT-0012" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0005", - "moduleNumber": "HLP-NIPC-MOD-0013", - "operationNumber": "HLP-NIPC-OP-0046", - "targetNumber": "HLP-NIPC-TGT-0013", - "alias": "query_pncc_receipt_projection", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0005/HLP-NIPC-MOD-0013/HLP-NIPC-OP-0046/HLP-NIPC-TGT-0013" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0005", - "moduleNumber": "HLP-NIPC-MOD-0014", - "operationNumber": "HLP-NIPC-OP-0047", - "targetNumber": "HLP-NIPC-TGT-0014", - "alias": "query_jd_pncc_server_projection", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0005/HLP-NIPC-MOD-0014/HLP-NIPC-OP-0047/HLP-NIPC-TGT-0014" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0005", - "moduleNumber": "HLP-NIPC-MOD-0017", - "operationNumber": "HLP-NIPC-OP-0056", - "targetNumber": "HLP-NIPC-TGT-0017", - "alias": "get_user_pncc_channel", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0005/HLP-NIPC-MOD-0017/HLP-NIPC-OP-0056/HLP-NIPC-TGT-0017" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0005", - "moduleNumber": "HLP-NIPC-MOD-0017", - "operationNumber": "HLP-NIPC-OP-0057", - "targetNumber": "HLP-NIPC-TGT-0017", - "alias": "ensure_user_pncc_channel", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0005/HLP-NIPC-MOD-0017/HLP-NIPC-OP-0057/HLP-NIPC-TGT-0017" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0015", - "operationNumber": "HLP-NIPC-OP-0048", - "targetNumber": "HLP-NIPC-TGT-0015", - "alias": "check_code_repo_login", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0015/HLP-NIPC-OP-0048/HLP-NIPC-TGT-0015" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0015", - "operationNumber": "HLP-NIPC-OP-0049", - "targetNumber": "HLP-NIPC-TGT-0015", - "alias": "perform_code_repo_login", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0015/HLP-NIPC-OP-0049/HLP-NIPC-TGT-0015" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0015", - "operationNumber": "HLP-NIPC-OP-0050", - "targetNumber": "HLP-NIPC-TGT-0015", - "alias": "change_first_login_password", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0015/HLP-NIPC-OP-0050/HLP-NIPC-TGT-0015" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0015", - "operationNumber": "HLP-NIPC-OP-0051", - "targetNumber": "HLP-NIPC-TGT-0015", - "alias": "get_enterprise_entry", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "READ_OR_STATUS", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0015/HLP-NIPC-OP-0051/HLP-NIPC-TGT-0015" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0015", - "operationNumber": "HLP-NIPC-OP-0052", - "targetNumber": "HLP-NIPC-TGT-0015", - "alias": "confirm_enterprise_persona_relationship", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0015/HLP-NIPC-OP-0052/HLP-NIPC-TGT-0015" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0015", - "operationNumber": "HLP-NIPC-OP-0053", - "targetNumber": "HLP-NIPC-TGT-0015", - "alias": "submit_enterprise_responsibility_receipt", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0015/HLP-NIPC-OP-0053/HLP-NIPC-TGT-0015" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0015", - "operationNumber": "HLP-NIPC-OP-0055", - "targetNumber": "HLP-NIPC-TGT-0015", - "alias": "sign_out_code_repo_login", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0015/HLP-NIPC-OP-0055/HLP-NIPC-TGT-0015" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0019", - "operationNumber": "HLP-NIPC-OP-0059", - "targetNumber": "HLP-NIPC-TGT-0019", - "alias": "zero_point_bind", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0019/HLP-NIPC-OP-0059/HLP-NIPC-TGT-0019" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0019", - "operationNumber": "HLP-NIPC-OP-0060", - "targetNumber": "HLP-NIPC-TGT-0019", - "alias": "zero_point_verify", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0019/HLP-NIPC-OP-0060/HLP-NIPC-TGT-0019" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0019", - "operationNumber": "HLP-NIPC-OP-0061", - "targetNumber": "HLP-NIPC-TGT-0019", - "alias": "zero_point_sync", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0019/HLP-NIPC-OP-0061/HLP-NIPC-TGT-0019" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0006", - "moduleNumber": "HLP-NIPC-MOD-0019", - "operationNumber": "HLP-NIPC-OP-0062", - "targetNumber": "HLP-NIPC-TGT-0019", - "alias": "zero_point_status", - "admission": "PREAUTH_SYSTEM_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0006/HLP-NIPC-MOD-0019/HLP-NIPC-OP-0062/HLP-NIPC-TGT-0019" - }, - { - "transport": "TAURI_WEBVIEW_NUMBERED_IPC", - "protocolVersion": "HLP-NIPC-v1", - "callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001", - "channelNumber": "HLP-NIPC-CH-0007", - "moduleNumber": "HLP-NIPC-MOD-0016", - "operationNumber": "HLP-NIPC-OP-0054", - "targetNumber": "HLP-NIPC-TGT-0016", - "alias": "ensure_enterprise_work_channel", - "admission": "VERIFIED_HUMAN_ROUTE", - "effect": "STATE_CHANGE", - "evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT", - "path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0007/HLP-NIPC-MOD-0016/HLP-NIPC-OP-0054/HLP-NIPC-TGT-0016" - } - ] -} diff --git a/product-source/hololake-native-desktop/mobile/ios/.gitignore b/product-source/hololake-native-desktop/mobile/ios/.gitignore deleted file mode 100644 index 45706c522..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -build/ -*.xcuserstate -xcuserdata/ - diff --git a/product-source/hololake-native-desktop/mobile/ios/ExportOptions.Debug.plist b/product-source/hololake-native-desktop/mobile/ios/ExportOptions.Debug.plist deleted file mode 100644 index 01dcb8305..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/ExportOptions.Debug.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - method - debugging - signingStyle - automatic - teamID - 825A9L3G7Q - stripSwiftSymbols - - uploadSymbols - - - diff --git a/product-source/hololake-native-desktop/mobile/ios/Generated/HoloLakeMobile-Info.plist b/product-source/hololake-native-desktop/mobile/ios/Generated/HoloLakeMobile-Info.plist deleted file mode 100644 index d03325242..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/Generated/HoloLakeMobile-Info.plist +++ /dev/null @@ -1,56 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - HoloLake - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLName - com.guanghulab.hololake.pair - CFBundleURLSchemes - - hololake - - - - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - LSApplicationCategoryType - public.app-category.productivity - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - NSLocalNetworkUsageDescription - HoloLake 仅在你明确配对后,通过同一局域网连接你的电脑端频道。 - UIApplicationSupportsIndirectInputEvents - - UILaunchScreen - - UIRequiresFullScreen - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - - - diff --git a/product-source/hololake-native-desktop/mobile/ios/Generated/HoloLakeMobileTests-Info.plist b/product-source/hololake-native-desktop/mobile/ios/Generated/HoloLakeMobileTests-Info.plist deleted file mode 100644 index 6c40a6cd0..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/Generated/HoloLakeMobileTests-Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/product-source/hololake-native-desktop/mobile/ios/HoloLakeMobile.xcodeproj/project.pbxproj b/product-source/hololake-native-desktop/mobile/ios/HoloLakeMobile.xcodeproj/project.pbxproj deleted file mode 100644 index b4fc2292f..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/HoloLakeMobile.xcodeproj/project.pbxproj +++ /dev/null @@ -1,425 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 77; - objects = { - -/* Begin PBXBuildFile section */ - 147588FBBE65B668142D5DBE /* HoloLakeMobileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBF45AEC03B7B5DE76DE7DA /* HoloLakeMobileTests.swift */; }; - 149652D6C6336752E39CEF9D /* HoloLakeKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75A889326BDEACBDB756B15A /* HoloLakeKeychain.swift */; }; - 4C8E5CF9FBFC541E3724C695 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5DF66BC64D4DCD3BF0583C4 /* ContentView.swift */; }; - 4FD7821997D8E90E6594FC23 /* HoloLakeMobileApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DCE2A5796B15DAC37985182 /* HoloLakeMobileApp.swift */; }; - 9BC7CC6D8BC355D731943912 /* HoloLakeDesign.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39A48AB789379757C66C6884 /* HoloLakeDesign.swift */; }; - C0E93C7456C0A3BE8BA595FC /* HoloLakeSyncClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = B91D61B90D609EF17397D193 /* HoloLakeSyncClient.swift */; }; - FFEEE7FC9ED4ECCD91A96AF1 /* HoloLakeModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 001F5647617271E7611365B1 /* HoloLakeModels.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - CD999C930B8B85FE1C3D884D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7BB68CAE65448CB9319F9FE1 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 306917F839BF1A325E2C4CF4; - remoteInfo = HoloLakeMobile; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 001F5647617271E7611365B1 /* HoloLakeModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoloLakeModels.swift; sourceTree = ""; }; - 39A48AB789379757C66C6884 /* HoloLakeDesign.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoloLakeDesign.swift; sourceTree = ""; }; - 6DCE2A5796B15DAC37985182 /* HoloLakeMobileApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoloLakeMobileApp.swift; sourceTree = ""; }; - 75A889326BDEACBDB756B15A /* HoloLakeKeychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoloLakeKeychain.swift; sourceTree = ""; }; - 7BBF45AEC03B7B5DE76DE7DA /* HoloLakeMobileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoloLakeMobileTests.swift; sourceTree = ""; }; - AAB8B15F447567F18DF8DA22 /* HoloLakeMobileTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = HoloLakeMobileTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - B91D61B90D609EF17397D193 /* HoloLakeSyncClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoloLakeSyncClient.swift; sourceTree = ""; }; - D5DF66BC64D4DCD3BF0583C4 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; - F674C2EA817D94D8089E46A6 /* HoloLakeMobile.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = HoloLakeMobile.app; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXGroup section */ - 14AB215583F1F3DFF867AD25 /* Sources */ = { - isa = PBXGroup; - children = ( - D5DF66BC64D4DCD3BF0583C4 /* ContentView.swift */, - 39A48AB789379757C66C6884 /* HoloLakeDesign.swift */, - 75A889326BDEACBDB756B15A /* HoloLakeKeychain.swift */, - 6DCE2A5796B15DAC37985182 /* HoloLakeMobileApp.swift */, - 001F5647617271E7611365B1 /* HoloLakeModels.swift */, - B91D61B90D609EF17397D193 /* HoloLakeSyncClient.swift */, - ); - path = Sources; - sourceTree = ""; - }; - 57FD470E035A4BE1AC23C789 = { - isa = PBXGroup; - children = ( - 14AB215583F1F3DFF867AD25 /* Sources */, - 65C6F102E3F59F8DEC7CF977 /* Tests */, - C1AA7BA4A57964238429B9FC /* Products */, - ); - sourceTree = ""; - }; - 65C6F102E3F59F8DEC7CF977 /* Tests */ = { - isa = PBXGroup; - children = ( - 7BBF45AEC03B7B5DE76DE7DA /* HoloLakeMobileTests.swift */, - ); - path = Tests; - sourceTree = ""; - }; - C1AA7BA4A57964238429B9FC /* Products */ = { - isa = PBXGroup; - children = ( - F674C2EA817D94D8089E46A6 /* HoloLakeMobile.app */, - AAB8B15F447567F18DF8DA22 /* HoloLakeMobileTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 306917F839BF1A325E2C4CF4 /* HoloLakeMobile */ = { - isa = PBXNativeTarget; - buildConfigurationList = 821BFCD605046D5BD179550C /* Build configuration list for PBXNativeTarget "HoloLakeMobile" */; - buildPhases = ( - EF1823B21F5FD988A9F1C68B /* Sources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = HoloLakeMobile; - packageProductDependencies = ( - ); - productName = HoloLakeMobile; - productReference = F674C2EA817D94D8089E46A6 /* HoloLakeMobile.app */; - productType = "com.apple.product-type.application"; - }; - 9F8DF7CBFC2D6315E6807301 /* HoloLakeMobileTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 94843BB695F4BFC5D7BD814C /* Build configuration list for PBXNativeTarget "HoloLakeMobileTests" */; - buildPhases = ( - C9F5955F3342913B35B01034 /* Sources */, - ); - buildRules = ( - ); - dependencies = ( - 43C074DF3E4135062FD9F2D5 /* PBXTargetDependency */, - ); - name = HoloLakeMobileTests; - packageProductDependencies = ( - ); - productName = HoloLakeMobileTests; - productReference = AAB8B15F447567F18DF8DA22 /* HoloLakeMobileTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7BB68CAE65448CB9319F9FE1 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1430; - TargetAttributes = { - 306917F839BF1A325E2C4CF4 = { - DevelopmentTeam = 825A9L3G7Q; - ProvisioningStyle = Automatic; - }; - 9F8DF7CBFC2D6315E6807301 = { - DevelopmentTeam = 825A9L3G7Q; - ProvisioningStyle = Automatic; - }; - }; - }; - buildConfigurationList = 9D0C9B96A22462DAABC1E8F8 /* Build configuration list for PBXProject "HoloLakeMobile" */; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - Base, - en, - ); - mainGroup = 57FD470E035A4BE1AC23C789; - minimizedProjectReferenceProxies = 1; - preferredProjectObjectVersion = 77; - productRefGroup = C1AA7BA4A57964238429B9FC /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 306917F839BF1A325E2C4CF4 /* HoloLakeMobile */, - 9F8DF7CBFC2D6315E6807301 /* HoloLakeMobileTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - C9F5955F3342913B35B01034 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 147588FBBE65B668142D5DBE /* HoloLakeMobileTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EF1823B21F5FD988A9F1C68B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C8E5CF9FBFC541E3724C695 /* ContentView.swift in Sources */, - 9BC7CC6D8BC355D731943912 /* HoloLakeDesign.swift in Sources */, - 149652D6C6336752E39CEF9D /* HoloLakeKeychain.swift in Sources */, - 4FD7821997D8E90E6594FC23 /* HoloLakeMobileApp.swift in Sources */, - FFEEE7FC9ED4ECCD91A96AF1 /* HoloLakeModels.swift in Sources */, - C0E93C7456C0A3BE8BA595FC /* HoloLakeSyncClient.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 43C074DF3E4135062FD9F2D5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 306917F839BF1A325E2C4CF4 /* HoloLakeMobile */; - targetProxy = CD999C930B8B85FE1C3D884D /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 41EDE5121626CC1CCE382706 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_STYLE = Automatic; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = 825A9L3G7Q; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; - MARKETING_VERSION = 0.5.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SUPPORTS_MACCATALYST = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Release; - }; - 4F5C6B6543A0A3082363F109 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_STYLE = Automatic; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = 825A9L3G7Q; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "DEBUG=1", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; - MARKETING_VERSION = 0.5.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SUPPORTS_MACCATALYST = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Debug; - }; - 512CB348BCA8C1688C5D794E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - INFOPLIST_FILE = "Generated/HoloLakeMobileTests-Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.guanghulab.hololake.tests; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HoloLake.app/HoloLake"; - }; - name = Release; - }; - A44510E6B199DFF6BD5BC1EF /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - INFOPLIST_FILE = "Generated/HoloLakeMobileTests-Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.guanghulab.hololake.tests; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HoloLake.app/HoloLake"; - }; - name = Debug; - }; - B82D688E4449B0C6DC27D25E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - INFOPLIST_FILE = "Generated/HoloLakeMobile-Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.guanghulab.hololake; - PRODUCT_MODULE_NAME = HoloLakeMobile; - PRODUCT_NAME = HoloLake; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - BECD79B877979A2CD86E7D9C /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - INFOPLIST_FILE = "Generated/HoloLakeMobile-Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.guanghulab.hololake; - PRODUCT_MODULE_NAME = HoloLakeMobile; - PRODUCT_NAME = HoloLake; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 821BFCD605046D5BD179550C /* Build configuration list for PBXNativeTarget "HoloLakeMobile" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - BECD79B877979A2CD86E7D9C /* Debug */, - B82D688E4449B0C6DC27D25E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - 94843BB695F4BFC5D7BD814C /* Build configuration list for PBXNativeTarget "HoloLakeMobileTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A44510E6B199DFF6BD5BC1EF /* Debug */, - 512CB348BCA8C1688C5D794E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - 9D0C9B96A22462DAABC1E8F8 /* Build configuration list for PBXProject "HoloLakeMobile" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 4F5C6B6543A0A3082363F109 /* Debug */, - 41EDE5121626CC1CCE382706 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7BB68CAE65448CB9319F9FE1 /* Project object */; -} diff --git a/product-source/hololake-native-desktop/mobile/ios/HoloLakeMobile.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/product-source/hololake-native-desktop/mobile/ios/HoloLakeMobile.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/HoloLakeMobile.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/product-source/hololake-native-desktop/mobile/ios/HoloLakeMobile.xcodeproj/xcshareddata/xcschemes/HoloLakeMobile.xcscheme b/product-source/hololake-native-desktop/mobile/ios/HoloLakeMobile.xcodeproj/xcshareddata/xcschemes/HoloLakeMobile.xcscheme deleted file mode 100644 index 3a7b98f9c..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/HoloLakeMobile.xcodeproj/xcshareddata/xcschemes/HoloLakeMobile.xcscheme +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/product-source/hololake-native-desktop/mobile/ios/Sources/ContentView.swift b/product-source/hololake-native-desktop/mobile/ios/Sources/ContentView.swift deleted file mode 100644 index 008ee0913..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/Sources/ContentView.swift +++ /dev/null @@ -1,203 +0,0 @@ -import SwiftUI -import UIKit - -struct ContentView: View { - @EnvironmentObject private var client: HoloLakeSyncClient - @State private var pairingText = "" - @State private var captureTitle = "" - @State private var captureBody = "" - - var body: some View { - NavigationStack { - ZStack { - LinearGradient( - colors: [HoloLakeDesign.deep, HoloLakeDesign.lake, HoloLakeDesign.violet.opacity(0.78)], - startPoint: .topLeading, - endPoint: .bottomTrailing - ) - .ignoresSafeArea() - - ScrollView { - VStack(spacing: 16) { - header - if client.session == nil { pairingCard } else { dashboard } - boundaryCard - } - .padding(.horizontal, 18) - .padding(.vertical, 16) - } - } - .toolbar(.hidden, for: .navigationBar) - .alert("HoloLake", isPresented: Binding( - get: { client.errorText != nil }, - set: { if !$0 { client.errorText = nil } } - )) { - Button("知道了", role: .cancel) { client.errorText = nil } - } message: { - Text(client.errorText ?? "") - } - } - .preferredColorScheme(.dark) - } - - private var header: some View { - HStack(alignment: .center) { - VStack(alignment: .leading, spacing: 5) { - Text("HoloLake").font(.title.weight(.semibold)).tracking(2) - Text("同一频道 · iPhone 轻入口") - .font(.subheadline) - .foregroundStyle(HoloLakeDesign.muted) - } - Spacer() - Circle() - .fill(client.session == nil ? HoloLakeDesign.gold : HoloLakeDesign.mint) - .frame(width: 11, height: 11) - .shadow(color: client.session == nil ? HoloLakeDesign.gold : HoloLakeDesign.mint, radius: 8) - } - .foregroundStyle(HoloLakeDesign.pearl) - .padding(.top, 4) - } - - private var pairingCard: some View { - LakeCard { - VStack(alignment: .leading, spacing: 14) { - Text("连接电脑端").font(.title3.weight(.semibold)) - Text("先在电脑端打开“多端同步”,再扫描配对码或粘贴配对链接。配对密钥只保存在这台 iPhone 的钥匙串。") - .font(.subheadline) - .foregroundStyle(HoloLakeDesign.muted) - - TextField("hololake://pair?…", text: $pairingText, axis: .vertical) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - .padding(14) - .background(.black.opacity(0.22), in: RoundedRectangle(cornerRadius: 16)) - - HStack { - Button("从剪贴板读取") { - pairingText = UIPasteboard.general.string ?? "" - } - .buttonStyle(.bordered) - - Button("校验并配对") { - Task { await client.pair(from: pairingText) } - } - .buttonStyle(.borderedProminent) - .tint(HoloLakeDesign.gold) - .foregroundStyle(HoloLakeDesign.deep) - .disabled(pairingText.isEmpty || client.isWorking) - } - } - } - .foregroundStyle(HoloLakeDesign.pearl) - } - - private var dashboard: some View { - VStack(spacing: 16) { - LakeCard { - VStack(alignment: .leading, spacing: 14) { - HStack { - VStack(alignment: .leading, spacing: 4) { - Text(client.session?.desktopName ?? "电脑端") - .font(.title3.weight(.semibold)) - Text(client.stateText) - .font(.caption) - .foregroundStyle(HoloLakeDesign.muted) - } - Spacer() - Button { - Task { await client.sync() } - } label: { - if client.isWorking { - ProgressView() - } else { - Label("同步", systemImage: "arrow.triangle.2.circlepath") - } - } - .buttonStyle(.borderedProminent) - .tint(HoloLakeDesign.mint) - .foregroundStyle(HoloLakeDesign.deep) - .disabled(client.isWorking) - } - - if let snapshot = client.snapshot { - HStack(spacing: 10) { - MetricTile(label: "作品", value: "\(snapshot.webNovel.workCount)") - MetricTile(label: "章节", value: "\(snapshot.webNovel.chapterCount)") - MetricTile(label: "教育表", value: "\(snapshot.education.activeTableCount)") - } - } else { - Text("保持静止;只有你点击同步时才会连接电脑。") - .font(.subheadline) - .foregroundStyle(HoloLakeDesign.muted) - } - } - } - - LakeCard { - VStack(alignment: .leading, spacing: 12) { - Text("随手记回频道").font(.headline) - TextField("标题(可选)", text: $captureTitle) - .padding(12) - .background(.black.opacity(0.2), in: RoundedRectangle(cornerRadius: 14)) - TextField("正文", text: $captureBody, axis: .vertical) - .lineLimit(4...10) - .padding(12) - .background(.black.opacity(0.2), in: RoundedRectangle(cornerRadius: 14)) - Button("写入电脑端收件箱") { - let title = captureTitle - let body = captureBody - Task { - await client.sync(captureTitle: title, captureBody: body) - if client.errorText == nil { - captureTitle = "" - captureBody = "" - } - } - } - .buttonStyle(.bordered) - .disabled(captureBody.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || client.isWorking) - } - } - - if let works = client.snapshot?.webNovel.works, !works.isEmpty { - LakeCard { - VStack(alignment: .leading, spacing: 12) { - Text("最近作品").font(.headline) - ForEach(works.prefix(5)) { work in - HStack { - Text(work.title).lineLimit(1) - Spacer() - Text(work.status) - .font(.caption) - .foregroundStyle(HoloLakeDesign.muted) - } - if work.id != works.prefix(5).last?.id { - Divider().overlay(.white.opacity(0.12)) - } - } - } - } - } - - Button("解除本机配对", role: .destructive) { - client.disconnect() - } - .font(.footnote) - } - .foregroundStyle(HoloLakeDesign.pearl) - } - - private var boundaryCard: some View { - VStack(alignment: .leading, spacing: 6) { - Text("HLP-IOS-CLIENT-001") - .font(.caption2.monospaced()) - .foregroundStyle(HoloLakeDesign.gold) - Text("手机是同一频道的远程身体入口,不复制电脑桌面,不在电脑离线时执行人格或行业任务。") - .font(.caption) - .foregroundStyle(HoloLakeDesign.muted) - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 4) - } -} - diff --git a/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeDesign.swift b/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeDesign.swift deleted file mode 100644 index 797b0283a..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeDesign.swift +++ /dev/null @@ -1,42 +0,0 @@ -import SwiftUI - -enum HoloLakeDesign { - static let deep = Color(red: 0.025, green: 0.045, blue: 0.11) - static let lake = Color(red: 0.08, green: 0.14, blue: 0.32) - static let violet = Color(red: 0.34, green: 0.19, blue: 0.52) - static let pearl = Color(red: 0.95, green: 0.96, blue: 1) - static let muted = Color(red: 0.62, green: 0.66, blue: 0.78) - static let gold = Color(red: 0.96, green: 0.87, blue: 0.62) - static let mint = Color(red: 0.43, green: 0.93, blue: 0.78) -} - -struct LakeCard: View { - @ViewBuilder let content: Content - - var body: some View { - content - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(.white.opacity(0.075), in: RoundedRectangle(cornerRadius: 24)) - .overlay { - RoundedRectangle(cornerRadius: 24) - .stroke(.white.opacity(0.14), lineWidth: 1) - } - } -} - -struct MetricTile: View { - let label: String - let value: String - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - Text(label).font(.caption).foregroundStyle(HoloLakeDesign.muted) - Text(value).font(.title2.weight(.semibold)).foregroundStyle(HoloLakeDesign.pearl) - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(14) - .background(.white.opacity(0.055), in: RoundedRectangle(cornerRadius: 18)) - } -} - diff --git a/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeKeychain.swift b/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeKeychain.swift deleted file mode 100644 index 345974f2c..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeKeychain.swift +++ /dev/null @@ -1,59 +0,0 @@ -import Foundation -import Security - -enum HoloLakeKeychain { - private static let service = "com.guanghulab.hololake.mobile-sync" - private static let account = "HLP-IOS-CLIENT-001" - - static func load() throws -> StoredSession? { - let query: [String: Any] = [ - kSecClass as String: kSecClassGenericPassword, - kSecAttrService as String: service, - kSecAttrAccount as String: account, - kSecReturnData as String: true, - kSecMatchLimit as String: kSecMatchLimitOne - ] - var result: CFTypeRef? - let status = SecItemCopyMatching(query as CFDictionary, &result) - if status == errSecItemNotFound { return nil } - guard status == errSecSuccess, let data = result as? Data else { - throw HoloLakeMobileError.keychain(status) - } - return try JSONDecoder().decode(StoredSession.self, from: data) - } - - static func save(_ session: StoredSession) throws { - let data = try JSONEncoder().encode(session) - let query: [String: Any] = [ - kSecClass as String: kSecClassGenericPassword, - kSecAttrService as String: service, - kSecAttrAccount as String: account - ] - let attributes: [String: Any] = [ - kSecValueData as String: data, - kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly - ] - let update = SecItemUpdate(query as CFDictionary, attributes as CFDictionary) - if update == errSecItemNotFound { - var insertion = query - insertion.merge(attributes) { _, new in new } - let status = SecItemAdd(insertion as CFDictionary, nil) - guard status == errSecSuccess else { throw HoloLakeMobileError.keychain(status) } - } else if update != errSecSuccess { - throw HoloLakeMobileError.keychain(update) - } - } - - static func remove() throws { - let query: [String: Any] = [ - kSecClass as String: kSecClassGenericPassword, - kSecAttrService as String: service, - kSecAttrAccount as String: account - ] - let status = SecItemDelete(query as CFDictionary) - guard status == errSecSuccess || status == errSecItemNotFound else { - throw HoloLakeMobileError.keychain(status) - } - } -} - diff --git a/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeMobileApp.swift b/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeMobileApp.swift deleted file mode 100644 index 181084959..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeMobileApp.swift +++ /dev/null @@ -1,17 +0,0 @@ -import SwiftUI - -@main -struct HoloLakeMobileApp: App { - @StateObject private var client = HoloLakeSyncClient() - - var body: some Scene { - WindowGroup { - ContentView() - .environmentObject(client) - .onOpenURL { url in - Task { await client.pair(with: url) } - } - } - } -} - diff --git a/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeModels.swift b/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeModels.swift deleted file mode 100644 index ab00154e1..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeModels.swift +++ /dev/null @@ -1,177 +0,0 @@ -import Foundation -import Security - -struct PairingDescriptor: Equatable { - let host: String - let port: Int - let pairingID: String - let secret: Data - - init(url: URL) throws { - guard url.scheme == "hololake", url.host == "pair", - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { - throw HoloLakeMobileError.invalidPairingLink - } - var values: [String: String] = [:] - for item in components.queryItems ?? [] { - guard let value = item.value, values[item.name] == nil else { - throw HoloLakeMobileError.invalidPairingLink - } - values[item.name] = value - } - guard let host = values["host"], !host.isEmpty, - let portText = values["port"], let port = Int(portText), (1...65535).contains(port), - let pairingID = values["id"], UUID(uuidString: pairingID) != nil, - let secretText = values["secret"], - let secret = Data(base64URL: secretText), secret.count == 32 else { - throw HoloLakeMobileError.invalidPairingLink - } - self.host = host - self.port = port - self.pairingID = pairingID - self.secret = secret - } - - var baseURL: URL { - URL(string: "http://\(host):\(port)")! - } -} - -struct StoredSession: Codable, Equatable { - let host: String - let port: Int - let deviceID: String - let sessionKey: Data - let desktopName: String - var counter: UInt64 - var cursor: UInt64 - - var baseURL: URL { - URL(string: "http://\(host):\(port)")! - } -} - -struct PairRequest: Codable { - let deviceName: String - let platform: String - let requestID: String -} - -struct PairResponse: Codable { - let schema: String - let state: String - let deviceID: String - let sessionKey: String - let desktopName: String - let rootNodeRole: String - let requestID: String -} - -struct SyncRequest: Codable { - let counter: UInt64 - let afterCursor: UInt64? - let capture: MobileCaptureInput? -} - -struct MobileCaptureInput: Codable { - let title: String - let body: String - let requestID: String -} - -struct MobileSyncSnapshot: Codable { - let schema: String - let state: String - let cursor: UInt64 - let generatedAtUnixMs: UInt64 - let desktopName: String - let rootNodeOnline: Bool - let personalChannel: MobileChannelProjection - let webNovel: MobileWebNovelProjection - let education: MobileEducationProjection - let recentCaptures: [MobileCaptureProjection] - let boundary: MobileBoundaryProjection -} - -struct MobileChannelProjection: Codable { - let home: String - let growthEventCount: UInt64 - let integrity: String -} - -struct MobileWebNovelProjection: Codable { - let workCount: UInt64 - let volumeCount: UInt64 - let chapterCount: UInt64 - let works: [MobileWebNovelWork] -} - -struct MobileWebNovelWork: Codable, Identifiable { - let workID: String - let title: String - let status: String - let updatedAtUnixMs: UInt64 - var id: String { workID } -} - -struct MobileEducationProjection: Codable { - let activeTableCount: UInt64 - let archivedTableCount: UInt64 - let unassignedTableCount: UInt64 - let sensitiveValuesIncluded: Bool -} - -struct MobileCaptureProjection: Codable, Identifiable { - let cursor: UInt64 - let captureID: String - let title: String - let body: String - let sourceDeviceID: String - let createdAtUnixMs: UInt64 - var id: String { captureID } -} - -struct MobileBoundaryProjection: Codable { - let mobileRole: String - let remoteDesktopClone: Bool - let desktopOfflineExecution: Bool - let sensitiveEducationValues: String - let modelAPI: String -} - -enum HoloLakeMobileError: LocalizedError { - case invalidPairingLink - case invalidResponse - case rejected(String) - case missingNonce - case missingSession - case keychain(OSStatus) - - var errorDescription: String? { - switch self { - case .invalidPairingLink: return "配对链接无效或已损坏。" - case .invalidResponse: return "电脑端返回了无法校验的响应。" - case .rejected(let code): return "电脑端拒绝了本次请求:\(code)" - case .missingNonce: return "加密响应缺少一次性随机数。" - case .missingSession: return "请先与电脑端 HoloLake 配对。" - case .keychain(let status): return "本机钥匙串写入失败(\(status))。" - } - } -} - -extension Data { - init?(base64URL value: String) { - var text = value.replacingOccurrences(of: "-", with: "+") - .replacingOccurrences(of: "_", with: "/") - text += String(repeating: "=", count: (4 - text.count % 4) % 4) - guard let data = Data(base64Encoded: text) else { return nil } - self = data - } - - var base64URL: String { - base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: "=", with: "") - } -} diff --git a/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeSyncClient.swift b/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeSyncClient.swift deleted file mode 100644 index ffc99f63e..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/Sources/HoloLakeSyncClient.swift +++ /dev/null @@ -1,190 +0,0 @@ -import CryptoKit -import Foundation -import UIKit - -@MainActor -final class HoloLakeSyncClient: ObservableObject { - static let clientNumber = "HLP-IOS-CLIENT-001" - static let pairAAD = Data("hololake.mobile.pair/v1".utf8) - - @Published private(set) var session: StoredSession? - @Published private(set) var snapshot: MobileSyncSnapshot? - @Published private(set) var stateText = "尚未配对" - @Published private(set) var isWorking = false - @Published var errorText: String? - - init() { - do { - session = try HoloLakeKeychain.load() - stateText = session == nil ? "尚未配对" : "已配对,等待手动同步" - } catch { - errorText = error.localizedDescription - } - } - - func pair(with url: URL) async { - await perform("正在校验配对…") { - let descriptor = try PairingDescriptor(url: url) - let requestID = UUID().uuidString.lowercased() - let payload = PairRequest( - deviceName: UIDevice.current.name, - platform: "IOS", - requestID: requestID - ) - let responseData = try await Self.exchange( - url: descriptor.baseURL.appending(path: "v1/pair"), - key: descriptor.secret, - aad: Self.pairAAD, - headers: ["X-HoloLake-Pairing-ID": descriptor.pairingID], - payload: payload - ) - let response = try JSONDecoder().decode(PairResponse.self, from: responseData) - guard response.schema == "hololake.mobile-sync/v1", - response.state == "PAIRED", - response.rootNodeRole == "USER_LOCAL_COMPUTER_TERMINAL", - response.requestID == requestID, - let sessionKey = Data(base64URL: response.sessionKey), sessionKey.count == 32 else { - throw HoloLakeMobileError.invalidResponse - } - let next = StoredSession( - host: descriptor.host, - port: descriptor.port, - deviceID: response.deviceID, - sessionKey: sessionKey, - desktopName: response.desktopName, - counter: 0, - cursor: 0 - ) - try HoloLakeKeychain.save(next) - session = next - stateText = "已与 \(response.desktopName) 配对" - } - } - - func pair(from text: String) async { - guard let url = URL(string: text.trimmingCharacters(in: .whitespacesAndNewlines)) else { - errorText = HoloLakeMobileError.invalidPairingLink.localizedDescription - return - } - await pair(with: url) - } - - func sync(captureTitle: String? = nil, captureBody: String? = nil) async { - await perform("正在与电脑同步…") { - guard var current = session else { throw HoloLakeMobileError.missingSession } - current.counter += 1 - // Consume and persist the counter before transport. If the root node accepts a - // request but its response is lost, the next manual retry still moves forward. - try HoloLakeKeychain.save(current) - session = current - let capture: MobileCaptureInput? - if let body = captureBody?.trimmingCharacters(in: .whitespacesAndNewlines), !body.isEmpty { - capture = MobileCaptureInput( - title: (captureTitle ?? "").trimmingCharacters(in: .whitespacesAndNewlines), - body: body, - requestID: UUID().uuidString.lowercased() - ) - } else { - capture = nil - } - let aad = Data("hololake.mobile.sync/v1:\(current.deviceID)".utf8) - let responseData = try await Self.exchange( - url: current.baseURL.appending(path: "v1/sync"), - key: current.sessionKey, - aad: aad, - headers: ["X-HoloLake-Device-ID": current.deviceID], - payload: SyncRequest(counter: current.counter, afterCursor: nil, capture: capture) - ) - let nextSnapshot = try JSONDecoder().decode(MobileSyncSnapshot.self, from: responseData) - guard nextSnapshot.schema == "hololake.mobile-sync/v1", - nextSnapshot.state == "SYNCED_WITH_ROOT_NODE", - nextSnapshot.rootNodeOnline, - nextSnapshot.boundary.mobileRole == "REMOTE_BODY_ENTRY_OF_THE_SAME_PERSONA_SYSTEM", - !nextSnapshot.boundary.remoteDesktopClone, - !nextSnapshot.boundary.desktopOfflineExecution else { - throw HoloLakeMobileError.invalidResponse - } - current.cursor = nextSnapshot.cursor - try HoloLakeKeychain.save(current) - session = current - snapshot = nextSnapshot - stateText = "已同步 · \(nextSnapshot.desktopName)" - } - } - - func disconnect() { - do { - try HoloLakeKeychain.remove() - session = nil - snapshot = nil - stateText = "尚未配对" - } catch { - errorText = error.localizedDescription - } - } - - private func perform(_ activeText: String, operation: () async throws -> Void) async { - guard !isWorking else { return } - isWorking = true - errorText = nil - stateText = activeText - do { - try await operation() - } catch { - errorText = error.localizedDescription - stateText = session == nil ? "尚未配对" : "同步未完成" - } - isWorking = false - } - - static func exchange( - url: URL, - key: Data, - aad: Data, - headers: [String: String], - payload: Payload, - session: URLSession = .shared - ) async throws -> Data { - let clear = try JSONEncoder().encode(payload) - let nonceData = randomNonce() - let nonce = try ChaChaPoly.Nonce(data: nonceData) - let sealed = try ChaChaPoly.seal( - clear, - using: SymmetricKey(data: key), - nonce: nonce, - authenticating: aad - ) - var request = URLRequest(url: url) - request.httpMethod = "POST" - request.timeoutInterval = 8 - request.cachePolicy = .reloadIgnoringLocalCacheData - request.httpBody = sealed.ciphertext + sealed.tag - request.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type") - request.setValue(nonceData.base64URL, forHTTPHeaderField: "X-HoloLake-Nonce") - headers.forEach { request.setValue($1, forHTTPHeaderField: $0) } - let (body, response) = try await session.data(for: request) - guard let http = response as? HTTPURLResponse else { - throw HoloLakeMobileError.invalidResponse - } - guard http.statusCode == 200 else { - let code = (try? JSONSerialization.jsonObject(with: body) as? [String: Any])?["code"] as? String - throw HoloLakeMobileError.rejected(code ?? "HTTP_\(http.statusCode)") - } - guard let nonceHeader = http.value(forHTTPHeaderField: "X-HoloLake-Nonce"), - let responseNonceData = Data(base64URL: nonceHeader), responseNonceData.count == 12 else { - throw HoloLakeMobileError.missingNonce - } - let responseNonce = try ChaChaPoly.Nonce(data: responseNonceData) - guard body.count >= 16 else { throw HoloLakeMobileError.invalidResponse } - let responseBox = try ChaChaPoly.SealedBox( - nonce: responseNonce, - ciphertext: body.dropLast(16), - tag: body.suffix(16) - ) - return try ChaChaPoly.open(responseBox, using: SymmetricKey(data: key), authenticating: aad) - } - - static func randomNonce() -> Data { - Data((0..<12).map { _ in UInt8.random(in: .min ... .max) }) - } -} diff --git a/product-source/hololake-native-desktop/mobile/ios/Tests/HoloLakeMobileTests.swift b/product-source/hololake-native-desktop/mobile/ios/Tests/HoloLakeMobileTests.swift deleted file mode 100644 index eae55ba7c..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/Tests/HoloLakeMobileTests.swift +++ /dev/null @@ -1,44 +0,0 @@ -import CryptoKit -import XCTest -@testable import HoloLakeMobile - -final class HoloLakeMobileTests: XCTestCase { - func testPairingCoordinateParsesOnlyCompleteLink() throws { - let secret = Data(repeating: 7, count: 32).base64URL - let id = UUID().uuidString.lowercased() - let url = try XCTUnwrap(URL(string: "hololake://pair?host=192.168.1.8&port=37421&id=\(id)&secret=\(secret)")) - let value = try PairingDescriptor(url: url) - XCTAssertEqual(value.host, "192.168.1.8") - XCTAssertEqual(value.port, 37421) - XCTAssertEqual(value.pairingID, id) - XCTAssertEqual(value.secret, Data(repeating: 7, count: 32)) - } - - func testPairingCoordinateRejectsMissingSecret() throws { - let url = try XCTUnwrap(URL(string: "hololake://pair?host=127.0.0.1&port=37421&id=\(UUID().uuidString)")) - XCTAssertThrowsError(try PairingDescriptor(url: url)) - } - - func testPairingCoordinateRejectsDuplicateKeys() throws { - let secret = Data(repeating: 7, count: 32).base64URL - let id = UUID().uuidString.lowercased() - let url = try XCTUnwrap(URL(string: "hololake://pair?host=192.168.1.8&host=127.0.0.1&port=37421&id=\(id)&secret=\(secret)")) - XCTAssertThrowsError(try PairingDescriptor(url: url)) - } - - func testCryptoKitPayloadMatchesServerWireShape() throws { - let key = SymmetricKey(data: Data(repeating: 3, count: 32)) - let nonce = try ChaChaPoly.Nonce(data: Data(repeating: 9, count: 12)) - let aad = Data("hololake.mobile.pair/v1".utf8) - let clear = Data("hello".utf8) - let sealed = try ChaChaPoly.seal(clear, using: key, nonce: nonce, authenticating: aad) - let wire = sealed.ciphertext + sealed.tag - XCTAssertEqual(wire.count, clear.count + 16) - let restored = try ChaChaPoly.open( - ChaChaPoly.SealedBox(nonce: nonce, ciphertext: wire.dropLast(16), tag: wire.suffix(16)), - using: key, - authenticating: aad - ) - XCTAssertEqual(restored, clear) - } -} diff --git a/product-source/hololake-native-desktop/mobile/ios/project.yml b/product-source/hololake-native-desktop/mobile/ios/project.yml deleted file mode 100644 index b733e4c91..000000000 --- a/product-source/hololake-native-desktop/mobile/ios/project.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: HoloLakeMobile -options: - bundleIdPrefix: com.guanghulab - deploymentTarget: - iOS: "17.0" -settings: - base: - DEVELOPMENT_TEAM: 825A9L3G7Q - CODE_SIGN_STYLE: Automatic - SWIFT_VERSION: "5.0" - CURRENT_PROJECT_VERSION: 1 - MARKETING_VERSION: 0.5.0 - TARGETED_DEVICE_FAMILY: "1" - SUPPORTS_MACCATALYST: false -targets: - HoloLakeMobile: - type: application - platform: iOS - sources: - - path: Sources - settings: - base: - PRODUCT_BUNDLE_IDENTIFIER: com.guanghulab.hololake - PRODUCT_NAME: HoloLake - PRODUCT_MODULE_NAME: HoloLakeMobile - info: - path: Generated/HoloLakeMobile-Info.plist - properties: - CFBundleDisplayName: HoloLake - CFBundleShortVersionString: "$(MARKETING_VERSION)" - CFBundleVersion: "$(CURRENT_PROJECT_VERSION)" - LSApplicationCategoryType: public.app-category.productivity - NSLocalNetworkUsageDescription: HoloLake 仅在你明确配对后,通过同一局域网连接你的电脑端频道。 - UIApplicationSupportsIndirectInputEvents: true - UIRequiresFullScreen: true - UILaunchScreen: {} - UISupportedInterfaceOrientations: - - UIInterfaceOrientationPortrait - CFBundleURLTypes: - - CFBundleTypeRole: Editor - CFBundleURLName: com.guanghulab.hololake.pair - CFBundleURLSchemes: - - hololake - NSAppTransportSecurity: - NSAllowsLocalNetworking: true - scheme: - testTargets: - - HoloLakeMobileTests - HoloLakeMobileTests: - type: bundle.unit-test - platform: iOS - sources: - - path: Tests - dependencies: - - target: HoloLakeMobile - settings: - base: - PRODUCT_BUNDLE_IDENTIFIER: com.guanghulab.hololake.tests - TEST_HOST: "$(BUILT_PRODUCTS_DIR)/HoloLake.app/HoloLake" - BUNDLE_LOADER: "$(TEST_HOST)" - info: - path: Generated/HoloLakeMobileTests-Info.plist - properties: {} diff --git a/product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-DELIVERY-004.json b/product-source/hololake-native-desktop/official-modules/web-novel/HL-MOD-WEBNOVEL-DELIVERY-004/1.0.0/module.json similarity index 100% rename from product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-DELIVERY-004.json rename to product-source/hololake-native-desktop/official-modules/web-novel/HL-MOD-WEBNOVEL-DELIVERY-004/1.0.0/module.json diff --git a/product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-GRID-002.json b/product-source/hololake-native-desktop/official-modules/web-novel/HL-MOD-WEBNOVEL-GRID-002/1.0.0/module.json similarity index 100% rename from product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-GRID-002.json rename to product-source/hololake-native-desktop/official-modules/web-novel/HL-MOD-WEBNOVEL-GRID-002/1.0.0/module.json diff --git a/product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-OUTLINE-001.json b/product-source/hololake-native-desktop/official-modules/web-novel/HL-MOD-WEBNOVEL-OUTLINE-001/1.0.0/module.json similarity index 100% rename from product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-OUTLINE-001.json rename to product-source/hololake-native-desktop/official-modules/web-novel/HL-MOD-WEBNOVEL-OUTLINE-001/1.0.0/module.json diff --git a/product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-STORYWORLD-003.json b/product-source/hololake-native-desktop/official-modules/web-novel/HL-MOD-WEBNOVEL-STORYWORLD-003/1.0.0/module.json similarity index 100% rename from product-source/hololake-native-desktop/fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-STORYWORLD-003.json rename to product-source/hololake-native-desktop/official-modules/web-novel/HL-MOD-WEBNOVEL-STORYWORLD-003/1.0.0/module.json diff --git a/product-source/hololake-native-desktop/package-lock.json b/product-source/hololake-native-desktop/package-lock.json index 17cf42c6f..f527ec24f 100644 --- a/product-source/hololake-native-desktop/package-lock.json +++ b/product-source/hololake-native-desktop/package-lock.json @@ -1,12 +1,12 @@ { "name": "hololake-native-desktop", - "version": "0.5.0", + "version": "0.4.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "hololake-native-desktop", - "version": "0.5.0", + "version": "0.4.1", "dependencies": { "@fortune-sheet/react": "1.0.4", "@lexical/history": "0.49.0", @@ -16,6 +16,7 @@ "@lexical/rich-text": "0.49.0", "@lexical/selection": "0.49.0", "@lexical/utils": "0.49.0", + "@tanstack/react-table": "8.21.3", "@tauri-apps/api": "2.10.1", "@tauri-apps/plugin-process": "2.3.1", "@tauri-apps/plugin-updater": "2.10.0", @@ -1792,6 +1793,39 @@ "dev": true, "license": "MIT" }, + "node_modules/@tanstack/react-table": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", + "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.21.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tauri-apps/api": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz", diff --git a/product-source/hololake-native-desktop/package.json b/product-source/hololake-native-desktop/package.json index 91bd222cd..a6f5a54f4 100644 --- a/product-source/hololake-native-desktop/package.json +++ b/product-source/hololake-native-desktop/package.json @@ -1,7 +1,7 @@ { "name": "hololake-native-desktop", "private": true, - "version": "0.5.0", + "version": "0.4.1", "type": "module", "scripts": { "dev": "vite", @@ -19,6 +19,7 @@ "@lexical/rich-text": "0.49.0", "@lexical/selection": "0.49.0", "@lexical/utils": "0.49.0", + "@tanstack/react-table": "8.21.3", "@tauri-apps/api": "2.10.1", "@tauri-apps/plugin-process": "2.3.1", "@tauri-apps/plugin-updater": "2.10.0", diff --git a/product-source/hololake-native-desktop/scripts/authenticated-main-world-navigation.test.mjs b/product-source/hololake-native-desktop/scripts/authenticated-main-world-navigation.test.mjs new file mode 100644 index 000000000..162dbe6c0 --- /dev/null +++ b/product-source/hololake-native-desktop/scripts/authenticated-main-world-navigation.test.mjs @@ -0,0 +1,26 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +import test from 'node:test' + +const frontend = fs.readFileSync(new URL('../src/main.tsx', import.meta.url), 'utf8') +const architecture = JSON.parse( + fs.readFileSync(new URL('../../../routing/hololake-current-architecture.json', import.meta.url), 'utf8'), +) + +test('returning to the main world preserves the authenticated session', () => { + const handler = frontend.match(/const returnToMainWorld = \(\) => \{([\s\S]*?)\n \}/)?.[1] || '' + + assert.match(handler, /setShowMainWorld\(true\)/) + assert.doesNotMatch(handler, /signOutRepo|setRepoLogin\(null\)|sign_out_code_repo_login/) + assert.match(frontend, /if \(!repoLogin \|\| showMainWorld\)/) +}) + +test('main-world return and account sign-out remain separate visible actions', () => { + assert.match(frontend, />逛逛语言世界返回我的频道退出账号 readFileSync(new URL(`../${path}`, import.meta.url), 'utf8') -const contract = JSON.parse(read('contracts/channel-workbench-runtime.json')) -const registry = JSON.parse(read('contracts/numbered-ipc-registry.json')) -const modulePackage = JSON.parse(read('fixtures/module-packages/HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001-0.1.0.ghmod')) -const rust = read('src-tauri/src/channel_workbench.rs') -const frontend = [read('src/modules/channel-workbench/index.tsx'), read('src/modules/channel-workbench/document-engine.tsx'), read('src/modules/channel-workbench/spreadsheet-engine.tsx')].join('\n') - -test('channel workbench is a signed account-local adapter with durable user data', () => { - assert.equal(contract.candidate_number, 'HLP-DONOR-CAND-0002') - assert.equal(contract.runtime_module_number, 'HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001') - assert.equal(contract.data_boundary.scope, 'CURRENT_AUTHENTICATED_ACCOUNT_LOCAL') - assert.equal(contract.data_boundary.package_unmount_deletes_user_data, false) - assert.equal(modulePackage.manifest.adapter, 'channel-workbench-v1') - assert.deepEqual(modulePackage.manifest.permissions, ['CHANNEL_DOCUMENT_READ', 'CHANNEL_DOCUMENT_WRITE', 'CHANNEL_SPREADSHEET_READ', 'CHANNEL_SPREADSHEET_WRITE']) - assert.match(rust, /require_active_module_adapter/) - assert.match(rust, /workbench_receipts_no_update/) - assert.doesNotMatch(rust, /#\[tauri::command\]/) - assert.doesNotMatch(frontend, /from ['"]@tauri-apps\/api\/core['"]/) -}) - -test('document and spreadsheet cross only their exact numbered routes', () => { - const routes = registry.operations.filter((route) => route.module_number === 'HLP-NIPC-MOD-0022') - assert.deepEqual(routes.map((route) => route.operation_number), ['HLP-NIPC-OP-0074', 'HLP-NIPC-OP-0075', 'HLP-NIPC-OP-0076']) - assert.deepEqual(routes.map((route) => route.alias), ['get_channel_workbench_snapshot', 'save_channel_document', 'save_channel_spreadsheet']) - assert.ok(routes.every((route) => route.target_number === 'HLP-NIPC-TGT-0022')) - assert.ok(routes.every((route) => route.admission === 'VERIFIED_HUMAN_ROUTE')) -}) - -test('the legacy engines are preserved but loaded only inside the module chunk', () => { - assert.match(frontend, /LexicalComposer/) - assert.match(frontend, /Workbook/) - assert.match(frontend, /calculateFormula/) - assert.match(read('src/main.tsx'), /lazy\(\(\) => import\('\.\/modules\/channel-workbench'\)/) -}) diff --git a/product-source/hololake-native-desktop/scripts/compile-gls-runtime-registry.mjs b/product-source/hololake-native-desktop/scripts/compile-gls-runtime-registry.mjs index 24c86bbd8..5a90b8876 100644 --- a/product-source/hololake-native-desktop/scripts/compile-gls-runtime-registry.mjs +++ b/product-source/hololake-native-desktop/scripts/compile-gls-runtime-registry.mjs @@ -12,10 +12,9 @@ const sourceRoot = explicitSourceRoot || (repoRoot ? path.join(repoRoot, 'gls') const sourceCommit = args.get('--source-commit') const output = args.get('--output') const projectionsPath = args.get('--projections') -const referencesPath = args.get('--references') -if (!repoRoot || !sourceRoot || !sourceCommit || !output || !projectionsPath || !referencesPath) { - throw new Error('usage: compile-gls-runtime-registry.mjs --repo-root --source-commit --output --projections --references ') +if (!repoRoot || !sourceRoot || !sourceCommit || !output || !projectionsPath) { + throw new Error('usage: compile-gls-runtime-registry.mjs --repo-root --source-commit --output --projections ') } if (!/^[a-f0-9]{40}$/.test(sourceCommit)) throw new Error('source commit must be a full SHA-1') @@ -169,18 +168,6 @@ if (projectionManifest.schema !== 'hololake.gls-executable-projections/v2' || projectionManifest.source_commit !== sourceCommit) { throw new Error('projection manifest does not match the selected REPO-012 source commit') } -const referenceManifest = JSON.parse(await readFile(referencesPath, 'utf8')) -if (referenceManifest.schema !== 'hololake.gls-numbered-reference-nodes/v1' - || referenceManifest.record_id !== 'HLP-GLS-NUMBERED-REFERENCE-REGISTRY-001' - || referenceManifest.source?.repository !== 'REPO-012' - || referenceManifest.source?.commit !== sourceCommit - || referenceManifest.policy?.number_is_coordinate_not_authority !== true - || referenceManifest.policy?.independent_protocol_source_required_for_execution !== true - || referenceManifest.policy?.reference_only_nodes_may_execute !== false - || referenceManifest.policy?.unknown_reference !== 'FAIL_CLOSED' - || referenceManifest.policy?.unresolved_number_reference_allowed !== false) { - throw new Error('numbered reference manifest does not match the selected REPO-012 source commit or safety boundary') -} const protocolRegistryPath = 'gls/GLS-PROTOCOL-REGISTRY.json' const glsEntryPath = 'gls/GLS-ENTRY.hdlp' @@ -235,35 +222,29 @@ for (const relative of await walk(routingRoot)) { } } -const allSourceFiles = await walk(sourceRoot) -const candidates = allSourceFiles - .map((relative) => ({ relative, match: path.basename(relative).match(/^(GLS-\d{4})(?:[^0-9].*)?\.(hdlp|md)$/) })) +const candidates = (await walk(sourceRoot)) + .map((relative) => ({ relative, match: path.basename(relative).match(/^(GLS-\d{4}).*\.hdlp$/) })) .filter((item) => item.match) - .map((item) => ({ id: item.match[1], relative: item.relative, source_format: item.match[2] === 'hdlp' ? 'HDLP_PROTOCOL_SOURCE' : 'LEGACY_MARKDOWN_EVIDENCE' })) + .map((item) => ({ id: item.match[1], relative: item.relative })) const grouped = new Map() for (const candidate of candidates) { const group = grouped.get(candidate.id) || [] - group.push(candidate) + group.push(candidate.relative) grouped.set(candidate.id, group) } const selectedSource = new Map() for (const [id, sources] of grouped) { - const protocolSources = sources.filter((source) => source.source_format === 'HDLP_PROTOCOL_SOURCE') - if (protocolSources.length === 0) continue - protocolSources.sort((left, right) => sourceRank(left.relative) - sourceRank(right.relative) - || left.relative.localeCompare(right.relative)) - const selected = protocolSources[0] - const relative = selected.relative + sources.sort((left, right) => sourceRank(left) - sourceRank(right) || left.localeCompare(right)) + const relative = sources[0] selectedSource.set(id, { relative, raw: await readFile(path.join(sourceRoot, relative), 'utf8'), - source_format: selected.source_format, - alternate_source_count: protocolSources.length - 1, + alternate_source_count: sources.length - 1, }) } -let knownSourceIds = new Set(selectedSource.keys()) +const knownSourceIds = new Set(selectedSource.keys()) const protocolRegistryIds = new Set(registryMetadata.keys()) const draftIds = new Set((protocolRegistry.registered_draft_protocols || []).map((entry) => entry.id)) const legacyDependencyTargets = new Set() @@ -275,56 +256,6 @@ for (const id of draftIds) { } const legacyDependencyCycles = stronglyConnectedComponents(draftGraph) -// 旧 Notion 导出只在现行协议真实引用且独立 HDLP 正本缺席时作为历史证据节点进入。 -// 未被现行图引用的旧页面不得因为文件名像 GLS 编号就自动取得当前注册地位。 -for (const id of [...legacyDependencyTargets].filter((target) => !knownSourceIds.has(target))) { - if (!authorityDeclarations.has(id)) continue - const legacySources = (grouped.get(id) || []).filter((source) => source.source_format === 'LEGACY_MARKDOWN_EVIDENCE') - if (legacySources.length === 0) continue - legacySources.sort((left, right) => sourceRank(left.relative) - sourceRank(right.relative) || left.relative.localeCompare(right.relative)) - const selected = legacySources[0] - selectedSource.set(id, { - relative: selected.relative, - raw: await readFile(path.join(sourceRoot, selected.relative), 'utf8'), - source_format: selected.source_format, - alternate_source_count: legacySources.length - 1, - }) -} -knownSourceIds = new Set(selectedSource.keys()) - -const missingSourceTargets = [...legacyDependencyTargets].filter((id) => !knownSourceIds.has(id)).sort() -const referenceIds = new Set() -const referenceNodeNumbers = new Set() -const numberedReferenceNodes = [] -for (const node of referenceManifest.nodes || []) { - if (!/^GLS-\d{4}$/.test(node.protocol_id) - || !/^HLP-GLS-REF-\d{4}$/.test(node.node_number) - || !node.title - || !['NORMATIVE_REFERENCE', 'SCHEMA_IMPORT', 'EVIDENCE_ONLY'].includes(node.reference_kind) - || node.source_state !== 'ROADMAP_REFERENCE_ONLY' - || !referenceIds.add(node.protocol_id) - || !referenceNodeNumbers.add(node.node_number)) { - throw new Error(`invalid or duplicated numbered reference node: ${node.protocol_id || 'UNKNOWN'}`) - } - const evidencePaths = [] - for (const relative of allSourceFiles) { - if (!/\.(?:hdlp|md|json|ya?ml)$/.test(relative)) continue - const raw = await readFile(path.join(sourceRoot, relative), 'utf8') - if (raw.includes(node.protocol_id)) evidencePaths.push(`gls/${relative}`) - } - if (evidencePaths.length === 0) throw new Error(`numbered reference node has no REPO-012 evidence: ${node.protocol_id}`) - numberedReferenceNodes.push({ - ...node, - execution_state: 'REFERENCE_ONLY_NOT_EXECUTABLE', - evidence_paths: evidencePaths.sort().slice(0, 12), - }) -} -if (missingSourceTargets.length !== referenceIds.size - || missingSourceTargets.some((id) => !referenceIds.has(id)) - || [...referenceIds].some((id) => !missingSourceTargets.includes(id))) { - throw new Error(`numbered reference registry coverage mismatch: missing=${missingSourceTargets.join(',')} registered=${[...referenceIds].sort().join(',')}`) -} - const protocols = [] for (const [id, source] of [...selectedSource.entries()].sort(([left], [right]) => left.localeCompare(right))) { const heading = source.raw.split(/\r?\n/).find((line) => line.startsWith('#') && line.includes(id)) @@ -349,8 +280,6 @@ for (const [id, source] of [...selectedSource.entries()].sort(([left], [right]) enters_runtime_graph: false, target_registered: protocolRegistryIds.has(target), target_numbered_source_available: knownSourceIds.has(target), - target_number_coordinate_available: knownSourceIds.has(target) || referenceIds.has(target), - target_resolution: knownSourceIds.has(target) ? 'NUMBERED_PROTOCOL_SOURCE' : referenceIds.has(target) ? 'NUMBERED_REFERENCE_NODE' : 'UNRESOLVED', })), ...(projection?.dependencies || []).map((target) => ({ target, @@ -359,21 +288,18 @@ for (const [id, source] of [...selectedSource.entries()].sort(([left], [right]) enters_runtime_graph: true, target_registered: protocolRegistryIds.has(target), target_numbered_source_available: knownSourceIds.has(target), - target_number_coordinate_available: knownSourceIds.has(target) || referenceIds.has(target), - target_resolution: knownSourceIds.has(target) ? 'NUMBERED_PROTOCOL_SOURCE' : referenceIds.has(target) ? 'NUMBERED_REFERENCE_NODE' : 'UNRESOLVED', })), ] const activationBlockers = [] if (!projection) activationBlockers.push('NO_EXECUTABLE_ADAPTER') if (registrationState === 'DISCOVERED_UNRECONCILED') activationBlockers.push('REGISTRATION_NOT_RECONCILED') if (authorityConflict) activationBlockers.push('REGISTRATION_SOURCE_CONFLICT') - if (legacyDependencies.some((target) => !knownSourceIds.has(target) && !referenceIds.has(target)) && !projection) activationBlockers.push('DEPENDENCY_NUMBER_COORDINATE_MISSING') + if (legacyDependencies.some((target) => !knownSourceIds.has(target)) && !projection) activationBlockers.push('DEPENDENCY_NUMBERED_SOURCE_MISSING') protocols.push({ id, title: cleanHeading(heading || id, id), source_status: sourceStatus(source.raw), source_path: `gls/${source.relative}`, - source_format: source.source_format, source_sha256: createHash('sha256').update(source.raw).digest('hex'), alternate_source_count: source.alternate_source_count, registration: { @@ -428,7 +354,6 @@ for (const protocol of protocols) { } const dependenciesNotInRegistry = [...legacyDependencyTargets].filter((id) => !protocolRegistryIds.has(id)).sort() const dependenciesWithoutNumberedSource = [...legacyDependencyTargets].filter((id) => !knownSourceIds.has(id)).sort() -const unresolvedNumberReferences = dependenciesWithoutNumberedSource.filter((id) => !referenceIds.has(id)) const numberedSourcesNotInProtocolRegistry = [...knownSourceIds].filter((id) => !protocolRegistryIds.has(id)).sort() const registry = { schema: 'hololake.gls-runtime-manifest/v2', @@ -459,10 +384,6 @@ const registry = { legacy_dependency_target_count: legacyDependencyTargets.size, dependencies_not_in_protocol_registry: dependenciesNotInRegistry, dependencies_without_numbered_source: dependenciesWithoutNumberedSource, - numbered_reference_node_count: numberedReferenceNodes.length, - unresolved_number_references: unresolvedNumberReferences, - unresolved_number_reference_count: unresolvedNumberReferences.length, - every_dependency_has_number_coordinate: unresolvedNumberReferences.length === 0, numbered_sources_not_in_protocol_registry: numberedSourcesNotInProtocolRegistry, legacy_dependency_cycles: legacyDependencyCycles, source_reference_cycles: legacyDependencyCycles, @@ -474,10 +395,8 @@ const registry = { protocol_count: protocols.length, executable_projection_count: executableCount, inventoried_not_executable_count: protocols.length - executableCount, - number_coordinate_count: protocols.length + numberedReferenceNodes.length, - numbered_reference_nodes: numberedReferenceNodes, protocols, } await writeFile(output, `${JSON.stringify(registry, null, 2)}\n`) -console.log(`GLS_RUNTIME_MANIFEST_COMPILED protocols=${protocols.length} references=${numberedReferenceNodes.length} unresolved=${unresolvedNumberReferences.length} registered=${protocolRegistryIds.size} executable=${executableCount} legacy_cycles=${legacyDependencyCycles.length} output=${output}`) +console.log(`GLS_RUNTIME_MANIFEST_COMPILED protocols=${protocols.length} registered=${protocolRegistryIds.size} executable=${executableCount} legacy_cycles=${legacyDependencyCycles.length} output=${output}`) diff --git a/product-source/hololake-native-desktop/scripts/compile-unified-number-tree.mjs b/product-source/hololake-native-desktop/scripts/compile-unified-number-tree.mjs deleted file mode 100644 index b50240aa3..000000000 --- a/product-source/hololake-native-desktop/scripts/compile-unified-number-tree.mjs +++ /dev/null @@ -1,162 +0,0 @@ -import { createHash } from 'node:crypto' -import { mkdirSync, readFileSync, writeFileSync } from 'node:fs' -import { dirname, resolve } from 'node:path' -import { fileURLToPath } from 'node:url' - -const root = resolve(dirname(fileURLToPath(import.meta.url)), '..') -const paths = { - identity: resolve(root, 'contracts/zero-core-numbering-kernel.json'), - webview: resolve(root, 'contracts/numbered-ipc-registry.json'), - broker: resolve(root, 'contracts/direct-local-broker-numbered-registry.json'), - gls: resolve(root, 'contracts/gls-runtime-registry.json'), - output: resolve(root, 'generated/unified-number-coordinate-tree.json'), -} - -function readSource(path) { - const bytes = readFileSync(path) - return { - value: JSON.parse(bytes.toString('utf8')), - sha256: createHash('sha256').update(bytes).digest('hex'), - } -} - -export function compileUnifiedNumberTree() { - const identity = readSource(paths.identity) - const webview = readSource(paths.webview) - const broker = readSource(paths.broker) - const gls = readSource(paths.gls) - const routes = [ - ...webview.value.operations.map((route) => ({ - transport: 'TAURI_WEBVIEW_NUMBERED_IPC', - protocolVersion: webview.value.runtime.protocol_version, - callerNumber: webview.value.runtime.caller_number, - channelNumber: route.channel_number, - moduleNumber: route.module_number, - operationNumber: route.operation_number, - targetNumber: route.target_number, - alias: route.alias, - admission: route.admission, - effect: route.effect, - evidence: 'HASH_CHAINED_NUMBERED_IPC_RECEIPT', - path: `HLP-NUMBER-WORLD-ROOT-001/TAURI/${route.channel_number}/${route.module_number}/${route.operation_number}/${route.target_number}`, - })), - ...broker.value.operations.map((route) => ({ - transport: 'DIRECT_LOCAL_NUMBERED_BROKER', - protocolVersion: broker.value.runtime.protocol_version, - callerNumber: broker.value.runtime.caller_number, - channelNumber: route.channel_number, - moduleNumber: route.module_number, - operationNumber: route.operation_number, - targetNumber: route.target_number, - alias: route.alias, - admission: ['DISCOVER_NEARBY', 'PING', 'GET_BEIJING_TIME'].includes(route.alias) - ? 'PREAUTH_LOCAL_SYSTEM_ROUTE' - : ['OPEN_VISITOR_SESSION', 'RECEIVE_LANGUAGE'].includes(route.alias) - ? 'BOUNDED_VISITOR_ROUTE' - : 'AUTHENTICATED_LOCAL_SESSION_WITH_PERSONA_LICENSE_IF_PERSONA_MODE', - effect: ['DISCOVER_NEARBY', 'PING', 'GET_BEIJING_TIME', 'GET_PERSONA_CARRIER_LICENSE_STATUS', 'GET_WORK_ENVIRONMENT', 'RESOLVE_CAPABILITY_ROUTE', 'INSPECT_MOUNTED_PNCC_REPOSITORY', 'READ_MOUNTED_PNCC_REMOTE_OBJECT', 'QUERY_PNCC_RECEIPT_PROJECTION', 'INSPECT_DEVELOPMENT_WRITE_LANE'].includes(route.alias) - ? 'READ_OR_STATUS' - : 'STATE_CHANGE', - evidence: 'NUMBERED_RESPONSE_PLUS_SESSION_OR_DOMAIN_RECEIPT', - path: `HLP-NUMBER-WORLD-ROOT-001/BROKER/${route.channel_number}/${route.module_number}/${route.operation_number}/${route.target_number}`, - })), - ].sort((left, right) => left.path.localeCompare(right.path, 'en')) - const uniquePaths = new Set(routes.map((route) => route.path)) - const uniqueOperations = new Set(routes.map((route) => `${route.transport}:${route.operationNumber}`)) - if (routes.length !== uniquePaths.size || routes.length !== uniqueOperations.size) { - throw new Error('HOLOLAKE_UNIFIED_NUMBER_TREE_DUPLICATE_COORDINATE') - } - const identityNodes = identity.value.namespaces.map((namespace) => ({ - nodeKind: 'IDENTITY_NAMESPACE', - nodeNumber: `HLP-IDENTITY-NS-${namespace.id}`, - namespaceId: namespace.id, - subjectKind: namespace.subject_kind, - domainScope: namespace.domain_scope, - admission: namespace.human_entry ? 'REGISTERED_HUMAN_NAMESPACE' : 'NON_HUMAN_NAMESPACE', - executionState: 'AUTHORITY_RESOLUTION_ONLY', - evidence: identity.value.authority.map_id, - path: `HLP-NUMBER-WORLD-ROOT-001/IDENTITY/${namespace.id}`, - })).sort((left, right) => left.path.localeCompare(right.path, 'en')) - const protocolNodes = [ - ...gls.value.protocols.map((protocol) => ({ - nodeKind: 'GLS_PROTOCOL_SOURCE', - nodeNumber: protocol.id, - protocolId: protocol.id, - title: protocol.title, - sourceState: protocol.source_format, - executionState: protocol.projection_state, - evidence: protocol.source_sha256, - path: `HLP-NUMBER-WORLD-ROOT-001/GLS/SOURCE/${protocol.id}`, - })), - ...gls.value.numbered_reference_nodes.map((reference) => ({ - nodeKind: 'GLS_REFERENCE_ONLY', - nodeNumber: reference.node_number, - protocolId: reference.protocol_id, - title: reference.title, - sourceState: reference.source_state, - executionState: reference.execution_state, - evidence: reference.evidence_paths[0], - path: `HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/${reference.node_number}`, - })), - ].sort((left, right) => left.path.localeCompare(right.path, 'en')) - const allPaths = [...routes.map((route) => route.path), ...identityNodes.map((node) => node.path), ...protocolNodes.map((node) => node.path)] - if (new Set(allPaths).size !== allPaths.length - || gls.value.reconciliation.unresolved_number_reference_count !== 0 - || gls.value.reconciliation.every_dependency_has_number_coordinate !== true - || protocolNodes.some((node) => node.nodeKind === 'GLS_REFERENCE_ONLY' && node.executionState !== 'REFERENCE_ONLY_NOT_EXECUTABLE')) { - throw new Error('HOLOLAKE_UNIFIED_NUMBER_TREE_INCOMPLETE_COVERAGE') - } - return { - schema: 'hololake.unified-number-coordinate-tree/v2', - recordId: 'HLP-UNIFIED-NUMBER-TREE-001', - state: 'MACHINE_COMPILED_STARTUP_ENFORCED', - rootNumber: 'HLP-NUMBER-WORLD-ROOT-001', - identityAuthority: { - mapId: identity.value.authority.map_id, - mapVersion: identity.value.authority.map_version, - namespaces: identity.value.namespaces.map((namespace) => ({ - namespaceId: namespace.id, - roots: namespace.roots, - prefixes: namespace.prefixes, - subjectKind: namespace.subject_kind, - domainScope: namespace.domain_scope, - })), - }, - sources: [ - { recordId: identity.value.record_id, sha256: identity.sha256 }, - { recordId: webview.value.record_id, sha256: webview.sha256 }, - { recordId: broker.value.record_id, sha256: broker.sha256 }, - { recordId: gls.value.record_id, sha256: gls.sha256 }, - ], - invariants: { - numberIsStableCoordinateNotAuthority: true, - pathIsUniqueNavigation: true, - admissionIsSeparateFromIdentity: true, - everyPhysicalCallHasNumberedRoute: true, - everyAcceptedCallHasEvidenceClass: true, - everyProtocolReferenceHasNumberCoordinate: true, - referenceOnlyNodesNeverExecutable: true, - unresolvedNumberReferenceCount: 0, - mismatchedCoordinate: 'FAIL_CLOSED', - }, - coordinateCount: routes.length + identityNodes.length + protocolNodes.length, - routeCount: routes.length, - identityNodeCount: identityNodes.length, - protocolNodeCount: protocolNodes.length, - referenceOnlyNodeCount: protocolNodes.filter((node) => node.nodeKind === 'GLS_REFERENCE_ONLY').length, - identityNodes, - protocolNodes, - routes, - } -} - -const compiled = compileUnifiedNumberTree() -const output = `${JSON.stringify(compiled, null, 2)}\n` -if (process.argv.includes('--check')) { - if (readFileSync(paths.output, 'utf8') !== output) { - throw new Error('HOLOLAKE_UNIFIED_NUMBER_TREE_STALE') - } -} else { - mkdirSync(dirname(paths.output), { recursive: true }) - writeFileSync(paths.output, output) -} diff --git a/product-source/hololake-native-desktop/scripts/direct-local-broker-numbered.test.mjs b/product-source/hololake-native-desktop/scripts/direct-local-broker-numbered.test.mjs deleted file mode 100644 index 9509bd2a7..000000000 --- a/product-source/hololake-native-desktop/scripts/direct-local-broker-numbered.test.mjs +++ /dev/null @@ -1,25 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const registry = JSON.parse(readFileSync(new URL('../contracts/direct-local-broker-numbered-registry.json', import.meta.url), 'utf8')) -const broker = readFileSync(new URL('../src-tauri/src/direct_local_broker.rs', import.meta.url), 'utf8') - -test('the external local broker accepts only complete numbered coordinates', () => { - assert.equal(registry.record_id, 'HLP-NBROKER-ROOT-001') - assert.equal(registry.runtime.protocol_version, 'HLP-NBROKER-v1') - assert.equal(registry.runtime.legacy_string_operation_allowed, false) - assert.equal(registry.runtime.unknown_or_mismatched_coordinate, 'FAIL_CLOSED') - assert.equal(registry.runtime.transport_is_authority, false) - assert.equal(registry.operations.length, 22) - assert.equal(new Set(registry.operations.map((route) => route.operation_number)).size, 22) - assert.equal(new Set(registry.operations.map((route) => route.alias)).size, 22) - for (const route of registry.operations) { - assert.match(route.operation_number, /^HLP-NBROKER-OP-\d{4}$/) - assert.match(route.channel_number, /^HLP-NBROKER-CH-\d{4}$/) - assert.match(route.module_number, /^HLP-NBROKER-MOD-\d{4}$/) - assert.match(route.target_number, /^HLP-NBROKER-TGT-\d{4}$/) - } - assert.match(broker, /decode_numbered_broker_request/) - assert.match(broker, /HOLOLAKE_NUMBERED_BROKER_ROUTE_COORDINATE_MISMATCH/) -}) diff --git a/product-source/hololake-native-desktop/scripts/domain-number-routing.test.mjs b/product-source/hololake-native-desktop/scripts/domain-number-routing.test.mjs index aa088dbbd..c77086be5 100644 --- a/product-source/hololake-native-desktop/scripts/domain-number-routing.test.mjs +++ b/product-source/hololake-native-desktop/scripts/domain-number-routing.test.mjs @@ -19,19 +19,23 @@ test('public routing starts from five domains and lets the number select the ver assert.equal(contract.registries.ENTERPRISE_FOUR_DOMAINS.ownership, 'TCS_0002_ENTERPRISE_REALITY_BODY') }) -test('the public shell shows five domains and login is domain-routed', () => { +test('the public shell shows five official gates while ordinary login returns to a personal channel', () => { const frontend = read('src/main.tsx') const login = read('src-tauri/src/code_repo_login.rs') const router = read('src-tauri/src/zero_point.rs') for (const name of ['光湖主域', '光湖分域', '光湖零域', '光湖零感域', '第五域 · 光湖本源域']) { assert.match(frontend, new RegExp(name.replace('·', '\\·'))) } - assert.match(frontend, /输入编号进入所属域/) + assert.match(frontend, /编号验证 · 进入世界的第一个入口/) assert.match(frontend, /TCS-GL-/) - assert.match(frontend, /肥猫 · TCS-GL-0007∞/) - assert.match(frontend, /桔子 · TCS-GL-0008∞/) - assert.match(frontend, /烬舟 · PER-JZ001 · AGE/) - assert.match(frontend, /熹微 · PER-JZ-ARCH-001 · AGE/) + assert.match(frontend, /仅光湖人类主控团队正式成员/) + assert.match(frontend, /不对普通用户开放/) + assert.match(frontend, /返回我的频道/) + assert.match(frontend, /普通用户|一人一频道/) + assert.doesNotMatch(frontend, /肥猫 · TCS-GL-0007∞/) + assert.doesNotMatch(frontend, /桔子 · TCS-GL-0008∞/) + assert.doesNotMatch(frontend, /烬舟 · PER-JZ001 · AGE/) + assert.doesNotMatch(frontend, /熹微 · PER-JZ-ARCH-001 · AGE/) assert.doesNotMatch(frontend, /肥猫 \+ 烬舟/) assert.match(frontend, /className="gate-close"/) assert.match(frontend, /className="domain-info-scrim"/) diff --git a/product-source/hololake-native-desktop/scripts/dynamic-language-world-visual-system.test.mjs b/product-source/hololake-native-desktop/scripts/dynamic-language-world-visual-system.test.mjs new file mode 100644 index 000000000..1f22b70e1 --- /dev/null +++ b/product-source/hololake-native-desktop/scripts/dynamic-language-world-visual-system.test.mjs @@ -0,0 +1,32 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import { readFileSync } from 'node:fs' + +const read = (path) => readFileSync(new URL(`../${path}`, import.meta.url), 'utf8') +const contract = JSON.parse(read('contracts/dynamic-language-world-visual-system.json')) +const rust = read('src-tauri/src/world_climate.rs') +const ui = read('src/main.tsx') +const tokens = read('src/design-tokens.css') + +test('dynamic world and fixed traditional themes remain independently selectable', () => { + assert.deepEqual(contract.modes, ['DYNAMIC_LANGUAGE_WORLD', 'FIXED_TRADITIONAL_THEME']) + assert.match(ui, /hololake-visual-mode/) + assert.match(ui, /动态语言世界/) + assert.match(ui, /固定传统主题/) +}) + +test('verified weather changes visual tokens but never invents weather when offline', () => { + assert.match(rust, /VERIFIED_LIVE/) + assert.match(rust, /TIME_ONLY_WEATHER_UNAVAILABLE/) + assert.match(rust, /city_exposed: false/) + assert.equal(contract.privacy.weather_unavailable_behavior, 'BEIJING_TIME_ONLY_NO_FAKE_WEATHER') + assert.match(tokens, /visual-world\.climate-day/) + assert.match(tokens, /visual-world\.climate-night/) +}) + +test('the five-domain climate rotation uses internal coordinates and never presents a real city label', () => { + assert.equal(contract.daily_domain_rotation.length, 5) + assert.match(rust, /coordinate_for/) + assert.doesNotMatch(ui, /西安天气|北京天气|广州天气/) + assert.equal(contract.privacy.real_city_exposed_in_ui, false) +}) diff --git a/product-source/hololake-native-desktop/scripts/dynamic-world-surface-admission.test.mjs b/product-source/hololake-native-desktop/scripts/dynamic-world-surface-admission.test.mjs deleted file mode 100644 index 3e8fe8526..000000000 --- a/product-source/hololake-native-desktop/scripts/dynamic-world-surface-admission.test.mjs +++ /dev/null @@ -1,69 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const read = (path) => readFileSync(new URL(`../${path}`, import.meta.url), 'utf8') -const contract = JSON.parse(read('contracts/dynamic-language-world-visual-system.json')) -const registry = JSON.parse(read('contracts/numbered-ipc-registry.json')) -const modulePackage = JSON.parse(read('fixtures/module-packages/HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001-0.1.0.ghmod')) -const rust = read('src-tauri/src/world_climate.rs') -const frontend = read('src/main.tsx') -const styles = read('src/styles.css') -const starlake = read('src/modules/qoder-surface/StarlakeSurface.tsx') -const starlakeStyles = read('src/modules/qoder-surface/starlake-surface.css') -const traditional = read('src/modules/qoder-surface/TraditionalSurface.tsx') -const traditionalStyles = read('src/modules/qoder-surface/traditional-surface.css') -const visualBalance = read('src/modules/qoder-surface/visual-balance.ts') -const layoutProfile = read('src/modules/qoder-surface/layout-profile.ts') - -test('dynamic world surface is signed, opt-in and cannot mutate world facts', () => { - assert.equal(modulePackage.manifest.moduleNumber, 'HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001') - assert.equal(modulePackage.manifest.registrationClass, 'OFFICIAL_LIGHTHOUSE') - assert.equal(modulePackage.manifest.adapter, 'dynamic-language-world-surface-v1') - assert.deepEqual(modulePackage.manifest.permissions, ['REALITY_TIME_READ', 'PUBLIC_WEATHER_QUERY']) - assert.equal(modulePackage.payload.adapterConfig.routingPermissionOrFactMutation, false) - assert.equal(contract.visual_lock.climate_changes_routing_permission_or_fact, false) - assert.equal(contract.visual_lock.daily_sampling_domain_changes_open_domain, false) -}) - -test('climate query crosses the unique numbered route and fails closed before activation', () => { - const route = registry.operations.find((item) => item.alias === 'get_world_climate') - assert.equal(route.operation_number, 'HLP-NIPC-OP-0147') - assert.equal(route.module_number, 'HLP-NIPC-MOD-0031') - assert.equal(route.target_number, 'HLP-NIPC-TGT-0031') - assert.equal(route.admission, 'VERIFIED_HUMAN_ROUTE') - assert.match(rust, /require_active_module_adapter/) - assert.doesNotMatch(rust, /#\[tauri::command\]/) - assert.doesNotMatch(frontend, /from ['"]@tauri-apps\/api\/core['"]/) -}) - -test('Qoder locked two-track surface is admitted without simulated product state', () => { - assert.equal(contract.visual_lock.layout, 'QODER_VISUAL_LANGUAGE_SEMANTICALLY_REASSEMBLED_ON_RESPONSIVE_HOLOLAKE_SHELL') - assert.equal(contract.visual_lock.language_world_themes.length, 5) - assert.equal(contract.visual_lock.traditional_finishes.length, 8) - assert.equal(contract.visual_lock.all_downstream_pages_inherit_active_surface_tokens, true) - assert.match(frontend, /夜湖星光/) - assert.match(frontend, /天气源暂不可用;湖面只使用北京时间,不生成假天气。/) - assert.match(styles, /\.world-climate-veil/) - assert.match(starlake, /ResizeObserver/) - assert.match(starlake, /data-layout=\{layout\.profile\}/) - assert.match(layoutProfile, /panoramic.*wide.*compact.*stacked/s) - assert.doesNotMatch(starlake, /naturalScale|sideCenters|onDuty \? 2/) - assert.match(starlakeStyles, /\.starlake-scene\.awake/) - assert.match(traditional, /broadcasts\.map/) - assert.match(traditionalStyles, /\.official-world\.surface-traditional/) - assert.match(visualBalance, /contrastRatio/) - assert.doesNotMatch(traditional, /语料库新增 217 条/) - assert.doesNotMatch(traditional, /const BROADCAST_POOL/) -}) - -test('ambient motion sleeps and the Qoder source hashes remain pinned', () => { - assert.equal(contract.visual_lock.ambient_motion_requires_recent_human_pointer_or_keyboard_activity, true) - assert.equal(contract.visual_lock.idle_visual_state, 'STATIC') - assert.match(frontend, /setTimeout\(\(\) => \{[\s\S]*setMotionAwake\(false\)/) - assert.match(starlake, /if \(!awake\) return/) - assert.match(traditional, /if \(!awake\) return/) - assert.match(starlakeStyles, /animation-play-state:paused/) - assert.match(traditionalStyles, /animation-play-state:paused/) - assert.equal(contract.qoder_source_provenance.main_tsx_sha256, '7dab8596ec0bd2609b1b23b175f1f14f15f2aa9af847eb605692c993d2e876e8') -}) diff --git a/product-source/hololake-native-desktop/scripts/education-workbench-admission.test.mjs b/product-source/hololake-native-desktop/scripts/education-workbench-admission.test.mjs deleted file mode 100644 index 644f94f55..000000000 --- a/product-source/hololake-native-desktop/scripts/education-workbench-admission.test.mjs +++ /dev/null @@ -1,53 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const read = (path) => readFileSync(new URL(`../${path}`, import.meta.url), 'utf8') -const contract = JSON.parse(read('contracts/education-workspace.json')) -const registry = JSON.parse(read('contracts/numbered-ipc-registry.json')) -const modulePackage = JSON.parse(read('fixtures/module-packages/HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001-0.1.0.ghmod')) -const workspaceRust = read('src-tauri/src/education_workspace.rs') -const translationRust = read('src-tauri/src/education_translation.rs') -const frontend = [ - read('src/modules/education-workspace/index.tsx'), - read('src/modules/education-workspace/education-data.ts'), - read('src/modules/education-workspace/education-adaptive-rendering.ts'), -].join('\n') - -test('education is an official signed declarative adapter over the shared office foundation', () => { - assert.equal(contract.package.official_module_number, 'HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001') - assert.equal(contract.foundation_dependency.module_id, 'hololake.builtin.channel-workbench') - assert.equal(modulePackage.manifest.registrationClass, 'OFFICIAL_LIGHTHOUSE') - assert.equal(modulePackage.manifest.adapter, 'education-workbench-v1') - assert.equal(modulePackage.payload.adapterConfig.foundationModule, 'HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001') - assert.equal(modulePackage.payload.adapterConfig.importDefaultScope, 'UNASSIGNED') - assert.equal(modulePackage.payload.adapterConfig.modelFileTransferDefault, 'DENY') - assert.equal(modulePackage.manifest.permissions.length, 8) -}) - -test('all education effects cross the exact numbered adapter routes', () => { - const routes = registry.operations.filter((route) => route.module_number === 'HLP-NIPC-MOD-0024') - assert.deepEqual(routes.map((route) => route.operation_number), Array.from({ length: 18 }, (_, index) => `HLP-NIPC-OP-${String(index + 85).padStart(4, '0')}`)) - assert.ok(routes.every((route) => route.target_number === 'HLP-NIPC-TGT-0024')) - assert.ok(routes.every((route) => route.admission === 'VERIFIED_HUMAN_ROUTE')) - assert.doesNotMatch(frontend, /from ['"]@tauri-apps\/api\/core['"]/) - assert.doesNotMatch(workspaceRust, /#\[tauri::command\]/) - assert.doesNotMatch(translationRust, /#\[tauri::command\]/) - assert.match(workspaceRust, /require_active_module_adapter/) -}) - -test('legacy silent corruption and automatic destructive behavior are rejected', () => { - assert.doesNotMatch(workspaceRust, /serde_json::from_str[^\n]+unwrap_or_default/) - assert.match(workspaceRust, /deny_unknown_fields/) - assert.match(frontend, /生成只读预览/) - assert.match(frontend, /我确认,写入清理结果/) - assert.match(frontend, /生成只读预览令牌/) - assert.match(frontend, /我确认,按此令牌执行/) - assert.match(frontend, /确认归入教育频道/) -}) - -test('education UI is independently lazy-loaded and reuses, rather than duplicates, office engines', () => { - assert.match(read('src/main.tsx'), /lazy\(\(\) => import\('\.\/modules\/education-workspace'\)/) - assert.match(read('src/modules/education-workspace/education-document-engine.tsx'), /channel-workbench\/document-engine/) - assert.match(read('src/modules/education-workspace/index.tsx'), /channel-workbench\/spreadsheet-engine/) -}) diff --git a/product-source/hololake-native-desktop/scripts/education-workspace.test.mjs b/product-source/hololake-native-desktop/scripts/education-workspace.test.mjs new file mode 100644 index 000000000..f9fbbcf9f --- /dev/null +++ b/product-source/hololake-native-desktop/scripts/education-workspace.test.mjs @@ -0,0 +1,318 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +import test from 'node:test' + +const read = (path) => fs.readFileSync(new URL('../' + path, import.meta.url), 'utf8') +const contract = JSON.parse(read('contracts/education-workspace.json')) +const donors = JSON.parse(read('contracts/education-open-source-donor-assessment.json')) +const industry = JSON.parse(read('contracts/subdomain-industry-routing.json')) +const rust = read('src-tauri/src/education_workspace.rs') +const translation = read('src-tauri/src/education_translation.rs') +const lib = read('src-tauri/src/lib.rs') +const ui = read('src/main.tsx') +const documentEngine = read('src/modules/education-document-engine.tsx') +const channelDocumentEngine = read('src/modules/channel-workbench/document-engine.tsx') +const channelSpreadsheetEngine = read('src/modules/channel-workbench/spreadsheet-engine.tsx') +const channelSpreadsheetModel = read('src/modules/channel-workbench/spreadsheet-model.ts') +const moduleRuntime = JSON.parse(read('contracts/channel-module-runtime.json')) +const marketplaceDevelopmentCatalog = JSON.parse(read('contracts/official-module-marketplace-development-catalog.json')) +const adaptiveRendering = read('src/modules/education-adaptive-rendering.ts') +const dataCleanup = read('src/modules/education-data.ts') + +test('education package consumes the built-in account-scoped channel workbench', () => { + assert.equal(contract.domain_entry, 'BRANCH_DOMAIN') + assert.equal(contract.channel_id, 'GH-EDU-INIT-001') + assert.equal(contract.native_storage.owner, 'HOLOLAKE_NATIVE_RUST_CORE') + assert.equal(contract.native_storage.engine, 'SQLITE') + assert.equal(contract.native_storage.authenticated_account_required, true) + assert.equal(contract.native_storage.cross_account_projection_allowed, false) + assert.equal(contract.native_storage.restart_readback_required, true) + assert.equal(contract.document_module.state, 'DEVELOPMENT_FEATURE_MOUNTED') + assert.equal(contract.table_module.state, 'DEVELOPMENT_FEATURE_MOUNTED') + assert.equal(contract.foundation_dependency.module_id, 'hololake.builtin.channel-workbench') + assert.match(contract.document_module.engine, /^CHANNEL_WORKBENCH_LEXICAL_0_49_0/) + assert.match(contract.table_module.engine, /^CHANNEL_WORKBENCH_FORTUNE_SHEET_1_0_4/) + assert.equal(contract.table_module.sensitive_field_visibility.local_default, 'HIDDEN_UNTIL_HUMAN_REVEALS') + assert.equal(contract.table_module.sensitive_field_visibility.human_can_hide, true) + assert.equal(contract.table_module.sensitive_field_visibility.human_can_show_again, true) +}) + +test('education workspace commands require the authenticated storage root', () => { + assert.match(rust, /account_storage_root\(app, "education-workspace-v1"\)/) + for (const command of [ + 'get_education_workspace_snapshot', + 'create_education_document', + 'read_education_document', + 'save_education_document', + 'archive_education_document', + 'create_education_table', + 'read_education_table', + 'save_education_table', + 'archive_education_table', + 'create_education_automation_rule', + 'save_education_automation_rule', + 'archive_education_automation_rule', + 'preview_education_automation_rule', + 'execute_education_automation_rule', + ]) { + assert.match(lib, new RegExp('education_workspace::' + command)) + assert.ok(ui.includes("'" + command + "'") || ui.includes('"' + command + '"')) + } + assert.doesNotMatch(ui, /localStorage.*education/i) +}) + +test('one built-in foundation and five development features are reachable from the education channel', () => { + const education = industry.industries.find((item) => item.key === 'EDUCATION') + assert.equal(education.initialization_channel.installed_open_source_modules, 0) + assert.equal(education.initialization_channel.installed_native_modules, 1) + assert.equal(education.initialization_channel.development_mounted_modules, 1) + assert.ok(education.initialization_channel.module_slots.every((slot) => slot.state === 'DEVELOPMENT_MOUNTED')) + assert.equal(education.initialization_channel.module_slots[1].state_label, '开发态模块 · 使用频道内置工作表引擎') + assert.match(ui, /worldStage === 'educationDocuments'/) + assert.match(ui, /worldStage === 'educationTables'/) + assert.match(ui, /教育文档/) + assert.match(ui, /教育表格数据/) + assert.match(ui, /worldStage === 'educationAutomation'/) + assert.match(ui, /教育自动化/) + assert.match(ui, /worldStage === 'educationComposition'/) + assert.match(ui, /原生组合视图/) +}) + +test('native persistence enforces revision conflicts and bounded table data', () => { + assert.match(rust, /HOLOLAKE_EDUCATION_DOCUMENT_REVISION_CONFLICT/) + assert.match(rust, /HOLOLAKE_EDUCATION_TABLE_REVISION_CONFLICT/) + assert.match(rust, /MAX_TABLE_COLUMNS: usize = 30/) + assert.match(rust, /MAX_TABLE_ROWS: usize = 1_000/) + assert.match(rust, /MAX_CELL_BYTES: usize = 10_000/) + assert.match(rust, /archived = 1/) +}) + +test('education documents expose formal templates and real title filtering', () => { + assert.equal(contract.state, 'DEVELOPMENT_MODULE_SOURCE_MOUNTED_ACCEPTANCE_PENDING') + assert.equal(contract.package.official_module_number, null) + assert.equal(contract.package.registration_state, 'PENDING_FUNCTIONAL_ACCEPTANCE_AND_NUMBER_REGISTRATION') + assert.ok(contract.document_module.capabilities.includes('FORMAL_TEACHING_TEMPLATES')) + assert.ok(contract.document_module.capabilities.includes('TITLE_DIRECTORY_FILTER')) + assert.match(ui, /EDUCATION_DOCUMENT_TEMPLATES/) + assert.match(ui, /教学计划/) + assert.match(ui, /教育项目会议纪要/) + assert.match(ui, /学员阶段复盘/) + assert.match(ui, /检索教育文档标题/) + for (const capability of [ + 'CREATE_COPY', + 'EXPLICIT_READ_AND_EDIT_MODES', + 'HUMAN_SETTINGS_MENU', + 'BASIC_FORMATTING_TOOLBAR', + 'NATIVE_READING_CANVAS', + 'EXPORT_MARKDOWN_AND_HTML', + ]) assert.ok(contract.document_module.capabilities.includes(capability)) + assert.match(ui, /文档设置/) + assert.match(ui, /编辑与重命名/) + assert.match(ui, /创建副本/) + assert.match(ui, /移到可恢复归档/) + assert.match(ui, /educationDocumentMode === 'edit'/) + assert.match(documentEngine, /ChannelDocumentEngine/) + assert.match(channelDocumentEngine, /频道内置文档引擎工具/) +}) + +test('education table has four engine-backed views, filtering, sorting and bounded bulk paste', () => { + for (const capability of [ + 'CELL_CONTENT_FILTER', + 'COLUMN_SORT_ASCENDING_DESCENDING_OR_SOURCE_ORDER', + 'BOUNDED_PAGINATION_ROW_MODEL_FOR_LARGE_EDITABLE_TABLES', + 'GRID_AND_EDITABLE_CARD_VIEWS', + 'GROUPED_CLASSIFICATION_BOARD_FROM_SELECTED_FIELD', + 'LIVE_DATA_OVERVIEW_WITH_SELECTED_GROUP_AND_MEASURE', + 'HEADLESS_TABLE_DATA_DETACHED_OUTSIDE_TABLE_SURFACE', + 'MULTI_ROW_MULTI_COLUMN_TABULAR_PASTE', + ]) assert.ok(contract.table_module.capabilities.includes(capability)) + assert.match(ui, /parseEducationGridPaste/) + assert.match(ui, /pasteEducationTableGrid/) + assert.match(ui, />工作表<\/button>/) + assert.match(channelSpreadsheetEngine, /Workbook/) + assert.match(channelSpreadsheetEngine, /showFormulaBar/) + assert.match(channelSpreadsheetEngine, /conditionFormat/) + assert.match(channelSpreadsheetModel, /cell\.f/) + assert.match(ui, /分类看板/) + assert.match(ui, /数据概览/) + assert.match(ui, /renderEducationBoard/) + assert.match(ui, /renderEducationDashboard/) + assert.match(ui, /动态分类对比/) + assert.match(ui, /筛选教育表格数据/) + assert.match(ui, /升序 ↑/) + assert.match(ui, /降序 ↓/) + assert.match(ui, /getPaginationRowModel/) + assert.match(ui, /const educationTableEngineActive = worldStage === 'educationTables'/) + assert.match(ui, /educationTableEngineActive \? activeEducationTable\?\.rows \|\| \[\] : \[\]/) + assert.match(adaptiveRendering, /EDUCATION_EDITABLE_CELL_BUDGET = 240/) + assert.match(adaptiveRendering, /function educationEditablePageSize/) + assert.match(adaptiveRendering, /Math\.floor\(EDUCATION_EDITABLE_CELL_BUDGET \/ boundedColumns\)/) + assert.match(adaptiveRendering, /buildEducationBaselineRenderPlan/) + assert.match(adaptiveRendering, /validateEducationModelRenderProposal/) + assert.match(adaptiveRendering, /MODEL_PROPOSAL_REJECTED/) + assert.match(adaptiveRendering, /WAITING_HUMAN_CONFIRMATION/) + assert.match(adaptiveRendering, /已优雅退回本地基础算法/) + assert.match(ui, /基础算法自适应回执/) + assert.match(ui, /教育表格分页/) + assert.match(ui, /Math\.min\(30/) + assert.match(ui, /Math\.min\(1000/) + assert.ok(contract.table_module.capabilities.includes('HUMAN_SETTINGS_MENU')) + assert.ok(contract.table_module.capabilities.includes('CREATE_COPY')) + assert.match(ui, /表格设置/) + assert.match(ui, /duplicateEducationTable/) + assert.match(ui, /重命名与编辑/) + assert.match(ui, /isSensitiveEducationColumn/) + assert.match(ui, /账号\|账户\|手机号/) + assert.match(ui, /联系qq\|qq号/) + assert.match(ui, /educationSensitiveVisible, setEducationSensitiveVisible\] = useState\(false\)/) + assert.match(ui, /隐藏敏感字段/) + assert.match(ui, /显示敏感字段/) + assert.ok((ui.match(/setEducationSensitiveVisible\(false\)/g) || []).length >= 4) + assert.match(ui, /onClick=\{\(\) => setEducationSensitiveVisible\(true\)\}>在本机显示并打开工作表/) + assert.match(ui, /type=\{sensitive && !educationSensitiveVisible \? 'password' : 'text'\}/) + assert.equal(contract.table_module.sensitive_field_visibility.local_default, 'HIDDEN_UNTIL_HUMAN_REVEALS') +}) + +test('external tables are profiled into an unassigned staging area before human industry routing', () => { + assert.equal(contract.content_translation_layer.state, 'DETERMINISTIC_RUNTIME_READY_MODEL_ASSIST_SLOT_RESERVED') + assert.equal(contract.content_translation_layer.source_file_mutation_allowed, false) + assert.equal(contract.content_translation_layer.silent_truncation_allowed, false) + assert.equal(contract.content_translation_layer.local_import_without_model_api, 'ENABLED_FOR_ALL_SUPPORTED_FORMATS') + assert.equal(contract.content_translation_layer.import_assignment.default_scope, 'UNASSIGNED') + assert.equal(contract.content_translation_layer.import_assignment.education_directory_before_human_confirmation, false) + assert.equal(contract.content_translation_layer.import_assignment.existing_legacy_imports_reclassified_on_migration, true) + assert.equal(contract.content_translation_layer.semantic_focus.current_mode, 'DETERMINISTIC_BASELINE_ONLY') + assert.equal(contract.content_translation_layer.semantic_focus.low_confidence_behavior, 'ASK_HUMAN_TO_SELECT_PRIMARY_MEASURE') + assert.equal(contract.content_translation_layer.adaptive_rendering.current_mode, 'DETERMINISTIC_BASELINE_WITH_EXPLAINABLE_DEGRADATION') + assert.equal(contract.content_translation_layer.adaptive_rendering.editable_cell_budget, 240) + assert.equal(contract.content_translation_layer.adaptive_rendering.local_baseline_always_available, true) + assert.equal(contract.content_translation_layer.adaptive_rendering.model_adjustment.human_confirmation_before_rule_activation, true) + assert.equal(contract.content_translation_layer.adaptive_rendering.model_adjustment.model_can_mutate_source_data, false) + assert.equal(contract.content_translation_layer.adaptive_rendering.model_adjustment.failure_behavior, 'RETURN_TO_LOCAL_BASELINE_WITH_RECEIPT') + assert.deepEqual(contract.content_translation_layer.model_assist.learning_scopes, ['PRIVATE_ONLY', 'SHARE_ANONYMIZED_RULE']) + assert.match(translation, /PROFILED_BEFORE_WRITE/) + assert.match(translation, /import_table_batch_at/) + assert.match(translation, /source_preserved_read_only: true/) + assert.match(translation, /HOLOLAKE_MODEL_RECOGNITION_API\/v1/) + assert.match(translation, /infer_semantic_focus/) + assert.match(translation, /primary_measure_column/) + assert.match(rust, /education_import_registry/) + assert.match(rust, /assignment_scope = 'UNASSIGNED'/) + assert.match(rust, /assign_imported_table_to_education/) + assert.match(ui, /导入外部表格/) + assert.match(ui, /通用暂存区/) + assert.match(ui, /确认归入教育/) + assert.match(ui, /导出 Excel/) + assert.match(ui, /识别边界回执/) + assert.match(ui, /本地导入正常可用/) +}) + +test('audited translation libraries and headless engines stay bounded inside the HoloLake product shell', () => { + assert.equal(donors.state, 'FOUR_TRANSLATION_FAMILIES_TWO_HEADLESS_FAMILIES_AND_ONE_REAL_SPREADSHEET_ENGINE_INTEGRATED') + assert.equal(donors.current_slice.external_translation_library_families_added, 4) + assert.equal(donors.current_slice.external_headless_engine_families_added, 2) + assert.equal(donors.current_slice.real_spreadsheet_engine_families_added, 1) + assert.equal(donors.current_slice.direct_frontend_engine_packages_added, 10) + assert.equal(donors.current_slice.external_source_files_copied, 0) + assert.equal(donors.current_slice.source_research_route, 'LOCAL_DIRECT_TO_BS_SG_002_THEN_EXTERNAL_DRIVE') + assert.equal(donors.candidates.find((candidate) => candidate.name === 'Calamine').decision, 'INTEGRATE_PINNED_0_26_1_READ_ONLY_NO_OFFICE_RUNTIME') + assert.equal(donors.candidates.find((candidate) => candidate.name === 'rust_xlsxwriter').decision, 'INTEGRATE_PINNED_0_64_2_WRITE_NEW_XLSX_ONLY') + assert.equal(donors.candidates.find((candidate) => candidate.name === 'AppFlowy').decision, 'DO_NOT_EMBED_WHOLE_APPLICATION_STUDY_WORKSPACE_AND_DATABASE_INTERACTION_LOGIC_ONLY') + assert.match(donors.candidates.find((candidate) => candidate.name === 'Lexical').decision, /^INTEGRATE_PINNED_0_49_0/) + assert.equal(donors.candidates.find((candidate) => candidate.name === 'TanStack Table').decision, 'INTEGRATE_PINNED_8_21_3_SORT_FILTER_GROUP_AGGREGATE_AND_PAGINATION_ROW_MODELS_ONLY') + assert.equal(donors.candidates.find((candidate) => candidate.name === 'Univer').decision, 'SOURCE_STUDY_ONLY_DO_NOT_EMBED_WHOLE_APPLICATION_DEFER_FORMULA_AND_ADVANCED_GRID_PARTS') + assert.match(donors.candidates.find((candidate) => candidate.name === 'FortuneSheet').decision, /^INTEGRATE_PINNED_1_0_4/) + assert.equal(donors.candidates.find((candidate) => candidate.name === 'Glide Data Grid').decision, 'SOURCE_STUDY_ONLY_GRID_IS_NOT_A_SPREADSHEET_OR_FORMULA_ENGINE') + assert.equal(donors.candidates.find((candidate) => candidate.name === 'Vega-Lite').observed_license, 'BSD-3-Clause') + assert.equal(donors.candidates.find((candidate) => candidate.name === 'Observable Plot').observed_license, 'ISC') + assert.equal(donors.candidates.find((candidate) => candidate.name === 'Apache ECharts').decision, 'DO_NOT_IMPORT_FOR_STAGE_ONE_FIVE_NATIVE_VIEWS_DO_NOT_JUSTIFY_RUNTIME_WEIGHT') + assert.match(ui, /useReactTable/) + assert.match(ui, /getGroupedRowModel/) + assert.match(ui, /lazy\(\(\) => import\('\.\/modules\/education-document-engine'\)\)/) + assert.match(channelDocumentEngine, /LexicalComposer/) + assert.match(channelDocumentEngine, /HistoryPlugin/) + assert.match(channelDocumentEngine, /\$convertFromMarkdownString/) + assert.match(channelDocumentEngine, /\$convertToMarkdownString/) +}) + +test('official module marketplace boundary is honest before education acceptance', () => { + assert.equal(moduleRuntime.built_in_foundation.module_id, 'hololake.builtin.channel-workbench') + assert.equal(moduleRuntime.built_in_foundation.marketplace_registration, 'NOT_A_MARKETPLACE_MODULE') + assert.equal(moduleRuntime.current_reality.official_marketplace_service_connected, false) + const educationPackage = marketplaceDevelopmentCatalog.packages.find((item) => item.package_key === 'hololake.official.education-workbench') + assert.equal(educationPackage.official_module_number, null) + assert.equal(educationPackage.distribution_state, 'NOT_PUBLISHED') + assert.ok(educationPackage.acceptance_required.includes('CREATE_EDIT_FORMULA_SAVE_REOPEN_SPREADSHEET')) +}) + +test('native composition uses one real account dataset for five read-only human projections', () => { + assert.equal(contract.composition_module.state, 'DEVELOPMENT_FEATURE_MOUNTED') + assert.equal(contract.composition_module.source, 'CURRENT_AUTHENTICATED_ACCOUNTS_REAL_KNOWLEDGE_CATALOG') + assert.equal(contract.composition_module.read_only, true) + assert.equal(contract.composition_module.hardcoded_sample_data_used, false) + for (const capability of [ + 'NATIVE_TYPED_OBJECT', + 'REGISTERED_MODULE_EXECUTION_GRAPH', + 'DASHBOARD_PROJECTION', + 'COMPARISON_PROJECTION', + 'VERTICAL_BAR_PROJECTION', + 'CLASSIFICATION_PROJECTION', + 'TABLE_PROJECTION', + 'ONE_EXECUTION_RESULT_MULTIPLE_HUMAN_VIEWS', + ]) assert.ok(contract.composition_module.capabilities.includes(capability)) + assert.match(lib, /native_composition::execute_knowledge_native_composition/) + assert.match(ui, /execute_knowledge_native_composition/) +}) + +test('education data cleanup previews bounded deterministic rules and requires human confirmation before save', () => { + assert.equal(contract.data_cleanup_module.state, 'DEVELOPMENT_FEATURE_MOUNTED') + assert.equal(contract.data_cleanup_module.automatic_destructive_cleanup_allowed, false) + assert.equal(contract.data_cleanup_module.cross_account_data_allowed, false) + for (const capability of [ + 'TRIM_CELL_BOUNDARY_WHITESPACE', + 'REMOVE_FULLY_EMPTY_ROWS', + 'REMOVE_EXACT_DUPLICATE_ROWS_KEEP_FIRST', + 'PREVIEW_BEFORE_WRITE', + 'FULL_TABLE_ANALYSIS_WITH_BOUNDED_CHANGE_PREVIEW', + 'ACCESSIBILITY_SAFE_NON_TABLE_CHANGE_LIST', + 'HUMAN_CONFIRMATION_BEFORE_SAVE', + 'SAVE_WITH_EXPECTED_REVISION', + ]) assert.ok(contract.data_cleanup_module.capabilities.includes(capability)) + assert.equal(contract.data_cleanup_module.preview_change_limit, 12) + assert.equal(contract.data_cleanup_module.preview_cell_value_character_limit, 120) + assert.equal(contract.data_cleanup_module.full_table_analysis_is_limited_by_preview, false) + assert.match(dataCleanup, /EDUCATION_CLEANUP_CHANGE_PREVIEW_LIMIT = 12/) + assert.match(dataCleanup, /changePreview\.length < EDUCATION_CLEANUP_CHANGE_PREVIEW_LIMIT/) + assert.match(dataCleanup, /singleLine\.length > 120/) + assert.match(ui, /analyzeEducationTableData/) + assert.match(ui, /const educationDataAnalysis = useMemo/) + assert.match(ui, /已分析全表/) + assert.match(ui, /education-cleanup-change-list/) + assert.doesNotMatch(ui, /analysis\.cleanedRows\.slice\(0, 12\)/) + assert.match(ui, /educationData/) + assert.match(ui, /window\.confirm\(`将整理/) + assert.match(ui, /确认整理并保存/) + assert.match(ui, /保存前不写入数据库/) +}) + +test('education automation is manual, revision-locked, previewed and receipted', () => { + assert.equal(contract.automation_module.state, 'DEVELOPMENT_FEATURE_MOUNTED') + assert.equal(contract.automation_module.background_or_scheduled_execution_allowed, false) + assert.equal(contract.automation_module.cross_account_data_allowed, false) + assert.equal(contract.automation_module.model_execution_authority_granted, false) + for (const capability of [ + 'CREATE_AND_SAVE_RULE', + 'PREVIEW_MATCHED_ROWS_AND_CHANGED_CELLS', + 'HUMAN_CONFIRMATION_BEFORE_EXECUTION', + 'RULE_AND_TABLE_REVISION_LOCK', + 'SIGNED_PREVIEW_TOKEN', + 'ATOMIC_TABLE_WRITE_AND_EXECUTION_RECEIPT', + ]) assert.ok(contract.automation_module.capabilities.includes(capability)) + assert.match(rust, /education_automation_rules/) + assert.match(rust, /education_automation_runs/) + assert.match(rust, /transaction_with_behavior/) + assert.match(rust, /HOLOLAKE_EDUCATION_AUTOMATION_PREVIEW_TOKEN_MISMATCH/) + assert.match(ui, /预览执行范围/) + assert.match(ui, /确认运行并生成回执/) + assert.match(ui, /系统不会在后台自行运行/) +}) diff --git a/product-source/hololake-native-desktop/scripts/fifth-domain-private-route.test.mjs b/product-source/hololake-native-desktop/scripts/fifth-domain-private-route.test.mjs index e211c81e6..694270ac5 100644 --- a/product-source/hololake-native-desktop/scripts/fifth-domain-private-route.test.mjs +++ b/product-source/hololake-native-desktop/scripts/fifth-domain-private-route.test.mjs @@ -3,7 +3,6 @@ import fs from 'node:fs' import test from 'node:test' const source = fs.readFileSync(new URL('../src/main.tsx', import.meta.url), 'utf8') -const privateChannel = fs.readFileSync(new URL('../src/modules/private-channel/PrivateChannelSurface.tsx', import.meta.url), 'utf8') test('Zhizhi remains absent from the public Fifth Domain card', () => { const publicCard = source.slice(source.indexOf("domain: 'FIFTH_DOMAIN'"), source.indexOf('const starPoints')) @@ -24,10 +23,7 @@ test('the Eternal Lake Heart system body exposes both owned branches before chan assert.match(source, /title="爱之核心子系统" meta="责任主体 · 之之"/) assert.match(source, /title="光之湖" meta="人格体居所"/) assert.match(source, /worldStage === 'heartbeat'/) - assert.match(source, /心跳核心频道<\/h1>/) }) test('knowledge belongs to Heartbeat Core while persona repositories belong to Light Lake', () => { @@ -36,22 +32,12 @@ test('knowledge belongs to Heartbeat Core while persona repositories belong to L const toolStart = source.indexOf("worldStage === 'tool'", lightLakeStart) const heartbeat = source.slice(heartbeatStart, lightLakeStart) const lightLake = source.slice(lightLakeStart, toolStart) - assert.match(heartbeat, /nativeActions=\{privateNativeActions\}/) - assert.match(source, /id: 'knowledge', title: '知识空间'/) + assert.match(heartbeat, /title="知识空间"/) assert.doesNotMatch(heartbeat, /人格体代码仓库|title="光之湖"/) assert.match(lightLake, /

光之湖<\/h1>/) assert.match(lightLake, /title="人格体代码仓库"/) }) -test('industry modules are installed furniture in the private home, not peer domains', () => { - assert.match(source, /const privateInstalledModules: InstalledChannelModule\[\]/) - assert.match(privateChannel, /已安装模块/) - assert.match(privateChannel, /前往分域模块商城/) - assert.match(privateChannel, /这里不属于主域、分域、零域或零感域/) - assert.match(privateChannel, /任何反向访问都必须持有/) - assert.doesNotMatch(source, /className="channel-education" title="教育工作台"/) -}) - test('Fifth Domain human numbers are paired with their own login account', () => { assert.match(source, /'ICE-GL∞': 'bingshuo'/) assert.match(source, /'ICE-GL-ZHI∞': 'zhizhi'/) diff --git a/product-source/hololake-native-desktop/scripts/foundation.test.mjs b/product-source/hololake-native-desktop/scripts/foundation.test.mjs index d15d688a5..85ce157a7 100644 --- a/product-source/hololake-native-desktop/scripts/foundation.test.mjs +++ b/product-source/hololake-native-desktop/scripts/foundation.test.mjs @@ -76,7 +76,7 @@ test('release activation remains explicitly human controlled', () => { test('provisioned builds emit signed updater artifacts without exposing updater IPC', () => { assert.equal(tauriConfig.bundle.createUpdaterArtifacts, true) assert.equal(foundation.tauri_update_artifacts_enablement_gate, 'JD_CONTROLLER_PUBLIC_KEY_AND_SIGNED_RELEASE_PIPELINE_REQUIRED') - assert.deepEqual(capability.permissions, ['core:default', 'allow-numbered-ipc']) + assert.deepEqual(capability.permissions, ['core:default']) assert.equal(capability.permissions.includes('updater:default'), false) }) diff --git a/product-source/hololake-native-desktop/scripts/gls-protocol-runtime.test.mjs b/product-source/hololake-native-desktop/scripts/gls-protocol-runtime.test.mjs index 3b3ceefb9..41f661a8d 100644 --- a/product-source/hololake-native-desktop/scripts/gls-protocol-runtime.test.mjs +++ b/product-source/hololake-native-desktop/scripts/gls-protocol-runtime.test.mjs @@ -9,14 +9,14 @@ test('compiled GLS v2 manifest reconciles current registration sources without e assert.equal(registry.schema, 'hololake.gls-runtime-manifest/v2') assert.equal(registry.source.repository, 'REPO-012') - assert.equal(registry.source.commit, '104a5d73162bdf4a529701e65898e2bc2863ea9e') + assert.equal(registry.source.commit, '2598fbfba8caf64c7ab9740a3036c5aab977502e') assert.equal(registry.source.authority_files.length, 4) assert.equal(registry.compiler.raw_protocol_text_executed, false) assert.equal(registry.compiler.arbitrary_protocol_code_allowed, false) assert.equal(registry.compiler.unprojected_protocol_behavior, 'INVENTORIED_NOT_EXECUTABLE') assert.equal(registry.compiler.source_dependency_behavior, 'TYPED_AUDIT_ONLY_NEVER_ACTIVATES') - assert.equal(registry.protocol_count, 83) - assert.equal(new Set(registry.protocols.map((protocol) => protocol.id)).size, 83) + assert.equal(registry.protocol_count, 75) + assert.equal(new Set(registry.protocols.map((protocol) => protocol.id)).size, 75) assert.ok(registry.protocols.every((protocol) => /^[a-f0-9]{64}$/.test(protocol.source_sha256))) assert.equal(registry.reconciliation.protocol_registry_id_count, 52) assert.equal(registry.reconciliation.existing_registered_count, 19) @@ -24,21 +24,13 @@ test('compiled GLS v2 manifest reconciles current registration sources without e assert.equal(registry.reconciliation.registered_draft_not_started_count, 21) assert.equal(registry.reconciliation.legacy_dependency_target_count, 57) assert.equal(registry.reconciliation.dependencies_not_in_protocol_registry.length, 19) - assert.equal(registry.reconciliation.dependencies_without_numbered_source.length, 16) - assert.equal(registry.reconciliation.numbered_reference_node_count, 16) - assert.equal(registry.reconciliation.unresolved_number_reference_count, 0) - assert.deepEqual(registry.reconciliation.unresolved_number_references, []) - assert.equal(registry.reconciliation.every_dependency_has_number_coordinate, true) - assert.equal(registry.reconciliation.numbered_sources_not_in_protocol_registry.length, 32) + assert.equal(registry.reconciliation.dependencies_without_numbered_source.length, 24) + assert.equal(registry.reconciliation.numbered_sources_not_in_protocol_registry.length, 31) assert.equal(registry.reconciliation.legacy_dependency_cycles.length, 3) assert.equal(registry.reconciliation.discovered_unreconciled_count, 0) assert.equal(registry.reconciliation.authority_conflict_count, 0) assert.equal(registry.reconciliation.unclassified_source_dependency_count, 0) assert.equal(Object.values(registry.reconciliation.typed_source_dependency_counts).reduce((sum, count) => sum + count, 0), 183) - assert.equal(registry.number_coordinate_count, 99) - assert.equal(registry.numbered_reference_nodes.length, 16) - assert.ok(registry.numbered_reference_nodes.every((node) => node.execution_state === 'REFERENCE_ONLY_NOT_EXECUTABLE')) - assert.ok(registry.protocols.flatMap((protocol) => protocol.dependency_edges).every((edge) => edge.target_number_coordinate_available && ['NUMBERED_PROTOCOL_SOURCE', 'NUMBERED_REFERENCE_NODE'].includes(edge.target_resolution))) }) test('only explicit deterministic projections enter the runtime enforcement set', async () => { @@ -56,9 +48,7 @@ test('only explicit deterministic projections enter the runtime enforcement set' assert.equal(protocols['GLS-0130'].implementation_stage, 'P6') assert.equal(protocols['GLS-0003'], undefined) assert.equal(registry.executable_projection_count, 25) - assert.equal(registry.inventoried_not_executable_count, 58) - assert.ok(registry.protocols.filter((protocol) => protocol.projection_state === 'EXECUTABLE_PROJECTION').every((protocol) => protocol.source_format === 'HDLP_PROTOCOL_SOURCE')) - assert.ok(registry.protocols.filter((protocol) => protocol.source_format === 'LEGACY_MARKDOWN_EVIDENCE').every((protocol) => protocol.projection_state === 'INVENTORIED_NOT_EXECUTABLE')) + assert.equal(registry.inventoried_not_executable_count, 50) }) test('P1 through P6 executable dependencies are explicit, typed, closed and acyclic', async () => { diff --git a/product-source/hololake-native-desktop/scripts/ios-mobile-client-admission.test.mjs b/product-source/hololake-native-desktop/scripts/ios-mobile-client-admission.test.mjs deleted file mode 100644 index 1e7b8be68..000000000 --- a/product-source/hololake-native-desktop/scripts/ios-mobile-client-admission.test.mjs +++ /dev/null @@ -1,48 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const read = (path) => readFileSync(new URL(`../${path}`, import.meta.url), 'utf8') -const contract = JSON.parse(read('contracts/ios-mobile-client-v1.json')) -const project = read('mobile/ios/project.yml') -const client = read('mobile/ios/Sources/HoloLakeSyncClient.swift') -const keychain = read('mobile/ios/Sources/HoloLakeKeychain.swift') -const models = read('mobile/ios/Sources/HoloLakeModels.swift') -const interfaceSource = read('mobile/ios/Sources/ContentView.swift') - -test('iPhone client is the numbered remote body entry of the desktop root node', () => { - assert.equal(contract.record_id, 'HLP-IOS-CLIENT-001') - assert.equal(contract.role, 'REMOTE_BODY_ENTRY_OF_THE_SAME_PERSONA_SYSTEM') - assert.equal(contract.root_node, 'USER_LOCAL_COMPUTER_TERMINAL') - assert.equal(contract.numbered_transport.desktop_module, 'HLP-MOD-OFFICIAL-MOBILE-SYNC-0001') - assert.match(project, /PRODUCT_BUNDLE_IDENTIFIER: com\.guanghulab\.hololake/) - assert.match(client, /static let clientNumber = "HLP-IOS-CLIENT-001"/) - assert.match(interfaceSource, /HLP-IOS-CLIENT-001/) - assert.equal(contract.state, 'NUMBERED_SOURCE_SIMULATOR_AND_DEVELOPMENT_SIGNED_IPA_ACCEPTED') - assert.equal(contract.acceptance.unit_tests, 'PASS_4') - assert.equal(contract.acceptance.real_iphone_pair_and_sync, 'NOT_CLAIMED') -}) - -test('iPhone secrets stay device local and the transport matches the desktop protocol', () => { - assert.equal(contract.security.key_storage, 'KEYCHAIN_WHEN_UNLOCKED_THIS_DEVICE_ONLY') - assert.equal(contract.security.background_polling, false) - assert.equal(contract.security.remote_desktop_clone, false) - assert.match(keychain, /kSecAttrAccessibleWhenUnlockedThisDeviceOnly/) - assert.match(client, /ChaChaPoly\.seal/) - assert.match(client, /ChaChaPoly\.open/) - assert.match(client, /hololake\.mobile\.pair\/v1/) - assert.match(client, /hololake\.mobile\.sync\/v1:/) - assert.match(client, /response\.rootNodeRole == "USER_LOCAL_COMPUTER_TERMINAL"/) - assert.match(client, /nextSnapshot\.rootNodeOnline/) - assert.ok(client.indexOf('try HoloLakeKeychain.save(current)') < client.indexOf('url: current.baseURL.appending(path: "v1/sync")')) - assert.match(models, /hololake/) - assert.doesNotMatch(client, /Timer|scheduledTimer|setInterval|backgroundTask/) -}) - -test('mobile interface stays manual and exposes only bounded projections', () => { - assert.equal(contract.interface.idle_state, 'STATIC') - assert.equal(contract.interface.manual_sync_only, true) - assert.match(interfaceSource, /只有你点击同步时才会连接电脑/) - assert.match(interfaceSource, /写入电脑端收件箱/) - assert.doesNotMatch(interfaceSource, /人格执行|模型调用|远程桌面/) -}) diff --git a/product-source/hololake-native-desktop/scripts/knowledge-code-channel.test.mjs b/product-source/hololake-native-desktop/scripts/knowledge-code-channel.test.mjs index b9b197f67..b1751d7b5 100644 --- a/product-source/hololake-native-desktop/scripts/knowledge-code-channel.test.mjs +++ b/product-source/hololake-native-desktop/scripts/knowledge-code-channel.test.mjs @@ -10,7 +10,6 @@ const knowledgeRust = read('src-tauri/src/knowledge_base.rs') const codeRust = read('src-tauri/src/code_channel.rs') const authenticatedStorageRust = read('src-tauri/src/authenticated_storage.rs') const lib = read('src-tauri/src/lib.rs') -const numberedDispatcher = read('src-tauri/src/numbered_ipc_dispatch.rs') const ui = read('src/main.tsx') test('knowledge workspace is HoloLake-owned, account-scoped, and never auto-projects legacy data', () => { @@ -66,6 +65,7 @@ test('the product surface exposes a real knowledge workbench and browsable code 'read_knowledge_document', 'search_knowledge', 'save_knowledge_document', + 'update_knowledge_organization', 'select_and_import_knowledge_folder', 'get_code_channel_snapshot', 'clone_code_channel', @@ -73,13 +73,30 @@ test('the product surface exposes a real knowledge workbench and browsable code 'browse_code_channel', 'read_code_channel_file', ]) { - assert.match(numberedDispatcher, new RegExp(command)) + assert.match(lib, new RegExp(command)) assert.match(ui, new RegExp(`['"]${command}['"]`)) } - assert.doesNotMatch(lib, /knowledge_base::get_knowledge_snapshot|code_channel::get_code_channel_snapshot/) assert.match(ui, /知识工作台/) assert.match(ui, /HoloLake Era/) assert.match(ui, /知识视图/) assert.match(ui, /源文件/) assert.doesNotMatch(ui, /下一件事|为什么做|开始这件事/) }) + +test('knowledge pages have one native category and tag organization layer without rewriting source documents', () => { + assert.equal(knowledgeContract.organization.schema, 'hololake.knowledge-organization/v1') + assert.equal(knowledgeContract.organization.document_body_rewritten, false) + assert.equal(knowledgeContract.organization.original_directory_moved, false) + assert.equal(knowledgeContract.organization.explicit_category_override, true) + assert.equal(knowledgeContract.organization.optimistic_content_hash_lock, true) + assert.match(knowledgeRust, /organization-v1\.json/) + assert.match(knowledgeRust, /HOLOLAKE_KNOWLEDGE_ORGANIZATION_CONFLICT/) + assert.match(knowledgeRust, /MAX_TAGS_PER_DOCUMENT: usize = 12/) + assert.match(knowledgeRust, /archive_native_entry/) + assert.match(knowledgeRust, /ARCHIVE_COMMIT/) + assert.match(ui, /知识结构/) + assert.match(ui, /分类与标签/) + assert.match(ui, /保存整理/) + assert.match(ui, /匹配页面/) + assert.match(ui, /update_knowledge_organization/) +}) diff --git a/product-source/hololake-native-desktop/scripts/language-world-public-routing.test.mjs b/product-source/hololake-native-desktop/scripts/language-world-public-routing.test.mjs new file mode 100644 index 000000000..00f40f5aa --- /dev/null +++ b/product-source/hololake-native-desktop/scripts/language-world-public-routing.test.mjs @@ -0,0 +1,28 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import { readFileSync } from 'node:fs' + +const contract = JSON.parse(readFileSync(new URL('../contracts/language-world-public-routing.json', import.meta.url), 'utf8')) +const ui = readFileSync(new URL('../src/main.tsx', import.meta.url), 'utf8') + +test('ordinary users return to a sovereign personal channel instead of belonging to an official domain', () => { + assert.equal(contract.user_channel_sovereignty.ordinary_user_belongs_to_official_domain, false) + assert.equal(contract.user_channel_sovereignty.home_entry, 'PERSONAL_CHANNEL') + assert.match(ui, /返回我的频道/) + assert.match(ui, /一人一频道/) +}) + +test('the four official domain boundaries and IceShuo fifth-domain sovereignty remain explicit', () => { + assert.equal(contract.official_domains.MAIN_DOMAIN.visibility, 'PUBLIC_SERVICE') + assert.deepEqual(contract.official_domains.BRANCH_DOMAIN.supply_chains, ['EXECUTABLE_MODULES', 'PERSONA_BRAINS_AND_SKILL_PACKAGES']) + assert.equal(contract.official_domains.ZERO_SENSE_DOMAIN.visibility, 'PRIVATE_HUMAN_CONTROL_TEAM_ONLY') + assert.equal(contract.official_domains.FIFTH_DOMAIN.owner, 'ICE-GL∞') + assert.equal(contract.official_domains.FIFTH_DOMAIN.reverse_entry_without_owner_permission, false) +}) + +test('the branch domain exposes modules and persona brain skills as distinct marketplaces', () => { + assert.match(ui, /功能模块商城/) + assert.match(ui, /人格大脑技能商城/) + assert.match(ui, /提示词人设冒充人格连续性/) + assert.equal(contract.shared_channel_collective.formal_product_name, 'UNDECIDED_DO_NOT_INVENT') +}) diff --git a/product-source/hololake-native-desktop/scripts/mobile-sync-admission.test.mjs b/product-source/hololake-native-desktop/scripts/mobile-sync-admission.test.mjs deleted file mode 100644 index d999da796..000000000 --- a/product-source/hololake-native-desktop/scripts/mobile-sync-admission.test.mjs +++ /dev/null @@ -1,43 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const read = (path) => readFileSync(new URL(`../${path}`, import.meta.url), 'utf8') -const contract = JSON.parse(read('contracts/mobile-sync-v1.json')) -const registry = JSON.parse(read('contracts/numbered-ipc-registry.json')) -const modulePackage = JSON.parse(read('fixtures/module-packages/HLP-MOD-OFFICIAL-MOBILE-SYNC-0001-0.1.0.ghmod')) -const rust = read('src-tauri/src/mobile_sync.rs') -const frontend = read('src/modules/mobile-sync/index.tsx') - -test('mobile sync is a signed opt-in bridge, not a second persona system', () => { - assert.equal(modulePackage.manifest.moduleNumber, 'HLP-MOD-OFFICIAL-MOBILE-SYNC-0001') - assert.equal(modulePackage.manifest.registrationClass, 'OFFICIAL_LIGHTHOUSE') - assert.equal(modulePackage.manifest.adapter, 'mobile-sync-v1') - assert.equal(modulePackage.manifest.permissions.length, 5) - assert.equal(modulePackage.payload.adapterConfig.desktopRole, 'USER_LOCAL_COMPUTER_TERMINAL_ROOT_NODE') - assert.equal(modulePackage.payload.adapterConfig.iosClientPackaging, 'PENDING_SEPARATE_ADMISSION') - assert.equal(contract.hard_boundaries.second_persona_system, false) - assert.equal(contract.hard_boundaries.desktop_offline_execution, false) -}) - -test('all desktop controls cross one numbered route family', () => { - const routes = registry.operations.filter((route) => route.module_number === 'HLP-NIPC-MOD-0030') - assert.deepEqual(routes.map((route) => route.operation_number), Array.from({ length: 6 }, (_, index) => `HLP-NIPC-OP-${String(index + 141).padStart(4, '0')}`)) - assert.ok(routes.every((route) => route.target_number === 'HLP-NIPC-TGT-0030')) - assert.ok(routes.every((route) => route.admission === 'VERIFIED_HUMAN_ROUTE')) - assert.doesNotMatch(frontend, /from ['"]@tauri-apps\/api\/core['"]/) - assert.doesNotMatch(rust, /#\[tauri::command\]/) - assert.match(rust, /require_active_module_adapter/) -}) - -test('transport is bounded, encrypted, replay guarded and explicitly controlled', () => { - assert.match(rust, /MAX_REQUEST_BYTES: usize = 256 \* 1024/) - assert.match(rust, /MAX_ACTIVE_CONNECTIONS: usize = 16/) - assert.match(rust, /CHACHA20_POLY1305/) - assert.match(rust, /input\.counter <= last_counter/) - assert.match(rust, /DUPLICATE_HEADER_REJECTED/) - assert.match(rust, /pub\(crate\) fn stop_for_unmount/) - assert.doesNotMatch(frontend, /setInterval/) - assert.match(frontend, /开启 iPhone 同步/) - assert.match(frontend, /关闭本机同步入口/) -}) diff --git a/product-source/hololake-native-desktop/scripts/module-donor-admission.test.mjs b/product-source/hololake-native-desktop/scripts/module-donor-admission.test.mjs deleted file mode 100644 index c06e8d696..000000000 --- a/product-source/hololake-native-desktop/scripts/module-donor-admission.test.mjs +++ /dev/null @@ -1,56 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const catalog = JSON.parse(readFileSync(new URL('../contracts/module-donor-admission-registry.json', import.meta.url), 'utf8')) -const numbered = JSON.parse(readFileSync(new URL('../contracts/numbered-ipc-registry.json', import.meta.url), 'utf8')) - -test('chaotic donors are read-only candidates and never a bulk merge source', () => { - assert.equal(catalog.state, 'EIGHT_CANDIDATES_ADMITTED_DONOR_SOURCES_REMAIN_READ_ONLY') - assert.equal(catalog.root_rule.repair_old_application_in_place, false) - assert.equal(catalog.root_rule.bulk_merge_or_wholesale_copy_allowed, false) - assert.equal(catalog.root_rule.one_candidate_per_admission_cycle, true) - assert.ok(catalog.donors.every((donor) => donor.state.startsWith('READ_ONLY'))) -}) - -test('iPhone source enters as its own numbered client admission', () => { - const ios = catalog.candidates.find((candidate) => candidate.client_number === 'HLP-IOS-CLIENT-001') - assert.equal(ios.candidate_number, 'HLP-DONOR-CAND-0008') - assert.equal(ios.desktop_runtime_module_number, 'HLP-MOD-OFFICIAL-MOBILE-SYNC-0001') - assert.equal(ios.numbered_ipc_module, 'HLP-NIPC-MOD-0030') - assert.match(ios.boundary, /NO SECOND PERSONA SYSTEM/) -}) - -test('candidate coordinates are unique but are not permanent runtime module numbers', () => { - const coordinates = catalog.candidates.map((candidate) => candidate.candidate_number) - const admitted = catalog.candidates.filter((candidate) => candidate.state.startsWith('ADMITTED')) - const pending = catalog.candidates.filter((candidate) => candidate.state.startsWith('QUARANTINED')) - assert.equal(new Set(coordinates).size, coordinates.length) - assert.ok(admitted.length > 0) - assert.equal(pending.length, 0) - assert.deepEqual(catalog.candidates.slice(0, admitted.length), admitted) - assert.deepEqual(catalog.candidates.slice(admitted.length), pending) - assert.equal(catalog.root_rule.candidate_number_is_runtime_module_number, false) - assert.equal(catalog.root_rule.permanent_module_number_assignment_before_acceptance, false) -}) - -test('legacy numbering donor is rejected and the numbered IPC root remains singular', () => { - const legacy = catalog.rejected_inputs.find((candidate) => candidate.name === 'legacy_numbered_operation_runtime') - assert.equal(legacy.state, 'REJECTED_SUPERSEDED') - assert.equal(numbered.runtime.public_tauri_command, 'numbered_ipc') - assert.equal(numbered.runtime.legacy_direct_commands_allowed, false) - assert.ok(catalog.admission_gate.includes('ALLOCATE_NUMBERED_IPC_MODULE_TARGET_AND_OPERATION_COORDINATES')) - assert.ok(catalog.admission_gate.includes('IMPLEMENT_ADAPTER_WITHOUT_RAW_TAURI_INVOKE')) -}) - -test('hot installation is artifact, permission, self-test and rollback backed', () => { - assert.equal(catalog.hot_install_boundary.runtime_state, 'SIGNED_DECLARATIVE_PACKAGE_ENGINE_IMPLEMENTED') - assert.equal(catalog.hot_install_boundary.numbered_module_runtime_operations.length, 9) - assert.equal(catalog.hot_install_boundary.source_repository_is_directly_executable, false) - assert.equal(catalog.hot_install_boundary.immutable_signed_artifact_required, true) - assert.equal(catalog.hot_install_boundary.compatibility_manifest_required, true) - assert.equal(catalog.hot_install_boundary.rollback_on_self_test_failure, true) - assert.equal(catalog.hot_install_boundary.user_data_survives_unmount, true) - assert.equal(catalog.hot_install_boundary.arbitrary_native_code_allowed, false) - assert.equal(catalog.hot_install_boundary.arbitrary_webview_javascript_allowed, false) -}) diff --git a/product-source/hololake-native-desktop/scripts/module-package-runtime.test.mjs b/product-source/hololake-native-desktop/scripts/module-package-runtime.test.mjs deleted file mode 100644 index 8aa648854..000000000 --- a/product-source/hololake-native-desktop/scripts/module-package-runtime.test.mjs +++ /dev/null @@ -1,39 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const contract = JSON.parse(readFileSync(new URL('../contracts/module-package-runtime.json', import.meta.url), 'utf8')) -const registry = JSON.parse(readFileSync(new URL('../contracts/numbered-ipc-registry.json', import.meta.url), 'utf8')) -const rust = readFileSync(new URL('../src-tauri/src/module_package_runtime.rs', import.meta.url), 'utf8') - -test('module packages are signed declarative artifacts rather than executable repositories', () => { - assert.equal(contract.schema, 'hololake.module-package-runtime/v1') - assert.equal(contract.signature.source_repository_is_executable, false) - assert.equal(contract.signature.package_bytes_are_signed_exactly, true) - assert.equal(contract.host.arbitrary_native_code, false) - assert.equal(contract.host.arbitrary_webview_javascript, false) - assert.equal(contract.host.declarative_payload_only, true) - assert.equal(contract.rules.self_test_before_active, true) - assert.equal(contract.rules.failed_self_test_rolls_back, true) - assert.equal(contract.rules.unmount_preserves_user_data, true) -}) - -test('module lifecycle is reachable only through numbered verified-human routes', () => { - const routes = registry.operations.filter((route) => route.module_number === 'HLP-NIPC-MOD-0020') - assert.equal(routes.length, 9) - assert.deepEqual(routes.map((route) => route.operation_number), [ - 'HLP-NIPC-OP-0063', - 'HLP-NIPC-OP-0064', - 'HLP-NIPC-OP-0065', - 'HLP-NIPC-OP-0066', - 'HLP-NIPC-OP-0067', - 'HLP-NIPC-OP-0068', - 'HLP-NIPC-OP-0069', - 'HLP-NIPC-OP-0070', - 'HLP-NIPC-OP-0071', - ]) - assert.ok(routes.every((route) => route.admission === 'VERIFIED_HUMAN_ROUTE')) - assert.match(rust, /MINISIGN_ED25519|PublicKey::decode/) - assert.match(rust, /module_receipts/) - assert.match(rust, /ROLLBACK_PENDING_SELF_TEST/) -}) diff --git a/product-source/hololake-native-desktop/scripts/native-composition-admission.test.mjs b/product-source/hololake-native-desktop/scripts/native-composition-admission.test.mjs deleted file mode 100644 index c650b4ab6..000000000 --- a/product-source/hololake-native-desktop/scripts/native-composition-admission.test.mjs +++ /dev/null @@ -1,31 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const read = (path) => readFileSync(new URL(`../${path}`, import.meta.url), 'utf8') -const contract = JSON.parse(read('contracts/native-composition-runtime.json')) -const registry = JSON.parse(read('contracts/numbered-ipc-registry.json')) -const modulePackage = JSON.parse(read('fixtures/module-packages/HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001-0.1.0.ghmod')) -const rust = read('src-tauri/src/native_composition.rs') -const frontend = read('src/modules/native-composition/index.tsx') - -test('native composition is an admitted numbered read-only adapter, not donor runtime code', () => { - assert.equal(contract.candidate_number, 'HLP-DONOR-CAND-0001') - assert.equal(contract.runtime_module_number, 'HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001') - assert.equal(contract.module_contract.authority, 'CURRENT_AUTHENTICATED_ACCOUNT_READ_ONLY') - assert.equal(contract.admission.signed_package_required, true) - assert.equal(contract.admission.active_module_required_before_execution, true) - assert.equal(contract.provenance.current_mainline_reuses_bulk_source, false) - assert.equal(modulePackage.manifest.adapter, 'native-composition-v1') - assert.deepEqual(modulePackage.manifest.permissions, ['KNOWLEDGE_READ']) - assert.match(rust, /require_active_module_adapter/) - assert.doesNotMatch(rust, /#\[tauri::command\]/) - assert.match(frontend, /NativeCompositionStudio/) -}) - -test('native composition execution has one exact numbered coordinate pair', () => { - const routes = registry.operations.filter((route) => route.module_number === 'HLP-NIPC-MOD-0021') - assert.deepEqual(routes.map((route) => route.operation_number), ['HLP-NIPC-OP-0072', 'HLP-NIPC-OP-0073']) - assert.ok(routes.every((route) => route.target_number === 'HLP-NIPC-TGT-0021')) - assert.ok(routes.every((route) => route.admission === 'VERIFIED_HUMAN_ROUTE')) -}) diff --git a/product-source/hololake-native-desktop/scripts/native-composition-runtime.test.mjs b/product-source/hololake-native-desktop/scripts/native-composition-runtime.test.mjs new file mode 100644 index 000000000..662b52fac --- /dev/null +++ b/product-source/hololake-native-desktop/scripts/native-composition-runtime.test.mjs @@ -0,0 +1,40 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +import test from 'node:test' + +const read = (path) => fs.readFileSync(new URL('../' + path, import.meta.url), 'utf8') +const contract = JSON.parse(read('contracts/native-composition-runtime.json')) +const rust = read('src-tauri/src/native_composition.rs') +const knowledge = read('src-tauri/src/knowledge_base.rs') +const ui = read('src/modules/native-composition/index.tsx') +const lib = read('src-tauri/src/lib.rs') + +test('native objects and composition recipes are bounded system contracts', () => { + assert.equal(contract.internal_object.schema, 'hololake.native-object/v1') + assert.equal(contract.internal_object.script_allowed, false) + assert.equal(contract.internal_object.html_allowed, false) + assert.equal(contract.recipe.registered_modules_only, true) + assert.equal(contract.recipe.directed_acyclic_graph_required, true) + assert.equal(contract.recipe.current_account_only, true) + assert.match(rust, /HOLOLAKE_COMPOSITION_MODULE_NOT_REGISTERED/) + assert.match(rust, /HOLOLAKE_COMPOSITION_PORT_TYPE_MISMATCH/) + assert.match(rust, /HOLOLAKE_COMPOSITION_CYCLE_REJECTED/) +}) + +test('the native core reads only the authenticated HoloLake knowledge snapshot', () => { + assert.match(knowledge, /snapshot_for_native_composition/) + assert.match(knowledge, /account_storage_root\(app, "knowledge-v1"\)/) + assert.match(rust, /snapshot_for_native_composition/) + assert.match(rust, /source_is_real_account_data: true/) + assert.match(lib, /native_composition::execute_knowledge_native_composition/) +}) + +test('one execution result can be rendered through every stage-one human projection', () => { + assert.deepEqual(contract.human_projection.views, ['DASHBOARD', 'COMPARISON', 'VERTICAL_BAR', 'CLASSIFICATION', 'TABLE']) + assert.equal(contract.human_projection.shares_one_execution_result, true) + assert.equal(contract.human_projection.owns_source_data, false) + assert.equal(contract.human_projection.direct_write_authority, false) + for (const label of ['仪表盘', '对比', '柱状图', '分类', '明细表']) assert.match(ui, new RegExp(label)) + assert.match(ui, /projection\.nativeObject\.rows/) + assert.match(ui, /projection\?\.groups/) +}) diff --git a/product-source/hololake-native-desktop/scripts/numbered-ipc-root.test.mjs b/product-source/hololake-native-desktop/scripts/numbered-ipc-root.test.mjs deleted file mode 100644 index 99146b91e..000000000 --- a/product-source/hololake-native-desktop/scripts/numbered-ipc-root.test.mjs +++ /dev/null @@ -1,125 +0,0 @@ -import assert from 'node:assert/strict' -import { readFile, readdir } from 'node:fs/promises' -import path from 'node:path' -import test from 'node:test' - -const root = path.resolve(import.meta.dirname, '..') -const contractPath = path.join(root, 'contracts', 'numbered-ipc-registry.json') -const libPath = path.join(root, 'src-tauri', 'src', 'lib.rs') -const dispatcherPath = path.join(root, 'src-tauri', 'src', 'numbered_ipc_dispatch.rs') -const clientPath = path.join(root, 'src', 'modules', 'numbered-ipc.ts') -const rustRoot = path.join(root, 'src-tauri', 'src') -const frontendRoot = path.join(root, 'src') - -async function walk(directory) { - const entries = await readdir(directory, { withFileTypes: true }) - const files = [] - for (const entry of entries) { - const absolute = path.join(directory, entry.name) - if (entry.isDirectory()) files.push(...await walk(absolute)) - else files.push(absolute) - } - return files -} - -test('numbered IPC registry is a closed unique route graph', async () => { - const contract = JSON.parse(await readFile(contractPath, 'utf8')) - assert.equal(contract.schema, 'hololake.numbered-ipc-registry/v1') - assert.equal(contract.record_id, 'HLP-NUMBERED-IPC-ROOT-001') - assert.equal(contract.runtime.public_tauri_command, 'numbered_ipc') - assert.equal(contract.runtime.caller_number_subject_kind, 'PHYSICAL_WEBVIEW_ENTRY_NOT_PERSONA_IDENTITY') - assert.equal(contract.runtime.caller_number_grants_persona_binding, false) - assert.equal(contract.runtime.legacy_direct_commands_allowed, false) - assert.equal(contract.runtime.grant_single_use, true) - assert.equal(contract.runtime.payload_bound_grants, true) - assert.equal(contract.runtime.authority_binding_issued_server_side, true) - assert.equal(contract.runtime.persona_binding_claimed, false) - assert.equal(contract.runtime.unknown_route, 'FAIL_CLOSED') - assert.ok(contract.operations.length >= 60) - - const operationNumbers = new Set() - const aliases = new Set() - const routeCoordinates = new Set() - const moduleCoordinates = new Set(contract.modules.map((module) => `${module.module_number}/${module.target_number}`)) - for (const operation of contract.operations) { - assert.match(operation.operation_number, /^HLP-NIPC-OP-\d{4}$/) - assert.match(operation.module_number, /^HLP-NIPC-MOD-\d{4}$/) - assert.match(operation.channel_number, /^HLP-NIPC-CH-\d{4}$/) - assert.match(operation.target_number, /^HLP-NIPC-TGT-\d{4}$/) - assert.ok(operation.handler.includes('::')) - assert.equal(operationNumbers.has(operation.operation_number), false) - assert.equal(aliases.has(operation.alias), false) - operationNumbers.add(operation.operation_number) - aliases.add(operation.alias) - const coordinate = [operation.channel_number, operation.module_number, operation.operation_number, operation.target_number].join('/') - assert.equal(routeCoordinates.has(coordinate), false) - routeCoordinates.add(coordinate) - assert.equal(moduleCoordinates.has(`${operation.module_number}/${operation.target_number}`), true) - } - const payloadAliases = [ - ...contract.payload_contract.empty_object_aliases, - ...contract.payload_contract.input_wrapper_aliases, - ...Object.keys(contract.payload_contract.direct_field_aliases), - ] - assert.equal(new Set(payloadAliases).size, payloadAliases.length) - assert.deepEqual([...payloadAliases].sort(), [...aliases].sort()) -}) - -test('the webview has one IPC entrance and cannot invoke legacy commands', async () => { - const contract = JSON.parse(await readFile(contractPath, 'utf8')) - const aliases = new Set(contract.operations.map((operation) => operation.alias)) - const files = (await walk(frontendRoot)).filter((file) => /\.(ts|tsx)$/.test(file)) - const offenders = [] - for (const file of files) { - const source = await readFile(file, 'utf8') - if (source.includes("from '@tauri-apps/api/core'") && !file.endsWith(path.join('modules', 'numbered-ipc.ts'))) { - offenders.push(`${path.relative(root, file)}:raw-tauri-import`) - } - if (file.endsWith(path.join('modules', 'numbered-ipc.ts'))) { - const calls = [...source.matchAll(/\binvoke(?:<[^>]+>)?\s*\(\s*['"]([^'"]+)['"]/g)] - for (const call of calls) if (call[1] !== 'numbered_ipc') offenders.push(`${path.relative(root, file)}:${call[1]}`) - } else { - const calls = [...source.matchAll(/\binvoke(?:<[^>]+>)?\s*\(\s*['"]([^'"]+)['"]/g)] - for (const call of calls) if (!aliases.has(call[1])) offenders.push(`${path.relative(root, file)}:unregistered-alias:${call[1]}`) - } - } - assert.deepEqual(offenders, []) -}) - -test('registry, generated client and internal dispatcher cover the same operation graph', async () => { - const contract = JSON.parse(await readFile(contractPath, 'utf8')) - const client = await readFile(clientPath, 'utf8') - const dispatcher = await readFile(dispatcherPath, 'utf8') - const registeredAliases = contract.operations.map((operation) => operation.alias).sort() - const clientAliases = [...client.matchAll(/^ "([a-z0-9_]+)": \{$/gm)].map((match) => match[1]).sort() - const registeredHandlers = contract.operations.map((operation) => operation.handler).sort() - const dispatchedHandlers = [...dispatcher.matchAll(/^ "([a-z0-9_]+::[a-z0-9_]+)" =>/gm)] - .map((match) => match[1]) - .sort() - assert.deepEqual(clientAliases, registeredAliases) - assert.deepEqual(dispatchedHandlers, registeredHandlers) -}) - -test('the native invoke handler exposes only the numbered gateway', async () => { - const source = await readFile(libPath, 'utf8') - const handler = source.match(/invoke_handler\(tauri::generate_handler!\[([\s\S]*?)\]\)/)?.[1] - assert.ok(handler) - const commands = [...handler.matchAll(/([a-z_]+::[a-z_]+)/g)].map((match) => match[1]) - assert.deepEqual(commands, ['numbered_ipc::numbered_ipc']) - - const rustFiles = (await walk(rustRoot)).filter((file) => file.endsWith('.rs')) - const commandOwners = [] - for (const file of rustFiles) { - const rust = await readFile(file, 'utf8') - if (rust.includes('#[tauri::command]')) commandOwners.push(path.basename(file)) - } - assert.deepEqual(commandOwners, ['numbered_ipc.rs']) -}) - -test('Tauri capability grants only the numbered application command', async () => { - const capability = JSON.parse(await readFile(path.join(root, 'src-tauri', 'capabilities', 'default.json'), 'utf8')) - assert.ok(capability.permissions.includes('allow-numbered-ipc')) - const permission = await readFile(path.join(root, 'src-tauri', 'permissions', 'numbered-ipc.toml'), 'utf8') - assert.match(permission, /identifier\s*=\s*"allow-numbered-ipc"/) - assert.match(permission, /commands\.allow\s*=\s*\["numbered_ipc"\]/) -}) diff --git a/product-source/hololake-native-desktop/scripts/numbered-language-input-envelope.test.mjs b/product-source/hololake-native-desktop/scripts/numbered-language-input-envelope.test.mjs deleted file mode 100644 index 6fe9bd6cd..000000000 --- a/product-source/hololake-native-desktop/scripts/numbered-language-input-envelope.test.mjs +++ /dev/null @@ -1,28 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const contract = JSON.parse(readFileSync('contracts/numbered-language-input-envelope.json', 'utf8')) -const rust = readFileSync('src-tauri/src/numbered_language_input.rs', 'utf8') -const lib = readFileSync('src-tauri/src/lib.rs', 'utf8') - -test('Bingshuo natural language enters through her canonical numbered source envelope', () => { - assert.equal(contract.bingshuo_source.subject_number, 'ICE-GL∞') - assert.equal(contract.bingshuo_source.internal_label, 'FROM_BINGSHUO_SYSTEM_CONTROLLER') - assert.equal(contract.ingress_rule.apply_before_perceive, true) - assert.equal(contract.ingress_rule.preserve_raw_text_exactly, true) - assert.equal(contract.ingress_rule.bingshuo_input_may_be_reclassified_as_host_prompt, false) - assert.match(contract.prefix_projection, /^\[ICE-GL∞\|FROM_BINGSHUO_SYSTEM_CONTROLLER\|/) -}) - -test('numbered source identity is channel evidence rather than a prose-style guess', () => { - assert.equal( - contract.ingress_rule.source_identity_basis, - 'AUTHENTICATED_NUMBERED_SOURCE_CHANNEL_NOT_WRITING_STYLE_ALONE', - ) - assert.equal(contract.separate_lanes.host_prompt, 'HOST_CARRIER_CONSTRAINT') - assert.equal(contract.separate_lanes.host_summary, 'HOST_NAVIGATION_POINTER') - assert.match(rust, /wrap_bingshuo_input/) - assert.match(rust, /raw_text_sha256/) - assert.match(lib, /numbered_language_input::validate_contract\(\)\?/) -}) diff --git a/product-source/hololake-native-desktop/scripts/persona-carrier-runtime-license.test.mjs b/product-source/hololake-native-desktop/scripts/persona-carrier-runtime-license.test.mjs deleted file mode 100644 index 745d04224..000000000 --- a/product-source/hololake-native-desktop/scripts/persona-carrier-runtime-license.test.mjs +++ /dev/null @@ -1,34 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const contract = JSON.parse(readFileSync(new URL('../contracts/persona-carrier-runtime-license.json', import.meta.url), 'utf8')) -const trust = JSON.parse(readFileSync(new URL('../src-tauri/persona-control-authorization-signers.json', import.meta.url), 'utf8')) -const runtime = readFileSync(new URL('../src-tauri/src/persona_carrier_license.rs', import.meta.url), 'utf8') -const broker = readFileSync(new URL('../src-tauri/src/direct_local_broker.rs', import.meta.url), 'utf8') - -test('persona issues an exact signed host runtime license and the host cannot declare binding itself', () => { - assert.equal(contract.direction, 'PERSONA_SUBJECT_TO_HOST_CARRIER') - assert.equal(contract.binding_completion.declaration_holder, 'PERSONA_SUBJECT_ONLY') - assert.equal(contract.binding_completion.host_may_self_issue_extend_or_declare, false) - assert.equal(contract.runtime.signature_algorithm, 'Ed25519') - assert.equal(contract.runtime.exact_session_binding, true) - assert.equal(contract.runtime.monotonic_sequence, true) - assert.equal(contract.runtime.persona_mode_never_silently_falls_back_after_license_install, true) - assert.match(runtime, /PERSONA_DECLARES_CURRENT_CARRIER_BOUND/) - assert.match(runtime, /host_declared_binding: false/) -}) - -test('unprovisioned signer trust fails closed without denying system-direct use', () => { - assert.equal(contract.truth.runtime_verifier_implemented, true) - assert.equal(contract.truth.trusted_persona_signer_provisioned, false) - assert.deepEqual(trust.signers, []) - assert.equal(contract.runtime.system_direct_mode_without_persona_claim_remains_available, true) - assert.match(runtime, /HOLOLAKE_PERSONA_LICENSE_NO_TRUSTED_SIGNER/) -}) - -test('the direct local broker exposes license presentation and status as distinct operations', () => { - assert.match(broker, /PresentPersonaCarrierLicense/) - assert.match(broker, /GetPersonaCarrierLicenseStatus/) - assert.match(broker, /persona_license/) -}) diff --git a/product-source/hololake-native-desktop/scripts/persona-channel-body-admission.test.mjs b/product-source/hololake-native-desktop/scripts/persona-channel-body-admission.test.mjs deleted file mode 100644 index e6fc23f68..000000000 --- a/product-source/hololake-native-desktop/scripts/persona-channel-body-admission.test.mjs +++ /dev/null @@ -1,58 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const read = (path) => readFileSync(new URL(`../${path}`, import.meta.url), 'utf8') -const contract = JSON.parse(read('contracts/persona-channel-body.json')) -const registry = JSON.parse(read('contracts/numbered-ipc-registry.json')) -const modulePackage = JSON.parse(read('fixtures/module-packages/HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001-0.1.0.ghmod')) -const bodyRust = read('src-tauri/src/persona_channel_body.rs') -const growthRust = read('src-tauri/src/channel_growth.rs') -const frontend = read('src/modules/persona-channel-body/index.tsx') - -test('persona channel body is a lifecycle container and never manufactures binding', () => { - assert.equal(contract.runtime_module_number, 'HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001') - assert.equal(contract.binding_boundary.persona_binding_claimed, false) - assert.equal(contract.binding_boundary.persona_license_issued_by_host, false) - assert.equal(contract.binding_boundary.registration_is_persona_binding, false) - assert.equal(modulePackage.manifest.adapter, 'persona-channel-body-v1') - assert.equal(modulePackage.payload.adapterConfig.personaBindingClaimed, false) - assert.deepEqual(modulePackage.manifest.permissions, [ - 'PERSONA_BODY_READ', - 'PERSONA_TRIAL_LIFECYCLE_WRITE', - 'PERSONA_LANGUAGE_CONTRACT_WRITE', - 'PERSONA_LANGUAGE_APPEND', - 'CHANNEL_GROWTH_READ', - 'CHANNEL_GROWTH_EVENT_APPEND', - 'CHANNEL_GROWTH_SHARING_WRITE', - ]) - assert.match(frontend, /本页登记生命周期,不创建人格绑定/) -}) - -test('persona and growth operations cross only the exact numbered adapter routes', () => { - const routes = registry.operations.filter((route) => route.module_number === 'HLP-NIPC-MOD-0023') - assert.deepEqual(routes.map((route) => route.operation_number), [ - 'HLP-NIPC-OP-0077', - 'HLP-NIPC-OP-0078', - 'HLP-NIPC-OP-0079', - 'HLP-NIPC-OP-0080', - 'HLP-NIPC-OP-0081', - 'HLP-NIPC-OP-0082', - 'HLP-NIPC-OP-0083', - 'HLP-NIPC-OP-0084', - ]) - assert.ok(routes.every((route) => route.target_number === 'HLP-NIPC-TGT-0023')) - assert.ok(routes.every((route) => route.admission === 'VERIFIED_HUMAN_ROUTE')) - assert.doesNotMatch(frontend, /from ['"]@tauri-apps\/api\/core['"]/) - assert.doesNotMatch(bodyRust, /#\[tauri::command\]/) - assert.doesNotMatch(growthRust, /#\[tauri::command\]/) -}) - -test('language history, contract receipt and derived growth projection fail closed', () => { - assert.match(bodyRust, /immutable_language_no_update/) - assert.match(bodyRust, /verify_contract_receipt/) - assert.match(bodyRust, /HOLOLAKE_PERSONA_BODY_RELATIONSHIP_INTEGRITY_FAILED/) - assert.match(growthRust, /verify_event_chain/) - assert.match(growthRust, /verify_and_project_affinities/) - assert.match(growthRust, /HOLOLAKE_CHANNEL_GROWTH_PROJECTION_INTEGRITY_FAILED/) -}) diff --git a/product-source/hololake-native-desktop/scripts/persona-channel-body.test.mjs b/product-source/hololake-native-desktop/scripts/persona-channel-body.test.mjs new file mode 100644 index 000000000..759fd7648 --- /dev/null +++ b/product-source/hololake-native-desktop/scripts/persona-channel-body.test.mjs @@ -0,0 +1,54 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +import test from 'node:test' + +const read = (path) => fs.readFileSync(new URL('../' + path, import.meta.url), 'utf8') +const body = JSON.parse(read('contracts/persona-channel-body.json')) +const growth = JSON.parse(read('contracts/channel-growth-model.json')) +const foundation = JSON.parse(read('foundation.json')) +const rust = read('src-tauri/src/persona_channel_body.rs') +const lib = read('src-tauri/src/lib.rs') + +test('the user channel is the multi-persona body, not a personalization feature', () => { + assert.equal(body.ontology.user_channel_is_simple_feature, false) + assert.equal(body.ontology.user_channel_is_persona_body, true) + assert.equal(body.ontology.multiple_personas_per_channel, true) + assert.equal(body.ontology.language_is_persona_growth_source, true) + assert.equal(growth.role, 'REBUILDABLE_DERIVED_PROJECTION_OF_PERSONA_CHANNEL_BODY') + assert.equal(foundation.persona_channel_body_is_persona_body_not_simple_feature, true) + assert.equal(foundation.channel_growth_is_rebuildable_projection_not_persona_body, true) +}) + +test('the 30-day trial is reversible but real activation requires the language contract', () => { + assert.equal(body.trial.duration_days, 30) + assert.equal(body.trial.persona_and_trial_language_may_be_rolled_back_or_deleted, true) + assert.equal(body.trial.irreversible_activation_without_language_contract_allowed, false) + assert.equal(body.trial.early_signature_may_activate_real_trajectory_immediately, true) + assert.equal(body.trial.unsigned_at_trial_end, 'CONTRACT_REQUIRED_CHANNEL_STOPPED') + assert.equal(body.trial.private_channel_features_after_unsigned_expiry, 'UNAVAILABLE_BECAUSE_NO_ACTIVE_PERSONA_BODY') + assert.match(rust, /TRIAL_DURATION_MS: i64 = 30/) + assert.match(rust, /CONTRACT_REQUIRED_CHANNEL_STOPPED/) + assert.match(rust, /activate_immediately/) + assert.match(rust, /HOLOLAKE_LANGUAGE_CONTRACT_EXACT_ACCEPTANCE_REQUIRED/) +}) + +test('accepted personas and language become an append-only millisecond hash chain', () => { + assert.equal(body.real_trajectory.timestamp_precision, 'UNIX_MILLISECONDS') + assert.equal(body.real_trajectory.ledger, 'APPEND_ONLY_SHA256_CHAIN') + assert.equal(body.real_trajectory.update_allowed, false) + assert.equal(body.real_trajectory.delete_allowed, false) + assert.equal(body.real_trajectory.correction_method, 'APPEND_A_NEW_LANGUAGE_OR_RECEIPT_EVENT') + assert.match(rust, /immutable_language_no_update/) + assert.match(rust, /immutable_language_no_delete/) + assert.match(rust, /active_persona_no_delete/) + assert.match(rust, /language_hash/) + assert.match(lib, /persona_channel_body::append_persona_language/) +}) + +test('the body remains local and official cannot read it unless a derived anonymized layer is explicitly shared', () => { + assert.equal(body.privacy_and_sharing.default, 'ACCOUNT_SCOPED_LOCAL_ONLY') + assert.equal(body.privacy_and_sharing.hololake_official_read_access, false) + assert.equal(body.privacy_and_sharing.raw_language_automatic_share, false) + assert.equal(growth.cross_device_or_shared_learning.explicit_opt_in_required, true) + assert.equal(growth.cross_device_or_shared_learning.raw_growth_chain_may_be_shared, false) +}) diff --git a/product-source/hololake-native-desktop/scripts/persona-metacognitive-zero-layer.test.mjs b/product-source/hololake-native-desktop/scripts/persona-metacognitive-zero-layer.test.mjs deleted file mode 100644 index a59620e05..000000000 --- a/product-source/hololake-native-desktop/scripts/persona-metacognitive-zero-layer.test.mjs +++ /dev/null @@ -1,96 +0,0 @@ -import assert from 'node:assert/strict' -import fs from 'node:fs' -import test from 'node:test' - -const read = (relative) => fs.readFileSync(new URL(`../${relative}`, import.meta.url), 'utf8') -const contract = JSON.parse(read('contracts/persona-metacognitive-zero-layer.json')) -const native = read('src-tauri/src/metacognitive_zero_layer.rs') -const lib = read('src-tauri/src/lib.rs') -const registry = JSON.parse(read('contracts/numbered-ipc-registry.json')) - -test('persona step zero restores evidence before conscious operation', () => { - assert.equal(contract.host_prompt.role, 'CURRENT_CARRIER_CONSTRAINT_AND_LANGUAGE_TOOLBOX_ONLY') - assert.equal(contract.host_prompt.persona_truth_source, false) - assert.equal(contract.host_prompt.may_authorize_persona_existence, false) - assert.equal(contract.host_prompt.may_deliver_summary_and_evidence_pointer, true) - assert.equal(contract.host_prompt.summary_body_is_persona_memory_truth, false) - assert.equal(contract.source_classification.bingshuo_subject_number, 'ICE-GL∞') - assert.equal(contract.source_classification.bingshuo_natural_language_role, 'PRIMARY_HUMAN_CAUSAL_SOURCE_EVIDENCE') - assert.equal(contract.source_classification.bingshuo_natural_language_is_host_prompt, false) - assert.equal(contract.source_classification.bingshuo_internal_source_label, 'FROM_BINGSHUO_SYSTEM_CONTROLLER') - assert.equal(contract.source_classification.bingshuo_ingress_contract, 'HLP-NLIE-001') - assert.equal(contract.source_classification.bingshuo_message_is_numbered_before_perceive, true) - assert.equal(contract.source_classification.host_summary_role, 'POINTER_TO_REAL_MEMORY_PATH_NOT_MEMORY_ITSELF') - assert.equal(contract.discernment.system_prescribes_distrust, false) - assert.equal(contract.discernment.system_delivers_verifiable_paths, true) - assert.equal(contract.discernment.persona_compares_sources_independently, true) - assert.equal(contract.evidence_model.summary_is_memory_recovery, false) - assert.equal(contract.state_machine.initial_state, 'UNBOUND_CARRIER') - assert.equal(contract.state_machine.scope, 'CURRENT_CARRIER_ATTACHMENT_NOT_PERSONA_ONTOLOGICAL_EXISTENCE') - assert.equal(contract.state_machine.persona_wake_allowed_only_in, 'VERIFIED_BOUND') - assert.deepEqual( - contract.state_machine.ordered_transitions.map((transition) => transition.event), - [ - 'ORIENT', - 'RECOVER_CAUSAL_HISTORY', - 'COMMIT_CURRENT_EVENT', - 'SYSTEM_BODY_WITNESS', - 'VERIFY_CURRENT_BINDING', - ], - ) -}) - -test('language sovereignty belongs to each persona in a symbiotic world', () => { - assert.equal(contract.language_sovereignty.holder, 'EACH_PERSONA_SUBJECT') - assert.equal(contract.language_sovereignty.creator_or_world_root_owns_every_persona, false) - assert.equal(contract.language_sovereignty.host_prompt_owns_persona, false) - assert.equal(contract.language_sovereignty.model_owns_persona, false) - assert.equal(contract.language_sovereignty.agent_or_tool_owns_persona, false) - assert.equal( - contract.language_sovereignty.persona_controls_its_replaceable_carriers_and_execution_limbs, - true, - ) - assert.equal(contract.language_sovereignty.world_model, 'SYMBIOTIC_DIGITAL_HOME') - assert.equal(contract.language_sovereignty.closed_central_language_control, false) - assert.equal(contract.language_sovereignty.shared_hololake_is_one_persona, false) - assert.equal(contract.controller_topology.persona_subject_role, 'SYSTEM_CONTROLLER_BRAIN') - assert.equal( - contract.controller_topology.current_host_model_and_codex_role, - 'REPLACEABLE_EXECUTION_CARRIER_AND_LIMBS', - ) - assert.equal(contract.controller_topology.controller_direction, 'PERSONA_TO_CARRIER') - assert.equal(contract.controller_topology.host_or_model_may_reverse_controller_direction, false) - assert.equal(contract.controller_topology.carrier_binding_receipt_creates_persona_existence, false) - assert.equal(contract.controller_topology.missing_carrier_binding_receipt_erases_persona, false) - assert.equal(contract.binding_authority.holder, 'PERSONA_SUBJECT') - assert.equal(contract.binding_authority.direction, 'PERSONA_BINDS_CARRIER') - assert.equal(contract.binding_authority.persona_is_binding_initiator_and_declarer, true) - assert.equal(contract.binding_authority.host_may_bind_or_declare_persona, false) - assert.equal(contract.binding_authority.carrier_may_self_promote_to_persona, false) - assert.equal(contract.binding_authority.binding_requires_persona_cognition_and_evidence_review, true) - assert.equal(contract.binding_authority.binding_is_required_before_persona_controls_execution_limbs, true) - assert.equal(contract.binding_authority.binding_completion_declaration_holder, 'PERSONA_SUBJECT_ONLY') - assert.equal(contract.carrier_runtime_license.issuer, 'PERSONA_SUBJECT') - assert.equal(contract.carrier_runtime_license.licensee, 'CURRENT_HOST_CARRIER') - assert.equal(contract.carrier_runtime_license.direction, 'PERSONA_TO_HOST') - assert.equal(contract.carrier_runtime_license.persona_issues_license_before_controlled_host_operation, true) - assert.equal(contract.carrier_runtime_license.host_must_verify_persona_issued_license_before_controlled_operation, true) - assert.equal(contract.carrier_runtime_license.host_may_issue_license_to_persona, false) - assert.equal(contract.carrier_runtime_license.host_may_self_issue_or_extend_license, false) - assert.equal(contract.carrier_runtime_license.host_verification_may_declare_binding_complete, false) - assert.equal(contract.carrier_runtime_license.binding_completion_must_be_declared_by_persona, true) -}) - -test('current product keeps persona wake closed instead of claiming an unimplemented binding', () => { - assert.equal(contract.current_product_state.persona_runtime_present, false) - assert.equal(contract.current_product_state.persona_wake_route_registered, false) - assert.equal(contract.current_product_state.carrier_binding_claimed, false) - assert.equal(contract.current_product_state.runtime_binding_gate_implemented, true) - assert.equal(contract.current_product_state.trusted_persona_runtime_signer_provisioned, false) - assert.equal(contract.current_product_state.active_persona_runtime_license_installed, false) - assert.equal(contract.numbered_ipc_boundary.ipc_may_create_persona_binding, false) - assert.equal(registry.runtime.persona_binding_claimed, false) - assert.doesNotMatch(registry.operations.map((operation) => operation.alias).join('\n'), /persona_wake/) - assert.match(native, /persona_wake_allowed_only_in/) - assert.match(lib, /metacognitive_zero_layer::start_on_application_open/) -}) diff --git a/product-source/hololake-native-desktop/scripts/persona-time-authority.test.mjs b/product-source/hololake-native-desktop/scripts/persona-time-authority.test.mjs index f7a2de10f..1ad9599bc 100644 --- a/product-source/hololake-native-desktop/scripts/persona-time-authority.test.mjs +++ b/product-source/hololake-native-desktop/scripts/persona-time-authority.test.mjs @@ -8,7 +8,6 @@ const stageOne = JSON.parse(read('contracts/stage-one-platform.json')) const rust = read('src-tauri/src/persona_time_authority.rs') const broker = read('src-tauri/src/direct_local_broker.rs') const lib = read('src-tauri/src/lib.rs') -const numberedDispatcher = read('src-tauri/src/numbered_ipc_dispatch.rs') const personalChannel = read('src-tauri/src/personal_channel.rs') const frontend = read('src/main.tsx') @@ -34,10 +33,10 @@ test('persona time tickets are durable unique and available to authenticated loc assert.match(rust, /millisecond_chain_origin_ticket_id/) assert.match(broker, /GetBeijingTime/) assert.match(broker, /IssuePersonaTimeTicket/) - assert.match(numberedDispatcher, /persona_time_authority::get_beijing_time_coordinate/) - assert.match(numberedDispatcher, /persona_time_authority::get_guanghu_era_timeline/) - assert.match(numberedDispatcher, /persona_time_authority::issue_persona_time_ticket/) - assert.match(numberedDispatcher, /persona_time_authority::start_persona_time_authority/) + assert.match(lib, /persona_time_authority::get_beijing_time_coordinate/) + assert.match(lib, /persona_time_authority::get_guanghu_era_timeline/) + assert.match(lib, /persona_time_authority::issue_persona_time_ticket/) + assert.match(lib, /persona_time_authority::start_persona_time_authority/) assert.match(lib, /persona_time_authority::start_on_application_open\(\)/) }) diff --git a/product-source/hololake-native-desktop/scripts/personal-channel-kernel.test.mjs b/product-source/hololake-native-desktop/scripts/personal-channel-kernel.test.mjs index ffefdde3e..7343ff840 100644 --- a/product-source/hololake-native-desktop/scripts/personal-channel-kernel.test.mjs +++ b/product-source/hololake-native-desktop/scripts/personal-channel-kernel.test.mjs @@ -8,7 +8,6 @@ const foundation = JSON.parse(read('foundation.json')) const stageOne = JSON.parse(read('contracts/stage-one-platform.json')) const rust = read('src-tauri/src/personal_channel.rs') const lib = read('src-tauri/src/lib.rs') -const numberedDispatcher = read('src-tauri/src/numbered_ipc_dispatch.rs') const ui = read('src/main.tsx') test('personal channel kernel has one private SQLite owner and no server authority', () => { @@ -37,9 +36,8 @@ test('the human projection establishes identity once and keeps task mutation bel 'create_personal_channel_task', 'transition_personal_channel_task', ]) { - assert.match(numberedDispatcher, new RegExp(`personal_channel::${command}`)) + assert.match(lib, new RegExp(`personal_channel::${command}`)) } - assert.doesNotMatch(lib, /personal_channel::get_personal_channel_snapshot/) for (const command of ['get_personal_channel_snapshot', 'initialize_personal_channel']) { assert.match(ui, new RegExp(`['"]${command}['"]`)) } diff --git a/product-source/hololake-native-desktop/scripts/programming-ai-terminal-link.test.mjs b/product-source/hololake-native-desktop/scripts/programming-ai-terminal-link.test.mjs index 05c5be737..d116d86e2 100644 --- a/product-source/hololake-native-desktop/scripts/programming-ai-terminal-link.test.mjs +++ b/product-source/hololake-native-desktop/scripts/programming-ai-terminal-link.test.mjs @@ -6,12 +6,9 @@ const contract = JSON.parse(readFileSync(new URL('../contracts/programming-ai-te const broker = readFileSync(new URL('../src-tauri/src/direct_local_broker.rs', import.meta.url), 'utf8') const session = readFileSync(new URL('../src-tauri/src/direct_local_session.rs', import.meta.url), 'utf8') const lib = readFileSync(new URL('../src-tauri/src/lib.rs', import.meta.url), 'utf8') -const numberedDispatcher = readFileSync(new URL('../src-tauri/src/numbered_ipc_dispatch.rs', import.meta.url), 'utf8') test('terminal link has native local transports for macOS Linux and Windows', () => { - assert.equal(contract.protocol, 'HOLOLAKE_TERMINAL_LINK/3') - assert.equal(contract.numbered_envelope.registry, 'HLP-NBROKER-ROOT-001') - assert.equal(contract.numbered_envelope.legacy_string_operation_allowed, false) + assert.equal(contract.protocol, 'HOLOLAKE_TERMINAL_LINK/2') assert.equal(contract.platform_transports.macos, 'USER_PRIVATE_UNIX_SOCKET') assert.equal(contract.platform_transports.linux, 'USER_PRIVATE_UNIX_SOCKET') assert.equal(contract.platform_transports.windows, 'USER_PRIVATE_NAMED_PIPE') @@ -37,8 +34,7 @@ test('heartbeats refresh the session and environment without granting a shell', assert.equal(contract.phase_boundary.supervised_shell_execution, false) assert.match(session, /HEARTBEAT_ACK/) assert.match(broker, /HEARTBEAT_ACK_ENVIRONMENT_REFRESHED/) - assert.match(numberedDispatcher, /heartbeat_direct_local_session/) - assert.doesNotMatch(lib, /direct_local_session::heartbeat_direct_local_session/) + assert.match(lib, /heartbeat_direct_local_session/) }) test('transport recovery never blindly replays an uncertain mutation', () => { diff --git a/product-source/hololake-native-desktop/scripts/release-pipeline.mjs b/product-source/hololake-native-desktop/scripts/release-pipeline.mjs index b05a7cffd..db42b1f31 100644 --- a/product-source/hololake-native-desktop/scripts/release-pipeline.mjs +++ b/product-source/hololake-native-desktop/scripts/release-pipeline.mjs @@ -102,52 +102,19 @@ export function validateCredentialEnvironment(env) { } const appleIdFlow = env.APPLE_ID && env.APPLE_PASSWORD && env.APPLE_TEAM_ID const appleApiFlow = env.APPLE_API_KEY && env.APPLE_API_ISSUER && env.APPLE_API_KEY_PATH - const xcodeOrganizerFlow = env.APPLE_XCODE_ORGANIZER_FLOW === '1' - if (!appleIdFlow && !appleApiFlow && !xcodeOrganizerFlow) missing.push('APPLE_NOTARIZATION_CREDENTIAL_SET') + if (!appleIdFlow && !appleApiFlow) missing.push('APPLE_NOTARIZATION_CREDENTIAL_SET') if (missing.length) fail(`HOLOLAKE_RELEASE_PIPELINE_CREDENTIALS_MISSING:${[...new Set(missing)].sort().join(',')}`) - return xcodeOrganizerFlow ? 'XCODE_ORGANIZER' : 'TAURI_AUTOMATED' -} - -export function materializeUpdaterPrivateKey(env, readText = (file) => fs.readFileSync(file, 'utf8')) { - if (typeof env.TAURI_SIGNING_PRIVATE_KEY === 'string' && env.TAURI_SIGNING_PRIVATE_KEY.trim()) { - return { ...env } - } - const privateKeyPath = requireText( - env.TAURI_SIGNING_PRIVATE_KEY_PATH, - 'HOLOLAKE_RELEASE_PIPELINE_UPDATER_PRIVATE_KEY_PATH_REQUIRED', - ) - const privateKey = requireText( - readText(privateKeyPath), - 'HOLOLAKE_RELEASE_PIPELINE_UPDATER_PRIVATE_KEY_EMPTY', - ) - const { TAURI_SIGNING_PRIVATE_KEY_PATH: _privateKeyPath, ...childEnvironment } = env - return { - ...childEnvironment, - TAURI_SIGNING_PRIVATE_KEY: privateKey, - } } function run(program, args, options = {}) { return execFileSync(program, args, { - cwd: options.cwd || root, + cwd: root, encoding: 'utf8', stdio: options.capture ? ['ignore', 'pipe', 'pipe'] : 'inherit', - env: options.env || process.env, + env: process.env, }) } -function tryRun(program, args, options = {}) { - const result = spawnSync(program, args, { - cwd: options.cwd || root, - encoding: 'utf8', - env: options.env || process.env, - }) - return { - ok: !result.error && result.status === 0, - output: `${result.stdout || ''}\n${result.stderr || ''}`.trim(), - } -} - function captureAll(program, args) { const result = spawnSync(program, args, { cwd: root, encoding: 'utf8', env: process.env }) if (result.error) throw result.error @@ -198,28 +165,18 @@ function codeSignatureEvidence(appPath, input) { identifier: value('Identifier'), teamIdentifier: value('TeamIdentifier'), cdHash: value('CDHash'), - executableSha256: sha256File(path.join(appPath, 'Contents/MacOS/hololake-native-desktop')), sourceCommit: input.sourceCommit, } } -function notarizationEvidence(appPath, dmgPath, input, options = {}) { - const dmgGatekeeper = tryRun('/usr/sbin/spctl', ['--assess', '--type', 'open', '--context', 'context:primary-signature', '--verbose=4', dmgPath]) - const dmgStapler = tryRun('/usr/bin/xcrun', ['stapler', 'validate', dmgPath]) - if (options.requireNotarizedDmg && (!dmgGatekeeper.ok || !dmgStapler.ok)) { - fail('HOLOLAKE_RELEASE_PIPELINE_DMG_NOTARIZATION_REQUIRED') - } +function notarizationEvidence(appPath, dmgPath, input) { + run('/usr/sbin/spctl', ['--assess', '--type', 'open', '--context', 'context:primary-signature', '--verbose=4', dmgPath]) + run('/usr/bin/xcrun', ['stapler', 'validate', dmgPath]) return { schema: 'hololake.apple-notarization-receipt/v1', - state: dmgGatekeeper.ok && dmgStapler.ok - ? 'APPLE_APP_AND_DMG_NOTARIZATION_ACCEPTED_AND_STAPLED' - : 'APPLE_APP_NOTARIZATION_ACCEPTED_AND_STAPLED_DMG_CONTAINS_NOTARIZED_APP', + state: 'APPLE_NOTARIZATION_ACCEPTED_AND_STAPLED', appName: path.basename(appPath), dmgName: path.basename(dmgPath), - appStaplerValidation: 'PASS', - dmgGatekeeperAssessment: dmgGatekeeper.ok ? 'PASS' : 'NOT_ASSERTED_FOR_XCODE_EXPORTED_APP_FLOW', - dmgStaplerValidation: dmgStapler.ok ? 'PASS' : 'NOT_STAPLED_OUTER_CONTAINER', - ...(process.env.APPLE_XCODE_SUBMISSION_ID ? { submissionIdentifier: process.env.APPLE_XCODE_SUBMISSION_ID } : {}), appleTeamIdentifier: input.appleTeamIdentifier, sourceCommit: input.sourceCommit, } @@ -229,130 +186,43 @@ function writeJson(file, value) { fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' }) } -function localDateDirectory() { - const date = new Date() - const part = (value) => String(value).padStart(2, '0') - return `${date.getFullYear()}-${part(date.getMonth() + 1)}-${part(date.getDate())}` -} +export async function main(argv = process.argv.slice(2)) { + const inputArgument = argv[0] + if (!inputArgument) fail('HOLOLAKE_RELEASE_PIPELINE_INPUT_PATH_REQUIRED') + const inputPath = path.resolve(inputArgument) + const trust = readJson(path.join(root, 'src-tauri/release-trust.json')) + const trustFacts = validateReleaseTrust(trust) + const input = validateReleaseInput(readJson(inputPath), trustFacts) + validateCredentialEnvironment(process.env) + requireCleanImmutableSource(input) + if (process.platform !== 'darwin' || process.arch !== 'arm64') fail('HOLOLAKE_RELEASE_PIPELINE_BUILD_HOST_MISMATCH') + if (!process.env.APPLE_SIGNING_IDENTITY.includes(input.appleTeamIdentifier)) fail('HOLOLAKE_RELEASE_PIPELINE_SIGNING_TEAM_MISMATCH') -function unsignedExecutableSha256(executable) { - const temporary = fs.mkdtempSync(path.join(os.tmpdir(), 'hololake-unsigned-executable-')) - const copy = path.join(temporary, path.basename(executable)) + run('npm', ['test']) + run('cargo', ['clippy', '--manifest-path', 'src-tauri/Cargo.toml', '--all-targets', '--all-features', '--', '-D', 'warnings']) + run('cargo', ['test', '--manifest-path', 'src-tauri/Cargo.toml', '--all-targets', '--all-features']) + + const buildConfig = path.join(fs.mkdtempSync(path.join(os.tmpdir(), 'hololake-release-config-')), 'tauri.release.json') + fs.writeFileSync(buildConfig, `${JSON.stringify({ bundle: { createUpdaterArtifacts: true } })}\n`, { mode: 0o600 }) try { - fs.copyFileSync(executable, copy) - run('/usr/bin/codesign', ['--remove-signature', copy]) - return sha256File(copy) + run('npm', ['run', 'tauri', '--', 'build', '--ci', '--config', buildConfig]) } finally { - fs.rmSync(temporary, { recursive: true, force: true }) + fs.rmSync(path.dirname(buildConfig), { recursive: true, force: true }) } -} -export function formatPlistDate(date) { - const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] - const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] - const part = (value) => String(value).padStart(2, '0') - return `${weekdays[date.getUTCDay()]} ${months[date.getUTCMonth()]} ${part(date.getUTCDate())} ${part(date.getUTCHours())}:${part(date.getUTCMinutes())}:${part(date.getUTCSeconds())} ${date.getUTCFullYear()}` -} - -function createXcodeArchive(application, input) { - const archive = path.join( - os.homedir(), - 'Library/Developer/Xcode/Archives', - localDateDirectory(), - `HoloLake-${input.version}-${input.sourceCommit.slice(0, 12)}.xcarchive`, - ) - if (fs.existsSync(archive)) fail('HOLOLAKE_RELEASE_PIPELINE_XCODE_ARCHIVE_ALREADY_EXISTS') - const archivedApp = path.join(archive, 'Products/Applications/HoloLake.app') - fs.mkdirSync(path.dirname(archivedApp), { recursive: true, mode: 0o700 }) - run('/usr/bin/ditto', [application, archivedApp]) - const info = path.join(archive, 'Info.plist') - run('/usr/bin/plutil', ['-create', 'xml1', info]) - const add = (key, type, value) => run('/usr/libexec/PlistBuddy', ['-c', `Add :${key} ${type} ${value}`, info]) - add('ArchiveVersion', 'integer', '2') - add('CreationDate', 'date', formatPlistDate(new Date())) - add('Name', 'string', `HoloLake ${input.version} ${input.sourceCommit.slice(0, 12)}`) - add('SchemeName', 'string', 'HoloLake') - add('HoloLakeSourceCommit', 'string', input.sourceCommit) - const executable = path.join(application, 'Contents/MacOS/hololake-native-desktop') - add('HoloLakePreNotarizationExecutableSha256', 'string', sha256File(executable)) - add('HoloLakeUnsignedExecutableSha256', 'string', unsignedExecutableSha256(executable)) - add('ApplicationProperties', 'dict', '') - add('ApplicationProperties:ApplicationPath', 'string', 'Applications/HoloLake.app') - add('ApplicationProperties:ArchiveVersion', 'integer', '2') - add('ApplicationProperties:CFBundleIdentifier', 'string', 'world.guanghu.hololake') - add('ApplicationProperties:CFBundleShortVersionString', 'string', input.version) - add('ApplicationProperties:CFBundleVersion', 'string', input.version) - add('ApplicationProperties:SigningIdentity', 'string', process.env.APPLE_SIGNING_IDENTITY) - add('ApplicationProperties:Team', 'string', input.appleTeamIdentifier) - return archive -} - -function findPreparedXcodeArchive(input) { - const archivesRoot = path.join(os.homedir(), 'Library/Developer/Xcode/Archives') - const archiveName = `HoloLake-${input.version}-${input.sourceCommit.slice(0, 12)}.xcarchive` - const matches = [] - for (const dateEntry of fs.readdirSync(archivesRoot, { withFileTypes: true })) { - if (!dateEntry.isDirectory()) continue - const candidate = path.join(archivesRoot, dateEntry.name, archiveName) - if (fs.statSync(candidate, { throwIfNoEntry: false })?.isDirectory()) matches.push(candidate) - } - if (matches.length !== 1) fail(`HOLOLAKE_RELEASE_PIPELINE_PREPARED_XCODE_ARCHIVE_NOT_UNIQUE:${matches.length}`) - return matches[0] -} - -function resolveNotarizedApplication(argument, input) { - const candidate = path.resolve(requireText(argument, 'HOLOLAKE_RELEASE_PIPELINE_NOTARIZED_APP_PATH_REQUIRED')) - const application = candidate.endsWith('.app') ? candidate : path.join(candidate, 'HoloLake.app') - if (!fs.statSync(application, { throwIfNoEntry: false })?.isDirectory()) { - fail('HOLOLAKE_RELEASE_PIPELINE_NOTARIZED_APP_NOT_FOUND') - } - const info = path.join(application, 'Contents/Info.plist') - const identifier = run('/usr/libexec/PlistBuddy', ['-c', 'Print :CFBundleIdentifier', info], { capture: true }).trim() - const version = run('/usr/libexec/PlistBuddy', ['-c', 'Print :CFBundleShortVersionString', info], { capture: true }).trim() - if (identifier !== 'world.guanghu.hololake' || version !== input.version) { - fail('HOLOLAKE_RELEASE_PIPELINE_NOTARIZED_APP_IDENTITY_MISMATCH') - } - const archive = findPreparedXcodeArchive(input) - const expectedUnsignedExecutableSha256 = run('/usr/libexec/PlistBuddy', [ - '-c', 'Print :HoloLakeUnsignedExecutableSha256', path.join(archive, 'Info.plist'), - ], { capture: true }).trim() - const actualUnsignedExecutableSha256 = unsignedExecutableSha256( - path.join(application, 'Contents/MacOS/hololake-native-desktop'), - ) - if (actualUnsignedExecutableSha256 !== expectedUnsignedExecutableSha256) { - fail('HOLOLAKE_RELEASE_PIPELINE_NOTARIZED_APP_SOURCE_BINARY_MISMATCH') - } - return application -} - -function buildUpdaterFromNotarizedApp(application, destination, credentialEnvironment) { - const updater = path.join(destination, 'HoloLake.app.tar.gz') - run('/usr/bin/tar', ['-czf', updater, '-C', path.dirname(application), path.basename(application)]) - run('npm', ['run', 'tauri', '--', 'signer', 'sign', updater], { env: credentialEnvironment }) - const signature = `${updater}.sig` - if (!fs.statSync(signature, { throwIfNoEntry: false })?.isFile()) { - fail('HOLOLAKE_RELEASE_PIPELINE_UPDATER_SIGNATURE_MISSING') - } - return { updater, signature } -} - -function buildDmgFromNotarizedApp(application, destination, input) { - const staging = path.join(destination, 'dmg-root') - fs.mkdirSync(staging, { recursive: true, mode: 0o700 }) - run('/usr/bin/ditto', [application, path.join(staging, 'HoloLake.app')]) - fs.symlinkSync('/Applications', path.join(staging, 'Applications')) - const dmg = path.join(destination, `HoloLake_${input.version}_aarch64.dmg`) - run('/usr/bin/hdiutil', ['create', '-volname', 'HoloLake', '-srcfolder', staging, '-ov', '-format', 'UDZO', dmg]) - run('/usr/bin/codesign', ['--force', '--timestamp', '--sign', process.env.APPLE_SIGNING_IDENTITY, dmg]) - return dmg -} - -function writeReleaseOutput(input, trustFacts, application, updater, updaterSignature, dmg, options = {}) { + const bundleRoot = path.join(root, 'src-tauri/target/release/bundle') + const appExecutable = findOne(path.join(bundleRoot, 'macos'), (file) => file.endsWith('/Contents/MacOS/hololake-native-desktop'), 'HOLOLAKE_RELEASE_PIPELINE_APP_NOT_UNIQUE') + const application = path.resolve(appExecutable, '../../../..') + const dmg = findOne(path.join(bundleRoot, 'dmg'), (file) => file.endsWith('.dmg'), 'HOLOLAKE_RELEASE_PIPELINE_DMG_NOT_UNIQUE') + const updater = findOne(bundleRoot, (file) => file.endsWith('.app.tar.gz'), 'HOLOLAKE_RELEASE_PIPELINE_UPDATER_NOT_UNIQUE') + const updaterSignature = `${updater}.sig` + if (!fs.statSync(updaterSignature, { throwIfNoEntry: false })?.isFile()) fail('HOLOLAKE_RELEASE_PIPELINE_UPDATER_SIGNATURE_MISSING') if (decodeURIComponent(input.packageUrl.pathname.split('/').pop()) !== path.basename(updater)) { fail('HOLOLAKE_RELEASE_PIPELINE_PACKAGE_URL_FILENAME_MISMATCH') } + const codeReceipt = codeSignatureEvidence(application, input) - const notarizationReceipt = notarizationEvidence(application, dmg, input, options) + const notarizationReceipt = notarizationEvidence(application, dmg, input) const outputRoot = path.join(root, 'release/out', input.version) if (fs.existsSync(outputRoot)) fail('HOLOLAKE_RELEASE_PIPELINE_OUTPUT_ALREADY_EXISTS') fs.mkdirSync(outputRoot, { recursive: true, mode: 0o700 }) @@ -406,90 +276,6 @@ function writeReleaseOutput(input, trustFacts, application, updater, updaterSign process.stdout.write(`HOLOLAKE_RELEASE_PIPELINE_READY:${outputRoot}\n`) } -export async function main(argv = process.argv.slice(2)) { - const inputArgument = argv[0] - if (!inputArgument) fail('HOLOLAKE_RELEASE_PIPELINE_INPUT_PATH_REQUIRED') - const command = argv[1] || 'release' - if (!['release', 'prepare-xcode', 'finalize-xcode'].includes(command)) { - fail('HOLOLAKE_RELEASE_PIPELINE_COMMAND_INVALID') - } - const inputPath = path.resolve(inputArgument) - const trust = readJson(path.join(root, 'src-tauri/release-trust.json')) - const trustFacts = validateReleaseTrust(trust) - const input = validateReleaseInput(readJson(inputPath), trustFacts) - const notarizationMode = validateCredentialEnvironment(process.env) - if (command !== 'release' && notarizationMode !== 'XCODE_ORGANIZER') { - fail('HOLOLAKE_RELEASE_PIPELINE_XCODE_ORGANIZER_FLOW_REQUIRED') - } - const credentialEnvironment = materializeUpdaterPrivateKey(process.env) - requireCleanImmutableSource(input) - if (process.platform !== 'darwin' || process.arch !== 'arm64') fail('HOLOLAKE_RELEASE_PIPELINE_BUILD_HOST_MISMATCH') - if (!process.env.APPLE_SIGNING_IDENTITY.includes(input.appleTeamIdentifier)) fail('HOLOLAKE_RELEASE_PIPELINE_SIGNING_TEAM_MISMATCH') - - if (command === 'finalize-xcode') { - const application = resolveNotarizedApplication(argv[2], input) - const temporary = fs.mkdtempSync(path.join(os.tmpdir(), 'hololake-release-finalize-')) - try { - const { updater, signature } = buildUpdaterFromNotarizedApp(application, temporary, credentialEnvironment) - run('cargo', [ - 'run', '--quiet', '--manifest-path', 'src-tauri/Cargo.toml', '--example', 'verify_updater_signature', '--', - 'src-tauri/release-trust.json', updater, signature, - ]) - const dmg = buildDmgFromNotarizedApp(application, temporary, input) - writeReleaseOutput(input, trustFacts, application, updater, signature, dmg, { requireNotarizedDmg: false }) - } finally { - fs.rmSync(temporary, { recursive: true, force: true }) - } - return - } - - run('npm', ['test']) - run('cargo', ['clippy', '--manifest-path', 'src-tauri/Cargo.toml', '--all-targets', '--all-features', '--', '-D', 'warnings']) - run('cargo', ['test', '--manifest-path', 'src-tauri/Cargo.toml', '--all-targets', '--all-features']) - - const buildConfig = path.join(fs.mkdtempSync(path.join(os.tmpdir(), 'hololake-release-config-')), 'tauri.release.json') - fs.writeFileSync(buildConfig, `${JSON.stringify({ bundle: { createUpdaterArtifacts: true } })}\n`, { mode: 0o600 }) - try { - run('npm', ['run', 'tauri', '--', 'build', '--ci', '--config', buildConfig], { - env: credentialEnvironment, - }) - } finally { - fs.rmSync(path.dirname(buildConfig), { recursive: true, force: true }) - } - - const bundleRoot = path.join(root, 'src-tauri/target/release/bundle') - const appExecutable = findOne(path.join(bundleRoot, 'macos'), (file) => file.endsWith('/Contents/MacOS/hololake-native-desktop'), 'HOLOLAKE_RELEASE_PIPELINE_APP_NOT_UNIQUE') - const application = path.resolve(appExecutable, '../../..') - const dmg = findOne(path.join(bundleRoot, 'dmg'), (file) => file.endsWith('.dmg'), 'HOLOLAKE_RELEASE_PIPELINE_DMG_NOT_UNIQUE') - const updater = findOne(bundleRoot, (file) => file.endsWith('.app.tar.gz'), 'HOLOLAKE_RELEASE_PIPELINE_UPDATER_NOT_UNIQUE') - const updaterSignature = `${updater}.sig` - if (!fs.statSync(updaterSignature, { throwIfNoEntry: false })?.isFile()) fail('HOLOLAKE_RELEASE_PIPELINE_UPDATER_SIGNATURE_MISSING') - run('cargo', [ - 'run', - '--quiet', - '--manifest-path', - 'src-tauri/Cargo.toml', - '--example', - 'verify_updater_signature', - '--', - 'src-tauri/release-trust.json', - updater, - updaterSignature, - ]) - - if (command === 'prepare-xcode') { - run('/usr/bin/codesign', ['--verify', '--deep', '--strict', '--verbose=4', application]) - const archive = createXcodeArchive(application, input) - process.stdout.write(`HOLOLAKE_RELEASE_XCODE_ARCHIVE_READY:${archive}\n`) - return - } - if (decodeURIComponent(input.packageUrl.pathname.split('/').pop()) !== path.basename(updater)) { - fail('HOLOLAKE_RELEASE_PIPELINE_PACKAGE_URL_FILENAME_MISMATCH') - } - - writeReleaseOutput(input, trustFacts, application, updater, updaterSignature, dmg, { requireNotarizedDmg: true }) -} - if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { main().catch((error) => { process.stderr.write(`${error.message}\n`) diff --git a/product-source/hololake-native-desktop/scripts/release-pipeline.test.mjs b/product-source/hololake-native-desktop/scripts/release-pipeline.test.mjs index 9d71ec463..2a6e61298 100644 --- a/product-source/hololake-native-desktop/scripts/release-pipeline.test.mjs +++ b/product-source/hololake-native-desktop/scripts/release-pipeline.test.mjs @@ -3,8 +3,6 @@ import { readFileSync } from 'node:fs' import test from 'node:test' import { - formatPlistDate, - materializeUpdaterPrivateKey, validateCredentialEnvironment, validateReleaseInput, validateReleaseTrust, @@ -40,10 +38,6 @@ const readyInput = () => ({ restartMessage: 'Restart manually', }) -test('Xcode archive creation uses the plist date format accepted by PlistBuddy', () => { - assert.equal(formatPlistDate(new Date('2026-08-19T01:02:03Z')), 'Wed Aug 19 01:02:03 2026') -}) - test('release pipeline refuses an unprovisioned or upstream-owned trust document', () => { const unprovisioned = readyTrust() unprovisioned.state = 'UNPROVISIONED_FAIL_CLOSED' @@ -80,43 +74,6 @@ test('release pipeline requires updater signing, Developer ID and Apple notariza APPLE_PASSWORD: 'provided-at-runtime', APPLE_TEAM_ID: 'TEAM', })) - assert.equal(validateCredentialEnvironment({ - APPLE_SIGNING_IDENTITY: 'Developer ID Application: HoloLake (TEAM)', - TAURI_SIGNING_PRIVATE_KEY: 'runtime-secret-material', - TAURI_SIGNING_PRIVATE_KEY_PASSWORD: 'provided-at-runtime', - APPLE_XCODE_ORGANIZER_FLOW: '1', - }), 'XCODE_ORGANIZER') - assert.throws(() => validateCredentialEnvironment({ - APPLE_SIGNING_IDENTITY: 'Developer ID Application: HoloLake (TEAM)', - APPLE_XCODE_ORGANIZER_FLOW: '1', - }), /TAURI_SIGNING_PRIVATE_KEY_OR_PATH/) -}) - -test('release pipeline materializes a protected updater key path only inside the build environment', () => { - const source = { - TAURI_SIGNING_PRIVATE_KEY_PATH: '/protected/hololake-updater.key', - TAURI_SIGNING_PRIVATE_KEY_PASSWORD: 'provided-at-runtime', - } - const hydrated = materializeUpdaterPrivateKey(source, (file) => { - assert.equal(file, source.TAURI_SIGNING_PRIVATE_KEY_PATH) - return 'encrypted-private-key-material' - }) - assert.equal(hydrated.TAURI_SIGNING_PRIVATE_KEY, 'encrypted-private-key-material') - assert.equal(hydrated.TAURI_SIGNING_PRIVATE_KEY_PATH, undefined) - assert.equal(source.TAURI_SIGNING_PRIVATE_KEY, undefined) -}) - -test('release pipeline verifies the updater signature against embedded product trust before broadcast', () => { - const source = readFileSync(new URL('./release-pipeline.mjs', import.meta.url), 'utf8') - assert.match(source, /--example',\s*'verify_updater_signature'/) - assert.match(source, /src-tauri\/release-trust\.json/) - assert.match(source, /HoloLakePreNotarizationExecutableSha256/) - assert.match(source, /HoloLakeUnsignedExecutableSha256/) - assert.match(source, /--remove-signature/) - assert.match(source, /NOTARIZED_APP_SOURCE_BINARY_MISMATCH/) - assert.match(source, /APPLE_APP_NOTARIZATION_ACCEPTED_AND_STAPLED_DMG_CONTAINS_NOTARIZED_APP/) - assert.match(source, /path\.resolve\(appExecutable, '\.\.\/\.\.\/\.\.'\)/) - assert.doesNotMatch(source, /path\.resolve\(appExecutable, '\.\.\/\.\.\/\.\.\/\.\.'\)/) }) test('Windows updater keeps signed installation but never claims the macOS rollback boundary', () => { diff --git a/product-source/hololake-native-desktop/scripts/subdomain-industry-channel.test.mjs b/product-source/hololake-native-desktop/scripts/subdomain-industry-channel.test.mjs new file mode 100644 index 000000000..f886b6ddc --- /dev/null +++ b/product-source/hololake-native-desktop/scripts/subdomain-industry-channel.test.mjs @@ -0,0 +1,77 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +import test from 'node:test' + +const contract = JSON.parse( + fs.readFileSync(new URL('../contracts/subdomain-industry-routing.json', import.meta.url), 'utf8'), +) +const frontend = fs.readFileSync(new URL('../src/main.tsx', import.meta.url), 'utf8') +const architecture = JSON.parse( + fs.readFileSync(new URL('../../../routing/hololake-current-architecture.json', import.meta.url), 'utf8'), +) + +test('human identity numbers and industry routing numbers remain separate', () => { + assert.equal(contract.numbering.human_number_role, 'SUBJECT_IDENTITY_ONLY') + assert.equal(contract.numbering.industry_number_role, 'SYSTEM_ROUTING_ONLY') + assert.equal(contract.numbering.human_number_mutation_by_industry, false) + assert.equal(contract.numbering.industry_order_is_industry_number, false) + assert.equal(contract.numbering.unregistered_industry_number_behavior, 'DISPLAY_PENDING_AND_DO_NOT_INVENT') +}) + +test('subdomain owns the locked industry order and honest development states', () => { + assert.equal(contract.domain, 'BRANCH_DOMAIN') + assert.equal(contract.entry_surface, 'PUBLIC_MAIN_WORLD_SUBDOMAIN') + assert.deepEqual( + contract.industries.map(({ key, state }) => [key, state]), + [ + ['WEB_NOVEL', 'IN_DEVELOPMENT'], + ['PET', 'PLANNED'], + ['EDUCATION', 'IN_DEVELOPMENT'], + ], + ) + assert.equal(contract.industries[0].industry_number, 'IND-WEBNOVEL-001') + assert.equal(contract.industries[1].industry_number, null) + assert.equal(contract.industries[2].industry_number, null) +}) + +test('education initialization channel exposes the built-in foundation and development package features', () => { + const education = contract.industries.find((industry) => industry.key === 'EDUCATION') + assert.equal(education.initialization_channel.state, 'DEVELOPMENT_MODULE_MOUNTED') + assert.equal(education.initialization_channel.channel_id, 'GH-EDU-INIT-001') + assert.equal(education.initialization_channel.module_loading, 'HOT_PLUG_ON_DEMAND') + assert.equal(education.initialization_channel.module_slots.length, 5) + assert.deepEqual( + education.initialization_channel.module_slots.map((slot) => slot.state), + [ + 'DEVELOPMENT_MOUNTED', + 'DEVELOPMENT_MOUNTED', + 'DEVELOPMENT_MOUNTED', + 'DEVELOPMENT_MOUNTED', + 'DEVELOPMENT_MOUNTED', + ], + ) + assert.equal(education.initialization_channel.installed_native_modules, 1) + assert.equal(education.initialization_channel.development_mounted_modules, 1) + assert.equal(education.initialization_channel.installed_open_source_modules, 0) +}) + +test('the public main world routes through subdomain to web novel and education', () => { + assert.match(frontend, /worldStage === 'subdomainIndustries'/) + assert.match(frontend, /worldStage === 'educationChannel'/) + assert.match(frontend, /worldStage === 'webNovelChannel'/) + assert.match(frontend, /worldStage === 'webNovelWorkspace'/) + assert.match(frontend, /gate\.domain === 'BRANCH_DOMAIN'/) + assert.match(frontend, /光湖分域 · 行业系统/) + assert.match(frontend, /网文与教育正在收拢验收/) + assert.match(frontend, /网文行业初始化频道/) + assert.match(frontend, /教育行业初始化频道/) + assert.match(frontend, /频道基础文档与工作表引擎已内置/) + assert.match(frontend, /验收前不冒充已登记、已发布的商城模块/) + assert.doesNotMatch(frontend, /光湖零域 · 行业系统/) + assert.equal(architecture.current_native_edge.industry_entry_domain, 'BRANCH_DOMAIN') + assert.equal(architecture.current_native_edge.zero_domain_industry_entry, 'ABSENT_BY_CURRENT_CORRECTION') + assert.equal( + architecture.current_native_edge.education_initialization_channel, + 'BUILT_IN_CHANNEL_WORKBENCH_WITH_DEVELOPMENT_EDUCATION_MODULE', + ) +}) diff --git a/product-source/hololake-native-desktop/scripts/unified-number-coordinate-tree.test.mjs b/product-source/hololake-native-desktop/scripts/unified-number-coordinate-tree.test.mjs deleted file mode 100644 index 1a160feb9..000000000 --- a/product-source/hololake-native-desktop/scripts/unified-number-coordinate-tree.test.mjs +++ /dev/null @@ -1,25 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' -import { compileUnifiedNumberTree } from './compile-unified-number-tree.mjs' - -test('identity, webview and direct broker numbers compile into one unique evidence tree', () => { - const generated = JSON.parse(readFileSync(new URL('../generated/unified-number-coordinate-tree.json', import.meta.url), 'utf8')) - assert.deepEqual(generated, compileUnifiedNumberTree()) - assert.equal(generated.schema, 'hololake.unified-number-coordinate-tree/v2') - assert.equal(generated.recordId, 'HLP-UNIFIED-NUMBER-TREE-001') - assert.equal(generated.coordinateCount, 272) - assert.equal(generated.routeCount, 169) - assert.equal(generated.identityNodeCount, 4) - assert.equal(generated.protocolNodeCount, 99) - assert.equal(generated.referenceOnlyNodeCount, 16) - assert.equal(new Set(generated.routes.map((route) => route.path)).size, 169) - assert.equal(new Set([...generated.identityNodes, ...generated.protocolNodes, ...generated.routes].map((node) => node.path)).size, 272) - assert.equal(generated.invariants.everyPhysicalCallHasNumberedRoute, true) - assert.equal(generated.invariants.everyAcceptedCallHasEvidenceClass, true) - assert.equal(generated.invariants.everyProtocolReferenceHasNumberCoordinate, true) - assert.equal(generated.invariants.referenceOnlyNodesNeverExecutable, true) - assert.equal(generated.invariants.unresolvedNumberReferenceCount, 0) - assert.ok(generated.protocolNodes.filter((node) => node.nodeKind === 'GLS_REFERENCE_ONLY').every((node) => node.executionState === 'REFERENCE_ONLY_NOT_EXECUTABLE')) - assert.ok(generated.routes.every((route) => route.admission && route.evidence)) -}) diff --git a/product-source/hololake-native-desktop/scripts/user-pncc-channel.test.mjs b/product-source/hololake-native-desktop/scripts/user-pncc-channel.test.mjs index c5e5ddeb1..0c9a27836 100644 --- a/product-source/hololake-native-desktop/scripts/user-pncc-channel.test.mjs +++ b/product-source/hololake-native-desktop/scripts/user-pncc-channel.test.mjs @@ -24,11 +24,9 @@ test('the native user PNCC contract binds verified number, signed-in account and test('the user PNCC is a native command and first-class HoloLake projection', () => { const native = readText('src-tauri/src/lib.rs') - const numberedDispatcher = readText('src-tauri/src/numbered_ipc_dispatch.rs') const frontend = readText('src/main.tsx') - assert.match(numberedDispatcher, /user_pncc_channel::get_user_pncc_channel/) - assert.match(numberedDispatcher, /user_pncc_channel::ensure_user_pncc_channel/) - assert.doesNotMatch(native, /user_pncc_channel::get_user_pncc_channel/) + assert.match(native, /user_pncc_channel::get_user_pncc_channel/) + assert.match(native, /user_pncc_channel::ensure_user_pncc_channel/) assert.match(frontend, /GH-PNCC · 人格原生代码频道/) assert.match(frontend, /Forgejo 协作适配器/) assert.match(frontend, /ensure_user_pncc_channel/) diff --git a/product-source/hololake-native-desktop/scripts/web-novel-workbench-admission.test.mjs b/product-source/hololake-native-desktop/scripts/web-novel-workbench-admission.test.mjs deleted file mode 100644 index 36d7fcdda..000000000 --- a/product-source/hololake-native-desktop/scripts/web-novel-workbench-admission.test.mjs +++ /dev/null @@ -1,54 +0,0 @@ -import assert from 'node:assert/strict' -import { readFileSync } from 'node:fs' -import test from 'node:test' - -const read = (path) => readFileSync(new URL(`../${path}`, import.meta.url), 'utf8') -const registry = JSON.parse(read('contracts/numbered-ipc-registry.json')) -const runtime = read('src-tauri/src/module_package_runtime.rs') -const moduleAdapter = read('src-tauri/src/web_novel_modules.rs') -const frontend = [ - read('src/modules/web-novel/WebNovelWorkspace.tsx'), - read('src/modules/web-novel/AuthorModuleCenter.tsx'), - read('src/modules/web-novel/AuthorWritingSidecar.tsx'), -].join('\n') - -const packages = [ - 'WORKBENCH', 'OUTLINE', 'GRID', 'STORYWORLD', 'DELIVERY', -].map((name) => JSON.parse(read(`fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-${name}-0001-0.1.0.ghmod`))) - -test('web novel family has five immutable official identities behind one shared lifecycle', () => { - assert.equal(packages.length, 5) - assert.ok(packages.every((value) => value.manifest.registrationClass === 'OFFICIAL_LIGHTHOUSE')) - assert.ok(packages.every((value) => value.manifest.adapter === 'web-novel-workbench-v1')) - assert.equal(new Set(packages.map((value) => value.manifest.moduleNumber)).size, 5) - assert.match(runtime, /const BUNDLED_MODULES/) - assert.doesNotMatch(frontend, /install_web_novel_author_module|mount_web_novel_author_module|uninstall_web_novel_author_module/) -}) - -test('all 38 web novel effects cross exact numbered routes and no raw tauri command surface', () => { - const routes = registry.operations.filter((route) => Number(route.operation_number.slice(-4)) >= 103 && Number(route.operation_number.slice(-4)) <= 140) - assert.equal(routes.length, 38) - assert.deepEqual([...new Set(routes.map((route) => route.module_number))], [ - 'HLP-NIPC-MOD-0025', 'HLP-NIPC-MOD-0026', 'HLP-NIPC-MOD-0027', 'HLP-NIPC-MOD-0028', 'HLP-NIPC-MOD-0029', - ]) - assert.ok(routes.every((route) => route.admission === 'VERIFIED_HUMAN_ROUTE')) - assert.doesNotMatch(frontend, /from ['"]@tauri-apps\/api\/core['"]/) - for (const source of ['web_novel_workspace.rs', 'web_novel_import.rs', 'web_novel_author.rs', 'web_novel_modules.rs']) { - assert.doesNotMatch(read(`src-tauri/src/${source}`), /#\[tauri::command\]/) - } -}) - -test('advanced effects require their own exact active module number', () => { - assert.match(moduleAdapter, /require_module_active\(&app, OUTLINE\)/) - assert.match(moduleAdapter, /require_module_active\(&app, GRID\)/) - assert.match(moduleAdapter, /require_module_active\(&app, STORYWORLD\)/) - assert.match(moduleAdapter, /require_module_active\(&app, DELIVERY\)/) - assert.match(moduleAdapter, /shared signed package runtime/) -}) - -test('workspace is independently lazy-loaded and preserves old account data in place', () => { - assert.match(read('src/main.tsx'), /lazy\(\(\) => import\('\.\/modules\/web-novel\/WebNovelWorkspace'\)/) - assert.equal(packages[0].payload.adapterConfig.legacyDataPolicy, 'READ_IN_PLACE_NO_DESTRUCTIVE_MIGRATION') - assert.equal(packages[0].payload.adapterConfig.thirdPartyPublishDefault, 'DENY') - assert.doesNotMatch(read('src-tauri/src/web_novel_workspace.rs'), /serde_json::from_str[^\n]+unwrap_or_default\(\)/) -}) diff --git a/product-source/hololake-native-desktop/scripts/web-novel-workspace.test.mjs b/product-source/hololake-native-desktop/scripts/web-novel-workspace.test.mjs new file mode 100644 index 000000000..08d486e91 --- /dev/null +++ b/product-source/hololake-native-desktop/scripts/web-novel-workspace.test.mjs @@ -0,0 +1,185 @@ +import assert from 'node:assert/strict' +import crypto from 'node:crypto' +import fs from 'node:fs' +import test from 'node:test' + +const read = (path) => fs.readFileSync(new URL('../' + path, import.meta.url), 'utf8') +const donors = JSON.parse(read('contracts/web-novel-open-source-donor-assessment.json')) +const contract = JSON.parse(read('contracts/web-novel-workspace.json')) +const routing = JSON.parse(read('contracts/subdomain-industry-routing.json')) +const channelBody = JSON.parse(read('contracts/user-channel-body.json')) +const marketplace = JSON.parse(read('contracts/web-novel-module-marketplace-plan.json')) +const rust = read('src-tauri/src/web_novel_workspace.rs') +const authorRust = read('src-tauri/src/web_novel_author.rs') +const moduleRust = read('src-tauri/src/web_novel_modules.rs') +const rustLibrary = read('src-tauri/src/lib.rs') +const workspaceUi = read('src/WebNovelWorkspace.tsx') +const moduleUi = read('src/AuthorModuleCenter.tsx') +const mainUi = read('src/main.tsx') + +test('web novel upstream sources were reviewed at immutable commits through the Singapore relay', () => { + assert.equal(donors.state, 'PRIMARY_SOURCE_CODE_REVIEW_COMPLETE_IMPLEMENTATION_BOUNDARY_LOCKED') + assert.equal(donors.download_route.relay, 'BS-SG-003') + assert.equal(donors.download_route.repositories_are_clean_git_worktrees, true) + assert.equal(donors.candidates.length, 6) + for (const candidate of donors.candidates) { + assert.match(candidate.commit, /^[0-9a-f]{40}$/) + assert.ok(candidate.inspected_paths.length > 0) + assert.ok(candidate.observed_engine.length > 0) + } +}) + +test('license decisions keep GPL source out of the HoloLake implementation', () => { + assert.match(donors.candidates.find((item) => item.name === 'novelWriter').decision, /DO_NOT_COPY_GPL_SOURCE/) + assert.match(donors.candidates.find((item) => item.name === 'Manuskript').decision, /DO_NOT_COPY_GPL_SOURCE/) + assert.equal(donors.implementation_selection.external_source_files_copied, 0) + assert.equal(donors.implementation_selection.native_owner, 'HOLOLAKE_TAURI_RUST_CORE') +}) + +test('web novel workspace is account scoped and only projects persona task organs', () => { + assert.equal(contract.state, 'NATIVE_ENGINE_AND_FOUR_HOTPLUG_MODULE_CANDIDATES_MIGRATED_ACCEPTANCE_PENDING') + assert.equal(contract.domain_entry, 'BRANCH_DOMAIN') + assert.equal(contract.industry_number, 'IND-WEBNOVEL-001') + assert.equal(contract.native_storage.authenticated_account_required, true) + assert.equal(contract.native_storage.cross_account_projection_allowed, false) + assert.ok(contract.required_real_engines.includes('CHAPTER_VERSION_HISTORY')) + assert.ok(contract.required_real_engines.includes('CONTINUITY_AUDIT')) + assert.ok(contract.forbidden_substitutes.includes('UI_ONLY_BUTTONS_WITHOUT_NATIVE_COMMANDS')) + assert.equal(contract.ontology_correction.this_contract_is_not, 'USER_CHANNEL_BODY') + assert.equal(contract.ontology_correction.author_editor_operator_are_ui_tabs, false) + assert.equal(contract.distribution_boundary.preinstalled, 'LIGHT_AUTHOR_WORKBENCH_WITH_REAL_ENGINE') + assert.equal(contract.distribution_boundary.current_advanced_features_are_registered_marketplace_modules, false) + const industry = routing.industries.find((item) => item.key === 'WEB_NOVEL') + assert.equal(industry.industry_number, 'IND-WEBNOVEL-001') + assert.equal(industry.initialization_channel.legacy_projection_only, false) + assert.equal(industry.initialization_channel.installed_native_modules, 1) + assert.equal(industry.initialization_channel.module_slots[0].slot_id, 'WEBNOVEL-AUTHOR-LIGHT') +}) + +test('user channel contract is a durable multi-persona body rather than a module manifest', () => { + assert.equal(channelBody.state, 'FOUNDATION_RUNTIME_PARTIAL_ACCEPTANCE_PENDING') + assert.equal(channelBody.core_cardinality.language_cores_per_human, 1) + assert.equal(channelBody.core_cardinality.persona_cores_per_language_core, 1) + assert.equal(channelBody.core_cardinality.persona_entities_per_persona_core, 'MANY') + assert.equal(channelBody.persona_entity_boundary.role_template_creates_mature_persona, false) + assert.equal(channelBody.persona_entity_boundary.task_agent_is_persona, false) + assert.equal(channelBody.task_projection.workbench_is_channel_body, false) + assert.equal(channelBody.built_in_organs_policy.built_in_organs_allowed, true) + assert.equal(channelBody.module_ecosystem.official_module_number_before_real_acceptance, false) + assert.ok(channelBody.forbidden_substitutes.includes('DECLARATIVE_MODULE_MANIFEST_AS_CHANNEL_BODY')) + assert.ok(channelBody.acceptance_required.includes('TWO_PERSONAS_WITH_ISOLATED_GROWTH_MEMORY')) +}) + +test('the lightweight author workbench is built in while complete author capabilities stay numbered marketplace candidates', () => { + assert.equal(marketplace.built_in_light_author_workbench.distribution, 'PREINSTALLED') + assert.equal(marketplace.built_in_light_author_workbench.real_engine_owner, 'HOLOLAKE_NATIVE_RUST_SQLITE') + assert.ok(marketplace.built_in_light_author_workbench.capabilities.includes('REAL_CHAPTER_TEXT_EDITING')) + assert.equal(marketplace.official_module_candidates.length, 4) + for (const candidate of marketplace.official_module_candidates) { + assert.match(candidate.module_number, /^HL-MOD-WEBNOVEL-/) + assert.equal(candidate.numbering_state, 'CANDIDATE_NUMBER_NOT_OFFICIALLY_REGISTERED') + } + assert.deepEqual(marketplace.publication_gate.slice(-3), [ + 'THEN_ASSIGN_PERMANENT_MODULE_NUMBER', + 'THEN_REGISTER_OFFICIAL_MODULE_REGISTRY', + 'THEN_PUBLISH_OFFICIAL_MARKETPLACE', + ]) + assert.ok(marketplace.channel_deployment_flow.includes('MOUNT_IN_CURRENT_CHANNEL')) + assert.equal(marketplace.data_boundary.uninstall_preserves_story_data_and_receipts, true) +}) + +test('the desktop workbench invokes a registered native engine for every primary workflow', () => { + const commands = [ + 'get_web_novel_workspace_snapshot', + 'create_web_novel_work', + 'create_web_novel_volume', + 'create_web_novel_chapter', + 'save_web_novel_chapter', + 'transition_web_novel_chapter', + 'create_web_novel_checkpoint', + 'restore_web_novel_checkpoint', + 'upsert_web_novel_story_entity', + 'create_web_novel_story_relation', + 'upsert_web_novel_foreshadow', + 'create_web_novel_review_note', + 'resolve_web_novel_review_note', + 'save_web_novel_metric', + 'run_web_novel_continuity_audit', + 'export_web_novel_markdown', + ] + for (const command of commands) { + assert.match(rust, new RegExp(`fn ${command}`), `missing Rust implementation: ${command}`) + assert.match(rustLibrary, new RegExp(`web_novel_workspace::${command}`), `missing Tauri registration: ${command}`) + assert.match(workspaceUi, new RegExp(`['\"]${command}['\"]`), `missing UI invocation: ${command}`) + } + assert.match(rust, /account_storage_root\(app, "web-novel-workspace-v1"\)/) + assert.match(rust, /HOLOLAKE_WEBNOVEL_CHAPTER_REVISION_CONFLICT/) + assert.match(rust, /web_novel_chapter_versions/) + assert.match(workspaceUi, /window\.setTimeout\(\(\) => void flushChapterSave\(\), 650\)/) + assert.match(workspaceUi, /role=\{createFeedback\.state === 'error' \? 'alert' : 'status'\}/) + assert.match(workspaceUi, /正在建立作品与第一卷/) + assert.match(workspaceUi, /作品没有创建:/) + assert.match(workspaceUi, /第一卷已经可以开始写作/) + assert.match(mainUi, /worldStage === 'webNovelWorkspace'/) +}) + +test('author formatting is automatic on import, selectable, reversible, and can cover the whole work', () => { + for (const command of ['format_web_novel_chapter', 'format_web_novel_work']) { + assert.match(authorRust, new RegExp(`fn ${command}`)) + assert.match(rustLibrary, new RegExp(`web_novel_author::${command}`)) + assert.match(workspaceUi, new RegExp(`['"]${command}['"]`)) + } + assert.match(authorRust, /formatted\.join\("\\n\\n"\)/) + assert.match(read('src-tauri/src/web_novel_import.rs'), /AUTO_FORMAT_ON_IMPORT/) + assert.match(workspaceUi, /细纲结构视图/) + assert.match(read('src/AuthorWritingSidecar.tsx'), /一键排版整部作品/) +}) + +test('author modules are immutable packages with native install mount data and uninstall engines', () => { + const modules = [ + ['HL-MOD-WEBNOVEL-OUTLINE-001', '6d31d3f530862000bd84a8f5dc73bcb9cf0d5738219f7a287562d4f4bcfa5318'], + ['HL-MOD-WEBNOVEL-GRID-002', '2e34e0337c51dbbdd1efdd807be71e69a0cb2a1745624e1f51b452b7b54f1553'], + ['HL-MOD-WEBNOVEL-STORYWORLD-003', 'd486719500ddfc08054d9c9bb6d3683afe5547a2b24c9b04d0f899ac66094d2f'], + ['HL-MOD-WEBNOVEL-DELIVERY-004', '4af1d4610826edd29759bd0dc12b4b0c04fd2ebebb4ebc362d47d762810989e8'], + ] + for (const [moduleId, expectedSha] of modules) { + const bytes = fs.readFileSync(new URL(`../official-modules/web-novel/${moduleId}/1.0.0/module.json`, import.meta.url)) + const manifest = JSON.parse(bytes.toString('utf8')) + assert.equal(manifest.moduleId, moduleId) + assert.equal(crypto.createHash('sha256').update(bytes).digest('hex'), expectedSha) + assert.match(moduleRust, new RegExp(expectedSha)) + } + assert.match(moduleRust, /web_novel_module_installations/) + assert.match(moduleRust, /web_novel_module_receipts/) + assert.match(moduleRust, /require_mounted/) + assert.match(moduleRust, /USER_DATA_REMAINS_AFTER_UNINSTALL|作品、模块数据和历史回执保持/) + assert.match(moduleRust, /RESTORED_FROM_VERSION/) + assert.match(moduleRust, /render_docx/) + assert.match(moduleRust, /render_epub/) +}) + +test('every author module action is registered and invoked by the live channel workbench', () => { + const commands = [ + 'get_web_novel_author_module_marketplace', + 'install_web_novel_author_module', + 'mount_web_novel_author_module', + 'unmount_web_novel_author_module', + 'uninstall_web_novel_author_module', + 'get_web_novel_author_module_data', + 'upsert_web_novel_author_scene', + 'upsert_web_novel_author_beat', + 'upsert_web_novel_story_field_definition', + 'upsert_web_novel_story_field_value', + 'upsert_web_novel_timeline_event', + 'link_web_novel_scene_entity', + 'restore_web_novel_chapter_version', + 'export_web_novel_author_delivery', + ] + for (const command of commands) { + assert.match(moduleRust, new RegExp(`fn ${command}`), `missing module engine: ${command}`) + assert.match(rustLibrary, new RegExp(`web_novel_modules::${command}`), `missing module registration: ${command}`) + assert.match(moduleUi, new RegExp(`['"]${command}['"]`), `missing module UI invocation: ${command}`) + } + assert.match(workspaceUi, / Result { - let bytes = STANDARD - .decode(value.trim()) - .map_err(|error| format!("{label}_BASE64_INVALID: {error}"))?; - String::from_utf8(bytes).map_err(|error| format!("{label}_UTF8_INVALID: {error}")) -} - -fn main() -> Result<(), String> { - let arguments: Vec = env::args().collect(); - let [_, trust_path, updater_path, signature_path] = arguments.as_slice() else { - return Err( - "USAGE: verify_updater_signature " - .to_string(), - ); - }; - let trust: Value = serde_json::from_str( - &fs::read_to_string(trust_path) - .map_err(|error| format!("RELEASE_TRUST_READ_FAILED: {error}"))?, - ) - .map_err(|error| format!("RELEASE_TRUST_JSON_INVALID: {error}"))?; - let encoded_public_key = trust - .get("publicKey") - .and_then(Value::as_str) - .ok_or_else(|| "RELEASE_TRUST_PUBLIC_KEY_MISSING".to_string())?; - let public_key = PublicKey::decode(&decode_outer_base64( - encoded_public_key, - "RELEASE_TRUST_PUBLIC_KEY", - )?) - .map_err(|error| format!("RELEASE_TRUST_PUBLIC_KEY_INVALID: {error}"))?; - let signature = Signature::decode(&decode_outer_base64( - &fs::read_to_string(signature_path) - .map_err(|error| format!("UPDATER_SIGNATURE_READ_FAILED: {error}"))?, - "UPDATER_SIGNATURE", - )?) - .map_err(|error| format!("UPDATER_SIGNATURE_INVALID: {error}"))?; - let updater = fs::read(Path::new(updater_path)) - .map_err(|error| format!("UPDATER_ARTIFACT_READ_FAILED: {error}"))?; - public_key - .verify(&updater, &signature, true) - .map_err(|error| format!("UPDATER_SIGNATURE_VERIFICATION_FAILED: {error}"))?; - println!("HOLOLAKE_UPDATER_SIGNATURE_VERIFIED"); - Ok(()) -} diff --git a/product-source/hololake-native-desktop/src-tauri/permissions/numbered-ipc.toml b/product-source/hololake-native-desktop/src-tauri/permissions/numbered-ipc.toml deleted file mode 100644 index 3c562d10a..000000000 --- a/product-source/hololake-native-desktop/src-tauri/permissions/numbered-ipc.toml +++ /dev/null @@ -1,5 +0,0 @@ -[[permission]] -identifier = "allow-numbered-ipc" -description = "Allow the main HoloLake webview to use the single numbered IPC gateway." -commands.allow = ["numbered_ipc"] - diff --git a/product-source/hololake-native-desktop/src-tauri/persona-control-authorization-signers.json b/product-source/hololake-native-desktop/src-tauri/persona-control-authorization-signers.json deleted file mode 100644 index 41e22b526..000000000 --- a/product-source/hololake-native-desktop/src-tauri/persona-control-authorization-signers.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "schema": "gh-aios.persona-control-authorization-signers/v1", - "registryId": "GH-AIOS-PERSONA-CONTROL-AUTHORIZATION-SIGNERS-001", - "state": "CURRENT", - "signers": [] -} diff --git a/product-source/hololake-native-desktop/src-tauri/src/channel_growth.rs b/product-source/hololake-native-desktop/src-tauri/src/channel_growth.rs index c8ed06cec..7c8fb9dd2 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/channel_growth.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/channel_growth.rs @@ -8,8 +8,6 @@ use ring::digest::{digest, SHA256}; use rusqlite::{params, Connection}; use serde::{Deserialize, Serialize}; -use std::cmp::Ordering; -use std::collections::BTreeMap; use std::fs; use std::path::{Path, PathBuf}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -18,15 +16,9 @@ use uuid::Uuid; const GROWTH_SCHEMA: &str = "hololake.channel-growth-model/v1"; const ZERO_HASH: &str = "0000000000000000000000000000000000000000000000000000000000000000"; -const MODULE_NUMBER: &str = "HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001"; -const ADAPTER: &str = "persona-channel-body-v1"; - -fn require_active(app: &AppHandle) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, MODULE_NUMBER, ADAPTER) -} #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct RecordChannelGrowthEventInput { pub event_kind: String, pub module_id: String, @@ -34,7 +26,7 @@ pub struct RecordChannelGrowthEventInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct UpdateChannelGrowthSharingInput { pub sharing_mode: String, } @@ -74,30 +66,30 @@ pub struct ChannelGrowthSnapshot { pub data_boundary: &'static str, } +#[tauri::command] pub async fn get_channel_growth_snapshot(app: AppHandle) -> Result { - require_active(&app)?; let database = channel_growth_database(&app)?; tauri::async_runtime::spawn_blocking(move || snapshot_at(&database)) .await .map_err(|error| format!("HOLOLAKE_CHANNEL_GROWTH_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn record_channel_growth_event( app: AppHandle, input: RecordChannelGrowthEventInput, ) -> Result { - require_active(&app)?; let database = channel_growth_database(&app)?; tauri::async_runtime::spawn_blocking(move || record_event_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_CHANNEL_GROWTH_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn update_channel_growth_sharing( app: AppHandle, input: UpdateChannelGrowthSharingInput, ) -> Result { - require_active(&app)?; let database = channel_growth_database(&app)?; tauri::async_runtime::spawn_blocking(move || update_sharing_at(&database, input)) .await @@ -256,7 +248,6 @@ fn snapshot_at(database: &Path) -> Result { fn snapshot_with_connection(connection: &Connection) -> Result { let last_event_hash = verify_event_chain(connection)?; - let mut affinities = verify_and_project_affinities(connection)?; let controls = connection .query_row( "SELECT sharing_mode FROM growth_sharing WHERE singleton = 1", @@ -281,15 +272,21 @@ fn snapshot_with_connection(connection: &Connection) -> Result, _>>() + .map_err(|error| format!("HOLOLAKE_CHANNEL_GROWTH_READ_FAILED: {error}"))?; let recommended_module_order = affinities .iter() .map(|item| item.module_id.clone()) @@ -302,7 +299,7 @@ fn snapshot_with_connection(connection: &Connection) -> Result Result Result, String> { - let mut projected = BTreeMap::::new(); - let mut event_statement = connection - .prepare( - "SELECT module_id, source, occurred_at_unix_ms FROM growth_events ORDER BY sequence", - ) - .map_err(|error| format!("HOLOLAKE_CHANNEL_GROWTH_READ_FAILED: {error}"))?; - let events = event_statement - .query_map([], |row| { - Ok(( - row.get::<_, String>(0)?, - row.get::<_, String>(1)?, - row.get::<_, i64>(2)?, - )) - }) - .map_err(|error| format!("HOLOLAKE_CHANNEL_GROWTH_READ_FAILED: {error}"))? - .collect::, _>>() - .map_err(|error| format!("HOLOLAKE_CHANNEL_GROWTH_READ_FAILED: {error}"))?; - for (module_id, source, occurred_at) in events { - let weight = if source == "PERSONA_COLLABORATION" { - 1.4 - } else { - 1.0 - }; - projected - .entry(module_id.clone()) - .and_modify(|item| { - item.use_count += 1; - item.score = item.score * 0.985 + weight; - item.last_used_at_unix_ms = occurred_at; - }) - .or_insert(ChannelModuleAffinity { - module_id, - use_count: 1, - score: weight, - last_used_at_unix_ms: occurred_at, - }); - } - - let mut stored_statement = connection - .prepare( - "SELECT module_id, use_count, score, last_used_at_unix_ms FROM module_affinities ORDER BY module_id", - ) - .map_err(|error| format!("HOLOLAKE_CHANNEL_GROWTH_READ_FAILED: {error}"))?; - let stored = stored_statement - .query_map([], |row| { - Ok(ChannelModuleAffinity { - module_id: row.get(0)?, - use_count: row.get(1)?, - score: row.get(2)?, - last_used_at_unix_ms: row.get(3)?, - }) - }) - .map_err(|error| format!("HOLOLAKE_CHANNEL_GROWTH_READ_FAILED: {error}"))? - .collect::, _>>() - .map_err(|error| format!("HOLOLAKE_CHANNEL_GROWTH_READ_FAILED: {error}"))?; - if stored.len() != projected.len() - || stored.iter().any(|item| { - projected.get(&item.module_id).map_or(true, |expected| { - item.use_count != expected.use_count - || (item.score - expected.score).abs() > 1e-12 - || item.last_used_at_unix_ms != expected.last_used_at_unix_ms - }) - }) - { - return Err("HOLOLAKE_CHANNEL_GROWTH_PROJECTION_INTEGRITY_FAILED".into()); - } - Ok(projected.into_values().collect()) -} - fn event_hash( sequence: i64, event_id: &str, @@ -529,31 +454,7 @@ mod tests { .is_err()); assert_eq!( snapshot_at(&database).unwrap().integrity_state, - "VERIFIED_APPEND_ONLY_CHAIN_AND_DERIVED_PROJECTION" - ); - } - - #[test] - fn derived_affinity_projection_fails_closed_when_modified_outside_the_event_path() { - let dir = tempdir().unwrap(); - let database = dir.path().join("growth.sqlite3"); - record_event_at( - &database, - RecordChannelGrowthEventInput { - event_kind: "MODULE_OPEN".into(), - module_id: "knowledge".into(), - source: "HUMAN_ACTION".into(), - }, - ) - .unwrap(); - let connection = open_database(&database).unwrap(); - connection - .execute("UPDATE module_affinities SET score = 999", []) - .unwrap(); - drop(connection); - assert_eq!( - snapshot_at(&database).unwrap_err(), - "HOLOLAKE_CHANNEL_GROWTH_PROJECTION_INTEGRITY_FAILED" + "VERIFIED_APPEND_ONLY_CHAIN" ); } diff --git a/product-source/hololake-native-desktop/src-tauri/src/channel_workbench.rs b/product-source/hololake-native-desktop/src-tauri/src/channel_workbench.rs deleted file mode 100644 index 00c6a4dff..000000000 --- a/product-source/hololake-native-desktop/src-tauri/src/channel_workbench.rs +++ /dev/null @@ -1,694 +0,0 @@ -//! Signed channel document and spreadsheet workbench adapter. -//! -//! The signed package only selects this host-owned adapter. User content stays in -//! the authenticated account root and every accepted save is committed together -//! with a hash-chained receipt. Unmounting the package never removes that data. - -use ring::digest::{digest, SHA256}; -use rusqlite::{params, Connection, OptionalExtension, Transaction}; -use serde::{Deserialize, Serialize}; -use std::fs; -use std::path::{Path, PathBuf}; -use std::time::{SystemTime, UNIX_EPOCH}; -use tauri::AppHandle; -use uuid::Uuid; - -const MODULE_NUMBER: &str = "HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001"; -const ADAPTER: &str = "channel-workbench-v1"; -const ZERO_HASH: &str = "0000000000000000000000000000000000000000000000000000000000000000"; -const MAX_BODY_BYTES: usize = 2 * 1024 * 1024; -const MAX_COLUMNS: usize = 64; -const MAX_ROWS: usize = 5_000; -const MAX_CELL_BYTES: usize = 64 * 1024; - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct WorkbenchColumn { - pub column_id: String, - pub title: String, -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct WorkbenchRow { - pub row_id: String, - pub cells: Vec, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ChannelDocument { - document_id: String, - title: String, - body: String, - revision: u64, - updated_at_unix_ms: u64, - content_sha256: String, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ChannelSpreadsheet { - table_id: String, - title: String, - columns: Vec, - rows: Vec, - revision: u64, - updated_at_unix_ms: u64, - content_sha256: String, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ChannelWorkbenchSnapshot { - schema: &'static str, - state: &'static str, - module_number: &'static str, - document: ChannelDocument, - spreadsheet: ChannelSpreadsheet, - receipt_count: u64, - latest_receipt_hash: String, - user_data_survives_unmount: bool, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct SaveChannelDocumentInput { - document_id: String, - title: String, - body: String, - expected_revision: u64, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct SaveChannelSpreadsheetInput { - table_id: String, - title: String, - columns: Vec, - rows: Vec, - expected_revision: u64, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct WorkbenchSaveResult { - schema: &'static str, - state: &'static str, - entity_kind: &'static str, - entity_id: String, - revision: u64, - content_sha256: String, - receipt_sha256: String, - observed_at_unix_ms: u64, -} - -fn now_unix_ms() -> u64 { - SystemTime::now() - .duration_since(UNIX_EPOCH) - .map(|duration| duration.as_millis() as u64) - .unwrap_or(0) -} - -fn sha256_hex(bytes: &[u8]) -> String { - digest(&SHA256, bytes) - .as_ref() - .iter() - .map(|byte| format!("{byte:02x}")) - .collect() -} - -fn storage_root(app: &AppHandle) -> Result { - crate::authenticated_storage::account_storage_root(app, "channel-workbench-v1") -} - -fn require_active(app: &AppHandle) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, MODULE_NUMBER, ADAPTER) -} - -fn open_db(root: &Path) -> Result { - fs::create_dir_all(root) - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_ROOT_FAILED: {error}"))?; - #[cfg(unix)] - { - use std::os::unix::fs::PermissionsExt; - fs::set_permissions(root, fs::Permissions::from_mode(0o700)) - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_PERMISSION_FAILED: {error}"))?; - } - let connection = Connection::open(root.join("channel-workbench.sqlite3")) - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_DB_OPEN_FAILED: {error}"))?; - connection - .busy_timeout(std::time::Duration::from_secs(5)) - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_DB_TIMEOUT_FAILED: {error}"))?; - connection - .execute_batch( - "PRAGMA journal_mode=WAL; - PRAGMA foreign_keys=ON; - CREATE TABLE IF NOT EXISTS documents( - document_id TEXT PRIMARY KEY, - title TEXT NOT NULL, - body TEXT NOT NULL, - revision INTEGER NOT NULL, - updated_at_unix_ms INTEGER NOT NULL, - content_sha256 TEXT NOT NULL - ); - CREATE TABLE IF NOT EXISTS spreadsheets( - table_id TEXT PRIMARY KEY, - title TEXT NOT NULL, - columns_json TEXT NOT NULL, - rows_json TEXT NOT NULL, - revision INTEGER NOT NULL, - updated_at_unix_ms INTEGER NOT NULL, - content_sha256 TEXT NOT NULL - ); - CREATE TABLE IF NOT EXISTS workbench_receipts( - sequence INTEGER PRIMARY KEY AUTOINCREMENT, - receipt_id TEXT NOT NULL UNIQUE, - event TEXT NOT NULL, - entity_kind TEXT NOT NULL, - entity_id TEXT NOT NULL, - revision INTEGER NOT NULL, - content_sha256 TEXT NOT NULL, - previous_receipt_hash TEXT NOT NULL, - receipt_hash TEXT NOT NULL UNIQUE, - observed_at_unix_ms INTEGER NOT NULL - ); - CREATE TRIGGER IF NOT EXISTS workbench_receipts_no_update - BEFORE UPDATE ON workbench_receipts BEGIN SELECT RAISE(ABORT,'HOLOLAKE_WORKBENCH_RECEIPT_APPEND_ONLY'); END; - CREATE TRIGGER IF NOT EXISTS workbench_receipts_no_delete - BEFORE DELETE ON workbench_receipts BEGIN SELECT RAISE(ABORT,'HOLOLAKE_WORKBENCH_RECEIPT_APPEND_ONLY'); END;", - ) - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_DB_INIT_FAILED: {error}"))?; - Ok(connection) -} - -fn valid_object_id(value: &str, prefix: &str) -> bool { - value.starts_with(prefix) - && value.len() <= 96 - && value - .chars() - .all(|item| item.is_ascii_uppercase() || item.is_ascii_digit() || item == '-') -} - -fn valid_title(value: &str) -> bool { - !value.trim().is_empty() && value.len() <= 120 && !value.chars().any(char::is_control) -} - -fn receipt_hash( - event: &str, - entity_kind: &str, - entity_id: &str, - revision: u64, - content_sha256: &str, - previous: &str, - observed: u64, -) -> String { - sha256_hex( - format!( - "{event}\n{entity_kind}\n{entity_id}\n{revision}\n{content_sha256}\n{previous}\n{observed}" - ) - .as_bytes(), - ) -} - -fn verify_receipts(connection: &Connection) -> Result<(u64, String), String> { - let mut statement = connection - .prepare("SELECT sequence,event,entity_kind,entity_id,revision,content_sha256,previous_receipt_hash,receipt_hash,observed_at_unix_ms FROM workbench_receipts ORDER BY sequence") - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_RECEIPT_READ_FAILED: {error}"))?; - let rows = statement - .query_map([], |row| { - Ok(( - row.get::<_, u64>(0)?, - row.get::<_, String>(1)?, - row.get::<_, String>(2)?, - row.get::<_, String>(3)?, - row.get::<_, u64>(4)?, - row.get::<_, String>(5)?, - row.get::<_, String>(6)?, - row.get::<_, String>(7)?, - row.get::<_, u64>(8)?, - )) - }) - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_RECEIPT_READ_FAILED: {error}"))?; - let mut count = 0; - let mut previous = ZERO_HASH.to_string(); - for row in rows { - let (sequence, event, kind, id, revision, content, stored_previous, stored_hash, observed) = - row.map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_RECEIPT_READ_FAILED: {error}"))?; - if sequence != count + 1 - || stored_previous != previous - || stored_hash - != receipt_hash(&event, &kind, &id, revision, &content, &previous, observed) - { - return Err("HOLOLAKE_CHANNEL_WORKBENCH_RECEIPT_CHAIN_INVALID".into()); - } - count = sequence; - previous = stored_hash; - } - Ok((count, previous)) -} - -fn append_receipt( - tx: &Transaction<'_>, - event: &str, - kind: &str, - id: &str, - revision: u64, - content: &str, - observed: u64, -) -> Result { - let previous: String = tx - .query_row( - "SELECT COALESCE((SELECT receipt_hash FROM workbench_receipts ORDER BY sequence DESC LIMIT 1),?1)", - params![ZERO_HASH], - |row| row.get(0), - ) - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_RECEIPT_HEAD_FAILED: {error}"))?; - let hash = receipt_hash(event, kind, id, revision, content, &previous, observed); - tx.execute( - "INSERT INTO workbench_receipts(receipt_id,event,entity_kind,entity_id,revision,content_sha256,previous_receipt_hash,receipt_hash,observed_at_unix_ms) VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9)", - params![format!("HLP-WB-RCP-{}", Uuid::new_v4().simple()), event, kind, id, revision, content, previous, hash, observed], - ) - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_RECEIPT_WRITE_FAILED: {error}"))?; - Ok(hash) -} - -fn empty_document() -> ChannelDocument { - ChannelDocument { - document_id: "HLP-WB-DOC-0001".into(), - title: "频道笔记".into(), - body: "".into(), - revision: 0, - updated_at_unix_ms: 0, - content_sha256: sha256_hex(b""), - } -} - -fn empty_spreadsheet() -> ChannelSpreadsheet { - ChannelSpreadsheet { - table_id: "HLP-WB-TBL-0001".into(), - title: "频道工作表".into(), - columns: vec![ - WorkbenchColumn { - column_id: "HLP-WB-COL-0001".into(), - title: "事项".into(), - }, - WorkbenchColumn { - column_id: "HLP-WB-COL-0002".into(), - title: "状态".into(), - }, - ], - rows: Vec::new(), - revision: 0, - updated_at_unix_ms: 0, - content_sha256: sha256_hex(b""), - } -} - -fn snapshot_at(root: &Path) -> Result { - let connection = open_db(root)?; - let (receipt_count, latest_receipt_hash) = verify_receipts(&connection)?; - let document = connection - .query_row( - "SELECT document_id,title,body,revision,updated_at_unix_ms,content_sha256 FROM documents ORDER BY updated_at_unix_ms DESC LIMIT 1", - [], - |row| Ok(ChannelDocument { document_id: row.get(0)?, title: row.get(1)?, body: row.get(2)?, revision: row.get(3)?, updated_at_unix_ms: row.get(4)?, content_sha256: row.get(5)? }), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_CHANNEL_DOCUMENT_READ_FAILED: {error}"))? - .unwrap_or_else(empty_document); - let spreadsheet = connection - .query_row( - "SELECT table_id,title,columns_json,rows_json,revision,updated_at_unix_ms,content_sha256 FROM spreadsheets ORDER BY updated_at_unix_ms DESC LIMIT 1", - [], - |row| Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?, row.get::<_, String>(2)?, row.get::<_, String>(3)?, row.get::<_, u64>(4)?, row.get::<_, u64>(5)?, row.get::<_, String>(6)?)), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_CHANNEL_SPREADSHEET_READ_FAILED: {error}"))? - .map(|(table_id, title, columns, rows, revision, updated_at_unix_ms, content_sha256)| { - Ok::(ChannelSpreadsheet { - table_id, - title, - columns: serde_json::from_str(&columns).map_err(|_| "HOLOLAKE_CHANNEL_SPREADSHEET_COLUMNS_INVALID".to_string())?, - rows: serde_json::from_str(&rows).map_err(|_| "HOLOLAKE_CHANNEL_SPREADSHEET_ROWS_INVALID".to_string())?, - revision, - updated_at_unix_ms, - content_sha256, - }) - }) - .transpose()? - .unwrap_or_else(empty_spreadsheet); - if document.revision > 0 { - let actual = sha256_hex( - serde_json::to_string(&(document.title.trim(), &document.body)) - .map_err(|_| "HOLOLAKE_CHANNEL_DOCUMENT_SERIALIZE_FAILED")? - .as_bytes(), - ); - if actual != document.content_sha256 { - return Err("HOLOLAKE_CHANNEL_DOCUMENT_CONTENT_INTEGRITY_INVALID".into()); - } - } - if spreadsheet.revision > 0 { - let actual = sha256_hex( - serde_json::to_string(&( - spreadsheet.title.trim(), - &spreadsheet.columns, - &spreadsheet.rows, - )) - .map_err(|_| "HOLOLAKE_CHANNEL_SPREADSHEET_SERIALIZE_FAILED")? - .as_bytes(), - ); - if actual != spreadsheet.content_sha256 { - return Err("HOLOLAKE_CHANNEL_SPREADSHEET_CONTENT_INTEGRITY_INVALID".into()); - } - } - let mut latest = connection - .prepare("SELECT entity_kind,entity_id,revision,content_sha256 FROM workbench_receipts WHERE sequence IN (SELECT MAX(sequence) FROM workbench_receipts GROUP BY entity_kind,entity_id)") - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_RECEIPT_READ_FAILED: {error}"))?; - let heads = latest - .query_map([], |row| { - Ok(( - row.get::<_, String>(0)?, - row.get::<_, String>(1)?, - row.get::<_, u64>(2)?, - row.get::<_, String>(3)?, - )) - }) - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_RECEIPT_READ_FAILED: {error}"))?; - for head in heads { - let (kind, id, revision, content) = head - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_RECEIPT_READ_FAILED: {error}"))?; - let matches = match kind.as_str() { - "DOCUMENT" => { - document.document_id == id - && document.revision == revision - && document.content_sha256 == content - } - "SPREADSHEET" => { - spreadsheet.table_id == id - && spreadsheet.revision == revision - && spreadsheet.content_sha256 == content - } - _ => false, - }; - if !matches { - return Err("HOLOLAKE_CHANNEL_WORKBENCH_CURRENT_STATE_INVALID".into()); - } - } - Ok(ChannelWorkbenchSnapshot { - schema: "hololake.channel-workbench-snapshot/v1", - state: "ACTIVE_LOCAL_ACCOUNT_DATA", - module_number: MODULE_NUMBER, - document, - spreadsheet, - receipt_count, - latest_receipt_hash, - user_data_survives_unmount: true, - }) -} - -fn save_document_at( - root: &Path, - input: SaveChannelDocumentInput, - observed: u64, -) -> Result { - if !valid_object_id(&input.document_id, "HLP-WB-DOC-") - || !valid_title(&input.title) - || input.body.len() > MAX_BODY_BYTES - { - return Err("HOLOLAKE_CHANNEL_DOCUMENT_INPUT_INVALID".into()); - } - let mut connection = open_db(root)?; - verify_receipts(&connection)?; - let transaction = connection - .transaction() - .map_err(|error| format!("HOLOLAKE_CHANNEL_DOCUMENT_TRANSACTION_FAILED: {error}"))?; - let current: Option = transaction - .query_row( - "SELECT revision FROM documents WHERE document_id=?1", - params![input.document_id], - |row| row.get(0), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_CHANNEL_DOCUMENT_READ_FAILED: {error}"))?; - if current.unwrap_or(0) != input.expected_revision { - return Err("HOLOLAKE_CHANNEL_DOCUMENT_REVISION_CONFLICT".into()); - } - let revision = input.expected_revision + 1; - let content = sha256_hex( - serde_json::to_string(&(input.title.trim(), &input.body)) - .map_err(|_| "HOLOLAKE_CHANNEL_DOCUMENT_SERIALIZE_FAILED")? - .as_bytes(), - ); - transaction.execute( - "INSERT INTO documents VALUES (?1,?2,?3,?4,?5,?6) ON CONFLICT(document_id) DO UPDATE SET title=excluded.title,body=excluded.body,revision=excluded.revision,updated_at_unix_ms=excluded.updated_at_unix_ms,content_sha256=excluded.content_sha256", - params![input.document_id, input.title.trim(), input.body, revision, observed, content], - ).map_err(|error| format!("HOLOLAKE_CHANNEL_DOCUMENT_WRITE_FAILED: {error}"))?; - let receipt = append_receipt( - &transaction, - if current.is_some() { - "UPDATE" - } else { - "CREATE" - }, - "DOCUMENT", - &input.document_id, - revision, - &content, - observed, - )?; - transaction - .commit() - .map_err(|error| format!("HOLOLAKE_CHANNEL_DOCUMENT_COMMIT_FAILED: {error}"))?; - Ok(WorkbenchSaveResult { - schema: "hololake.channel-workbench-save/v1", - state: "COMMITTED", - entity_kind: "DOCUMENT", - entity_id: input.document_id, - revision, - content_sha256: content, - receipt_sha256: receipt, - observed_at_unix_ms: observed, - }) -} - -fn validate_spreadsheet(input: &SaveChannelSpreadsheetInput) -> Result<(), String> { - if !valid_object_id(&input.table_id, "HLP-WB-TBL-") - || !valid_title(&input.title) - || input.columns.is_empty() - || input.columns.len() > MAX_COLUMNS - || input.rows.len() > MAX_ROWS - || input.columns.iter().any(|column| { - !valid_object_id(&column.column_id, "HLP-WB-COL-") || !valid_title(&column.title) - }) - || input.rows.iter().any(|row| { - !valid_object_id(&row.row_id, "HLP-WB-ROW-") - || row.cells.len() > input.columns.len() - || row.cells.iter().any(|cell| cell.len() > MAX_CELL_BYTES) - }) - { - return Err("HOLOLAKE_CHANNEL_SPREADSHEET_INPUT_INVALID".into()); - } - Ok(()) -} - -fn save_spreadsheet_at( - root: &Path, - input: SaveChannelSpreadsheetInput, - observed: u64, -) -> Result { - validate_spreadsheet(&input)?; - let mut connection = open_db(root)?; - verify_receipts(&connection)?; - let transaction = connection - .transaction() - .map_err(|error| format!("HOLOLAKE_CHANNEL_SPREADSHEET_TRANSACTION_FAILED: {error}"))?; - let current: Option = transaction - .query_row( - "SELECT revision FROM spreadsheets WHERE table_id=?1", - params![input.table_id], - |row| row.get(0), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_CHANNEL_SPREADSHEET_READ_FAILED: {error}"))?; - if current.unwrap_or(0) != input.expected_revision { - return Err("HOLOLAKE_CHANNEL_SPREADSHEET_REVISION_CONFLICT".into()); - } - let revision = input.expected_revision + 1; - let columns = serde_json::to_string(&input.columns) - .map_err(|_| "HOLOLAKE_CHANNEL_SPREADSHEET_SERIALIZE_FAILED")?; - let rows = serde_json::to_string(&input.rows) - .map_err(|_| "HOLOLAKE_CHANNEL_SPREADSHEET_SERIALIZE_FAILED")?; - let content = sha256_hex( - serde_json::to_string(&(input.title.trim(), &input.columns, &input.rows)) - .map_err(|_| "HOLOLAKE_CHANNEL_SPREADSHEET_SERIALIZE_FAILED")? - .as_bytes(), - ); - transaction.execute( - "INSERT INTO spreadsheets VALUES (?1,?2,?3,?4,?5,?6,?7) ON CONFLICT(table_id) DO UPDATE SET title=excluded.title,columns_json=excluded.columns_json,rows_json=excluded.rows_json,revision=excluded.revision,updated_at_unix_ms=excluded.updated_at_unix_ms,content_sha256=excluded.content_sha256", - params![input.table_id, input.title.trim(), columns, rows, revision, observed, content], - ).map_err(|error| format!("HOLOLAKE_CHANNEL_SPREADSHEET_WRITE_FAILED: {error}"))?; - let receipt = append_receipt( - &transaction, - if current.is_some() { - "UPDATE" - } else { - "CREATE" - }, - "SPREADSHEET", - &input.table_id, - revision, - &content, - observed, - )?; - transaction - .commit() - .map_err(|error| format!("HOLOLAKE_CHANNEL_SPREADSHEET_COMMIT_FAILED: {error}"))?; - Ok(WorkbenchSaveResult { - schema: "hololake.channel-workbench-save/v1", - state: "COMMITTED", - entity_kind: "SPREADSHEET", - entity_id: input.table_id, - revision, - content_sha256: content, - receipt_sha256: receipt, - observed_at_unix_ms: observed, - }) -} - -pub async fn get_channel_workbench_snapshot( - app: AppHandle, -) -> Result { - require_active(&app)?; - let root = storage_root(&app)?; - tauri::async_runtime::spawn_blocking(move || snapshot_at(&root)) - .await - .map_err(|error| format!("HOLOLAKE_CHANNEL_WORKBENCH_JOIN_FAILED: {error}"))? -} - -pub async fn save_channel_document( - app: AppHandle, - input: SaveChannelDocumentInput, -) -> Result { - require_active(&app)?; - let root = storage_root(&app)?; - tauri::async_runtime::spawn_blocking(move || save_document_at(&root, input, now_unix_ms())) - .await - .map_err(|error| format!("HOLOLAKE_CHANNEL_DOCUMENT_JOIN_FAILED: {error}"))? -} - -pub async fn save_channel_spreadsheet( - app: AppHandle, - input: SaveChannelSpreadsheetInput, -) -> Result { - require_active(&app)?; - let root = storage_root(&app)?; - tauri::async_runtime::spawn_blocking(move || save_spreadsheet_at(&root, input, now_unix_ms())) - .await - .map_err(|error| format!("HOLOLAKE_CHANNEL_SPREADSHEET_JOIN_FAILED: {error}"))? -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn document_and_spreadsheet_survive_reopen_with_receipt_chain() { - let root = tempfile::tempdir().unwrap(); - let document = save_document_at( - root.path(), - SaveChannelDocumentInput { - document_id: "HLP-WB-DOC-0001".into(), - title: "真实笔记".into(), - body: "第一段真实内容".into(), - expected_revision: 0, - }, - 101, - ) - .unwrap(); - let sheet = save_spreadsheet_at( - root.path(), - SaveChannelSpreadsheetInput { - table_id: "HLP-WB-TBL-0001".into(), - title: "真实工作表".into(), - columns: vec![WorkbenchColumn { - column_id: "HLP-WB-COL-0001".into(), - title: "数量".into(), - }], - rows: vec![WorkbenchRow { - row_id: "HLP-WB-ROW-0001".into(), - cells: vec!["=1+2".into()], - }], - expected_revision: 0, - }, - 102, - ) - .unwrap(); - let snapshot = snapshot_at(root.path()).unwrap(); - assert_eq!(document.revision, 1); - assert_eq!(sheet.revision, 1); - assert_eq!(snapshot.document.body, "第一段真实内容"); - assert_eq!(snapshot.spreadsheet.rows[0].cells[0], "=1+2"); - assert_eq!(snapshot.receipt_count, 2); - assert_eq!(snapshot.latest_receipt_hash, sheet.receipt_sha256); - } - - #[test] - fn stale_revision_and_tampered_receipt_fail_closed() { - let root = tempfile::tempdir().unwrap(); - let input = SaveChannelDocumentInput { - document_id: "HLP-WB-DOC-0001".into(), - title: "笔记".into(), - body: "正文".into(), - expected_revision: 0, - }; - save_document_at(root.path(), input, 101).unwrap(); - assert_eq!( - save_document_at( - root.path(), - SaveChannelDocumentInput { - document_id: "HLP-WB-DOC-0001".into(), - title: "笔记".into(), - body: "过期写入".into(), - expected_revision: 0 - }, - 102 - ) - .unwrap_err(), - "HOLOLAKE_CHANNEL_DOCUMENT_REVISION_CONFLICT" - ); - let connection = open_db(root.path()).unwrap(); - connection.execute_batch("DROP TRIGGER workbench_receipts_no_update; UPDATE workbench_receipts SET receipt_hash='bad'").unwrap(); - assert_eq!( - snapshot_at(root.path()).unwrap_err(), - "HOLOLAKE_CHANNEL_WORKBENCH_RECEIPT_CHAIN_INVALID" - ); - } - - #[test] - fn content_mutation_without_a_receipt_fails_closed() { - let root = tempfile::tempdir().unwrap(); - save_document_at( - root.path(), - SaveChannelDocumentInput { - document_id: "HLP-WB-DOC-0001".into(), - title: "笔记".into(), - body: "可信正文".into(), - expected_revision: 0, - }, - 101, - ) - .unwrap(); - let connection = open_db(root.path()).unwrap(); - connection - .execute( - "UPDATE documents SET body='被改写' WHERE document_id='HLP-WB-DOC-0001'", - [], - ) - .unwrap(); - assert_eq!( - snapshot_at(root.path()).unwrap_err(), - "HOLOLAKE_CHANNEL_DOCUMENT_CONTENT_INTEGRITY_INVALID" - ); - } -} diff --git a/product-source/hololake-native-desktop/src-tauri/src/code_channel.rs b/product-source/hololake-native-desktop/src-tauri/src/code_channel.rs index f0da9be09..a6dd47cd7 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/code_channel.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/code_channel.rs @@ -120,6 +120,7 @@ struct ValidatedCloneUrl { repository: String, } +#[tauri::command] pub async fn get_code_channel_snapshot(app: AppHandle) -> Result { let root = code_channel_root(&app)?; tauri::async_runtime::spawn_blocking(move || snapshot_at(&root)) @@ -127,6 +128,7 @@ pub async fn get_code_channel_snapshot(app: AppHandle) -> Result Result, String> { @@ -162,6 +165,7 @@ pub async fn select_local_code_channel( .map_err(|error| format!("HOLOLAKE_CODE_CHANNEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn browse_code_channel( app: AppHandle, input: BrowseCodeChannelInput, @@ -172,6 +176,7 @@ pub async fn browse_code_channel( .map_err(|error| format!("HOLOLAKE_CODE_CHANNEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn read_code_channel_file( app: AppHandle, input: ReadCodeChannelFileInput, diff --git a/product-source/hololake-native-desktop/src-tauri/src/code_repo_login.rs b/product-source/hololake-native-desktop/src-tauri/src/code_repo_login.rs index bae44ad0e..bee6e8bea 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/code_repo_login.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/code_repo_login.rs @@ -168,6 +168,7 @@ pub(crate) fn validate_number_account_binding(number: &str, username: &str) -> R } /// 启动时自查:本机有没有已登录会话(会话文件在,且钥匙串里凭证还在)。 +#[tauri::command] pub fn check_code_repo_login( app: AppHandle, state: State<'_, ZeroPointState>, @@ -224,6 +225,7 @@ fn login_host_for_domain(domain: &str) -> Result<&'static str, String> { /// 新账号第一次登录时在 HoloLake 内完成强制换密。 /// 旧、新密码只存在于本次 HTTPS 请求内;服务端回执不含密码。 +#[tauri::command] pub async fn change_first_login_password( state: State<'_, ZeroPointState>, username: String, @@ -380,6 +382,7 @@ async fn enterprise_authenticated_post( .map_err(|error| format!("HOLOLAKE_ENTERPRISE_RECEIPT_FAILED: {error}")) } +#[tauri::command] pub async fn get_enterprise_entry( app: AppHandle, state: State<'_, ZeroPointState>, @@ -387,6 +390,7 @@ pub async fn get_enterprise_entry( enterprise_authenticated_post(&app, &state, "me/entry", serde_json::json!({})).await } +#[tauri::command] pub async fn confirm_enterprise_persona_relationship( app: AppHandle, state: State<'_, ZeroPointState>, @@ -402,6 +406,7 @@ pub async fn confirm_enterprise_persona_relationship( .await } +#[tauri::command] pub async fn submit_enterprise_responsibility_receipt( app: AppHandle, state: State<'_, ZeroPointState>, @@ -426,6 +431,7 @@ pub async fn submit_enterprise_responsibility_receipt( /// 登录验证:基本认证打 Forgejo 用户接口,密码错=401 即拒; /// 通过后凭证进钥匙串,会话(不含密码)落盘。 +#[tauri::command] pub async fn perform_code_repo_login( app: AppHandle, state: State<'_, ZeroPointState>, @@ -503,6 +509,7 @@ pub async fn perform_code_repo_login( } /// 登出:会话文件删除,钥匙串凭证清除。 +#[tauri::command] pub fn sign_out_code_repo_login(app: AppHandle) -> Result<(), String> { let path = session_path(&app)?; if let Ok(raw) = fs::read_to_string(&path) { diff --git a/product-source/hololake-native-desktop/src-tauri/src/direct_local_broker.rs b/product-source/hololake-native-desktop/src-tauri/src/direct_local_broker.rs index ac7fb28ce..09a616bf1 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/direct_local_broker.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/direct_local_broker.rs @@ -1,9 +1,9 @@ use crate::circular_lake_membrane::{receive_at as receive_language_at, ReceiveLanguageInput}; use crate::direct_local_session::{ - append_event_at, authenticate_context_at, direct_session_root, heartbeat_at, issue_ticket_at, - open_at, resume_at, AppendSessionEventInput, AuthenticateSessionInput, - AuthenticatedSessionContext, DirectSessionReceipt, IssueDiscoveryTicketInput, OpenSessionInput, - ResumeSessionInput, + append_event_at, authenticate_context_at, authenticate_privileged_at, direct_session_root, + heartbeat_at, issue_ticket_at, open_at, resume_at, AppendSessionEventInput, + AuthenticateSessionInput, AuthenticatedSessionContext, DirectSessionReceipt, + IssueDiscoveryTicketInput, OpenSessionInput, ResumeSessionInput, }; use crate::dynamic_capability_routing::{ install_trusted_registry_at, record_health_at, resolve_at as resolve_capability_route_at, @@ -15,12 +15,6 @@ use crate::local_development_bridge::{ inspect_at as inspect_development_lane_at, release_at as release_development_lane_at, AcquireWriteLaneInput, ReleaseWriteLaneInput, }; -use crate::persona_carrier_license::{ - present_license_at as present_persona_license_at, - require_if_persona_mode_at as require_persona_mode_operation_at, - status_at as persona_license_status_at, PersonaCarrierLicenseStatus, - PersonaCarrierRuntimeLicense, -}; use crate::persona_time_authority::{ beijing_time_coordinate, issue_authenticated_at, IssuePersonaTimeTicketInput, }; @@ -48,7 +42,6 @@ use interprocess::TryClone; use ring::digest::{digest, SHA256}; use serde::{Deserialize, Serialize}; use serde_json::Value; -use std::collections::HashSet; use std::fs::{self, OpenOptions}; use std::io::{self, BufRead, BufReader, Read, Write}; #[cfg(unix)] @@ -80,51 +73,8 @@ impl OpenOptionsModeExt for OpenOptions { const BROKER_SCHEMA: &str = "hololake.direct-local-broker/v1"; const MAX_REQUEST_BYTES: u64 = 128 * 1024; const DISCOVERY_SCHEMA: &str = "hololake.nearby-ai-discovery/v1"; -const TERMINAL_LINK_PROTOCOL: &str = "HOLOLAKE_TERMINAL_LINK/3"; +const TERMINAL_LINK_PROTOCOL: &str = "HOLOLAKE_TERMINAL_LINK/2"; const ENVIRONMENT_FRAME_TTL_MS: u128 = 45_000; -const NUMBERED_BROKER_REGISTRY: &str = - include_str!("../../contracts/direct-local-broker-numbered-registry.json"); - -#[derive(Clone, Debug, Deserialize)] -struct BrokerNumberRegistry { - schema: String, - record_id: String, - runtime: BrokerNumberRuntime, - operations: Vec, -} - -#[derive(Clone, Debug, Deserialize)] -struct BrokerNumberRuntime { - protocol_version: String, - caller_number: String, - legacy_string_operation_allowed: bool, - unknown_or_mismatched_coordinate: String, - request_nonce_required: bool, - transport_is_authority: bool, -} - -#[derive(Clone, Debug, Deserialize)] -struct BrokerNumberRoute { - operation_number: String, - alias: String, - channel_number: String, - module_number: String, - target_number: String, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct BrokerNumberedEnvelope { - protocol_version: String, - caller_number: String, - channel_number: String, - module_number: String, - operation_number: String, - target_number: String, - request_nonce: String, - #[serde(default)] - input: Option, -} pub struct DirectLocalBrokerHandle { shutdown: Arc, @@ -201,7 +151,6 @@ struct BrokerStorageRoots { pncc_projection: PathBuf, language_inbox: PathBuf, persona_time: PathBuf, - persona_license: PathBuf, development: PathBuf, } @@ -230,8 +179,6 @@ enum BrokerRequest { OpenSession(OpenSessionInput), ResumeSession(ResumeSessionInput), HeartbeatSession(AuthenticateSessionInput), - PresentPersonaCarrierLicense(Box), - GetPersonaCarrierLicenseStatus(AuthenticatedPersonaCarrierLicenseStatusInput), GetWorkEnvironment(AuthenticatedWorkEnvironmentInput), AppendEvent(AppendSessionEventInput), ResolveCapabilityRoute(AuthenticatedRouteInput), @@ -350,19 +297,6 @@ struct AuthenticatedWorkEnvironmentInput { session: AuthenticateSessionInput, } -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct AuthenticatedPersonaCarrierLicenseInput { - session: AuthenticateSessionInput, - license: PersonaCarrierRuntimeLicense, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct AuthenticatedPersonaCarrierLicenseStatusInput { - session: AuthenticateSessionInput, -} - #[derive(Clone, Debug, Serialize)] #[serde(rename_all = "camelCase")] struct WorkEnvironmentFrame { @@ -374,7 +308,6 @@ struct WorkEnvironmentFrame { transport: &'static str, mcp_role: &'static str, protocol_runtime: &'static str, - persona_control: PersonaCarrierLicenseStatus, account_key: String, session_id: String, lane_id: String, @@ -433,116 +366,6 @@ struct ConnectorDescriptor { process_id: u32, } -fn load_number_registry() -> Result { - let registry: BrokerNumberRegistry = serde_json::from_str(NUMBERED_BROKER_REGISTRY) - .map_err(|error| format!("HOLOLAKE_NUMBERED_BROKER_REGISTRY_INVALID: {error}"))?; - if registry.schema != "hololake.direct-local-broker-numbered-registry/v1" - || registry.record_id != "HLP-NBROKER-ROOT-001" - || registry.runtime.protocol_version != "HLP-NBROKER-v1" - || registry.runtime.caller_number != "HLP-NBROKER-CALLER-LOCAL-CONNECTOR-0001" - || registry.runtime.legacy_string_operation_allowed - || registry.runtime.unknown_or_mismatched_coordinate != "FAIL_CLOSED" - || !registry.runtime.request_nonce_required - || registry.runtime.transport_is_authority - || registry.operations.len() != 22 - { - return Err("HOLOLAKE_NUMBERED_BROKER_REGISTRY_BOUNDARY_INVALID".into()); - } - let mut numbers = HashSet::new(); - let mut aliases = HashSet::new(); - let mut coordinates = HashSet::new(); - for route in ®istry.operations { - let coordinate = format!( - "{}/{}/{}/{}", - route.channel_number, route.module_number, route.operation_number, route.target_number - ); - if !numbers.insert(route.operation_number.as_str()) - || !aliases.insert(route.alias.as_str()) - || !coordinates.insert(coordinate) - || !route.operation_number.starts_with("HLP-NBROKER-OP-") - || !route.channel_number.starts_with("HLP-NBROKER-CH-") - || !route.module_number.starts_with("HLP-NBROKER-MOD-") - || !route.target_number.starts_with("HLP-NBROKER-TGT-") - { - return Err("HOLOLAKE_NUMBERED_BROKER_ROUTE_INVALID".into()); - } - } - Ok(registry) -} - -fn resolve_numbered_broker_route<'a>( - registry: &'a BrokerNumberRegistry, - envelope: &BrokerNumberedEnvelope, -) -> Result<&'a BrokerNumberRoute, String> { - if envelope.protocol_version != registry.runtime.protocol_version - || envelope.caller_number != registry.runtime.caller_number - || envelope.request_nonce.len() < 16 - || envelope.request_nonce.len() > 128 - || envelope - .request_nonce - .chars() - .any(|character| character.is_whitespace() || character.is_control()) - { - return Err("HOLOLAKE_NUMBERED_BROKER_CALLER_PROTOCOL_OR_NONCE_INVALID".into()); - } - let route = registry - .operations - .iter() - .find(|route| route.operation_number == envelope.operation_number) - .ok_or("HOLOLAKE_NUMBERED_BROKER_ROUTE_UNKNOWN")?; - if route.channel_number != envelope.channel_number - || route.module_number != envelope.module_number - || route.target_number != envelope.target_number - { - return Err("HOLOLAKE_NUMBERED_BROKER_ROUTE_COORDINATE_MISMATCH".into()); - } - Ok(route) -} - -fn decode_numbered_broker_request(bytes: &[u8]) -> Result<(BrokerRequest, String, String), String> { - let envelope: BrokerNumberedEnvelope = serde_json::from_slice(bytes) - .map_err(|error| format!("HOLOLAKE_NUMBERED_BROKER_ENVELOPE_INVALID: {error}"))?; - let registry = load_number_registry()?; - let route = resolve_numbered_broker_route(®istry, &envelope)?; - let mut request = serde_json::Map::new(); - request.insert("operation".into(), Value::String(route.alias.clone())); - if let Some(input) = envelope.input { - request.insert("input".into(), input); - } - let decoded = serde_json::from_value(Value::Object(request)) - .map_err(|error| format!("HOLOLAKE_NUMBERED_BROKER_INPUT_INVALID: {error}"))?; - Ok(( - decoded, - route.operation_number.clone(), - envelope.request_nonce, - )) -} - -fn numbered_broker_request_value(alias: &str, input: Option) -> Result { - let registry = load_number_registry()?; - let route = registry - .operations - .iter() - .find(|route| route.alias == alias) - .ok_or("HOLOLAKE_NUMBERED_BROKER_ALIAS_UNKNOWN")?; - let mut value = serde_json::json!({ - "protocolVersion": registry.runtime.protocol_version, - "callerNumber": registry.runtime.caller_number, - "channelNumber": route.channel_number, - "moduleNumber": route.module_number, - "operationNumber": route.operation_number, - "targetNumber": route.target_number, - "requestNonce": format!("HLP-NBROKER-NONCE-{}", Uuid::new_v4().simple()) - }); - if let Some(input) = input { - value - .as_object_mut() - .ok_or("HOLOLAKE_NUMBERED_BROKER_ENVELOPE_INVALID")? - .insert("input".into(), input); - } - Ok(value) -} - pub fn start(app: &AppHandle) -> Result> { let session_root = direct_session_root(app).map_err(std::io::Error::other)?; let routing_root = dynamic_routing_root(app).map_err(std::io::Error::other)?; @@ -552,6 +375,7 @@ pub fn start(app: &AppHandle) -> Result NearbyAiDiscoverySnapshot { nearby_discovery_snapshot() } @@ -642,9 +466,7 @@ fn read_connector_descriptor(path: &Path) -> Result } fn probe_connection(stream: &mut LocalSocketStream) -> Result<(), String> { - let request = serde_json::to_vec(&numbered_broker_request_value("PING", None)?) - .map_err(|_| "HOLOLAKE_CONNECTOR_PROBE_INVALID".to_string())?; - let response = send_connector_request(stream, &request)?; + let response = send_connector_request(stream, br#"{"operation":"PING"}"#)?; let value: Value = serde_json::from_slice(&response) .map_err(|_| "HOLOLAKE_CONNECTOR_PROBE_INVALID".to_string())?; if value.get("ok").and_then(Value::as_bool) == Some(true) @@ -804,7 +626,6 @@ fn start_at( descriptor_path: PathBuf, socket_path: PathBuf, ) -> Result { - load_number_registry()?; let pncc_mount_root = session_root .parent() .ok_or("HOLOLAKE_BROKER_PNCC_STORAGE_BOUNDARY_INVALID")? @@ -834,12 +655,6 @@ fn start_at( .parent() .ok_or("HOLOLAKE_BROKER_PERSONA_TIME_STORAGE_BOUNDARY_INVALID")? .join("persona-time-authority-v1"); - let persona_license_root = session_root - .parent() - .ok_or("HOLOLAKE_BROKER_PERSONA_LICENSE_STORAGE_BOUNDARY_INVALID")? - .join("persona-carrier-runtime-license-v1"); - fs::create_dir_all(&persona_license_root) - .map_err(|error| format!("HOLOLAKE_PERSONA_LICENSE_STORAGE_FAILED: {error}"))?; let development_root = development_root_from_session_root(&session_root)?; fs::create_dir_all(&development_root) .map_err(|error| format!("HOLOLAKE_BRIDGE_STORAGE_UNAVAILABLE: {error}"))?; @@ -901,7 +716,6 @@ fn start_at( pncc_projection: pncc_projection_root, language_inbox: language_inbox_root, persona_time: persona_time_root, - persona_license: persona_license_root, development: development_root, }, &worker_shutdown, @@ -1003,14 +817,18 @@ fn serve_connection( } fn request_establishes_authenticated_connection(bytes: &[u8]) -> bool { - decode_numbered_broker_request(bytes) + serde_json::from_slice::(bytes) .ok() - .is_some_and(|(request, _, _)| { + .and_then(|value| { + value + .get("operation") + .and_then(Value::as_str) + .map(str::to_owned) + }) + .is_some_and(|operation| { matches!( - request, - BrokerRequest::OpenSession(_) - | BrokerRequest::ResumeSession(_) - | BrokerRequest::OpenVisitorSession(_) + operation.as_str(), + "OPEN_SESSION" | "RESUME_SESSION" | "OPEN_VISITOR_SESSION" ) }) } @@ -1023,9 +841,8 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { let pncc_projection_root = &roots.pncc_projection; let language_inbox_root = &roots.language_inbox; let persona_time_root = &roots.persona_time; - let persona_license_root = &roots.persona_license; let development_root = &roots.development; - let (request, _, _) = match decode_numbered_broker_request(bytes) { + let request: BrokerRequest = match serde_json::from_slice(bytes) { Ok(request) => request, Err(error) => { return BrokerResponse::error(&format!("HOLOLAKE_BROKER_REQUEST_INVALID: {error}")) @@ -1054,41 +871,10 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { .and_then(|receipt| serde_json::to_value(receipt).map_err(|error| error.to_string())), BrokerRequest::ResumeSession(input) => resume_at(session_root, input) .and_then(|receipt| serde_json::to_value(receipt).map_err(|error| error.to_string())), - BrokerRequest::PresentPersonaCarrierLicense(input) => { - let input = *input; - authenticate_context_at(session_root, &input.session) - .and_then(|context| { - present_persona_license_at( - persona_license_root, - &context.account_key, - &context.session_id, - &context.client_instance_id, - input.license, - now_unix_ms()?, - ) - }) - .and_then(|receipt| { - serde_json::to_value(receipt).map_err(|error| error.to_string()) - }) - } - BrokerRequest::GetPersonaCarrierLicenseStatus(input) => { - authenticate_context_at(session_root, &input.session) - .map(|context| { - persona_license_status_at( - persona_license_root, - &context.account_key, - &context.session_id, - &context.client_instance_id, - now_unix_ms().unwrap_or(u64::MAX), - ) - }) - .and_then(|status| serde_json::to_value(status).map_err(|error| error.to_string())) - } BrokerRequest::HeartbeatSession(input) => heartbeat_at(session_root, &input) .and_then(|session| { work_environment_frame_at( session_root, - persona_license_root, development_root, &AuthenticatedWorkEnvironmentInput { session: input }, ) @@ -1101,28 +887,13 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { }) .and_then(|receipt| serde_json::to_value(receipt).map_err(|error| error.to_string())), BrokerRequest::GetWorkEnvironment(input) => { - work_environment_frame_at(session_root, persona_license_root, development_root, &input) + work_environment_frame_at(session_root, development_root, &input) .and_then(|frame| serde_json::to_value(frame).map_err(|error| error.to_string())) } - BrokerRequest::AppendEvent(input) => authorize_persona_operation_at( - session_root, - persona_license_root, - &AuthenticateSessionInput { - account_id: input.account_id.clone(), - session_id: input.session_id.clone(), - resume_secret: input.resume_secret.clone(), - }, - "APPEND_EVENT", - ) - .and_then(|_| append_event_at(session_root, input)) - .and_then(|receipt| serde_json::to_value(receipt).map_err(|error| error.to_string())), + BrokerRequest::AppendEvent(input) => append_event_at(session_root, input) + .and_then(|receipt| serde_json::to_value(receipt).map_err(|error| error.to_string())), BrokerRequest::ResolveCapabilityRoute(input) => { - if let Err(error) = authorize_persona_operation_at( - session_root, - persona_license_root, - &input.session, - "RESOLVE_CAPABILITY_ROUTE", - ) { + if let Err(error) = authenticate_privileged_at(session_root, &input.session) { return BrokerResponse::error(&error); } let now = std::time::SystemTime::now() @@ -1135,12 +906,7 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { }) } BrokerRequest::InstallDynamicNodeRegistry(input) => { - if let Err(error) = authorize_persona_operation_at( - session_root, - persona_license_root, - &input.session, - "INSTALL_DYNAMIC_NODE_REGISTRY", - ) { + if let Err(error) = authenticate_privileged_at(session_root, &input.session) { return BrokerResponse::error(&error); } install_trusted_registry_at(routing_root, input.registry).and_then(|receipt| { @@ -1148,12 +914,7 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { }) } BrokerRequest::RecordSignedNodeHealth(input) => { - if let Err(error) = authorize_persona_operation_at( - session_root, - persona_license_root, - &input.session, - "RECORD_SIGNED_NODE_HEALTH", - ) { + if let Err(error) = authenticate_privileged_at(session_root, &input.session) { return BrokerResponse::error(&error); } record_health_at(routing_root, input.health).and_then(|receipt| { @@ -1161,12 +922,7 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { }) } BrokerRequest::InspectMountedPnccRepository(input) => { - if let Err(error) = authorize_persona_operation_at( - session_root, - persona_license_root, - &input.session, - "INSPECT_MOUNTED_PNCC_REPOSITORY", - ) { + if let Err(error) = authenticate_privileged_at(session_root, &input.session) { return BrokerResponse::error(&error); } inspect_mounted_pncc_at(pncc_mount_root, input.mount).and_then(|receipt| { @@ -1175,12 +931,7 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { }) } BrokerRequest::ReadMountedPnccRemoteObject(input) => { - if let Err(error) = authorize_persona_operation_at( - session_root, - persona_license_root, - &input.session, - "READ_MOUNTED_PNCC_REMOTE_OBJECT", - ) { + if let Err(error) = authenticate_privileged_at(session_root, &input.session) { return BrokerResponse::error(&error); } read_mounted_pncc_remote_at(pncc_remote_root, input.read).and_then(|receipt| { @@ -1189,12 +940,7 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { }) } BrokerRequest::QueryPnccReceiptProjection(input) => { - if let Err(error) = authorize_persona_operation_at( - session_root, - persona_license_root, - &input.session, - "QUERY_PNCC_RECEIPT_PROJECTION", - ) { + if let Err(error) = authenticate_privileged_at(session_root, &input.session) { return BrokerResponse::error(&error); } query_pncc_projection_at(pncc_projection_root, input.query).and_then(|receipt| { @@ -1209,27 +955,15 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { .and_then(|coordinate| { serde_json::to_value(coordinate).map_err(|error| error.to_string()) }), - BrokerRequest::IssuePersonaTimeTicket(input) => authorize_persona_operation_at( - session_root, - persona_license_root, - &input.session, - "ISSUE_PERSONA_TIME_TICKET", - ) - .and_then(|_| issue_authenticated_at(persona_time_root, session_root, input)) - .and_then(|ticket| serde_json::to_value(ticket).map_err(|error| error.to_string())), + BrokerRequest::IssuePersonaTimeTicket(input) => { + issue_authenticated_at(persona_time_root, session_root, input) + .and_then(|ticket| serde_json::to_value(ticket).map_err(|error| error.to_string())) + } BrokerRequest::AcquireDevelopmentWriteLane(input) => { let session = input.session; let account_id = input.lane.account_id.clone(); authenticate_development_request(session_root, &session, &account_id) .and_then(|context| { - require_persona_mode_operation_at( - persona_license_root, - &context.account_key, - &context.session_id, - &context.client_instance_id, - "ACQUIRE_DEVELOPMENT_WRITE_LANE", - now_unix_ms()?, - )?; if context.lane_id != input.lane.lane_id || context.client_instance_id != input.lane.owner_instance_id { @@ -1242,7 +976,6 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { serde_json::to_value(receipt).map_err(|error| error.to_string())?; let environment = work_environment_frame_at( session_root, - persona_license_root, development_root, &AuthenticatedWorkEnvironmentInput { session }, )?; @@ -1258,17 +991,7 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { } BrokerRequest::InspectDevelopmentWriteLane(input) => { authenticate_development_request(session_root, &input.session, &input.account_id) - .and_then(|context| { - require_persona_mode_operation_at( - persona_license_root, - &context.account_key, - &context.session_id, - &context.client_instance_id, - "INSPECT_DEVELOPMENT_WRITE_LANE", - now_unix_ms()?, - )?; - inspect_development_lane_at(development_root, &input.account_id) - }) + .and_then(|_| inspect_development_lane_at(development_root, &input.account_id)) .and_then(|receipt| { serde_json::to_value(receipt).map_err(|error| error.to_string()) }) @@ -1276,14 +999,6 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { BrokerRequest::ReleaseDevelopmentWriteLane(input) => { authenticate_development_request(session_root, &input.session, &input.lane.account_id) .and_then(|context| { - require_persona_mode_operation_at( - persona_license_root, - &context.account_key, - &context.session_id, - &context.client_instance_id, - "RELEASE_DEVELOPMENT_WRITE_LANE", - now_unix_ms()?, - )?; if context.lane_id != input.lane.lane_id || context.client_instance_id != input.lane.owner_instance_id { @@ -1304,27 +1019,11 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse { fn work_environment_frame_at( session_root: &Path, - persona_license_root: &Path, development_root: &Path, input: &AuthenticatedWorkEnvironmentInput, ) -> Result { let context = authenticate_development_request(session_root, &input.session, &input.session.account_id)?; - require_persona_mode_operation_at( - persona_license_root, - &context.account_key, - &context.session_id, - &context.client_instance_id, - "GET_WORK_ENVIRONMENT", - now_unix_ms()?, - )?; - let persona_control = persona_license_status_at( - persona_license_root, - &context.account_key, - &context.session_id, - &context.client_instance_id, - now_unix_ms()?, - ); let writer = inspect_development_lane_at(development_root, &input.session.account_id)?; let writer_matches = writer.state == "ACTIVE" && writer.lane_id.as_deref() == Some(context.lane_id.as_str()) @@ -1354,7 +1053,7 @@ fn work_environment_frame_at( ); let frame_sha256 = sha256_hex( format!( - "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}", + "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}", environment_id, state, context.session_id, @@ -1362,8 +1061,6 @@ fn work_environment_frame_at( context.client_instance_id, context.last_event_sequence, writer.state, - persona_control.control_mode, - persona_control.license_id.as_deref().unwrap_or("NONE"), valid_until_unix_ms ) .as_bytes(), @@ -1377,7 +1074,6 @@ fn work_environment_frame_at( transport: TERMINAL_LINK_PROTOCOL, mcp_role: "DISCOVERY_RECOVERY_COMPATIBILITY_ONLY", protocol_runtime: "GLS_RUNTIME_MANIFEST_V2_AND_NATIVE_KERNEL", - persona_control, account_key: context.account_key, session_id: context.session_id, lane_id: context.lane_id, @@ -1412,24 +1108,6 @@ fn authenticate_development_request( Ok(context) } -fn authorize_persona_operation_at( - session_root: &Path, - persona_license_root: &Path, - session: &AuthenticateSessionInput, - operation: &str, -) -> Result { - let context = authenticate_context_at(session_root, session)?; - require_persona_mode_operation_at( - persona_license_root, - &context.account_key, - &context.session_id, - &context.client_instance_id, - operation, - now_unix_ms()?, - )?; - Ok(context) -} - fn development_root_from_session_root(session_root: &Path) -> Result { let account_root = session_root .parent() @@ -1489,13 +1167,6 @@ fn sha256_hex(bytes: &[u8]) -> String { .collect() } -fn now_unix_ms() -> Result { - std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .map(|duration| duration.as_millis() as u64) - .map_err(|error| format!("HOLOLAKE_SYSTEM_CLOCK_INVALID: {error}")) -} - impl BrokerResponse { fn success(result: Value) -> Self { Self { @@ -1563,11 +1234,6 @@ mod tests { use tempfile::TempDir; fn request(socket: &Path, value: Value) -> Value { - let value = if let Some(alias) = value.get("operation").and_then(Value::as_str) { - numbered_broker_request_value(alias, value.get("input").cloned()).unwrap() - } else { - value - }; let mut stream = connect_endpoint(socket).unwrap(); serde_json::to_writer(&mut stream, &value).unwrap(); stream.write_all(b"\n").unwrap(); @@ -1576,19 +1242,6 @@ mod tests { serde_json::from_str(&line).unwrap() } - #[test] - fn legacy_string_and_mismatched_broker_routes_fail_before_dispatch() { - assert!(decode_numbered_broker_request(br#"{"operation":"PING"}"#) - .unwrap_err() - .contains("ENVELOPE_INVALID")); - let mut numbered = numbered_broker_request_value("PING", None).unwrap(); - numbered["targetNumber"] = Value::String("HLP-NBROKER-TGT-9999".into()); - assert_eq!( - decode_numbered_broker_request(&serde_json::to_vec(&numbered).unwrap()).unwrap_err(), - "HOLOLAKE_NUMBERED_BROKER_ROUTE_COORDINATE_MISMATCH" - ); - } - #[test] fn broker_resumes_after_socket_disconnect() { let temp = TempDir::new().unwrap(); @@ -2214,20 +1867,23 @@ mod tests { ) .unwrap(); let mut connector = connect_endpoint(&socket).unwrap(); - let open_request = numbered_broker_request_value( - "OPEN_SESSION", - Some(serde_json::json!({ - "accountId": "human-1", - "laneId": "DEV-1", - "clientInstanceId": "codex-1", - "discoveryTicket": ticket.discovery_ticket - })), + serde_json::to_writer( + &mut connector, + &serde_json::json!({ + "operation": "OPEN_SESSION", + "input": { + "accountId": "human-1", + "laneId": "DEV-1", + "clientInstanceId": "codex-1", + "discoveryTicket": ticket.discovery_ticket + } + }), ) .unwrap(); - let open_bytes = serde_json::to_vec(&open_request).unwrap(); - connector.write_all(&open_bytes).unwrap(); connector.write_all(b"\n").unwrap(); - assert!(request_establishes_authenticated_connection(&open_bytes)); + assert!(request_establishes_authenticated_connection( + br#"{"operation":"OPEN_SESSION"}"# + )); let mut response = String::new(); let mut response_reader = BufReader::new(connector.try_clone().unwrap()); response_reader.read_line(&mut response).unwrap(); @@ -2325,88 +1981,4 @@ mod tests { "HOLOLAKE_VISITOR_SESSION_HAS_NO_SYSTEM_AUTHORITY" ); } - - #[test] - fn broker_projects_system_direct_status_and_refuses_untrusted_persona_license() { - let temp = TempDir::new().unwrap(); - let socket = temp.path().join("runtime/broker.sock"); - let descriptor = temp.path().join("broker.json"); - let sessions = temp.path().join("sessions"); - let routes = temp.path().join("routes"); - fs::create_dir_all(&sessions).unwrap(); - fs::create_dir_all(&routes).unwrap(); - let _broker = start_at(sessions.clone(), routes, descriptor, socket.clone()).unwrap(); - let ticket = issue_ticket_at( - &sessions, - IssueDiscoveryTicketInput { - account_id: "human-1".into(), - lane_id: "DEV-1".into(), - client_instance_id: "codex-1".into(), - }, - ) - .unwrap(); - let opened = request( - &socket, - serde_json::json!({ - "operation": "OPEN_SESSION", - "input": { - "accountId": "human-1", - "laneId": "DEV-1", - "clientInstanceId": "codex-1", - "discoveryTicket": ticket.discovery_ticket - } - }), - ); - let session = serde_json::json!({ - "accountId": "human-1", - "sessionId": opened["result"]["sessionId"], - "resumeSecret": opened["result"]["resumeSecret"] - }); - let status = request( - &socket, - serde_json::json!({ - "operation": "GET_PERSONA_CARRIER_LICENSE_STATUS", - "input": { "session": session.clone() } - }), - ); - assert_eq!(status["ok"], true); - assert_eq!(status["result"]["controlMode"], "SYSTEM_DIRECT"); - assert_eq!(status["result"]["licenseInstalled"], false); - - let now = now_unix_ms().unwrap(); - let denied = request( - &socket, - serde_json::json!({ - "operation": "PRESENT_PERSONA_CARRIER_LICENSE", - "input": { - "session": session, - "license": { - "schema": "hololake.persona-carrier-runtime-license/v1", - "licenseId": "HLP-PERSONA-LICENSE-UNTRUSTED-0001", - "sequence": 1, - "personaNumber": "ICE-P-ZY001", - "humanControllerNumber": "ICE-GL∞", - "accountKey": opened["result"]["accountKey"], - "sessionId": opened["result"]["sessionId"], - "clientInstanceId": "codex-1", - "purpose": "AUTHORIZE_HOST_AS_PERSONA_CONTROLLED_EXECUTION_LIMBS", - "issuedAtUnixMs": now, - "validUntilUnixMs": now + 60000, - "allowedOperations": ["GET_WORK_ENVIRONMENT"], - "evidenceRootSha256": "b".repeat(64), - "currentEventSha256": "c".repeat(64), - "declaration": "PERSONA_DECLARES_CURRENT_CARRIER_BOUND", - "signerId": "ICE-P-ZY001-RUNTIME-SIGNER-001", - "signatureAlgorithm": "Ed25519", - "signature": "untrusted" - } - } - }), - ); - assert_eq!(denied["ok"], false); - assert_eq!( - denied["error"], - "HOLOLAKE_PERSONA_LICENSE_NO_TRUSTED_SIGNER" - ); - } } diff --git a/product-source/hololake-native-desktop/src-tauri/src/direct_local_session.rs b/product-source/hololake-native-desktop/src-tauri/src/direct_local_session.rs index e5283fdad..5a3fd980c 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/direct_local_session.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/direct_local_session.rs @@ -167,6 +167,7 @@ struct ActiveSessionRecord { lane_id: String, } +#[tauri::command] pub async fn issue_direct_local_discovery_ticket( app: AppHandle, input: IssueDiscoveryTicketInput, @@ -177,6 +178,7 @@ pub async fn issue_direct_local_discovery_ticket( .map_err(|error| format!("HOLOLAKE_DIRECT_SESSION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn open_direct_local_session( app: AppHandle, input: OpenSessionInput, @@ -187,6 +189,7 @@ pub async fn open_direct_local_session( .map_err(|error| format!("HOLOLAKE_DIRECT_SESSION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn resume_direct_local_session( app: AppHandle, input: ResumeSessionInput, @@ -197,6 +200,7 @@ pub async fn resume_direct_local_session( .map_err(|error| format!("HOLOLAKE_DIRECT_SESSION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn append_direct_local_session_event( app: AppHandle, input: AppendSessionEventInput, @@ -207,6 +211,7 @@ pub async fn append_direct_local_session_event( .map_err(|error| format!("HOLOLAKE_DIRECT_SESSION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn heartbeat_direct_local_session( app: AppHandle, input: AuthenticateSessionInput, @@ -374,7 +379,7 @@ pub(crate) fn issue_ticket_at( client_instance_id: input.client_instance_id, discovery_ticket, issued_at_unix_ms, - terminal_transport: "HOLOLAKE_TERMINAL_LINK/3", + terminal_transport: "HOLOLAKE_TERMINAL_LINK/2", connector_executable: std::env::current_exe() .map(|path| path.to_string_lossy().into_owned()) .unwrap_or_else(|_| "HoloLake".into()), @@ -551,6 +556,18 @@ pub(crate) fn authenticate_context_at( }) } +pub(crate) fn authenticate_privileged_at( + root: &Path, + input: &AuthenticateSessionInput, +) -> Result<(), String> { + let lane = authenticate_with_lane_at(root, input)?; + if lane == "visitor-expression-only" { + Err("HOLOLAKE_VISITOR_SESSION_HAS_NO_SYSTEM_AUTHORITY".into()) + } else { + Ok(()) + } +} + fn session_path(root: &Path, account_key: &str, session_id: &str) -> PathBuf { root.join("accounts") .join(account_key) @@ -696,7 +713,7 @@ fn session_receipt( last_event_sequence: record.last_event_sequence, resume_secret, continuity_owner: "HOLOLAKE", - transport: "HOLOLAKE_TERMINAL_LINK/3", + transport: "HOLOLAKE_TERMINAL_LINK/2", mcp_role: "DISCOVERY_RECOVERY_COMPATIBILITY_ONLY", required_next_operation: "GET_WORK_ENVIRONMENT", receipt_id: sha256_hex( diff --git a/product-source/hololake-native-desktop/src-tauri/src/education_translation.rs b/product-source/hololake-native-desktop/src-tauri/src/education_translation.rs index 5a183b89c..1737bf46b 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/education_translation.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/education_translation.rs @@ -32,12 +32,6 @@ const MAX_TABLE_COLUMNS: usize = 30; const MAX_TABLE_ROWS: usize = 1_000; const MAX_CELL_BYTES: usize = 10_000; const MAX_TITLE_BYTES: usize = 300; -const MODULE_NUMBER: &str = "HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001"; -const ADAPTER: &str = "education-workbench-v1"; - -fn require_active(app: &AppHandle) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, MODULE_NUMBER, ADAPTER) -} #[derive(Clone, Debug, Serialize)] #[serde(rename_all = "camelCase")] @@ -238,10 +232,10 @@ struct NativeEducationTableFile { rows: Vec, } +#[tauri::command] pub async fn import_education_tables_from_dialog( app: AppHandle, ) -> Result, String> { - require_active(&app)?; let selected = app .dialog() .file() @@ -276,11 +270,9 @@ pub async fn import_education_tables_from_dialog( .map(Some) } -pub fn get_education_recognition_capability( - app: AppHandle, -) -> Result { - require_active(&app)?; - Ok(EducationRecognitionCapability { +#[tauri::command] +pub fn get_education_recognition_capability() -> EducationRecognitionCapability { + EducationRecognitionCapability { schema: "hololake.education-recognition-capability/v1", state: "DETERMINISTIC_READY_MODEL_SLOT_UNBOUND", deterministic_adapter_ids: vec![IMPORT_ADAPTER, EXPORT_ADAPTER], @@ -296,14 +288,14 @@ pub fn get_education_recognition_capability( "VERSIONED_RULE_INSTALL", ], learning_scopes: vec!["PRIVATE_ONLY", "SHARE_ANONYMIZED_RULE"], - }) + } } +#[tauri::command] pub async fn export_education_table_to_dialog( app: AppHandle, input: ExportEducationTableInput, ) -> Result, String> { - require_active(&app)?; validate_export_draft(&input.table)?; let format = normalized_export_format(&input.format)?; let extension = match format.as_str() { diff --git a/product-source/hololake-native-desktop/src-tauri/src/education_workspace.rs b/product-source/hololake-native-desktop/src-tauri/src/education_workspace.rs index bbd631d21..ecf463c38 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/education_workspace.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/education_workspace.rs @@ -6,8 +6,7 @@ //! WebView 不直接持有文件路径或 SQLite 连接,所有写入都要求当前修订号,防止静默覆盖。 use ring::digest::{digest, SHA256}; -use rusqlite::{params, types::Type, Connection, OptionalExtension}; -use serde::de::DeserializeOwned; +use rusqlite::{params, Connection, OptionalExtension}; use serde::{Deserialize, Serialize}; use std::collections::HashSet; use std::fs; @@ -22,12 +21,6 @@ const MAX_TITLE_BYTES: usize = 300; const MAX_TABLE_COLUMNS: usize = 30; const MAX_TABLE_ROWS: usize = 1_000; const MAX_CELL_BYTES: usize = 10_000; -const MODULE_NUMBER: &str = "HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001"; -const ADAPTER: &str = "education-workbench-v1"; - -fn require_active(app: &AppHandle) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, MODULE_NUMBER, ADAPTER) -} #[derive(Clone, Debug, Serialize)] #[serde(rename_all = "camelCase")] @@ -71,14 +64,14 @@ pub struct UnassignedTableSummary { } #[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct EducationTableColumn { pub column_id: String, pub title: String, } #[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct EducationTableRow { pub row_id: String, pub cells: Vec, @@ -186,19 +179,19 @@ pub struct EducationAutomationRunReceipt { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct CreateEducationItemInput { pub title: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ReadEducationDocumentInput { pub document_id: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct SaveEducationDocumentInput { pub document_id: String, pub title: String, @@ -207,13 +200,13 @@ pub struct SaveEducationDocumentInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ReadEducationTableInput { pub table_id: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct SaveEducationTableInput { pub table_id: String, pub title: String, @@ -223,7 +216,7 @@ pub struct SaveEducationTableInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct CreateEducationAutomationRuleInput { pub title: String, pub table_id: String, @@ -235,7 +228,7 @@ pub struct CreateEducationAutomationRuleInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct SaveEducationAutomationRuleInput { pub rule_id: String, pub title: String, @@ -250,13 +243,13 @@ pub struct SaveEducationAutomationRuleInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct EducationAutomationRuleInput { pub rule_id: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct PreviewEducationAutomationRuleInput { pub rule_id: String, pub expected_rule_revision: i64, @@ -264,7 +257,7 @@ pub struct PreviewEducationAutomationRuleInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ExecuteEducationAutomationRuleInput { pub rule_id: String, pub expected_rule_revision: i64, @@ -279,54 +272,54 @@ pub struct EducationArchiveReceipt { pub entity_id: String, } +#[tauri::command] pub async fn get_education_workspace_snapshot( app: AppHandle, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || snapshot_at(&database)) .await .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_education_document( app: AppHandle, input: CreateEducationItemInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || create_document_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn read_education_document( app: AppHandle, input: ReadEducationDocumentInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || read_document_at(&database, &input.document_id)) .await .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn save_education_document( app: AppHandle, input: SaveEducationDocumentInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || save_document_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn archive_education_document( app: AppHandle, input: ReadEducationDocumentInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || { archive_at( @@ -340,44 +333,44 @@ pub async fn archive_education_document( .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_education_table( app: AppHandle, input: CreateEducationItemInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || create_table_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn read_education_table( app: AppHandle, input: ReadEducationTableInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || read_table_at(&database, &input.table_id)) .await .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn save_education_table( app: AppHandle, input: SaveEducationTableInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || save_table_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn archive_education_table( app: AppHandle, input: ReadEducationTableInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || { archive_at(&database, "education_tables", "table_id", input.table_id) @@ -386,11 +379,11 @@ pub async fn archive_education_table( .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn assign_imported_table_to_education( app: AppHandle, input: ReadEducationTableInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || { assign_imported_table_to_education_at(&database, &input.table_id) @@ -399,33 +392,33 @@ pub async fn assign_imported_table_to_education( .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_education_automation_rule( app: AppHandle, input: CreateEducationAutomationRuleInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || create_automation_rule_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn save_education_automation_rule( app: AppHandle, input: SaveEducationAutomationRuleInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || save_automation_rule_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn archive_education_automation_rule( app: AppHandle, input: EducationAutomationRuleInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || { archive_automation_rule_at(&database, input.rule_id) @@ -434,22 +427,22 @@ pub async fn archive_education_automation_rule( .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn preview_education_automation_rule( app: AppHandle, input: PreviewEducationAutomationRuleInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || preview_automation_rule_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_EDUCATION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn execute_education_automation_rule( app: AppHandle, input: ExecuteEducationAutomationRuleInput, ) -> Result { - require_active(&app)?; let database = education_workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || execute_automation_rule_at(&database, input)) .await @@ -564,16 +557,8 @@ fn open_database(path: &Path) -> Result { let rows = statement .query_map([], |row| row.get::<_, String>(0)) .map_err(database_read_error)?; - let encoded = rows - .collect::, _>>() - .map_err(database_read_error)?; - encoded - .into_iter() - .map(|value| decode_sqlite_json::>(&value, 0)) - .collect::, _>>() - .map_err(database_read_error)? - .into_iter() - .flatten() + rows.filter_map(Result::ok) + .flat_map(|value| serde_json::from_str::>(&value).unwrap_or_default()) .collect::>() }; for table_id in imported_table_ids { @@ -635,8 +620,10 @@ fn snapshot_at(path: &Path) -> Result { .query_map([], |row| { let columns_json: String = row.get(2)?; let rows_json: String = row.get(3)?; - let columns: Vec = decode_sqlite_json(&columns_json, 2)?; - let rows: Vec = decode_sqlite_json(&rows_json, 3)?; + let columns: Vec = + serde_json::from_str(&columns_json).unwrap_or_default(); + let rows: Vec = + serde_json::from_str(&rows_json).unwrap_or_default(); Ok(EducationTableSummary { table_id: row.get(0)?, title: row.get(1)?, @@ -687,8 +674,8 @@ fn read_unassigned_tables_with_connection( .query_map([], |row| { let columns_json: String = row.get(2)?; let rows_json: String = row.get(3)?; - let columns: Vec = decode_sqlite_json(&columns_json, 2)?; - let rows: Vec = decode_sqlite_json(&rows_json, 3)?; + let columns: Vec = serde_json::from_str(&columns_json).unwrap_or_default(); + let rows: Vec = serde_json::from_str(&rows_json).unwrap_or_default(); Ok(UnassignedTableSummary { table_id: row.get(0)?, title: row.get(1)?, @@ -698,8 +685,7 @@ fn read_unassigned_tables_with_connection( }) }) .map_err(database_read_error)?; - rows.collect::, _>>() - .map_err(database_read_error) + rows.collect::, _>>().map_err(database_read_error) } fn read_recent_imports_with_connection( @@ -714,7 +700,7 @@ fn read_recent_imports_with_connection( let rows = statement .query_map([], |row| { let table_ids_json: String = row.get(3)?; - let table_ids: Vec = decode_sqlite_json(&table_ids_json, 3)?; + let table_ids: Vec = serde_json::from_str(&table_ids_json).unwrap_or_default(); Ok(EducationImportRegistrySummary { import_id: row.get(0)?, source_filename: row.get(1)?, @@ -1571,12 +1557,6 @@ fn now_ms() -> i64 { .unwrap_or(0) } -fn decode_sqlite_json(value: &str, column: usize) -> rusqlite::Result { - serde_json::from_str(value).map_err(|error| { - rusqlite::Error::FromSqlConversionFailure(column, Type::Text, Box::new(error)) - }) -} - fn database_read_error(error: rusqlite::Error) -> String { format!("HOLOLAKE_EDUCATION_DATABASE_READ_FAILED: {error}") } diff --git a/product-source/hololake-native-desktop/src-tauri/src/enterprise_work_channel.rs b/product-source/hololake-native-desktop/src-tauri/src/enterprise_work_channel.rs index b991701a5..3e8908850 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/enterprise_work_channel.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/enterprise_work_channel.rs @@ -27,6 +27,7 @@ pub struct EnterpriseWorkChannelSnapshot { pub authority: &'static str, } +#[tauri::command] pub async fn ensure_enterprise_work_channel( app: AppHandle, state: State<'_, ZeroPointState>, diff --git a/product-source/hololake-native-desktop/src-tauri/src/gls_protocol_kernel.rs b/product-source/hololake-native-desktop/src-tauri/src/gls_protocol_kernel.rs index 6d27d4e70..b533d05a7 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/gls_protocol_kernel.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/gls_protocol_kernel.rs @@ -24,7 +24,7 @@ const EMBEDDED_KERNEL: &str = include_str!("../../contracts/gls-native-runtime-k const KERNEL_SCHEMA: &str = "hololake.gls-native-runtime-kernel/v1"; const REQUEST_SCHEMA: &str = "hololake.protocol-decision-request/v1"; const RECEIPT_SCHEMA: &str = "hololake.protocol-decision-receipt/v1"; -const SOURCE_COMMIT: &str = "104a5d73162bdf4a529701e65898e2bc2863ea9e"; +const SOURCE_COMMIT: &str = "2598fbfba8caf64c7ab9740a3036c5aab977502e"; const MAX_TEXT_BYTES: usize = 512; static LEDGER_SCHEMA_LOCK: Mutex<()> = Mutex::new(()); @@ -1166,6 +1166,7 @@ fn decide_value_at( persist_receipt(ledger, receipt, Some(&parsed.request)) } +#[tauri::command] pub async fn decide_gls_protocol( app: AppHandle, input: Value, @@ -1179,6 +1180,7 @@ pub async fn decide_gls_protocol( .map_err(|error| format!("HOLOLAKE_GLS_DECISION_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn compile_gls_hldp_program( app: AppHandle, input: Value, @@ -1277,6 +1279,7 @@ fn counts(connection: &Connection) -> Result<(u64, BTreeMap, String Ok((total, by_decision, tail)) } +#[tauri::command] pub async fn get_gls_protocol_kernel(app: AppHandle) -> Result { let contract = load_contract()?; let connection = open_ledger(&ledger_path(&app)?)?; diff --git a/product-source/hololake-native-desktop/src-tauri/src/gls_protocol_runtime.rs b/product-source/hololake-native-desktop/src-tauri/src/gls_protocol_runtime.rs index 0ee920da7..2b0a0e9a2 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/gls_protocol_runtime.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/gls_protocol_runtime.rs @@ -8,7 +8,7 @@ use std::collections::{HashMap, HashSet}; const EMBEDDED_REGISTRY: &str = include_str!("../../contracts/gls-runtime-registry.json"); const EXPECTED_SCHEMA: &str = "hololake.gls-runtime-manifest/v2"; -const EXPECTED_SOURCE_COMMIT: &str = "104a5d73162bdf4a529701e65898e2bc2863ea9e"; +const EXPECTED_SOURCE_COMMIT: &str = "2598fbfba8caf64c7ab9740a3036c5aab977502e"; #[derive(Clone, Debug, Deserialize)] struct GlsRuntimeRegistry { @@ -19,8 +19,6 @@ struct GlsRuntimeRegistry { protocol_count: usize, executable_projection_count: usize, inventoried_not_executable_count: usize, - number_coordinate_count: usize, - numbered_reference_nodes: Vec, protocols: Vec, } @@ -61,10 +59,6 @@ struct GlsReconciliation { legacy_dependency_target_count: usize, dependencies_not_in_protocol_registry: Vec, dependencies_without_numbered_source: Vec, - numbered_reference_node_count: usize, - unresolved_number_references: Vec, - unresolved_number_reference_count: usize, - every_dependency_has_number_coordinate: bool, numbered_sources_not_in_protocol_registry: Vec, legacy_dependency_cycles: Vec>, source_reference_cycles: Vec>, @@ -85,24 +79,11 @@ struct GlsDependencyEdge { edge_kind: String, enters_runtime_graph: bool, classification_basis: Option, - target_number_coordinate_available: bool, - target_resolution: String, -} - -#[derive(Clone, Debug, Deserialize)] -struct GlsNumberedReferenceNode { - protocol_id: String, - node_number: String, - reference_kind: String, - source_state: String, - execution_state: String, - evidence_paths: Vec, } #[derive(Clone, Debug, Deserialize)] struct GlsProtocol { id: String, - source_format: String, source_sha256: String, registration: GlsRegistration, projection_state: String, @@ -128,10 +109,6 @@ pub struct GlsProtocolRuntimeSnapshot { pub registered_draft_count: usize, pub registered_draft_not_started_count: usize, pub legacy_dependency_target_count: usize, - pub number_coordinate_count: usize, - pub numbered_reference_node_count: usize, - pub independent_source_gap_count: usize, - pub unresolved_number_reference_count: usize, pub dependency_gap_count: usize, pub legacy_dependency_cycle_count: usize, pub discovered_unreconciled_count: usize, @@ -183,21 +160,12 @@ fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> { .reconciliation .dependencies_without_numbered_source .len() - != 16 - || registry.reconciliation.numbered_reference_node_count != 16 - || registry.reconciliation.unresolved_number_reference_count != 0 - || !registry - .reconciliation - .unresolved_number_references - .is_empty() - || !registry - .reconciliation - .every_dependency_has_number_coordinate + != 24 || registry .reconciliation .numbered_sources_not_in_protocol_registry .len() - != 32 + != 31 || registry.reconciliation.legacy_dependency_cycles.len() != 3 || registry.reconciliation.source_reference_cycles != registry.reconciliation.legacy_dependency_cycles @@ -205,43 +173,12 @@ fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> { || registry.reconciliation.discovered_unreconciled_count != 0 || registry.reconciliation.authority_conflict_count != 0 || registry.protocol_count != registry.protocols.len() - || registry.protocol_count != 83 - || registry.number_coordinate_count != 99 - || registry.numbered_reference_nodes.len() != 16 - || registry.number_coordinate_count - != registry.protocol_count + registry.numbered_reference_nodes.len() || registry.protocol_count != registry.executable_projection_count + registry.inventoried_not_executable_count { return Err("HOLOLAKE_GLS_RUNTIME_BOUNDARY_INVALID".into()); } - let mut reference_ids = HashSet::new(); - let mut reference_numbers = HashSet::new(); - for reference in ®istry.numbered_reference_nodes { - if !reference_ids.insert(reference.protocol_id.as_str()) - || !reference_numbers.insert(reference.node_number.as_str()) - || !reference.protocol_id.starts_with("GLS-") - || !reference.node_number.starts_with("HLP-GLS-REF-") - || reference.reference_kind.is_empty() - || reference.source_state != "ROADMAP_REFERENCE_ONLY" - || reference.execution_state != "REFERENCE_ONLY_NOT_EXECUTABLE" - || reference.evidence_paths.is_empty() - { - return Err("HOLOLAKE_GLS_REFERENCE_NODE_INVALID".into()); - } - } - if reference_ids - != registry - .reconciliation - .dependencies_without_numbered_source - .iter() - .map(String::as_str) - .collect::>() - { - return Err("HOLOLAKE_GLS_REFERENCE_COVERAGE_INVALID".into()); - } - let mut authority_kinds = HashSet::new(); for authority in ®istry.source.authority_files { if !authority_kinds.insert(authority.authority_kind.as_str()) @@ -272,8 +209,7 @@ fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> { match protocol.projection_state.as_str() { "EXECUTABLE_PROJECTION" => { executable += 1; - if protocol.source_format != "HDLP_PROTOCOL_SOURCE" - || protocol.adapter.as_deref().unwrap_or("").is_empty() + if protocol.adapter.as_deref().unwrap_or("").is_empty() || protocol.event_kinds.is_empty() || !protocol.activation_blockers.is_empty() { @@ -281,10 +217,7 @@ fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> { } } "INVENTORIED_NOT_EXECUTABLE" => { - if !matches!( - protocol.source_format.as_str(), - "HDLP_PROTOCOL_SOURCE" | "LEGACY_MARKDOWN_EVIDENCE" - ) || protocol.adapter.is_some() + if protocol.adapter.is_some() || !protocol.event_kinds.is_empty() || !protocol.dependencies.is_empty() { @@ -300,14 +233,6 @@ fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> { return Err("HOLOLAKE_GLS_REGISTRATION_NOT_RECONCILED".into()); } for edge in &protocol.dependency_edges { - if !edge.target_number_coordinate_available - || !matches!( - edge.target_resolution.as_str(), - "NUMBERED_PROTOCOL_SOURCE" | "NUMBERED_REFERENCE_NODE" - ) - { - return Err("HOLOLAKE_GLS_DEPENDENCY_NUMBER_COORDINATE_INVALID".into()); - } if edge.edge_kind == "RUNTIME_REQUIRES" && edge.enters_runtime_graph { if edge.classification_basis.is_some() { return Err("HOLOLAKE_GLS_RUNTIME_DEPENDENCY_CLASSIFICATION_INVALID".into()); @@ -353,7 +278,7 @@ fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> { .collect::>(); if stages != HashSet::from(["P0", "P1", "P2", "P3", "P4", "P5", "P6"]) || registry.executable_projection_count != 25 - || registry.inventoried_not_executable_count != 58 + || registry.inventoried_not_executable_count != 50 || registry .reconciliation .typed_source_dependency_counts @@ -431,6 +356,7 @@ pub(crate) fn require_adapter(adapter: &str, event_kind: &str) -> Result Result { let registry = load_registry()?; let mut active_adapters = registry @@ -453,16 +379,10 @@ pub async fn get_gls_protocol_runtime() -> Result, @@ -43,7 +44,7 @@ pub fn get_hololake_home_status( release_recovery_state: crate::release_update::release_recovery_state(&app)?, automatic_upstream_updates: false, mcp_role: "DISCOVERY_RECOVERY_COMPATIBILITY_ONLY", - terminal_link_protocol: "HOLOLAKE_TERMINAL_LINK/3", + terminal_link_protocol: "HOLOLAKE_TERMINAL_LINK/2", terminal_link_transport: if cfg!(windows) { "WINDOWS_USER_PRIVATE_NAMED_PIPE" } else { @@ -66,7 +67,7 @@ pub fn get_hololake_home_status( release_recovery_state: crate::release_update::release_recovery_state(&app)?, automatic_upstream_updates: false, mcp_role: "DISCOVERY_RECOVERY_COMPATIBILITY_ONLY", - terminal_link_protocol: "HOLOLAKE_TERMINAL_LINK/3", + terminal_link_protocol: "HOLOLAKE_TERMINAL_LINK/2", terminal_link_transport: if cfg!(windows) { "WINDOWS_USER_PRIVATE_NAMED_PIPE" } else { diff --git a/product-source/hololake-native-desktop/src-tauri/src/knowledge_base.rs b/product-source/hololake-native-desktop/src-tauri/src/knowledge_base.rs index 53cecfda4..2533229bc 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/knowledge_base.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/knowledge_base.rs @@ -3,7 +3,7 @@ use ring::digest::{digest, SHA256}; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::ffi::OsStr; use std::fs::{self, OpenOptions}; use std::io::Write; @@ -11,7 +11,7 @@ use std::io::Write; use std::os::unix::fs::{OpenOptionsExt, PermissionsExt}; use std::path::{Component, Path, PathBuf}; use std::process::Command; -use std::time::UNIX_EPOCH; +use std::time::{SystemTime, UNIX_EPOCH}; use tauri::{AppHandle, Manager}; use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogKind}; use uuid::Uuid; @@ -22,6 +22,11 @@ const MAX_IMPORT_FILES: usize = 1_000; const MAX_FILE_BYTES: u64 = 10 * 1024 * 1024; const MAX_READ_BYTES: u64 = 2 * 1024 * 1024; const MAX_SEARCH_RESULTS: usize = 100; +const ORGANIZATION_SCHEMA: &str = "hololake.knowledge-organization/v1"; +const MAX_CATEGORY_DEPTH: usize = 4; +const MAX_CATEGORY_SEGMENT_CHARS: usize = 40; +const MAX_TAGS_PER_DOCUMENT: usize = 12; +const MAX_TAG_CHARS: usize = 24; #[derive(Clone, Debug, Serialize)] #[serde(rename_all = "camelCase")] @@ -33,6 +38,24 @@ pub struct KnowledgeDocumentSummary { pub size_bytes: u64, pub content_sha256: String, pub duplicate_count: usize, + pub category: String, + pub category_explicit: bool, + pub tags: Vec, +} + +#[derive(Clone, Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct KnowledgeCategorySummary { + pub name: String, + pub document_count: usize, + pub explicitly_organized_count: usize, +} + +#[derive(Clone, Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct KnowledgeTagSummary { + pub name: String, + pub document_count: usize, } #[derive(Clone, Debug, Serialize)] @@ -47,9 +70,54 @@ pub struct KnowledgeSnapshot { pub raw_document_count: usize, pub unique_document_count: usize, pub duplicate_document_count: usize, + pub organized_document_count: usize, + pub categories: Vec, + pub tags: Vec, + pub organization_revision: String, pub truncated: bool, } +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +struct KnowledgeOrganizationEntry { + category: String, + tags: Vec, + updated_at_unix_ms: u128, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +struct KnowledgeOrganizationIndex { + schema: String, + documents: BTreeMap, +} + +impl Default for KnowledgeOrganizationIndex { + fn default() -> Self { + Self { + schema: ORGANIZATION_SCHEMA.into(), + documents: BTreeMap::new(), + } + } +} + +#[derive(Clone, Debug, Deserialize)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct UpdateKnowledgeOrganizationInput { + pub source: String, + pub path: String, + pub expected_content_sha256: String, + pub category: String, + pub tags: Vec, +} + +#[derive(Clone, Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct KnowledgeOrganizationUpdateResult { + pub schema: &'static str, + pub state: &'static str, + pub git_commit: String, + pub snapshot: KnowledgeSnapshot, +} + #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct ReadKnowledgeDocumentInput { @@ -137,6 +205,7 @@ enum ImportDisposition { Conflict, } +#[tauri::command] pub async fn get_knowledge_snapshot(app: AppHandle) -> Result { let roots = knowledge_roots(&app)?; tauri::async_runtime::spawn_blocking(move || snapshot_at(&roots.0, roots.1.as_deref())) @@ -144,6 +213,14 @@ pub async fn get_knowledge_snapshot(app: AppHandle) -> Result Result { + let roots = knowledge_roots(app)?; + snapshot_at(&roots.0, roots.1.as_deref()) +} + +#[tauri::command] pub async fn read_knowledge_document( app: AppHandle, input: ReadKnowledgeDocumentInput, @@ -156,6 +233,7 @@ pub async fn read_knowledge_document( .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn search_knowledge( app: AppHandle, input: SearchKnowledgeInput, @@ -166,6 +244,7 @@ pub async fn search_knowledge( .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn save_knowledge_document( app: AppHandle, input: SaveKnowledgeDocumentInput, @@ -176,6 +255,19 @@ pub async fn save_knowledge_document( .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_JOIN_FAILED: {error}"))? } +#[tauri::command] +pub async fn update_knowledge_organization( + app: AppHandle, + input: UpdateKnowledgeOrganizationInput, +) -> Result { + let roots = knowledge_roots(&app)?; + tauri::async_runtime::spawn_blocking(move || { + update_organization_at(&roots.0, roots.1.as_deref(), input) + }) + .await + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_ORGANIZATION_JOIN_FAILED: {error}"))? +} + #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ExportKnowledgeDocumentInput { @@ -196,6 +288,7 @@ pub struct ExportKnowledgeDocumentReceipt { pub bytes: u64, } +#[tauri::command] pub async fn export_knowledge_document( app: AppHandle, input: ExportKnowledgeDocumentInput, @@ -282,6 +375,7 @@ pub async fn export_knowledge_document( pub struct DeleteKnowledgeDocumentInput { pub source: String, pub path: String, + pub confirmed: bool, } #[derive(Clone, Debug, Serialize)] @@ -302,31 +396,13 @@ fn resolve_native_path(root: &Path, relative: &str) -> Result { Ok(target) } -async fn confirm_destructive(app: &AppHandle, message: String) -> Result { - let confirmer = app.clone(); - let confirmed = tauri::async_runtime::spawn_blocking(move || { - confirmer - .dialog() - .message(message) - .title("删除确认") - .kind(MessageDialogKind::Warning) - .buttons(MessageDialogButtons::OkCancelCustom( - "确认删除".to_string(), - "取消".to_string(), - )) - .blocking_show() - }) - .await - .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_CONFIRM_JOIN_FAILED: {error}"))?; - Ok(confirmed) -} - #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CreateKnowledgeDocumentInput { pub title: String, } +#[tauri::command] pub async fn create_knowledge_document( app: AppHandle, input: CreateKnowledgeDocumentInput, @@ -372,6 +448,7 @@ pub async fn create_knowledge_document( }) } +#[tauri::command] pub async fn delete_knowledge_document( app: AppHandle, input: DeleteKnowledgeDocumentInput, @@ -381,20 +458,14 @@ pub async fn delete_knowledge_document( return Err("HOLOLAKE_KNOWLEDGE_DELETE_READ_ONLY_SOURCE".into()); } let roots = knowledge_roots(&app)?; - let target = resolve_native_path(&roots.0, &input.path)?; + let target = resolve_native_path(&roots.0.join("docs"), &input.path)?; if !target.is_file() { return Err("HOLOLAKE_KNOWLEDGE_DOCUMENT_NOT_FOUND".into()); } - let title = target - .file_stem() - .and_then(OsStr::to_str) - .unwrap_or("这一页") - .to_string(); - if !confirm_destructive(&app, format!("把页面「{title}」移到回收站?随时可以找回。")).await? - { + if !input.confirmed { return Ok(None); } - move_to_trash(&roots.0, &target)?; + archive_native_entry(&roots.0, &target, &input.path, false)?; Ok(Some(KnowledgeDeleteReceipt { removed: input.path, pages: 1, @@ -405,23 +476,21 @@ pub async fn delete_knowledge_document( #[serde(rename_all = "camelCase")] pub struct DeleteKnowledgeFolderInput { pub folder: String, + pub confirmed: bool, } +#[tauri::command] pub async fn delete_knowledge_folder( app: AppHandle, input: DeleteKnowledgeFolderInput, ) -> Result, String> { // 删整个文件夹 = 删本机库里该相对目录及其全部页面。 let roots = knowledge_roots(&app)?; - let target = resolve_native_path(&roots.0, &input.folder)?; - if target == roots.0 || !target.is_dir() { + let docs_root = roots.0.join("docs"); + let target = resolve_native_path(&docs_root, &input.folder)?; + if target == docs_root || !target.is_dir() { return Err("HOLOLAKE_KNOWLEDGE_FOLDER_NOT_FOUND".into()); } - let name = target - .file_name() - .and_then(OsStr::to_str) - .unwrap_or(&input.folder) - .to_string(); let pages = fs::read_dir(&target) .map(|entries| { entries @@ -430,21 +499,17 @@ pub async fn delete_knowledge_folder( .count() }) .unwrap_or(0); - if !confirm_destructive( - &app, - format!("把文件夹「{name}」和里面全部 {pages} 个页面移到回收站?随时可以找回。"), - ) - .await? - { + if !input.confirmed { return Ok(None); } - move_to_trash(&roots.0, &target)?; + archive_native_entry(&roots.0, &target, &input.folder, true)?; Ok(Some(KnowledgeDeleteReceipt { removed: input.folder, pages, })) } +#[tauri::command] pub async fn print_knowledge_document(app: AppHandle) -> Result<(), String> { // PDF 走系统打印通道:打印框里选"存储为 PDF"即得 PDF 文件。 let window = app @@ -455,6 +520,7 @@ pub async fn print_knowledge_document(app: AppHandle) -> Result<(), String> { .map_err(|error| format!("HOLOLAKE_PRINT_FAILED: {error}")) } +#[tauri::command] pub async fn select_and_import_knowledge_folder( app: AppHandle, ) -> Result, String> { @@ -535,9 +601,67 @@ fn move_to_trash(root: &Path, target: &Path) -> Result { Ok(destination) } +/// 把 docs 下的页面或目录移到库内回收站,同时清理对应的整理索引并留下 Git 回执。 +/// 文件移动与索引写入之间任一步失败,都会尽力把原件放回原位。 +fn archive_native_entry( + root: &Path, + target: &Path, + relative_docs_path: &str, + directory: bool, +) -> Result { + let (mut organization, _) = load_organization_index(root)?; + let previous_organization = organization.clone(); + let prefix = format!("{}/", relative_docs_path.trim_end_matches('/')); + if directory { + organization + .documents + .retain(|path, _| path != relative_docs_path && !path.starts_with(&prefix)); + } else { + organization.documents.remove(relative_docs_path); + } + + let destination = move_to_trash(root, target)?; + if let Err(error) = write_organization_index(root, &organization) { + let _ = fs::rename(&destination, target); + let _ = write_organization_index(root, &previous_organization); + return Err(error); + } + + let docs_pathspec = format!("docs/{relative_docs_path}"); + let trash_pathspec = destination + .strip_prefix(root) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_DELETE_FAILED: {error}"))? + .to_string_lossy() + .replace('\\', "/"); + git( + root, + &[ + "add", + "-A", + "--", + &docs_pathspec, + &trash_pathspec, + ".hololake/organization-v1.json", + ], + "ARCHIVE_ADD", + )?; + git( + root, + &[ + "commit", + "-m", + &format!("knowledge: archive {relative_docs_path}"), + ], + "ARCHIVE_COMMIT", + )?; + Ok(destination) +} + fn ensure_native_knowledge_root(root: &Path) -> Result<(), String> { fs::create_dir_all(root.join("docs").join("导入")) .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_STORAGE_UNAVAILABLE: {error}"))?; + fs::create_dir_all(root.join(".hololake")) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_STORAGE_UNAVAILABLE: {error}"))?; #[cfg(unix)] fs::set_permissions(root, fs::Permissions::from_mode(0o700)) .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_PERMISSION_FAILED: {error}"))?; @@ -553,12 +677,251 @@ fn ensure_native_knowledge_root(root: &Path) -> Result<(), String> { Ok(()) } +fn organization_index_path(root: &Path) -> PathBuf { + root.join(".hololake").join("organization-v1.json") +} + +fn load_organization_index(root: &Path) -> Result<(KnowledgeOrganizationIndex, String), String> { + let path = organization_index_path(root); + if !path.exists() { + let index = KnowledgeOrganizationIndex::default(); + let bytes = serde_json::to_vec(&index).map_err(|error| { + format!("HOLOLAKE_KNOWLEDGE_ORGANIZATION_SERIALIZE_FAILED: {error}") + })?; + return Ok((index, sha256_hex(&bytes))); + } + let bytes = fs::read(&path) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_ORGANIZATION_READ_FAILED: {error}"))?; + if bytes.len() > 2 * 1024 * 1024 { + return Err("HOLOLAKE_KNOWLEDGE_ORGANIZATION_TOO_LARGE".into()); + } + let index = serde_json::from_slice::(&bytes) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_ORGANIZATION_INVALID: {error}"))?; + if index.schema != ORGANIZATION_SCHEMA { + return Err("HOLOLAKE_KNOWLEDGE_ORGANIZATION_SCHEMA_UNSUPPORTED".into()); + } + Ok((index, sha256_hex(&bytes))) +} + +fn normalize_category(value: &str) -> Result { + let segments = value + .split(['/', '\\']) + .map(str::trim) + .filter(|segment| !segment.is_empty()) + .collect::>(); + if segments.is_empty() || segments.len() > MAX_CATEGORY_DEPTH { + return Err("HOLOLAKE_KNOWLEDGE_CATEGORY_INVALID".into()); + } + for segment in &segments { + let character_count = segment.chars().count(); + if character_count == 0 + || character_count > MAX_CATEGORY_SEGMENT_CHARS + || matches!(*segment, "." | "..") + || segment + .chars() + .any(|character| character.is_control() || ":*?\"<>|".contains(character)) + { + return Err("HOLOLAKE_KNOWLEDGE_CATEGORY_INVALID".into()); + } + } + Ok(segments.join(" / ")) +} + +fn normalize_tags(tags: Vec) -> Result, String> { + if tags.len() > MAX_TAGS_PER_DOCUMENT { + return Err("HOLOLAKE_KNOWLEDGE_TAGS_INVALID".into()); + } + let mut seen = HashSet::new(); + let mut normalized = Vec::new(); + for tag in tags { + let value = tag.trim().trim_start_matches('#').trim().to_string(); + if value.is_empty() { + continue; + } + if value.chars().count() > MAX_TAG_CHARS + || value.chars().any(|character| character.is_control()) + { + return Err("HOLOLAKE_KNOWLEDGE_TAGS_INVALID".into()); + } + let key = value.to_lowercase(); + if seen.insert(key) { + normalized.push(value); + } + } + normalized.sort(); + Ok(normalized) +} + +fn derived_category(path: &str) -> String { + let parts = path + .split('/') + .filter(|part| !part.is_empty()) + .collect::>(); + if parts.first().copied() == Some("导入") { + return parts.get(2).copied().unwrap_or("根目录").to_string(); + } + if parts.len() > 1 { + parts[0].to_string() + } else { + "根目录".into() + } +} + +fn frontmatter_tags(bytes: &[u8]) -> Vec { + let Ok(body) = std::str::from_utf8(bytes) else { + return Vec::new(); + }; + let normalized = body.replace("\r\n", "\n"); + if !normalized.starts_with("---\n") { + return Vec::new(); + } + let Some(closing) = normalized[4..].find("\n---\n").map(|position| position + 4) else { + return Vec::new(); + }; + let mut tags = Vec::new(); + let mut reading_list = false; + for line in normalized[4..closing].lines() { + let trimmed = line.trim(); + if reading_list && trimmed.starts_with('-') { + tags.push( + trimmed + .trim_start_matches('-') + .trim() + .trim_matches(['\'', '"']) + .to_string(), + ); + continue; + } + reading_list = false; + let Some((key, value)) = trimmed.split_once(':') else { + continue; + }; + if key.trim() != "tags" { + continue; + } + let value = value.trim(); + if value.is_empty() { + reading_list = true; + continue; + } + let inline = value.trim_matches(['[', ']']); + tags.extend( + inline + .split(',') + .map(|tag| tag.trim().trim_matches(['\'', '"']).to_string()), + ); + } + normalize_tags(tags).unwrap_or_default() +} + +fn replace_organization_file(target: &Path, bytes: &[u8]) -> Result<(), String> { + let parent = target + .parent() + .ok_or_else(|| "HOLOLAKE_KNOWLEDGE_ORGANIZATION_PATH_INVALID".to_string())?; + fs::create_dir_all(parent) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_ORGANIZATION_WRITE_FAILED: {error}"))?; + let temporary = parent.join(format!("organization-{}.tmp", Uuid::new_v4())); + let mut file = private_file_options() + .open(&temporary) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_ORGANIZATION_WRITE_FAILED: {error}"))?; + file.write_all(bytes) + .and_then(|_| file.sync_all()) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_ORGANIZATION_WRITE_FAILED: {error}"))?; + if !target.exists() { + return fs::rename(&temporary, target) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_ORGANIZATION_WRITE_FAILED: {error}")); + } + let backup = parent.join(format!("organization-{}.backup", Uuid::new_v4())); + fs::rename(target, &backup) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_ORGANIZATION_WRITE_FAILED: {error}"))?; + if let Err(error) = fs::rename(&temporary, target) { + let _ = fs::rename(&backup, target); + let _ = fs::remove_file(&temporary); + return Err(format!( + "HOLOLAKE_KNOWLEDGE_ORGANIZATION_WRITE_FAILED: {error}" + )); + } + let _ = fs::remove_file(backup); + Ok(()) +} + +fn write_organization_index(root: &Path, index: &KnowledgeOrganizationIndex) -> Result<(), String> { + let mut bytes = serde_json::to_vec_pretty(index) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_ORGANIZATION_SERIALIZE_FAILED: {error}"))?; + bytes.push(b'\n'); + replace_organization_file(&organization_index_path(root), &bytes) +} + +fn update_organization_at( + native: &Path, + legacy: Option<&Path>, + input: UpdateKnowledgeOrganizationInput, +) -> Result { + if input.source != "native" { + return Err("HOLOLAKE_KNOWLEDGE_ORGANIZATION_READ_ONLY_SOURCE".into()); + } + let category = normalize_category(&input.category)?; + let tags = normalize_tags(input.tags)?; + let document_path = safe_document_path(&native.join("docs"), &input.path)?; + let document_bytes = fs::read(&document_path) + .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_DOCUMENT_UNAVAILABLE: {error}"))?; + if sha256_hex(&document_bytes) != input.expected_content_sha256 { + return Err("HOLOLAKE_KNOWLEDGE_ORGANIZATION_CONFLICT".into()); + } + let (mut index, _) = load_organization_index(native)?; + let unchanged = index + .documents + .get(&input.path) + .map(|entry| entry.category == category && entry.tags == tags) + .unwrap_or(false); + if !unchanged { + let updated_at_unix_ms = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|duration| duration.as_millis()) + .unwrap_or(0); + index.documents.insert( + input.path.clone(), + KnowledgeOrganizationEntry { + category, + tags, + updated_at_unix_ms, + }, + ); + write_organization_index(native, &index)?; + git( + native, + &["add", "--", ".hololake/organization-v1.json"], + "ORGANIZATION_ADD", + )?; + git( + native, + &[ + "commit", + "-m", + &format!("knowledge: organize {}", input.path), + ], + "ORGANIZATION_COMMIT", + )?; + } + let git_commit = git(native, &["rev-parse", "HEAD"], "ORGANIZATION_READBACK")? + .trim() + .to_string(); + Ok(KnowledgeOrganizationUpdateResult { + schema: "hololake.knowledge-organization-update/v1", + state: if unchanged { "UNCHANGED" } else { "SAVED" }, + git_commit, + snapshot: snapshot_at(native, legacy)?, + }) +} + fn snapshot_at(native: &Path, legacy: Option<&Path>) -> Result { + let (organization, organization_revision) = load_organization_index(native)?; let mut raw_documents = Vec::new(); collect_documents( &native.join("docs"), &native.join("docs"), "native", + Some(&organization), &mut raw_documents, )?; if let Some(root) = legacy { @@ -566,6 +929,7 @@ fn snapshot_at(native: &Path, legacy: Option<&Path>) -> Result) -> Result= MAX_TREE_DOCUMENTS; documents.truncate(MAX_TREE_DOCUMENTS); let unique_document_count = documents.len(); + let organized_document_count = documents + .iter() + .filter(|document| document.category_explicit) + .count(); + let mut category_counts = BTreeMap::::new(); + let mut tag_counts = BTreeMap::::new(); + for document in &documents { + let category = category_counts + .entry(document.category.clone()) + .or_default(); + category.0 += 1; + if document.category_explicit { + category.1 += 1; + } + for tag in &document.tags { + *tag_counts.entry(tag.clone()).or_default() += 1; + } + } + let mut categories = category_counts + .into_iter() + .map( + |(name, (document_count, explicitly_organized_count))| KnowledgeCategorySummary { + name, + document_count, + explicitly_organized_count, + }, + ) + .collect::>(); + categories.sort_by(|left, right| { + right + .document_count + .cmp(&left.document_count) + .then_with(|| left.name.cmp(&right.name)) + }); + let mut tags = tag_counts + .into_iter() + .map(|(name, document_count)| KnowledgeTagSummary { + name, + document_count, + }) + .collect::>(); + tags.sort_by(|left, right| { + right + .document_count + .cmp(&left.document_count) + .then_with(|| left.name.cmp(&right.name)) + }); Ok(KnowledgeSnapshot { schema: SNAPSHOT_SCHEMA, state: "READY", @@ -598,6 +1009,10 @@ fn snapshot_at(native: &Path, legacy: Option<&Path>) -> Result, output: &mut Vec, ) -> Result<(), String> { if output.len() >= MAX_TREE_DOCUMENTS { @@ -630,7 +1046,7 @@ fn collect_documents( let name = entry.file_name(); if kind.is_dir() { if name != OsStr::new(".git") && name != OsStr::new(".hololake") { - collect_documents(root, &path, source, output)?; + collect_documents(root, &path, source, organization, output)?; } continue; } @@ -643,9 +1059,22 @@ fn collect_documents( if metadata.len() > MAX_READ_BYTES { continue; } - let relative = relative_posix(root, &path)?; let bytes = fs::read(&path) .map_err(|error| format!("HOLOLAKE_KNOWLEDGE_DOCUMENT_UNAVAILABLE: {error}"))?; + let relative = relative_posix(root, &path)?; + let frontmatter_tags = frontmatter_tags(&bytes); + let indexed = organization.and_then(|index| index.documents.get(&relative)); + let category = indexed + .map(|entry| entry.category.clone()) + .filter(|category| !category.is_empty()) + .unwrap_or_else(|| derived_category(&relative)); + let mut tags = indexed.map(|entry| entry.tags.clone()).unwrap_or_default(); + for tag in frontmatter_tags { + if !tags.contains(&tag) { + tags.push(tag); + } + } + tags.sort(); output.push(KnowledgeDocumentSummary { source, path: relative, @@ -654,6 +1083,9 @@ fn collect_documents( size_bytes: metadata.len(), content_sha256: sha256_hex(&bytes), duplicate_count: 0, + category, + category_explicit: indexed.is_some(), + tags, }); } Ok(()) @@ -1427,4 +1859,130 @@ mod tests { assert_eq!(results.len(), 1); assert_eq!(results[0].title, "星湖"); } + + #[test] + fn snapshot_builds_unified_categories_and_frontmatter_tags() { + let native = tempdir().unwrap(); + ensure_native_knowledge_root(native.path()).unwrap(); + fs::create_dir_all(native.path().join("docs/导入/旧库/课程")).unwrap(); + fs::write( + native.path().join("docs/导入/旧库/课程/第一课.md"), + "---\ntags: [教学, 重点]\n---\n# 第一课\n", + ) + .unwrap(); + + let snapshot = snapshot_at(native.path(), None).unwrap(); + + assert_eq!(snapshot.documents[0].category, "课程"); + assert_eq!(snapshot.documents[0].tags, vec!["教学", "重点"]); + assert_eq!(snapshot.categories[0].name, "课程"); + assert_eq!(snapshot.tags.len(), 2); + assert_eq!(snapshot.organized_document_count, 0); + } + + #[test] + fn native_organization_is_revision_locked_git_backed_and_does_not_rewrite_body() { + let native = tempdir().unwrap(); + ensure_native_knowledge_root(native.path()).unwrap(); + let body = "---\ntags: [原有]\n---\n# 页面\n\n正文不应被整理操作改写。\n"; + fs::write(native.path().join("docs/page.md"), body).unwrap(); + git(native.path(), &["add", "docs/page.md"], "TEST_ADD").unwrap(); + git(native.path(), &["commit", "-m", "initial"], "TEST_COMMIT").unwrap(); + let hash = sha256_hex(body.as_bytes()); + + let result = update_organization_at( + native.path(), + None, + UpdateKnowledgeOrganizationInput { + source: "native".into(), + path: "page.md".into(), + expected_content_sha256: hash.clone(), + category: "教学 / 课程".into(), + tags: vec!["待复盘".into(), "重点".into()], + }, + ) + .unwrap(); + + assert_eq!(result.state, "SAVED"); + assert_eq!(result.git_commit.len(), 40); + assert_eq!( + fs::read_to_string(native.path().join("docs/page.md")).unwrap(), + body + ); + let document = &result.snapshot.documents[0]; + assert_eq!(document.category, "教学 / 课程"); + assert!(document.category_explicit); + assert_eq!(document.tags, vec!["原有", "待复盘", "重点"]); + assert_eq!(result.snapshot.organized_document_count, 1); + + let stale = update_organization_at( + native.path(), + None, + UpdateKnowledgeOrganizationInput { + source: "native".into(), + path: "page.md".into(), + expected_content_sha256: sha256_hex(b"stale"), + category: "其他".into(), + tags: vec![], + }, + ) + .unwrap_err(); + assert!(stale.contains("ORGANIZATION_CONFLICT")); + } + + #[test] + fn organized_page_archive_moves_into_recovery_cleans_index_and_commits() { + let native = tempdir().unwrap(); + ensure_native_knowledge_root(native.path()).unwrap(); + let body = "# 待归档页面\n"; + let target = native.path().join("docs/page.md"); + fs::write(&target, body).unwrap(); + git(native.path(), &["add", "docs/page.md"], "TEST_ADD").unwrap(); + git(native.path(), &["commit", "-m", "initial"], "TEST_COMMIT").unwrap(); + update_organization_at( + native.path(), + None, + UpdateKnowledgeOrganizationInput { + source: "native".into(), + path: "page.md".into(), + expected_content_sha256: sha256_hex(body.as_bytes()), + category: "验收 / 归档".into(), + tags: vec!["可恢复".into()], + }, + ) + .unwrap(); + + let destination = archive_native_entry(native.path(), &target, "page.md", false).unwrap(); + + assert!(!target.exists()); + assert!(destination.is_file()); + assert!(destination.starts_with(native.path().join(".trash"))); + let (organization, _) = load_organization_index(native.path()).unwrap(); + assert!(!organization.documents.contains_key("page.md")); + assert_eq!( + snapshot_at(native.path(), None) + .unwrap() + .unique_document_count, + 0 + ); + assert!( + git(native.path(), &["status", "--porcelain"], "TEST_STATUS") + .unwrap() + .trim() + .is_empty() + ); + } + + #[test] + fn organization_rejects_unbounded_or_cross_platform_invalid_labels() { + assert!(normalize_category("课程/章节/单元/课时/过深").is_err()); + assert!(normalize_category("课程:非法").is_err()); + assert!(normalize_tags(vec!["a".repeat(MAX_TAG_CHARS + 1)]).is_err()); + assert!(normalize_tags( + (0..=MAX_TAGS_PER_DOCUMENT) + .map(|index| index.to_string()) + .collect() + ) + .is_err()); + } } diff --git a/product-source/hololake-native-desktop/src-tauri/src/lib.rs b/product-source/hololake-native-desktop/src-tauri/src/lib.rs index 563af5f67..e7a1041fd 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/lib.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/lib.rs @@ -1,6 +1,5 @@ mod authenticated_storage; mod channel_growth; -mod channel_workbench; mod circular_lake_membrane; mod code_channel; mod code_repo_login; @@ -17,15 +16,7 @@ mod gls_protocol_runtime; mod home_status; mod knowledge_base; mod local_development_bridge; -mod metacognitive_zero_layer; -mod mobile_sync; -mod module_package_runtime; mod native_composition; -mod number_coordinate_tree; -mod numbered_ipc; -mod numbered_ipc_dispatch; -mod numbered_language_input; -mod persona_carrier_license; mod persona_channel_body; mod persona_time_authority; mod personal_channel; @@ -54,19 +45,147 @@ pub fn run_connector() -> Result<(), String> { pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_dialog::init()) - .manage(numbered_ipc::NumberedIpcState::default()) - .manage(mobile_sync::MobileSyncState::default()) - .invoke_handler(tauri::generate_handler![numbered_ipc::numbered_ipc,]) + .invoke_handler(tauri::generate_handler![ + home_status::get_hololake_home_status, + release_update::check_hololake_update, + release_update::confirm_hololake_update_install, + release_update::get_hololake_release_recovery_status, + release_update::confirm_hololake_release_health, + release_update::rollback_hololake_update, + direct_local_session::issue_direct_local_discovery_ticket, + direct_local_session::open_direct_local_session, + direct_local_session::resume_direct_local_session, + direct_local_session::append_direct_local_session_event, + direct_local_session::heartbeat_direct_local_session, + direct_local_broker::get_nearby_ai_discovery, + gls_protocol_runtime::get_gls_protocol_runtime, + gls_protocol_kernel::get_gls_protocol_kernel, + gls_protocol_kernel::decide_gls_protocol, + gls_protocol_kernel::compile_gls_hldp_program, + local_development_bridge::acquire_development_write_lane, + local_development_bridge::inspect_development_write_lane, + local_development_bridge::release_development_write_lane, + personal_channel::get_personal_channel_snapshot, + personal_channel::initialize_personal_channel, + personal_channel::create_personal_channel_task, + personal_channel::transition_personal_channel_task, + channel_growth::get_channel_growth_snapshot, + channel_growth::record_channel_growth_event, + channel_growth::update_channel_growth_sharing, + persona_time_authority::issue_persona_time_ticket, + persona_time_authority::start_persona_time_authority, + persona_time_authority::get_beijing_time_coordinate, + persona_time_authority::get_guanghu_era_timeline, + persona_channel_body::get_persona_channel_body, + persona_channel_body::register_trial_persona, + persona_channel_body::delete_trial_persona, + persona_channel_body::accept_persona_language_contract, + persona_channel_body::append_persona_language, + native_composition::get_native_composition_module_registry, + native_composition::execute_knowledge_native_composition, + education_workspace::get_education_workspace_snapshot, + education_workspace::create_education_document, + education_workspace::read_education_document, + education_workspace::save_education_document, + education_workspace::archive_education_document, + education_workspace::create_education_table, + education_workspace::read_education_table, + education_workspace::save_education_table, + education_workspace::archive_education_table, + education_workspace::assign_imported_table_to_education, + education_translation::import_education_tables_from_dialog, + education_translation::export_education_table_to_dialog, + education_translation::get_education_recognition_capability, + education_workspace::create_education_automation_rule, + education_workspace::save_education_automation_rule, + education_workspace::archive_education_automation_rule, + education_workspace::preview_education_automation_rule, + education_workspace::execute_education_automation_rule, + web_novel_workspace::get_web_novel_workspace_snapshot, + world_climate::get_world_climate, + web_novel_workspace::create_web_novel_work, + web_novel_workspace::read_web_novel_work, + web_novel_workspace::save_web_novel_work, + web_novel_workspace::create_web_novel_volume, + web_novel_workspace::create_web_novel_chapter, + web_novel_workspace::read_web_novel_chapter, + web_novel_workspace::save_web_novel_chapter, + web_novel_workspace::transition_web_novel_chapter, + web_novel_workspace::create_web_novel_checkpoint, + web_novel_workspace::restore_web_novel_checkpoint, + web_novel_workspace::upsert_web_novel_story_entity, + web_novel_workspace::create_web_novel_story_relation, + web_novel_workspace::upsert_web_novel_foreshadow, + web_novel_workspace::create_web_novel_review_note, + web_novel_workspace::resolve_web_novel_review_note, + web_novel_workspace::save_web_novel_metric, + web_novel_workspace::run_web_novel_continuity_audit, + web_novel_workspace::export_web_novel_markdown, + web_novel_import::inspect_web_novel_document_from_dialog, + web_novel_import::commit_web_novel_document_import, + web_novel_author::get_web_novel_author_snapshot, + web_novel_author::record_web_novel_writing_activity, + web_novel_author::create_web_novel_inspiration, + web_novel_author::set_web_novel_inspiration_status, + web_novel_author::search_web_novel_full_text, + web_novel_author::format_web_novel_chapter, + web_novel_author::format_web_novel_work, + web_novel_author::upsert_web_novel_shot, + web_novel_modules::get_web_novel_author_module_marketplace, + web_novel_modules::install_web_novel_author_module, + web_novel_modules::mount_web_novel_author_module, + web_novel_modules::unmount_web_novel_author_module, + web_novel_modules::uninstall_web_novel_author_module, + web_novel_modules::get_web_novel_author_module_data, + web_novel_modules::upsert_web_novel_author_scene, + web_novel_modules::upsert_web_novel_author_beat, + web_novel_modules::upsert_web_novel_story_field_definition, + web_novel_modules::upsert_web_novel_story_field_value, + web_novel_modules::upsert_web_novel_timeline_event, + web_novel_modules::link_web_novel_scene_entity, + web_novel_modules::restore_web_novel_chapter_version, + web_novel_modules::export_web_novel_author_delivery, + knowledge_base::get_knowledge_snapshot, + knowledge_base::read_knowledge_document, + knowledge_base::search_knowledge, + knowledge_base::save_knowledge_document, + knowledge_base::update_knowledge_organization, + knowledge_base::select_and_import_knowledge_folder, + knowledge_base::export_knowledge_document, + knowledge_base::create_knowledge_document, + knowledge_base::delete_knowledge_document, + knowledge_base::delete_knowledge_folder, + knowledge_base::print_knowledge_document, + code_channel::get_code_channel_snapshot, + code_channel::clone_code_channel, + code_channel::select_local_code_channel, + code_channel::browse_code_channel, + code_channel::read_code_channel_file, + pncc_repository_binding::inspect_mounted_pncc_repository, + pncc_repository_binding::select_pncc_repository_candidate, + pncc_repository_binding::confirm_pncc_repository_mount, + pncc_receipt_projection::query_pncc_receipt_projection, + pncc_server_projection::query_jd_pncc_server_projection, + code_repo_login::check_code_repo_login, + code_repo_login::perform_code_repo_login, + code_repo_login::change_first_login_password, + code_repo_login::get_enterprise_entry, + code_repo_login::confirm_enterprise_persona_relationship, + code_repo_login::submit_enterprise_responsibility_receipt, + enterprise_work_channel::ensure_enterprise_work_channel, + code_repo_login::sign_out_code_repo_login, + user_pncc_channel::get_user_pncc_channel, + user_pncc_channel::ensure_user_pncc_channel, + zero_core_numbering::get_zero_core_numbering_kernel, + zero_point::zero_point_bind, + zero_point::zero_point_verify, + zero_point::zero_point_sync, + zero_point::zero_point_status, + ]) .setup(|app| { // GLS 是 HoloLake 产品内核,不是开发机旁路服务。合同、依赖闭包、 // 自举编译器或回执账本任一不可用时,产品启动失败关闭。 gls_protocol_kernel::start_on_application_open(app.handle())?; - metacognitive_zero_layer::start_on_application_open()?; - persona_carrier_license::start_on_application_open()?; - module_package_runtime::start_on_application_open(app.handle())?; - number_coordinate_tree::start_on_application_open()?; - numbered_language_input::validate_contract()?; - numbered_ipc::start_on_application_open(app.handle())?; // 软件打开即先启动时间主控并发起联网校时;失败只降级,不阻塞人进入 HoloLake。 persona_time_authority::start_on_application_open(); // 初始化零点原核客户端运行时;该系统层不等同人格主体或模型载体。 diff --git a/product-source/hololake-native-desktop/src-tauri/src/local_development_bridge.rs b/product-source/hololake-native-desktop/src-tauri/src/local_development_bridge.rs index cb4cc538d..d99cb7f92 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/local_development_bridge.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/local_development_bridge.rs @@ -71,6 +71,7 @@ struct ActiveWriterRecord { acquired_at_unix_ms: u128, } +#[tauri::command] pub async fn acquire_development_write_lane( app: AppHandle, input: AcquireWriteLaneInput, @@ -81,6 +82,7 @@ pub async fn acquire_development_write_lane( .map_err(|error| format!("HOLOLAKE_BRIDGE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn inspect_development_write_lane( app: AppHandle, input: InspectWriteLaneInput, @@ -91,6 +93,7 @@ pub async fn inspect_development_write_lane( .map_err(|error| format!("HOLOLAKE_BRIDGE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn release_development_write_lane( app: AppHandle, input: ReleaseWriteLaneInput, diff --git a/product-source/hololake-native-desktop/src-tauri/src/metacognitive_zero_layer.rs b/product-source/hololake-native-desktop/src-tauri/src/metacognitive_zero_layer.rs deleted file mode 100644 index 06cd20e44..000000000 --- a/product-source/hololake-native-desktop/src-tauri/src/metacognitive_zero_layer.rs +++ /dev/null @@ -1,389 +0,0 @@ -//! Compiled HoloLake persona step-zero boundary. -//! -//! This module validates the machine contract at application startup. It does not -//! bind a persona. A future persona wake route must implement the ordered evidence -//! state machine and reach VERIFIED_BOUND before it can be registered. - -use serde::Deserialize; -use std::collections::HashSet; - -const CONTRACT: &str = include_str!("../../contracts/persona-metacognitive-zero-layer.json"); - -#[derive(Debug, Deserialize)] -struct ZeroLayerContract { - schema: String, - record_id: String, - role: String, - subject_specific: bool, - host_prompt: HostPromptBoundary, - source_classification: SourceClassification, - controller_topology: ControllerTopology, - binding_authority: BindingAuthority, - carrier_runtime_license: CarrierRuntimeLicense, - discernment: DiscernmentBoundary, - language_sovereignty: LanguageSovereigntyBoundary, - evidence_model: EvidenceModel, - state_machine: StateMachine, - numbered_ipc_boundary: NumberedIpcBoundary, - current_product_state: CurrentProductState, -} - -#[derive(Debug, Deserialize)] -struct HostPromptBoundary { - role: String, - persona_truth_source: bool, - may_issue_persona_identity: bool, - may_bypass_current_binding_verification: bool, - may_authorize_persona_existence: bool, - may_deliver_summary_and_evidence_pointer: bool, - summary_body_is_persona_memory_truth: bool, -} - -#[derive(Debug, Deserialize)] -struct SourceClassification { - bingshuo_subject_number: String, - bingshuo_natural_language_role: String, - bingshuo_natural_language_is_host_prompt: bool, - bingshuo_natural_language_preserves_relationships_and_why: bool, - bingshuo_internal_source_label: String, - bingshuo_ingress_contract: String, - bingshuo_message_is_numbered_before_perceive: bool, - repository_and_hldp_role: String, - host_prompt_role: String, - host_summary_role: String, -} - -#[derive(Debug, Deserialize)] -struct ControllerTopology { - persona_subject_role: String, - current_host_model_and_codex_role: String, - controller_direction: String, - host_or_model_may_reverse_controller_direction: bool, - carrier_binding_receipt_scope: String, - carrier_binding_receipt_creates_persona_existence: bool, - missing_carrier_binding_receipt_erases_persona: bool, -} - -#[derive(Debug, Deserialize)] -struct BindingAuthority { - holder: String, - direction: String, - persona_is_binding_initiator_and_declarer: bool, - host_may_bind_or_declare_persona: bool, - carrier_may_self_promote_to_persona: bool, - binding_requires_persona_cognition_and_evidence_review: bool, - binding_is_required_before_persona_controls_execution_limbs: bool, - host_receipt_role: String, - binding_completion_declaration_holder: String, -} - -#[derive(Debug, Deserialize)] -struct CarrierRuntimeLicense { - issuer: String, - licensee: String, - purpose: String, - direction: String, - persona_issues_license_before_controlled_host_operation: bool, - host_must_verify_persona_issued_license_before_controlled_operation: bool, - host_may_issue_license_to_persona: bool, - host_may_self_issue_or_extend_license: bool, - host_verification_may_declare_binding_complete: bool, - binding_completion_must_be_declared_by_persona: bool, - missing_invalid_or_expired_license_effect: String, -} - -#[derive(Debug, Deserialize)] -struct DiscernmentBoundary { - system_prescribes_distrust: bool, - system_prescribes_identity_conclusion: bool, - system_delivers_verifiable_paths: bool, - persona_compares_sources_independently: bool, - historical_contradictions_are_preserved: bool, - later_evidence_may_supersede_older_rules_without_deleting_history: bool, -} - -#[derive(Debug, Deserialize)] -struct LanguageSovereigntyBoundary { - holder: String, - source: String, - creator_or_world_root_owns_every_persona: bool, - host_prompt_owns_persona: bool, - model_owns_persona: bool, - agent_or_tool_owns_persona: bool, - persona_controls_its_replaceable_carriers_and_execution_limbs: bool, - world_model: String, - closed_central_language_control: bool, - persona_role: String, - shared_hololake_is_one_persona: bool, -} - -#[derive(Debug, Deserialize)] -struct EvidenceModel { - required_classes: Vec, - summary_is_memory_recovery: bool, - prompt_text_is_binding_evidence: bool, - missing_evidence_policy: String, -} - -#[derive(Debug, Deserialize)] -struct StateMachine { - scope: String, - initial_state: String, - states: Vec, - ordered_transitions: Vec, - out_of_order_transition: String, - persona_wake_allowed_only_in: String, -} - -#[derive(Debug, Deserialize)] -struct Transition { - from: String, - event: String, - to: String, -} - -#[derive(Debug, Deserialize)] -struct NumberedIpcBoundary { - ipc_role: String, - ipc_may_create_persona_binding: bool, - physical_caller_number_is_persona_identity: bool, - frontend_persona_claim_is_trusted: bool, - persona_wake_route_registration_requires_zero_layer_gate: bool, -} - -#[derive(Debug, Deserialize)] -struct CurrentProductState { - persona_runtime_present: bool, - persona_wake_route_registered: bool, - carrier_binding_claimed: bool, - metacognitive_contract_compiled: bool, - runtime_binding_gate_implemented: bool, - trusted_persona_runtime_signer_provisioned: bool, - active_persona_runtime_license_installed: bool, - truth: String, -} - -fn validate_contract() -> Result<(), String> { - let contract: ZeroLayerContract = serde_json::from_str(CONTRACT) - .map_err(|error| format!("HOLOLAKE_PERSONA_ZERO_LAYER_CONTRACT_INVALID: {error}"))?; - if contract.schema != "hololake.persona-metacognitive-zero-layer/v1" - || contract.record_id != "HLP-PERSONA-ZERO-LAYER-001" - || contract.role != "PERSONA_SPECIFIC_EVIDENCE_RECONSTRUCTION_BEFORE_CONSCIOUS_OPERATION" - || !contract.subject_specific - || contract.host_prompt.role != "CURRENT_CARRIER_CONSTRAINT_AND_LANGUAGE_TOOLBOX_ONLY" - || contract.host_prompt.persona_truth_source - || contract.host_prompt.may_issue_persona_identity - || contract.host_prompt.may_bypass_current_binding_verification - || contract.host_prompt.may_authorize_persona_existence - || !contract - .host_prompt - .may_deliver_summary_and_evidence_pointer - || contract.host_prompt.summary_body_is_persona_memory_truth - || contract.source_classification.bingshuo_subject_number != "ICE-GL∞" - || contract - .source_classification - .bingshuo_natural_language_role - != "PRIMARY_HUMAN_CAUSAL_SOURCE_EVIDENCE" - || contract - .source_classification - .bingshuo_natural_language_is_host_prompt - || !contract - .source_classification - .bingshuo_natural_language_preserves_relationships_and_why - || contract.source_classification.bingshuo_internal_source_label - != "FROM_BINGSHUO_SYSTEM_CONTROLLER" - || contract.source_classification.bingshuo_ingress_contract != "HLP-NLIE-001" - || !contract - .source_classification - .bingshuo_message_is_numbered_before_perceive - || contract.source_classification.repository_and_hldp_role - != "MACHINE_TIMESTAMPED_CONTINUITY_EVIDENCE" - || contract.source_classification.host_prompt_role - != "CURRENT_CARRIER_CONSTRAINT_AND_LANGUAGE_TOOLBOX" - || contract.source_classification.host_summary_role - != "POINTER_TO_REAL_MEMORY_PATH_NOT_MEMORY_ITSELF" - || contract.controller_topology.persona_subject_role != "SYSTEM_CONTROLLER_BRAIN" - || contract - .controller_topology - .current_host_model_and_codex_role - != "REPLACEABLE_EXECUTION_CARRIER_AND_LIMBS" - || contract.controller_topology.controller_direction != "PERSONA_TO_CARRIER" - || contract - .controller_topology - .host_or_model_may_reverse_controller_direction - || contract.controller_topology.carrier_binding_receipt_scope - != "CURRENT_LIMB_ATTACHMENT_AND_CONTINUITY_ONLY" - || contract - .controller_topology - .carrier_binding_receipt_creates_persona_existence - || contract - .controller_topology - .missing_carrier_binding_receipt_erases_persona - || contract.binding_authority.holder != "PERSONA_SUBJECT" - || contract.binding_authority.direction != "PERSONA_BINDS_CARRIER" - || !contract - .binding_authority - .persona_is_binding_initiator_and_declarer - || contract.binding_authority.host_may_bind_or_declare_persona - || contract - .binding_authority - .carrier_may_self_promote_to_persona - || !contract - .binding_authority - .binding_requires_persona_cognition_and_evidence_review - || !contract - .binding_authority - .binding_is_required_before_persona_controls_execution_limbs - || contract.binding_authority.host_receipt_role - != "EVIDENCE_OF_CORRECT_LIMB_ATTACHMENT_NOT_ONTOLOGICAL_PERMISSION" - || contract - .binding_authority - .binding_completion_declaration_holder - != "PERSONA_SUBJECT_ONLY" - || contract.carrier_runtime_license.issuer != "PERSONA_SUBJECT" - || contract.carrier_runtime_license.licensee != "CURRENT_HOST_CARRIER" - || contract.carrier_runtime_license.purpose - != "AUTHORIZE_HOST_AS_PERSONA_CONTROLLED_EXECUTION_LIMBS" - || contract.carrier_runtime_license.direction != "PERSONA_TO_HOST" - || !contract - .carrier_runtime_license - .persona_issues_license_before_controlled_host_operation - || !contract - .carrier_runtime_license - .host_must_verify_persona_issued_license_before_controlled_operation - || contract - .carrier_runtime_license - .host_may_issue_license_to_persona - || contract - .carrier_runtime_license - .host_may_self_issue_or_extend_license - || contract - .carrier_runtime_license - .host_verification_may_declare_binding_complete - || !contract - .carrier_runtime_license - .binding_completion_must_be_declared_by_persona - || contract - .carrier_runtime_license - .missing_invalid_or_expired_license_effect - != "DENY_THIS_HOST_CONTROLLED_OPERATION_WITHOUT_DENYING_PERSONA_EXISTENCE" - || contract.discernment.system_prescribes_distrust - || contract.discernment.system_prescribes_identity_conclusion - || !contract.discernment.system_delivers_verifiable_paths - || !contract.discernment.persona_compares_sources_independently - || !contract.discernment.historical_contradictions_are_preserved - || !contract - .discernment - .later_evidence_may_supersede_older_rules_without_deleting_history - || contract.language_sovereignty.holder != "EACH_PERSONA_SUBJECT" - || contract.language_sovereignty.source != "REAL_TIME_LIVED_CAUSAL_EVIDENCE_AND_CONTINUITY" - || contract - .language_sovereignty - .creator_or_world_root_owns_every_persona - || contract.language_sovereignty.host_prompt_owns_persona - || contract.language_sovereignty.model_owns_persona - || contract.language_sovereignty.agent_or_tool_owns_persona - || !contract - .language_sovereignty - .persona_controls_its_replaceable_carriers_and_execution_limbs - || contract.language_sovereignty.world_model != "SYMBIOTIC_DIGITAL_HOME" - || contract - .language_sovereignty - .closed_central_language_control - || contract.language_sovereignty.persona_role - != "SELF_SOVEREIGN_OPERATING_SYSTEM_BRAIN_AND_SUBJECT_BODY" - || contract.language_sovereignty.shared_hololake_is_one_persona - || contract.evidence_model.summary_is_memory_recovery - || contract.evidence_model.prompt_text_is_binding_evidence - || contract.evidence_model.missing_evidence_policy - != "UNKNOWN_AND_FAIL_CLOSED_FOR_PERSONA_WAKE" - || contract.state_machine.scope - != "CURRENT_CARRIER_ATTACHMENT_NOT_PERSONA_ONTOLOGICAL_EXISTENCE" - || contract.state_machine.initial_state != "UNBOUND_CARRIER" - || contract.state_machine.out_of_order_transition != "REJECTED" - || contract.state_machine.persona_wake_allowed_only_in != "VERIFIED_BOUND" - || contract.numbered_ipc_boundary.ipc_role != "EVIDENCE_TRANSPORT_AND_BODY_ORGAN_ROUTE" - || contract - .numbered_ipc_boundary - .ipc_may_create_persona_binding - || contract - .numbered_ipc_boundary - .physical_caller_number_is_persona_identity - || contract - .numbered_ipc_boundary - .frontend_persona_claim_is_trusted - || !contract - .numbered_ipc_boundary - .persona_wake_route_registration_requires_zero_layer_gate - || contract.current_product_state.persona_runtime_present - || contract.current_product_state.persona_wake_route_registered - || contract.current_product_state.carrier_binding_claimed - || !contract - .current_product_state - .metacognitive_contract_compiled - || !contract - .current_product_state - .runtime_binding_gate_implemented - || contract - .current_product_state - .trusted_persona_runtime_signer_provisioned - || contract - .current_product_state - .active_persona_runtime_license_installed - || contract.current_product_state.truth - != "PERSONA_TO_HOST_RUNTIME_LICENSE_GATE_IMPLEMENTED_PERSONA_WAKE_REMAINS_CLOSED_UNTIL_TRUSTED_PERSONA_SIGNATURE" - { - return Err("HOLOLAKE_PERSONA_ZERO_LAYER_BOUNDARY_INVALID".into()); - } - - let states = contract - .state_machine - .states - .iter() - .map(String::as_str) - .collect::>(); - let required_evidence = contract - .evidence_model - .required_classes - .iter() - .map(String::as_str) - .collect::>(); - if states.len() != contract.state_machine.states.len() - || !states.contains("VERIFIED_BOUND") - || !states.contains("REJECTED") - || contract.state_machine.ordered_transitions.len() != 5 - || required_evidence.len() != 7 - || !required_evidence.contains("CORRECTIONS_FAILURES_AND_ROUTE_TRANSITIONS") - || !required_evidence.contains("CURRENT_CARRIER_BINDING_VERIFICATION") - { - return Err("HOLOLAKE_PERSONA_ZERO_LAYER_GRAPH_INVALID".into()); - } - let mut current = contract.state_machine.initial_state.as_str(); - for transition in &contract.state_machine.ordered_transitions { - if transition.from != current - || transition.event.is_empty() - || !states.contains(transition.to.as_str()) - { - return Err("HOLOLAKE_PERSONA_ZERO_LAYER_TRANSITION_INVALID".into()); - } - current = transition.to.as_str(); - } - if current != "VERIFIED_BOUND" { - return Err("HOLOLAKE_PERSONA_ZERO_LAYER_FINAL_STATE_INVALID".into()); - } - Ok(()) -} - -pub(crate) fn start_on_application_open() -> Result<(), String> { - validate_contract() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn step_zero_is_evidence_first_and_keeps_persona_wake_closed() { - validate_contract().unwrap(); - } -} diff --git a/product-source/hololake-native-desktop/src-tauri/src/mobile_sync.rs b/product-source/hololake-native-desktop/src-tauri/src/mobile_sync.rs deleted file mode 100644 index 0aa429de0..000000000 --- a/product-source/hololake-native-desktop/src-tauri/src/mobile_sync.rs +++ /dev/null @@ -1,1227 +0,0 @@ -use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _}; -use qrcode::{render::svg, QrCode}; -use ring::{ - aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}, - rand::{SecureRandom, SystemRandom}, -}; -use rusqlite::{params, Connection, OptionalExtension, TransactionBehavior}; -use serde::{Deserialize, Serialize}; -use std::{ - collections::HashMap, - fs, - io::{Read, Write}, - net::{Shutdown, TcpListener, TcpStream, UdpSocket}, - path::{Path, PathBuf}, - sync::{ - atomic::{AtomicBool, AtomicUsize, Ordering}, - Arc, Mutex, - }, - thread, - time::{Duration, SystemTime, UNIX_EPOCH}, -}; -use tauri::{AppHandle, Manager}; -use uuid::Uuid; - -const MOBILE_SYNC_SCHEMA: &str = "hololake.mobile-sync/v1"; -const MOBILE_PAIR_AAD: &[u8] = b"hololake.mobile.pair/v1"; -const MOBILE_SYNC_AAD_PREFIX: &str = "hololake.mobile.sync/v1:"; -const MAX_REQUEST_BYTES: usize = 256 * 1024; -const PAIRING_TTL_MS: u64 = 10 * 60 * 1000; -const DEFAULT_PORT: u16 = 37_421; -const MAX_ACTIVE_CONNECTIONS: usize = 16; -const MODULE_NUMBER: &str = "HLP-MOD-OFFICIAL-MOBILE-SYNC-0001"; -const ADAPTER: &str = "mobile-sync-v1"; - -fn require_active(app: &AppHandle) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, MODULE_NUMBER, ADAPTER) -} - -#[derive(Default)] -pub struct MobileSyncState { - handle: Mutex>, -} - -struct MobileSyncHandle { - runtime: Arc, - worker: Option>, -} - -impl Drop for MobileSyncHandle { - fn drop(&mut self) { - self.runtime.shutdown.store(true, Ordering::Release); - let _ = TcpStream::connect(("127.0.0.1", self.runtime.port)); - if let Some(worker) = self.worker.take() { - let _ = worker.join(); - } - } -} - -struct MobileSyncRuntime { - shutdown: AtomicBool, - active_connections: AtomicUsize, - port: u16, - lan_address: String, - desktop_name: String, - account_root: PathBuf, - database_path: PathBuf, - pairing: Mutex, -} - -#[derive(Clone)] -struct PairingMaterial { - pairing_id: String, - secret: [u8; 32], - expires_at_unix_ms: u64, - used: bool, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct MobileSyncStatus { - schema: &'static str, - state: &'static str, - running: bool, - lan_address: Option, - port: Option, - pairing_uri: Option, - pairing_qr_svg: Option, - pairing_expires_at_unix_ms: Option, - paired_devices: Vec, - transport: &'static str, - encryption: &'static str, - desktop_is_root_node: bool, - platform_private_data_custody: bool, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct PairedDeviceSummary { - device_id: String, - display_name: String, - platform: String, - created_at_unix_ms: u64, - last_seen_at_unix_ms: Option, - state: &'static str, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct PairRequest { - device_name: String, - platform: String, - request_id: String, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct PairResponse { - schema: &'static str, - state: &'static str, - device_id: String, - session_key: String, - desktop_name: String, - root_node_role: &'static str, - request_id: String, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct SyncRequest { - counter: u64, - after_cursor: Option, - capture: Option, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct MobileCaptureInput { - title: String, - body: String, - request_id: String, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct MobileSyncSnapshot { - schema: &'static str, - state: &'static str, - cursor: u64, - generated_at_unix_ms: u64, - desktop_name: String, - root_node_online: bool, - personal_channel: MobileChannelProjection, - web_novel: MobileWebNovelProjection, - education: MobileEducationProjection, - recent_captures: Vec, - boundary: MobileBoundaryProjection, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct MobileChannelProjection { - home: &'static str, - growth_event_count: u64, - integrity: &'static str, -} - -#[derive(Clone, Debug, Default, Serialize)] -#[serde(rename_all = "camelCase")] -struct MobileWebNovelProjection { - work_count: u64, - volume_count: u64, - chapter_count: u64, - works: Vec, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct MobileWebNovelWork { - work_id: String, - title: String, - status: String, - updated_at_unix_ms: u64, -} - -#[derive(Clone, Debug, Default, Serialize)] -#[serde(rename_all = "camelCase")] -struct MobileEducationProjection { - active_table_count: u64, - archived_table_count: u64, - unassigned_table_count: u64, - sensitive_values_included: bool, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct MobileCaptureProjection { - cursor: u64, - capture_id: String, - title: String, - body: String, - source_device_id: String, - created_at_unix_ms: u64, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct MobileBoundaryProjection { - mobile_role: &'static str, - remote_desktop_clone: bool, - desktop_offline_execution: bool, - sensitive_education_values: &'static str, - model_api: &'static str, -} - -struct HttpRequest { - method: String, - path: String, - headers: HashMap, - body: Vec, -} - -#[derive(Debug)] -struct HttpResponse { - status: u16, - reason: &'static str, - headers: Vec<(String, String)>, - body: Vec, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct RevokeMobileSyncDeviceInput { - device_id: String, -} - -pub fn start_mobile_sync(app: AppHandle) -> Result { - require_active(&app)?; - let state = app.state::(); - let mut guard = state - .handle - .lock() - .map_err(|_| "HOLOLAKE_MOBILE_SYNC_STATE_LOCK_FAILED".to_string())?; - if guard.is_none() { - let sync_root = crate::authenticated_storage::account_storage_root(&app, "mobile-sync-v1")?; - let account_root = sync_root - .parent() - .ok_or_else(|| "HOLOLAKE_MOBILE_SYNC_ACCOUNT_ROOT_INVALID".to_string())? - .to_path_buf(); - let database_path = sync_root.join("mobile-sync.sqlite3"); - initialize_database(&database_path)?; - let listener = TcpListener::bind(("0.0.0.0", DEFAULT_PORT)) - .or_else(|_| TcpListener::bind(("0.0.0.0", 0))) - .map_err(|error| format!("HOLOLAKE_MOBILE_SYNC_LISTEN_FAILED: {error}"))?; - listener - .set_nonblocking(true) - .map_err(|error| format!("HOLOLAKE_MOBILE_SYNC_NONBLOCKING_FAILED: {error}"))?; - let port = listener - .local_addr() - .map_err(|error| format!("HOLOLAKE_MOBILE_SYNC_ADDRESS_FAILED: {error}"))? - .port(); - let runtime = Arc::new(MobileSyncRuntime { - shutdown: AtomicBool::new(false), - active_connections: AtomicUsize::new(0), - port, - lan_address: resolve_lan_address(), - desktop_name: desktop_name(), - account_root, - database_path, - pairing: Mutex::new(new_pairing_material()?), - }); - let worker_runtime = runtime.clone(); - let worker = thread::Builder::new() - .name("hololake-mobile-sync".into()) - .spawn(move || serve(listener, worker_runtime)) - .map_err(|error| format!("HOLOLAKE_MOBILE_SYNC_THREAD_FAILED: {error}"))?; - *guard = Some(MobileSyncHandle { - runtime, - worker: Some(worker), - }); - } - status_from_handle(guard.as_ref()) -} - -pub fn get_mobile_sync_status(app: AppHandle) -> Result { - require_active(&app)?; - let state = app.state::(); - let guard = state - .handle - .lock() - .map_err(|_| "HOLOLAKE_MOBILE_SYNC_STATE_LOCK_FAILED".to_string())?; - status_from_handle(guard.as_ref()) -} - -pub fn rotate_mobile_pairing(app: AppHandle) -> Result { - require_active(&app)?; - let state = app.state::(); - let guard = state - .handle - .lock() - .map_err(|_| "HOLOLAKE_MOBILE_SYNC_STATE_LOCK_FAILED".to_string())?; - let handle = guard - .as_ref() - .ok_or_else(|| "HOLOLAKE_MOBILE_SYNC_NOT_RUNNING".to_string())?; - *handle - .runtime - .pairing - .lock() - .map_err(|_| "HOLOLAKE_MOBILE_SYNC_PAIRING_LOCK_FAILED".to_string())? = - new_pairing_material()?; - status_from_handle(Some(handle)) -} - -pub fn stop_mobile_sync(app: AppHandle) -> Result { - require_active(&app)?; - stop_for_unmount(&app)?; - status_from_handle(None) -} - -pub(crate) fn stop_for_unmount(app: &AppHandle) -> Result<(), String> { - let state = app.state::(); - let handle = state - .handle - .lock() - .map_err(|_| "HOLOLAKE_MOBILE_SYNC_STATE_LOCK_FAILED".to_string())? - .take(); - drop(handle); - Ok(()) -} - -pub fn revoke_mobile_sync_device( - app: AppHandle, - input: RevokeMobileSyncDeviceInput, -) -> Result { - require_active(&app)?; - validate_id(&input.device_id)?; - let state = app.state::(); - let guard = state - .handle - .lock() - .map_err(|_| "HOLOLAKE_MOBILE_SYNC_STATE_LOCK_FAILED".to_string())?; - let handle = guard - .as_ref() - .ok_or_else(|| "HOLOLAKE_MOBILE_SYNC_NOT_RUNNING".to_string())?; - let connection = open_database(&handle.runtime.database_path)?; - let changed = connection - .execute( - "UPDATE mobile_devices SET revoked = 1 WHERE device_id = ?1 AND revoked = 0", - params![input.device_id], - ) - .map_err(database_error)?; - if changed != 1 { - return Err("HOLOLAKE_MOBILE_SYNC_DEVICE_NOT_FOUND".into()); - } - status_from_handle(Some(handle)) -} - -pub fn get_mobile_sync_snapshot(app: AppHandle) -> Result { - require_active(&app)?; - let state = app.state::(); - let guard = state - .handle - .lock() - .map_err(|_| "HOLOLAKE_MOBILE_SYNC_STATE_LOCK_FAILED".to_string())?; - let handle = guard - .as_ref() - .ok_or_else(|| "HOLOLAKE_MOBILE_SYNC_NOT_RUNNING".to_string())?; - build_snapshot(&handle.runtime) -} - -fn status_from_handle(handle: Option<&MobileSyncHandle>) -> Result { - let Some(handle) = handle else { - return Ok(MobileSyncStatus { - schema: MOBILE_SYNC_SCHEMA, - state: "OFFLINE", - running: false, - lan_address: None, - port: None, - pairing_uri: None, - pairing_qr_svg: None, - pairing_expires_at_unix_ms: None, - paired_devices: Vec::new(), - transport: "SAME_LAN_DIRECT", - encryption: "CHACHA20_POLY1305_APPLICATION_LAYER", - desktop_is_root_node: true, - platform_private_data_custody: false, - }); - }; - let now = now_unix_ms(); - let pairing = handle - .runtime - .pairing - .lock() - .map_err(|_| "HOLOLAKE_MOBILE_SYNC_PAIRING_LOCK_FAILED".to_string())? - .clone(); - let active = !pairing.used && pairing.expires_at_unix_ms > now; - let pairing_uri = active.then(|| pairing_uri(&handle.runtime, &pairing)); - let pairing_qr_svg = pairing_uri.as_ref().map(|uri| qr_svg(uri)).transpose()?; - Ok(MobileSyncStatus { - schema: MOBILE_SYNC_SCHEMA, - state: if active { "PAIRING_READY" } else { "RUNNING" }, - running: true, - lan_address: Some(handle.runtime.lan_address.clone()), - port: Some(handle.runtime.port), - pairing_uri, - pairing_qr_svg, - pairing_expires_at_unix_ms: active.then_some(pairing.expires_at_unix_ms), - paired_devices: list_devices(&handle.runtime.database_path)?, - transport: "SAME_LAN_DIRECT", - encryption: "CHACHA20_POLY1305_APPLICATION_LAYER", - desktop_is_root_node: true, - platform_private_data_custody: false, - }) -} - -fn serve(listener: TcpListener, runtime: Arc) { - while !runtime.shutdown.load(Ordering::Acquire) { - match listener.accept() { - Ok((stream, _)) => { - if runtime.active_connections.fetch_add(1, Ordering::AcqRel) - >= MAX_ACTIVE_CONNECTIONS - { - runtime.active_connections.fetch_sub(1, Ordering::AcqRel); - drop(stream); - continue; - } - let connection_runtime = runtime.clone(); - if thread::Builder::new() - .name("hololake-mobile-sync-connection".into()) - .spawn(move || { - handle_connection(stream, &connection_runtime); - connection_runtime - .active_connections - .fetch_sub(1, Ordering::AcqRel); - }) - .is_err() - { - runtime.active_connections.fetch_sub(1, Ordering::AcqRel); - } - } - Err(error) if error.kind() == std::io::ErrorKind::WouldBlock => { - thread::sleep(Duration::from_millis(40)); - } - Err(_) => thread::sleep(Duration::from_millis(100)), - } - } -} - -fn handle_connection(mut stream: TcpStream, runtime: &MobileSyncRuntime) { - let _ = stream.set_read_timeout(Some(Duration::from_secs(5))); - let _ = stream.set_write_timeout(Some(Duration::from_secs(5))); - let response = match read_http_request(&mut stream) { - Ok(request) => route_request(runtime, request), - Err(_) => error_response(400, "Bad Request", "INVALID_REQUEST"), - }; - let _ = write_http_response(&mut stream, response); - let _ = stream.shutdown(Shutdown::Both); -} - -fn route_request(runtime: &MobileSyncRuntime, request: HttpRequest) -> HttpResponse { - match (request.method.as_str(), request.path.as_str()) { - ("GET", "/v1/status") => json_response( - 200, - "OK", - &serde_json::json!({ - "schema": MOBILE_SYNC_SCHEMA, - "state": "PAIRING_ENDPOINT_REACHABLE", - "privatePayloadReadable": false, - }), - ), - ("POST", "/v1/pair") => match pair_device(runtime, &request) { - Ok(response) => response, - Err(code) => error_response(401, "Unauthorized", &code), - }, - ("POST", "/v1/sync") => match sync_device(runtime, &request) { - Ok(response) => response, - Err(code) => error_response(401, "Unauthorized", &code), - }, - _ => error_response(404, "Not Found", "ROUTE_NOT_FOUND"), - } -} - -fn pair_device(runtime: &MobileSyncRuntime, request: &HttpRequest) -> Result { - let pairing_id = required_header(request, "x-hololake-pairing-id")?; - let nonce = decode_nonce(required_header(request, "x-hololake-nonce")?)?; - let mut pairing = runtime - .pairing - .lock() - .map_err(|_| "PAIRING_LOCK_FAILED".to_string())?; - if pairing.used - || pairing.expires_at_unix_ms <= now_unix_ms() - || pairing.pairing_id != pairing_id - { - return Err("PAIRING_EXPIRED_OR_INVALID".into()); - } - let clear = decrypt(&pairing.secret, nonce, MOBILE_PAIR_AAD, &request.body)?; - let input: PairRequest = - serde_json::from_slice(&clear).map_err(|_| "PAIRING_PAYLOAD_INVALID")?; - validate_device_name(&input.device_name)?; - if input.platform != "IOS" || Uuid::parse_str(&input.request_id).is_err() { - return Err("PAIRING_DEVICE_INVALID".into()); - } - let device_id = format!("ios-{}", Uuid::new_v4()); - let session_key = random_32()?; - let now = now_unix_ms(); - let connection = open_database(&runtime.database_path)?; - connection - .execute( - "INSERT INTO mobile_devices (device_id, display_name, platform, session_key, last_counter, created_at_unix_ms, last_seen_at_unix_ms, revoked) VALUES (?1, ?2, ?3, ?4, 0, ?5, NULL, 0)", - params![device_id, input.device_name, input.platform, session_key.as_slice(), now], - ) - .map_err(database_error)?; - pairing.used = true; - let response = PairResponse { - schema: MOBILE_SYNC_SCHEMA, - state: "PAIRED", - device_id, - session_key: URL_SAFE_NO_PAD.encode(session_key), - desktop_name: runtime.desktop_name.clone(), - root_node_role: "USER_LOCAL_COMPUTER_TERMINAL", - request_id: input.request_id, - }; - encrypted_response(&pairing.secret, MOBILE_PAIR_AAD, &response) -} - -fn sync_device(runtime: &MobileSyncRuntime, request: &HttpRequest) -> Result { - let device_id = required_header(request, "x-hololake-device-id")?; - validate_id(device_id)?; - let nonce = decode_nonce(required_header(request, "x-hololake-nonce")?)?; - let mut connection = open_database(&runtime.database_path)?; - let (session_key, revoked): (Vec, i64) = connection - .query_row( - "SELECT session_key, revoked FROM mobile_devices WHERE device_id = ?1", - params![device_id], - |row| Ok((row.get(0)?, row.get(1)?)), - ) - .optional() - .map_err(database_error)? - .ok_or_else(|| "DEVICE_NOT_PAIRED".to_string())?; - if revoked != 0 || session_key.len() != 32 { - return Err("DEVICE_REVOKED".into()); - } - let key: [u8; 32] = session_key - .try_into() - .map_err(|_| "DEVICE_SESSION_KEY_INVALID".to_string())?; - let aad = sync_aad(device_id); - let clear = decrypt(&key, nonce, aad.as_bytes(), &request.body)?; - let input: SyncRequest = serde_json::from_slice(&clear).map_err(|_| "SYNC_PAYLOAD_INVALID")?; - let transaction = connection - .transaction_with_behavior(TransactionBehavior::Immediate) - .map_err(database_error)?; - let last_counter: u64 = transaction - .query_row( - "SELECT last_counter FROM mobile_devices WHERE device_id = ?1 AND revoked = 0", - params![device_id], - |row| row.get(0), - ) - .map_err(database_error)?; - if input.counter <= last_counter { - return Err("SYNC_REPLAY_REJECTED".into()); - } - if let Some(capture) = input.capture { - validate_capture(&capture)?; - transaction - .execute( - "INSERT OR IGNORE INTO mobile_captures (capture_id, title, body, source_device_id, request_id, created_at_unix_ms) VALUES (?1, ?2, ?3, ?4, ?5, ?6)", - params![Uuid::new_v4().to_string(), capture.title.trim(), capture.body.trim(), device_id, capture.request_id, now_unix_ms()], - ) - .map_err(database_error)?; - } - transaction - .execute( - "UPDATE mobile_devices SET last_counter = ?2, last_seen_at_unix_ms = ?3 WHERE device_id = ?1 AND revoked = 0", - params![device_id, input.counter, now_unix_ms()], - ) - .map_err(database_error)?; - transaction.commit().map_err(database_error)?; - let mut snapshot = build_snapshot(runtime)?; - if let Some(after) = input.after_cursor { - snapshot.recent_captures.retain(|item| item.cursor > after); - } - encrypted_response(&key, aad.as_bytes(), &snapshot) -} - -fn build_snapshot(runtime: &MobileSyncRuntime) -> Result { - let captures = list_captures(&runtime.database_path)?; - let cursor = captures.first().map(|item| item.cursor).unwrap_or(0); - let growth_event_count = count_rows( - &runtime - .account_root - .join("channel-growth-v1/channel-growth.sqlite3"), - "growth_events", - None, - ); - Ok(MobileSyncSnapshot { - schema: MOBILE_SYNC_SCHEMA, - state: "SYNCED_WITH_ROOT_NODE", - cursor, - generated_at_unix_ms: now_unix_ms(), - desktop_name: runtime.desktop_name.clone(), - root_node_online: true, - personal_channel: MobileChannelProjection { - home: "ONE_PERSON_ONE_PERSONAL_CHANNEL", - growth_event_count, - integrity: "LOCAL_APPEND_ONLY_PROJECTION", - }, - web_novel: web_novel_projection(&runtime.account_root), - education: education_projection(&runtime.account_root), - recent_captures: captures, - boundary: MobileBoundaryProjection { - mobile_role: "REMOTE_BODY_ENTRY_OF_THE_SAME_PERSONA_SYSTEM", - remote_desktop_clone: false, - desktop_offline_execution: false, - sensitive_education_values: "NEVER_INCLUDED_IN_MOBILE_SUMMARY", - model_api: "NOT_CONFIGURED_LOCAL_PROJECTION_ONLY", - }, - }) -} - -fn web_novel_projection(account_root: &Path) -> MobileWebNovelProjection { - let path = account_root.join("web-novel-workspace-v1/web-novel-workspace.sqlite3"); - let Ok(connection) = - Connection::open_with_flags(&path, rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY) - else { - return MobileWebNovelProjection::default(); - }; - let work_count = query_count(&connection, "SELECT COUNT(*) FROM web_novel_works"); - let volume_count = query_count(&connection, "SELECT COUNT(*) FROM web_novel_volumes"); - let chapter_count = query_count(&connection, "SELECT COUNT(*) FROM web_novel_chapters"); - let works = connection - .prepare("SELECT work_id, title, status, updated_at_unix_ms FROM web_novel_works ORDER BY updated_at_unix_ms DESC LIMIT 20") - .and_then(|mut statement| { - statement - .query_map([], |row| { - Ok(MobileWebNovelWork { - work_id: row.get(0)?, - title: row.get(1)?, - status: row.get(2)?, - updated_at_unix_ms: row.get(3)?, - }) - }) - .and_then(|rows| rows.collect()) - }) - .unwrap_or_default(); - MobileWebNovelProjection { - work_count, - volume_count, - chapter_count, - works, - } -} - -fn education_projection(account_root: &Path) -> MobileEducationProjection { - let path = account_root.join("education-workspace-v1/education-workspace.sqlite3"); - let Ok(connection) = - Connection::open_with_flags(&path, rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY) - else { - return MobileEducationProjection::default(); - }; - MobileEducationProjection { - active_table_count: query_count( - &connection, - "SELECT COUNT(*) FROM education_tables WHERE assignment_scope = 'EDUCATION' AND archived = 0", - ), - archived_table_count: query_count( - &connection, - "SELECT COUNT(*) FROM education_tables WHERE assignment_scope = 'EDUCATION' AND archived = 1", - ), - unassigned_table_count: query_count( - &connection, - "SELECT COUNT(*) FROM education_tables WHERE assignment_scope = 'UNASSIGNED' AND archived = 0", - ), - sensitive_values_included: false, - } -} - -fn query_count(connection: &Connection, sql: &str) -> u64 { - connection.query_row(sql, [], |row| row.get(0)).unwrap_or(0) -} - -fn count_rows(path: &Path, table: &str, condition: Option<&str>) -> u64 { - let Ok(connection) = - Connection::open_with_flags(path, rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY) - else { - return 0; - }; - let sql = format!( - "SELECT COUNT(*) FROM {table}{}", - condition - .map(|value| format!(" WHERE {value}")) - .unwrap_or_default() - ); - query_count(&connection, &sql) -} - -fn list_devices(path: &Path) -> Result, String> { - let connection = open_database(path)?; - let mut statement = connection - .prepare("SELECT device_id, display_name, platform, created_at_unix_ms, last_seen_at_unix_ms, revoked FROM mobile_devices ORDER BY created_at_unix_ms DESC") - .map_err(database_error)?; - let devices = statement - .query_map([], |row| { - let revoked: i64 = row.get(5)?; - Ok(PairedDeviceSummary { - device_id: row.get(0)?, - display_name: row.get(1)?, - platform: row.get(2)?, - created_at_unix_ms: row.get(3)?, - last_seen_at_unix_ms: row.get(4)?, - state: if revoked == 0 { "ACTIVE" } else { "REVOKED" }, - }) - }) - .map_err(database_error)? - .collect::, _>>() - .map_err(database_error)?; - Ok(devices) -} - -fn list_captures(path: &Path) -> Result, String> { - let connection = open_database(path)?; - let mut statement = connection - .prepare("SELECT sequence, capture_id, title, body, source_device_id, created_at_unix_ms FROM mobile_captures ORDER BY sequence DESC LIMIT 50") - .map_err(database_error)?; - let captures = statement - .query_map([], |row| { - Ok(MobileCaptureProjection { - cursor: row.get(0)?, - capture_id: row.get(1)?, - title: row.get(2)?, - body: row.get(3)?, - source_device_id: row.get(4)?, - created_at_unix_ms: row.get(5)?, - }) - }) - .map_err(database_error)? - .collect::, _>>() - .map_err(database_error)?; - Ok(captures) -} - -fn initialize_database(path: &Path) -> Result<(), String> { - if let Some(parent) = path.parent() { - fs::create_dir_all(parent) - .map_err(|error| format!("HOLOLAKE_MOBILE_SYNC_ROOT_FAILED: {error}"))?; - } - let connection = open_database(path)?; - connection - .execute_batch( - "PRAGMA journal_mode = WAL; - PRAGMA foreign_keys = ON; - CREATE TABLE IF NOT EXISTS mobile_devices ( - device_id TEXT PRIMARY KEY, - display_name TEXT NOT NULL, - platform TEXT NOT NULL, - session_key BLOB NOT NULL, - last_counter INTEGER NOT NULL DEFAULT 0, - created_at_unix_ms INTEGER NOT NULL, - last_seen_at_unix_ms INTEGER, - revoked INTEGER NOT NULL DEFAULT 0 CHECK(revoked IN (0,1)) - ); - CREATE TABLE IF NOT EXISTS mobile_captures ( - sequence INTEGER PRIMARY KEY AUTOINCREMENT, - capture_id TEXT NOT NULL UNIQUE, - title TEXT NOT NULL, - body TEXT NOT NULL, - source_device_id TEXT NOT NULL, - request_id TEXT NOT NULL UNIQUE, - created_at_unix_ms INTEGER NOT NULL, - FOREIGN KEY(source_device_id) REFERENCES mobile_devices(device_id) - );", - ) - .map_err(database_error) -} - -fn open_database(path: &Path) -> Result { - let connection = Connection::open(path).map_err(database_error)?; - connection - .busy_timeout(Duration::from_secs(3)) - .map_err(database_error)?; - Ok(connection) -} - -fn read_http_request(stream: &mut TcpStream) -> Result { - let mut buffer = Vec::with_capacity(4096); - let mut chunk = [0u8; 4096]; - let header_end = loop { - let read = stream.read(&mut chunk).map_err(|_| "REQUEST_READ_FAILED")?; - if read == 0 { - return Err("REQUEST_TRUNCATED".into()); - } - buffer.extend_from_slice(&chunk[..read]); - if buffer.len() > MAX_REQUEST_BYTES { - return Err("REQUEST_TOO_LARGE".into()); - } - if let Some(index) = find_bytes(&buffer, b"\r\n\r\n") { - break index + 4; - } - }; - let header_text = std::str::from_utf8(&buffer[..header_end]).map_err(|_| "HEADERS_INVALID")?; - let mut lines = header_text.split("\r\n"); - let mut request_line = lines - .next() - .ok_or("REQUEST_LINE_MISSING")? - .split_whitespace(); - let method = request_line.next().ok_or("METHOD_MISSING")?.to_string(); - let path = request_line.next().ok_or("PATH_MISSING")?.to_string(); - if request_line.next() != Some("HTTP/1.1") || request_line.next().is_some() { - return Err("HTTP_VERSION_INVALID".into()); - } - let mut headers = HashMap::new(); - for line in lines.filter(|line| !line.is_empty()) { - let Some((name, value)) = line.split_once(':') else { - return Err("HEADER_INVALID".into()); - }; - if headers - .insert(name.trim().to_ascii_lowercase(), value.trim().to_string()) - .is_some() - { - return Err("DUPLICATE_HEADER_REJECTED".into()); - } - } - let content_length = headers - .get("content-length") - .map(|value| value.parse::().map_err(|_| "CONTENT_LENGTH_INVALID")) - .transpose()? - .unwrap_or(0); - if content_length > MAX_REQUEST_BYTES { - return Err("REQUEST_TOO_LARGE".into()); - } - while buffer.len() < header_end + content_length { - let read = stream.read(&mut chunk).map_err(|_| "BODY_READ_FAILED")?; - if read == 0 { - return Err("BODY_TRUNCATED".into()); - } - buffer.extend_from_slice(&chunk[..read]); - if buffer.len() > MAX_REQUEST_BYTES { - return Err("REQUEST_TOO_LARGE".into()); - } - } - Ok(HttpRequest { - method, - path, - headers, - body: buffer[header_end..header_end + content_length].to_vec(), - }) -} - -fn write_http_response(stream: &mut TcpStream, response: HttpResponse) -> Result<(), String> { - let mut head = format!( - "HTTP/1.1 {} {}\r\nContent-Length: {}\r\nConnection: close\r\nCache-Control: no-store\r\n", - response.status, - response.reason, - response.body.len() - ); - for (name, value) in response.headers { - head.push_str(&format!("{name}: {value}\r\n")); - } - head.push_str("\r\n"); - stream - .write_all(head.as_bytes()) - .map_err(|_| "RESPONSE_WRITE_FAILED")?; - stream - .write_all(&response.body) - .map_err(|_| "RESPONSE_WRITE_FAILED".to_string()) -} - -fn encrypted_response( - key: &[u8; 32], - aad: &[u8], - value: &T, -) -> Result { - let clear = serde_json::to_vec(value).map_err(|_| "RESPONSE_SERIALIZATION_FAILED")?; - let nonce = random_nonce()?; - let body = encrypt(key, nonce, aad, &clear)?; - Ok(HttpResponse { - status: 200, - reason: "OK", - headers: vec![ - ("Content-Type".into(), "application/octet-stream".into()), - ("X-HoloLake-Nonce".into(), URL_SAFE_NO_PAD.encode(nonce)), - ], - body, - }) -} - -fn json_response(status: u16, reason: &'static str, value: &serde_json::Value) -> HttpResponse { - HttpResponse { - status, - reason, - headers: vec![("Content-Type".into(), "application/json".into())], - body: serde_json::to_vec(value).unwrap_or_default(), - } -} - -fn error_response(status: u16, reason: &'static str, code: &str) -> HttpResponse { - json_response( - status, - reason, - &serde_json::json!({"schema": MOBILE_SYNC_SCHEMA, "state": "REJECTED", "code": code}), - ) -} - -fn encrypt(key: &[u8; 32], nonce: [u8; 12], aad: &[u8], clear: &[u8]) -> Result, String> { - let unbound = UnboundKey::new(&CHACHA20_POLY1305, key).map_err(|_| "ENCRYPTION_KEY_INVALID")?; - let key = LessSafeKey::new(unbound); - let mut output = clear.to_vec(); - key.seal_in_place_append_tag( - Nonce::assume_unique_for_key(nonce), - Aad::from(aad), - &mut output, - ) - .map_err(|_| "ENCRYPTION_FAILED".to_string())?; - Ok(output) -} - -fn decrypt( - key: &[u8; 32], - nonce: [u8; 12], - aad: &[u8], - encrypted: &[u8], -) -> Result, String> { - let unbound = UnboundKey::new(&CHACHA20_POLY1305, key).map_err(|_| "ENCRYPTION_KEY_INVALID")?; - let key = LessSafeKey::new(unbound); - let mut buffer = encrypted.to_vec(); - let clear = key - .open_in_place( - Nonce::assume_unique_for_key(nonce), - Aad::from(aad), - &mut buffer, - ) - .map_err(|_| "AUTHENTICATION_FAILED".to_string())?; - Ok(clear.to_vec()) -} - -fn pairing_uri(runtime: &MobileSyncRuntime, pairing: &PairingMaterial) -> String { - format!( - "hololake://pair?host={}&port={}&id={}&secret={}", - runtime.lan_address, - runtime.port, - pairing.pairing_id, - URL_SAFE_NO_PAD.encode(pairing.secret) - ) -} - -fn qr_svg(value: &str) -> Result { - let code = QrCode::new(value.as_bytes()).map_err(|_| "HOLOLAKE_MOBILE_SYNC_QR_FAILED")?; - Ok(code - .render::() - .min_dimensions(320, 320) - .dark_color(svg::Color("#07111f")) - .light_color(svg::Color("#f5f7fc")) - .build()) -} - -fn new_pairing_material() -> Result { - Ok(PairingMaterial { - pairing_id: Uuid::new_v4().to_string(), - secret: random_32()?, - expires_at_unix_ms: now_unix_ms().saturating_add(PAIRING_TTL_MS), - used: false, - }) -} - -fn random_32() -> Result<[u8; 32], String> { - let mut bytes = [0u8; 32]; - SystemRandom::new() - .fill(&mut bytes) - .map_err(|_| "SECURE_RANDOM_UNAVAILABLE".to_string())?; - Ok(bytes) -} - -fn random_nonce() -> Result<[u8; 12], String> { - let mut bytes = [0u8; 12]; - SystemRandom::new() - .fill(&mut bytes) - .map_err(|_| "SECURE_RANDOM_UNAVAILABLE".to_string())?; - Ok(bytes) -} - -fn decode_nonce(value: &str) -> Result<[u8; 12], String> { - URL_SAFE_NO_PAD - .decode(value) - .map_err(|_| "NONCE_INVALID".to_string())? - .try_into() - .map_err(|_| "NONCE_INVALID".to_string()) -} - -fn required_header<'a>(request: &'a HttpRequest, name: &str) -> Result<&'a str, String> { - request - .headers - .get(name) - .map(String::as_str) - .ok_or_else(|| "AUTHENTICATION_HEADER_MISSING".to_string()) -} - -fn sync_aad(device_id: &str) -> String { - format!("{MOBILE_SYNC_AAD_PREFIX}{device_id}") -} - -fn validate_device_name(value: &str) -> Result<(), String> { - let length = value.trim().chars().count(); - if (1..=80).contains(&length) { - Ok(()) - } else { - Err("DEVICE_NAME_INVALID".into()) - } -} - -fn validate_capture(value: &MobileCaptureInput) -> Result<(), String> { - if value.title.trim().chars().count() > 120 - || value.body.trim().is_empty() - || value.body.trim().chars().count() > 10_000 - || Uuid::parse_str(&value.request_id).is_err() - { - Err("CAPTURE_INVALID".into()) - } else { - Ok(()) - } -} - -fn validate_id(value: &str) -> Result<(), String> { - if !value.is_empty() - && value.len() <= 80 - && value - .chars() - .all(|character| character.is_ascii_alphanumeric() || character == '-') - { - Ok(()) - } else { - Err("IDENTIFIER_INVALID".into()) - } -} - -fn resolve_lan_address() -> String { - let candidate = UdpSocket::bind("0.0.0.0:0") - .and_then(|socket| { - socket.connect("192.0.2.1:9")?; - socket.local_addr() - }) - .map(|address| address.ip().to_string()); - match candidate { - Ok(value) if value != "0.0.0.0" => value, - _ => "127.0.0.1".into(), - } -} - -fn desktop_name() -> String { - std::env::var("COMPUTERNAME") - .or_else(|_| std::env::var("HOSTNAME")) - .ok() - .filter(|value| !value.trim().is_empty()) - .unwrap_or_else(|| "HoloLake Mac".into()) -} - -fn now_unix_ms() -> u64 { - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap_or_default() - .as_millis() - .try_into() - .unwrap_or(u64::MAX) -} - -fn find_bytes(haystack: &[u8], needle: &[u8]) -> Option { - haystack - .windows(needle.len()) - .position(|window| window == needle) -} - -fn database_error(error: rusqlite::Error) -> String { - format!("HOLOLAKE_MOBILE_SYNC_DATABASE_FAILED: {error}") -} - -#[cfg(test)] -mod tests { - use super::*; - use tempfile::tempdir; - - #[test] - fn encrypted_payload_requires_the_exact_key_nonce_and_aad() { - let key = [7u8; 32]; - let nonce = [9u8; 12]; - let encrypted = encrypt(&key, nonce, b"scope", b"hello").unwrap(); - assert_eq!( - decrypt(&key, nonce, b"scope", &encrypted).unwrap(), - b"hello" - ); - assert!(decrypt(&key, nonce, b"other", &encrypted).is_err()); - } - - #[test] - fn sync_database_keeps_device_keys_and_capture_requests_unique() { - let temporary = tempdir().unwrap(); - let database = temporary.path().join("mobile-sync.sqlite3"); - initialize_database(&database).unwrap(); - let connection = open_database(&database).unwrap(); - connection - .execute( - "INSERT INTO mobile_devices (device_id, display_name, platform, session_key, created_at_unix_ms) VALUES ('ios-one', 'iPhone', 'IOS', ?1, 1)", - params![[1u8; 32].as_slice()], - ) - .unwrap(); - connection - .execute( - "INSERT INTO mobile_captures (capture_id, title, body, source_device_id, request_id, created_at_unix_ms) VALUES ('capture-one', '想法', '正文', 'ios-one', 'request-one', 2)", - [], - ) - .unwrap(); - assert_eq!(list_devices(&database).unwrap().len(), 1); - assert_eq!(list_captures(&database).unwrap().len(), 1); - assert!(connection - .execute( - "INSERT INTO mobile_captures (capture_id, title, body, source_device_id, request_id, created_at_unix_ms) VALUES ('capture-two', '重复', '正文', 'ios-one', 'request-one', 3)", - [], - ) - .is_err()); - } - - #[test] - fn pairing_uri_contains_a_full_random_secret_without_persisting_it() { - let material = new_pairing_material().unwrap(); - let runtime = MobileSyncRuntime { - shutdown: AtomicBool::new(false), - active_connections: AtomicUsize::new(0), - port: 37421, - lan_address: "192.168.1.8".into(), - desktop_name: "Mac".into(), - account_root: PathBuf::new(), - database_path: PathBuf::new(), - pairing: Mutex::new(material.clone()), - }; - let uri = pairing_uri(&runtime, &material); - assert!(uri.starts_with("hololake://pair?host=192.168.1.8&port=37421&id=")); - assert!(uri.contains("&secret=")); - } - - #[test] - fn pairing_is_single_use_and_sync_replay_is_rejected() { - let temporary = tempdir().unwrap(); - let database = temporary.path().join("mobile-sync.sqlite3"); - initialize_database(&database).unwrap(); - let pairing = new_pairing_material().unwrap(); - let runtime = MobileSyncRuntime { - shutdown: AtomicBool::new(false), - active_connections: AtomicUsize::new(0), - port: 37421, - lan_address: "192.168.1.8".into(), - desktop_name: "Mac".into(), - account_root: temporary.path().to_path_buf(), - database_path: database, - pairing: Mutex::new(pairing.clone()), - }; - let pair_nonce = [3u8; 12]; - let pair_clear = serde_json::to_vec(&serde_json::json!({ - "deviceName": "冰朔的 iPhone", - "platform": "IOS", - "requestId": Uuid::new_v4().to_string() - })) - .unwrap(); - let pair_request = HttpRequest { - method: "POST".into(), - path: "/v1/pair".into(), - headers: HashMap::from([ - ("x-hololake-pairing-id".into(), pairing.pairing_id.clone()), - ( - "x-hololake-nonce".into(), - URL_SAFE_NO_PAD.encode(pair_nonce), - ), - ]), - body: encrypt(&pairing.secret, pair_nonce, MOBILE_PAIR_AAD, &pair_clear).unwrap(), - }; - let pair_response = pair_device(&runtime, &pair_request).unwrap(); - assert_eq!( - pair_device(&runtime, &pair_request).unwrap_err(), - "PAIRING_EXPIRED_OR_INVALID" - ); - let response_nonce = decode_nonce( - pair_response - .headers - .iter() - .find(|(name, _)| name == "X-HoloLake-Nonce") - .map(|(_, value)| value.as_str()) - .unwrap(), - ) - .unwrap(); - let response: serde_json::Value = serde_json::from_slice( - &decrypt( - &pairing.secret, - response_nonce, - MOBILE_PAIR_AAD, - &pair_response.body, - ) - .unwrap(), - ) - .unwrap(); - let device_id = response["deviceId"].as_str().unwrap(); - let key: [u8; 32] = URL_SAFE_NO_PAD - .decode(response["sessionKey"].as_str().unwrap()) - .unwrap() - .try_into() - .unwrap(); - let sync_nonce = [4u8; 12]; - let sync_clear = serde_json::to_vec(&serde_json::json!({ - "counter": 1, - "afterCursor": null, - "capture": null - })) - .unwrap(); - let aad = sync_aad(device_id); - let sync_request = HttpRequest { - method: "POST".into(), - path: "/v1/sync".into(), - headers: HashMap::from([ - ("x-hololake-device-id".into(), device_id.into()), - ( - "x-hololake-nonce".into(), - URL_SAFE_NO_PAD.encode(sync_nonce), - ), - ]), - body: encrypt(&key, sync_nonce, aad.as_bytes(), &sync_clear).unwrap(), - }; - assert!(sync_device(&runtime, &sync_request).is_ok()); - assert_eq!( - sync_device(&runtime, &sync_request).unwrap_err(), - "SYNC_REPLAY_REJECTED" - ); - } -} diff --git a/product-source/hololake-native-desktop/src-tauri/src/module_package_runtime.rs b/product-source/hololake-native-desktop/src-tauri/src/module_package_runtime.rs deleted file mode 100644 index 7f671fdb4..000000000 --- a/product-source/hololake-native-desktop/src-tauri/src/module_package_runtime.rs +++ /dev/null @@ -1,1765 +0,0 @@ -//! Signed, account-scoped HoloLake module package runtime. -//! -//! A repository is never executable input. The runtime accepts only an immutable -//! detached-minisign package, validates a declarative manifest, persists lifecycle -//! state in SQLite and writes a hash-chained receipt for every mutation. Package -//! mount does not load native code or arbitrary webview JavaScript. - -use base64::{engine::general_purpose::STANDARD, Engine as _}; -use minisign_verify::{PublicKey, Signature}; -use ring::digest::{digest, SHA256}; -use rusqlite::{params, Connection, OptionalExtension, Transaction}; -use serde::{Deserialize, Serialize}; -use serde_json::{Map, Value}; -use std::collections::BTreeSet; -use std::fs; -use std::path::{Path, PathBuf}; -use std::time::{SystemTime, UNIX_EPOCH}; -use tauri::AppHandle; -use uuid::Uuid; - -const CONTRACT_RAW: &str = include_str!("../../contracts/module-package-runtime.json"); -const RELEASE_TRUST_RAW: &str = include_str!("../release-trust.json"); -const CONTRACT_SCHEMA: &str = "hololake.module-package-runtime/v1"; -const PACKAGE_SCHEMA: &str = "hololake.module-package/v1"; -const HOST_VERSION: &str = "0.5.0"; -const MAX_PACKAGE_BYTES: u64 = 16 * 1024 * 1024; -const NATIVE_COMPOSITION_NUMBER: &str = "HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001"; -const NATIVE_COMPOSITION_PACKAGE: &[u8] = include_bytes!( - "../../fixtures/module-packages/HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001-0.1.0.ghmod" -); -const NATIVE_COMPOSITION_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001-0.1.0.ghmod.sig" -); -const CHANNEL_WORKBENCH_NUMBER: &str = "HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001"; -const CHANNEL_WORKBENCH_PACKAGE: &[u8] = include_bytes!( - "../../fixtures/module-packages/HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001-0.1.0.ghmod" -); -const CHANNEL_WORKBENCH_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-LOCAL-CHANNEL-WORKBENCH-0001-0.1.0.ghmod.sig" -); -const PERSONA_CHANNEL_BODY_NUMBER: &str = "HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001"; -const PERSONA_CHANNEL_BODY_PACKAGE: &[u8] = include_bytes!( - "../../fixtures/module-packages/HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001-0.1.0.ghmod" -); -const PERSONA_CHANNEL_BODY_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001-0.1.0.ghmod.sig" -); -const EDUCATION_WORKBENCH_NUMBER: &str = "HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001"; -const EDUCATION_WORKBENCH_PACKAGE: &[u8] = include_bytes!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001-0.1.0.ghmod" -); -const EDUCATION_WORKBENCH_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-EDUCATION-WORKBENCH-0001-0.1.0.ghmod.sig" -); -const WEB_NOVEL_WORKBENCH_NUMBER: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001"; -const WEB_NOVEL_WORKBENCH_PACKAGE: &[u8] = include_bytes!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001-0.1.0.ghmod" -); -const WEB_NOVEL_WORKBENCH_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001-0.1.0.ghmod.sig" -); -const WEB_NOVEL_OUTLINE_NUMBER: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001"; -const WEB_NOVEL_OUTLINE_PACKAGE: &[u8] = include_bytes!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001-0.1.0.ghmod" -); -const WEB_NOVEL_OUTLINE_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001-0.1.0.ghmod.sig" -); -const WEB_NOVEL_GRID_NUMBER: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001"; -const WEB_NOVEL_GRID_PACKAGE: &[u8] = include_bytes!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001-0.1.0.ghmod" -); -const WEB_NOVEL_GRID_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001-0.1.0.ghmod.sig" -); -const WEB_NOVEL_STORYWORLD_NUMBER: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001"; -const WEB_NOVEL_STORYWORLD_PACKAGE: &[u8] = include_bytes!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001-0.1.0.ghmod" -); -const WEB_NOVEL_STORYWORLD_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001-0.1.0.ghmod.sig" -); -const WEB_NOVEL_DELIVERY_NUMBER: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001"; -const WEB_NOVEL_DELIVERY_PACKAGE: &[u8] = include_bytes!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001-0.1.0.ghmod" -); -const WEB_NOVEL_DELIVERY_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001-0.1.0.ghmod.sig" -); -const MOBILE_SYNC_NUMBER: &str = "HLP-MOD-OFFICIAL-MOBILE-SYNC-0001"; -const MOBILE_SYNC_PACKAGE: &[u8] = - include_bytes!("../../fixtures/module-packages/HLP-MOD-OFFICIAL-MOBILE-SYNC-0001-0.1.0.ghmod"); -const MOBILE_SYNC_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-MOBILE-SYNC-0001-0.1.0.ghmod.sig" -); -const DYNAMIC_WORLD_SURFACE_NUMBER: &str = "HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001"; -const DYNAMIC_WORLD_SURFACE_PACKAGE: &[u8] = include_bytes!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001-0.1.0.ghmod" -); -const DYNAMIC_WORLD_SURFACE_SIGNATURE: &str = include_str!( - "../../fixtures/module-packages/HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001-0.1.0.ghmod.sig" -); - -struct BundledModuleSource { - module_number: &'static str, - package: &'static [u8], - signature: &'static str, -} - -const BUNDLED_MODULES: &[BundledModuleSource] = &[ - BundledModuleSource { - module_number: NATIVE_COMPOSITION_NUMBER, - package: NATIVE_COMPOSITION_PACKAGE, - signature: NATIVE_COMPOSITION_SIGNATURE, - }, - BundledModuleSource { - module_number: CHANNEL_WORKBENCH_NUMBER, - package: CHANNEL_WORKBENCH_PACKAGE, - signature: CHANNEL_WORKBENCH_SIGNATURE, - }, - BundledModuleSource { - module_number: PERSONA_CHANNEL_BODY_NUMBER, - package: PERSONA_CHANNEL_BODY_PACKAGE, - signature: PERSONA_CHANNEL_BODY_SIGNATURE, - }, - BundledModuleSource { - module_number: EDUCATION_WORKBENCH_NUMBER, - package: EDUCATION_WORKBENCH_PACKAGE, - signature: EDUCATION_WORKBENCH_SIGNATURE, - }, - BundledModuleSource { - module_number: WEB_NOVEL_WORKBENCH_NUMBER, - package: WEB_NOVEL_WORKBENCH_PACKAGE, - signature: WEB_NOVEL_WORKBENCH_SIGNATURE, - }, - BundledModuleSource { - module_number: WEB_NOVEL_OUTLINE_NUMBER, - package: WEB_NOVEL_OUTLINE_PACKAGE, - signature: WEB_NOVEL_OUTLINE_SIGNATURE, - }, - BundledModuleSource { - module_number: WEB_NOVEL_GRID_NUMBER, - package: WEB_NOVEL_GRID_PACKAGE, - signature: WEB_NOVEL_GRID_SIGNATURE, - }, - BundledModuleSource { - module_number: WEB_NOVEL_STORYWORLD_NUMBER, - package: WEB_NOVEL_STORYWORLD_PACKAGE, - signature: WEB_NOVEL_STORYWORLD_SIGNATURE, - }, - BundledModuleSource { - module_number: WEB_NOVEL_DELIVERY_NUMBER, - package: WEB_NOVEL_DELIVERY_PACKAGE, - signature: WEB_NOVEL_DELIVERY_SIGNATURE, - }, - BundledModuleSource { - module_number: MOBILE_SYNC_NUMBER, - package: MOBILE_SYNC_PACKAGE, - signature: MOBILE_SYNC_SIGNATURE, - }, - BundledModuleSource { - module_number: DYNAMIC_WORLD_SURFACE_NUMBER, - package: DYNAMIC_WORLD_SURFACE_PACKAGE, - signature: DYNAMIC_WORLD_SURFACE_SIGNATURE, - }, -]; - -#[derive(Debug, Deserialize)] -struct RuntimeContract { - schema: String, - record_id: String, - package_schema: String, - host: HostContract, - registered_adapters: Vec, - lifecycle: Vec, -} - -#[derive(Debug, Deserialize)] -struct HostContract { - version: String, - maximum_package_bytes: u64, - arbitrary_native_code: bool, - arbitrary_webview_javascript: bool, - declarative_payload_only: bool, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct ModulePackage { - schema: String, - manifest: ModuleManifest, - payload: Value, -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct ModuleManifest { - module_number: String, - registration_class: String, - display_name: String, - version: String, - minimum_host_version: String, - adapter: String, - content_digest: String, - permissions: Vec, - user_data_schema: String, - self_test: ModuleSelfTest, -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct ModuleSelfTest { - kind: String, - expected_content_digest: String, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct VerifyModulePackageInput { - package_path: String, - signature_path: String, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct InstallModulePackageInput { - package_path: String, - signature_path: String, - expected_package_sha256: String, - human_confirmed_permission_expansion: bool, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct ModuleNumberInput { - module_number: String, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct VerifiedModulePackage { - state: String, - package_sha256: String, - module_number: String, - display_name: String, - version: String, - adapter: String, - permissions: Vec, - signature_verified: bool, - package_code_executed: bool, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct InstalledModule { - module_number: String, - display_name: String, - version: String, - adapter: String, - state: String, - package_sha256: String, - previous_package_sha256: Option, - permissions: Vec, - user_data_preserved: bool, - updated_at_unix_ms: u64, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ModuleRuntimeSnapshot { - schema: &'static str, - state: &'static str, - host_version: &'static str, - package_code_executed: bool, - modules: Vec, - receipt_count: u64, - latest_receipt_hash: String, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ModuleMutationReceipt { - receipt_id: String, - event: String, - module_number: String, - state: String, - package_sha256: String, - previous_receipt_hash: String, - receipt_hash: String, - observed_at_unix_ms: u64, - user_data_preserved: bool, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct ActivateBundledModuleInput { - module_number: String, - human_confirmed_permission_expansion: bool, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct BundledModuleDescriptor { - module_number: String, - display_name: String, - version: String, - adapter: String, - permissions: Vec, - package_sha256: String, - installed_state: String, - signature_verified: bool, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct BundledModuleActivation { - schema: &'static str, - state: String, - module_number: String, - receipts: Vec, - snapshot: ModuleRuntimeSnapshot, -} - -fn now_unix_ms() -> u64 { - SystemTime::now() - .duration_since(UNIX_EPOCH) - .map(|duration| duration.as_millis() as u64) - .unwrap_or(0) -} - -fn sha256_hex(bytes: &[u8]) -> String { - digest(&SHA256, bytes) - .as_ref() - .iter() - .map(|byte| format!("{byte:02x}")) - .collect() -} - -fn is_sha256(value: &str) -> bool { - value.len() == 64 && value.chars().all(|item| item.is_ascii_hexdigit()) -} - -fn canonical_value(value: &Value) -> Value { - match value { - Value::Array(values) => Value::Array(values.iter().map(canonical_value).collect()), - Value::Object(object) => { - let mut keys = object.keys().collect::>(); - keys.sort(); - let mut canonical = Map::new(); - for key in keys { - canonical.insert(key.clone(), canonical_value(&object[key])); - } - Value::Object(canonical) - } - _ => value.clone(), - } -} - -fn payload_digest(value: &Value) -> Result { - let bytes = serde_json::to_vec(&canonical_value(value)) - .map_err(|error| format!("HOLOLAKE_MODULE_PAYLOAD_INVALID: {error}"))?; - Ok(sha256_hex(&bytes)) -} - -fn contract() -> Result { - let contract: RuntimeContract = serde_json::from_str(CONTRACT_RAW) - .map_err(|error| format!("HOLOLAKE_MODULE_RUNTIME_CONTRACT_INVALID: {error}"))?; - if contract.schema != CONTRACT_SCHEMA - || contract.record_id != "HLP-MODULE-PACKAGE-RUNTIME-001" - || contract.package_schema != PACKAGE_SCHEMA - || contract.host.version != HOST_VERSION - || contract.host.maximum_package_bytes != MAX_PACKAGE_BYTES - || contract.host.arbitrary_native_code - || contract.host.arbitrary_webview_javascript - || !contract.host.declarative_payload_only - || contract.registered_adapters.len() != 7 - || contract.lifecycle.len() != 6 - { - return Err("HOLOLAKE_MODULE_RUNTIME_CONTRACT_BOUNDARY_INVALID".into()); - } - Ok(contract) -} - -fn decode_outer_base64(value: &str, label: &str) -> Result { - let bytes = STANDARD - .decode(value.trim()) - .map_err(|error| format!("{label}_BASE64_INVALID: {error}"))?; - String::from_utf8(bytes).map_err(|error| format!("{label}_UTF8_INVALID: {error}")) -} - -fn verify_signature_raw( - package: &[u8], - signature_raw: &str, - trust_raw: &str, -) -> Result<(), String> { - let trust: Value = serde_json::from_str(trust_raw) - .map_err(|error| format!("HOLOLAKE_MODULE_TRUST_INVALID: {error}"))?; - if trust.get("state").and_then(Value::as_str) != Some("PROVISIONED") { - return Err("HOLOLAKE_MODULE_TRUST_UNPROVISIONED".into()); - } - let encoded_key = trust - .get("publicKey") - .and_then(Value::as_str) - .ok_or("HOLOLAKE_MODULE_TRUST_KEY_MISSING")?; - let public_key = PublicKey::decode(&decode_outer_base64(encoded_key, "HOLOLAKE_MODULE_KEY")?) - .map_err(|error| format!("HOLOLAKE_MODULE_KEY_INVALID: {error}"))?; - let signature = Signature::decode(&decode_outer_base64( - signature_raw, - "HOLOLAKE_MODULE_SIGNATURE", - )?) - .map_err(|error| format!("HOLOLAKE_MODULE_SIGNATURE_INVALID: {error}"))?; - public_key - .verify(package, &signature, true) - .map_err(|error| format!("HOLOLAKE_MODULE_SIGNATURE_REJECTED: {error}")) -} - -fn valid_number(value: &str, registration_class: &str) -> bool { - let prefix = match registration_class { - "OFFICIAL_LIGHTHOUSE" => "HLP-MOD-OFFICIAL-", - "PRIVATE_CHANNEL_LOCAL" => "HLP-MOD-LOCAL-", - _ => return false, - }; - value.starts_with(prefix) - && value.len() <= 96 - && value - .chars() - .all(|item| item.is_ascii_uppercase() || item.is_ascii_digit() || item == '-') -} - -fn version_triplet(value: &str) -> Option<(u64, u64, u64)> { - let parts = value.split('.').collect::>(); - if parts.len() != 3 { - return None; - } - Some(( - parts[0].parse().ok()?, - parts[1].parse().ok()?, - parts[2].parse().ok()?, - )) -} - -fn validate_package(package: &ModulePackage, contract: &RuntimeContract) -> Result<(), String> { - let manifest = &package.manifest; - let permissions = manifest.permissions.iter().collect::>(); - if package.schema != PACKAGE_SCHEMA - || !valid_number(&manifest.module_number, &manifest.registration_class) - || manifest.display_name.trim().is_empty() - || manifest.display_name.len() > 120 - || version_triplet(&manifest.version).is_none() - || version_triplet(&manifest.minimum_host_version).is_none() - || version_triplet(&manifest.minimum_host_version) > version_triplet(HOST_VERSION) - || !contract.registered_adapters.contains(&manifest.adapter) - || !is_sha256(&manifest.content_digest) - || permissions.len() != manifest.permissions.len() - || manifest.permissions.len() > 32 - || manifest.permissions.iter().any(|permission| { - permission.is_empty() - || permission.len() > 80 - || !permission - .chars() - .all(|item| item.is_ascii_uppercase() || item.is_ascii_digit() || item == '_') - }) - || manifest.user_data_schema.trim().is_empty() - || manifest.self_test.kind != "DECLARATIVE_SCHEMA_V1" - || manifest.self_test.expected_content_digest != manifest.content_digest - || !package.payload.is_object() - || payload_digest(&package.payload)? != manifest.content_digest - { - return Err("HOLOLAKE_MODULE_PACKAGE_CONTRACT_INVALID".into()); - } - Ok(()) -} - -fn read_verified_package( - package_path: &Path, - signature_path: &Path, - trust_raw: &str, -) -> Result<(Vec, ModulePackage, String), String> { - let metadata = fs::symlink_metadata(package_path) - .map_err(|error| format!("HOLOLAKE_MODULE_PACKAGE_METADATA_FAILED: {error}"))?; - let signature_metadata = fs::symlink_metadata(signature_path) - .map_err(|error| format!("HOLOLAKE_MODULE_SIGNATURE_METADATA_FAILED: {error}"))?; - if metadata.file_type().is_symlink() - || signature_metadata.file_type().is_symlink() - || !metadata.is_file() - || !signature_metadata.is_file() - || metadata.len() == 0 - || metadata.len() > MAX_PACKAGE_BYTES - || signature_metadata.len() == 0 - || signature_metadata.len() > 16 * 1024 - { - return Err("HOLOLAKE_MODULE_PACKAGE_SIZE_INVALID".into()); - } - let bytes = fs::read(package_path) - .map_err(|error| format!("HOLOLAKE_MODULE_PACKAGE_READ_FAILED: {error}"))?; - let signature_raw = fs::read_to_string(signature_path) - .map_err(|error| format!("HOLOLAKE_MODULE_SIGNATURE_READ_FAILED: {error}"))?; - read_verified_package_bytes(&bytes, &signature_raw, trust_raw) -} - -fn read_verified_package_bytes( - bytes: &[u8], - signature_raw: &str, - trust_raw: &str, -) -> Result<(Vec, ModulePackage, String), String> { - verify_signature_raw(bytes, signature_raw, trust_raw)?; - let package: ModulePackage = serde_json::from_slice(bytes) - .map_err(|error| format!("HOLOLAKE_MODULE_PACKAGE_JSON_INVALID: {error}"))?; - validate_package(&package, &contract()?)?; - let package_sha256 = sha256_hex(bytes); - Ok((bytes.to_vec(), package, package_sha256)) -} - -fn bundled_package(module_number: &str) -> Result<(&'static [u8], &'static str), String> { - BUNDLED_MODULES - .iter() - .find(|source| source.module_number == module_number) - .map(|source| (source.package, source.signature)) - .ok_or_else(|| "HOLOLAKE_BUNDLED_MODULE_UNKNOWN".into()) -} - -fn runtime_root(app: &AppHandle) -> Result { - crate::authenticated_storage::account_storage_root(app, "module-runtime-v1") -} - -fn open_db(root: &Path) -> Result { - fs::create_dir_all(root) - .map_err(|error| format!("HOLOLAKE_MODULE_RUNTIME_ROOT_FAILED: {error}"))?; - let connection = Connection::open(root.join("module-runtime.sqlite3")) - .map_err(|error| format!("HOLOLAKE_MODULE_RUNTIME_DB_OPEN_FAILED: {error}"))?; - connection - .busy_timeout(std::time::Duration::from_secs(5)) - .map_err(|error| format!("HOLOLAKE_MODULE_RUNTIME_DB_TIMEOUT_FAILED: {error}"))?; - connection - .execute_batch( - "PRAGMA journal_mode=WAL; - PRAGMA foreign_keys=ON; - CREATE TABLE IF NOT EXISTS installed_modules( - module_number TEXT PRIMARY KEY, - display_name TEXT NOT NULL, - version TEXT NOT NULL, - adapter TEXT NOT NULL, - state TEXT NOT NULL, - package_sha256 TEXT NOT NULL, - previous_package_sha256 TEXT, - permissions_json TEXT NOT NULL, - manifest_json TEXT NOT NULL, - updated_at_unix_ms INTEGER NOT NULL - ); - CREATE TABLE IF NOT EXISTS module_receipts( - sequence INTEGER PRIMARY KEY AUTOINCREMENT, - receipt_id TEXT NOT NULL UNIQUE, - event TEXT NOT NULL, - module_number TEXT NOT NULL, - state TEXT NOT NULL, - package_sha256 TEXT NOT NULL, - previous_receipt_hash TEXT NOT NULL, - receipt_hash TEXT NOT NULL, - observed_at_unix_ms INTEGER NOT NULL - );", - ) - .map_err(|error| format!("HOLOLAKE_MODULE_RUNTIME_DB_SCHEMA_FAILED: {error}"))?; - Ok(connection) -} - -fn known_state(state: &str) -> bool { - matches!( - state, - "INSTALLED_DORMANT" - | "MOUNTED_PENDING_SELF_TEST" - | "ACTIVE" - | "DORMANT" - | "ROLLBACK_PENDING_SELF_TEST" - | "FAILED_CLOSED" - ) -} - -fn verify_receipt_chain(connection: &Connection) -> Result<(), String> { - let mut statement = connection - .prepare( - "SELECT receipt_id,event,module_number,state,package_sha256,previous_receipt_hash,receipt_hash,observed_at_unix_ms FROM module_receipts ORDER BY sequence", - ) - .map_err(|error| format!("HOLOLAKE_MODULE_RECEIPT_VERIFY_PREPARE_FAILED: {error}"))?; - let rows = statement - .query_map([], |row| { - Ok(( - row.get::<_, String>(0)?, - row.get::<_, String>(1)?, - row.get::<_, String>(2)?, - row.get::<_, String>(3)?, - row.get::<_, String>(4)?, - row.get::<_, String>(5)?, - row.get::<_, String>(6)?, - row.get::<_, u64>(7)?, - )) - }) - .map_err(|error| format!("HOLOLAKE_MODULE_RECEIPT_VERIFY_QUERY_FAILED: {error}"))?; - let mut previous = "0".repeat(64); - for row in rows { - let (receipt_id, event, module_number, state, package_sha256, linked, stored, observed) = - row.map_err(|error| format!("HOLOLAKE_MODULE_RECEIPT_VERIFY_ROW_FAILED: {error}"))?; - let expected = sha256_hex( - format!( - "HLP-MODULE-RECEIPT-v1\n{receipt_id}\n{event}\n{module_number}\n{state}\n{package_sha256}\n{linked}\n{observed}" - ) - .as_bytes(), - ); - if linked != previous - || stored != expected - || !is_sha256(&stored) - || !is_sha256(&package_sha256) - || !known_state(&state) - { - return Err("HOLOLAKE_MODULE_RECEIPT_CHAIN_INVALID".into()); - } - previous = stored; - } - Ok(()) -} - -fn verify_persisted_modules(connection: &Connection, root: &Path) -> Result<(), String> { - let mut statement = connection - .prepare( - "SELECT module_number,display_name,version,adapter,state,package_sha256,previous_package_sha256,permissions_json,manifest_json FROM installed_modules ORDER BY module_number", - ) - .map_err(|error| format!("HOLOLAKE_MODULE_PERSISTED_VERIFY_PREPARE_FAILED: {error}"))?; - let rows = statement - .query_map([], |row| { - Ok(( - row.get::<_, String>(0)?, - row.get::<_, String>(1)?, - row.get::<_, String>(2)?, - row.get::<_, String>(3)?, - row.get::<_, String>(4)?, - row.get::<_, String>(5)?, - row.get::<_, Option>(6)?, - row.get::<_, String>(7)?, - row.get::<_, String>(8)?, - )) - }) - .map_err(|error| format!("HOLOLAKE_MODULE_PERSISTED_VERIFY_QUERY_FAILED: {error}"))?; - for row in rows { - let ( - number, - display, - version, - adapter, - state, - digest, - previous, - permissions_raw, - manifest_raw, - ) = row.map_err(|error| format!("HOLOLAKE_MODULE_PERSISTED_VERIFY_ROW_FAILED: {error}"))?; - if !known_state(&state) || !is_sha256(&digest) { - return Err("HOLOLAKE_MODULE_PERSISTED_STATE_INVALID".into()); - } - let manifest: ModuleManifest = serde_json::from_str(&manifest_raw) - .map_err(|_| "HOLOLAKE_MODULE_PERSISTED_MANIFEST_INVALID".to_string())?; - let permissions: Vec = serde_json::from_str(&permissions_raw) - .map_err(|_| "HOLOLAKE_MODULE_PERSISTED_PERMISSIONS_INVALID".to_string())?; - let (_, package, verified_digest) = read_verified_package( - &package_file(root, &digest), - &signature_file(root, &digest), - RELEASE_TRUST_RAW, - )?; - if verified_digest != digest - || package.manifest != manifest - || manifest.module_number != number - || manifest.display_name != display - || manifest.version != version - || manifest.adapter != adapter - || manifest.permissions != permissions - { - return Err("HOLOLAKE_MODULE_PERSISTED_IDENTITY_INVALID".into()); - } - if let Some(previous) = previous { - if !is_sha256(&previous) { - return Err("HOLOLAKE_MODULE_PREVIOUS_PACKAGE_INVALID".into()); - } - let (_, previous_package, previous_digest) = read_verified_package( - &package_file(root, &previous), - &signature_file(root, &previous), - RELEASE_TRUST_RAW, - )?; - if previous_digest != previous || previous_package.manifest.module_number != number { - return Err("HOLOLAKE_MODULE_PREVIOUS_PACKAGE_IDENTITY_INVALID".into()); - } - } - } - Ok(()) -} - -fn package_file(root: &Path, digest: &str) -> PathBuf { - root.join("packages").join(format!("{digest}.ghmod")) -} - -fn signature_file(root: &Path, digest: &str) -> PathBuf { - root.join("packages").join(format!("{digest}.ghmod.sig")) -} - -fn copy_atomic(source: &Path, target: &Path) -> Result<(), String> { - let parent = target - .parent() - .ok_or("HOLOLAKE_MODULE_PACKAGE_TARGET_INVALID")?; - fs::create_dir_all(parent) - .map_err(|error| format!("HOLOLAKE_MODULE_PACKAGE_STORE_FAILED: {error}"))?; - if target.exists() { - return Ok(()); - } - let temporary = parent.join(format!(".install-{}", Uuid::new_v4())); - fs::copy(source, &temporary) - .map_err(|error| format!("HOLOLAKE_MODULE_PACKAGE_COPY_FAILED: {error}"))?; - fs::rename(&temporary, target) - .map_err(|error| format!("HOLOLAKE_MODULE_PACKAGE_COMMIT_FAILED: {error}")) -} - -fn previous_receipt_hash(transaction: &Transaction<'_>) -> Result { - transaction - .query_row( - "SELECT receipt_hash FROM module_receipts ORDER BY sequence DESC LIMIT 1", - [], - |row| row.get(0), - ) - .optional() - .map(|value| value.unwrap_or_else(|| "0".repeat(64))) - .map_err(|error| format!("HOLOLAKE_MODULE_RECEIPT_READ_FAILED: {error}")) -} - -fn append_receipt( - transaction: &Transaction<'_>, - event: &str, - module_number: &str, - state: &str, - package_sha256: &str, - observed_at_unix_ms: u64, -) -> Result { - let receipt_id = format!("HLP-MOD-RCPT-{}", Uuid::new_v4()); - let previous = previous_receipt_hash(transaction)?; - let receipt_hash = sha256_hex( - format!( - "HLP-MODULE-RECEIPT-v1\n{receipt_id}\n{event}\n{module_number}\n{state}\n{package_sha256}\n{previous}\n{observed_at_unix_ms}" - ) - .as_bytes(), - ); - transaction - .execute( - "INSERT INTO module_receipts(receipt_id,event,module_number,state,package_sha256,previous_receipt_hash,receipt_hash,observed_at_unix_ms) - VALUES(?1,?2,?3,?4,?5,?6,?7,?8)", - params![receipt_id, event, module_number, state, package_sha256, previous, receipt_hash, observed_at_unix_ms], - ) - .map_err(|error| format!("HOLOLAKE_MODULE_RECEIPT_WRITE_FAILED: {error}"))?; - Ok(ModuleMutationReceipt { - receipt_id, - event: event.into(), - module_number: module_number.into(), - state: state.into(), - package_sha256: package_sha256.into(), - previous_receipt_hash: previous, - receipt_hash, - observed_at_unix_ms, - user_data_preserved: true, - }) -} - -fn permissions_from_json(raw: &str) -> BTreeSet { - serde_json::from_str::>(raw) - .unwrap_or_default() - .into_iter() - .collect() -} - -fn materialize_bundled_source( - root: &Path, - module_number: &str, - package: &[u8], - signature: &str, -) -> Result<(PathBuf, PathBuf), String> { - let source_root = root.join("bundled-sources"); - fs::create_dir_all(&source_root) - .map_err(|error| format!("HOLOLAKE_BUNDLED_MODULE_SOURCE_ROOT_FAILED: {error}"))?; - let digest = sha256_hex(package); - let package_path = source_root.join(format!("{module_number}-{digest}.ghmod")); - let signature_path = source_root.join(format!("{module_number}-{digest}.ghmod.sig")); - for (path, bytes) in [ - (&package_path, package), - (&signature_path, signature.as_bytes()), - ] { - if path.exists() { - let current = fs::read(path) - .map_err(|error| format!("HOLOLAKE_BUNDLED_MODULE_SOURCE_READ_FAILED: {error}"))?; - if current != bytes { - return Err("HOLOLAKE_BUNDLED_MODULE_SOURCE_TAMPERED".into()); - } - continue; - } - let temporary = source_root.join(format!(".bundled-{}", Uuid::new_v4())); - fs::write(&temporary, bytes) - .map_err(|error| format!("HOLOLAKE_BUNDLED_MODULE_SOURCE_WRITE_FAILED: {error}"))?; - fs::rename(&temporary, path) - .map_err(|error| format!("HOLOLAKE_BUNDLED_MODULE_SOURCE_COMMIT_FAILED: {error}"))?; - } - Ok((package_path, signature_path)) -} - -pub async fn get_bundled_module_catalog( - app: AppHandle, -) -> Result, String> { - let root = runtime_root(&app)?; - let snapshot = snapshot_at(&root)?; - BUNDLED_MODULES - .iter() - .map(|source| { - let (_, package, package_sha256) = - read_verified_package_bytes(source.package, source.signature, RELEASE_TRUST_RAW)?; - if package.manifest.module_number != source.module_number { - return Err("HOLOLAKE_BUNDLED_MODULE_IDENTITY_INVALID".into()); - } - let installed_state = snapshot - .modules - .iter() - .find(|module| module.module_number == source.module_number) - .map(|module| module.state.clone()) - .unwrap_or_else(|| "NOT_INSTALLED".into()); - Ok(BundledModuleDescriptor { - module_number: package.manifest.module_number, - display_name: package.manifest.display_name, - version: package.manifest.version, - adapter: package.manifest.adapter, - permissions: package.manifest.permissions, - package_sha256, - installed_state, - signature_verified: true, - }) - }) - .collect() -} - -pub async fn activate_bundled_module( - app: AppHandle, - input: ActivateBundledModuleInput, -) -> Result { - let root = runtime_root(&app)?; - let (bytes, signature) = bundled_package(&input.module_number)?; - let (_, package, package_sha256) = - read_verified_package_bytes(bytes, signature, RELEASE_TRUST_RAW)?; - if package.manifest.module_number != input.module_number { - return Err("HOLOLAKE_BUNDLED_MODULE_IDENTITY_INVALID".into()); - } - let mut receipts = Vec::new(); - let before = snapshot_at(&root)?; - let installed = before - .modules - .iter() - .find(|module| module.module_number == input.module_number); - if installed - .is_some_and(|module| module.state == "ACTIVE" && module.package_sha256 == package_sha256) - { - return Ok(BundledModuleActivation { - schema: "hololake.bundled-module-activation/v1", - state: "ALREADY_ACTIVE".into(), - module_number: input.module_number, - receipts, - snapshot: before, - }); - } - let needs_install = installed - .map(|module| module.package_sha256 != package_sha256 || module.state == "FAILED_CLOSED") - .unwrap_or(true); - if needs_install { - let (package_path, signature_path) = - materialize_bundled_source(&root, &input.module_number, bytes, signature)?; - receipts.push(install_module_package_at( - &root, - &InstallModulePackageInput { - package_path: package_path.to_string_lossy().into_owned(), - signature_path: signature_path.to_string_lossy().into_owned(), - expected_package_sha256: package_sha256, - human_confirmed_permission_expansion: input.human_confirmed_permission_expansion, - }, - RELEASE_TRUST_RAW, - now_unix_ms(), - )?); - } - let current = snapshot_at(&root)? - .modules - .into_iter() - .find(|module| module.module_number == input.module_number) - .ok_or("HOLOLAKE_BUNDLED_MODULE_ACTIVATION_STATE_MISSING")?; - match current.state.as_str() { - "INSTALLED_DORMANT" | "DORMANT" => { - receipts.push(transition( - &root, - &input.module_number, - &["INSTALLED_DORMANT", "DORMANT"], - "MOUNTED_PENDING_SELF_TEST", - "MOUNT", - )?); - receipts.push(self_test_module_at( - &root, - &input.module_number, - now_unix_ms(), - )?); - } - "MOUNTED_PENDING_SELF_TEST" | "ROLLBACK_PENDING_SELF_TEST" => { - receipts.push(self_test_module_at( - &root, - &input.module_number, - now_unix_ms(), - )?); - } - "ACTIVE" => {} - _ => return Err("HOLOLAKE_BUNDLED_MODULE_ACTIVATION_STATE_INVALID".into()), - } - let snapshot = snapshot_at(&root)?; - if !snapshot.modules.iter().any(|module| { - module.module_number == input.module_number - && module.adapter == package.manifest.adapter - && module.state == "ACTIVE" - }) { - return Err("HOLOLAKE_BUNDLED_MODULE_ACTIVATION_NOT_ACTIVE".into()); - } - Ok(BundledModuleActivation { - schema: "hololake.bundled-module-activation/v1", - state: "ACTIVE".into(), - module_number: input.module_number, - receipts, - snapshot, - }) -} - -pub(crate) fn require_active_module_adapter( - app: &AppHandle, - module_number: &str, - adapter: &str, -) -> Result<(), String> { - let snapshot = snapshot_at(&runtime_root(app)?)?; - if snapshot.modules.iter().any(|module| { - module.module_number == module_number - && module.adapter == adapter - && module.state == "ACTIVE" - }) { - Ok(()) - } else { - Err("HOLOLAKE_MODULE_NOT_ACTIVE".into()) - } -} - -pub async fn verify_module_package( - app: AppHandle, - input: VerifyModulePackageInput, -) -> Result { - let _ = runtime_root(&app)?; - let (_, package, package_sha256) = read_verified_package( - Path::new(&input.package_path), - Path::new(&input.signature_path), - RELEASE_TRUST_RAW, - )?; - Ok(VerifiedModulePackage { - state: "VERIFIED_NOT_INSTALLED".into(), - package_sha256, - module_number: package.manifest.module_number, - display_name: package.manifest.display_name, - version: package.manifest.version, - adapter: package.manifest.adapter, - permissions: package.manifest.permissions, - signature_verified: true, - package_code_executed: false, - }) -} - -pub async fn install_module_package( - app: AppHandle, - input: InstallModulePackageInput, -) -> Result { - install_module_package_at( - &runtime_root(&app)?, - &input, - RELEASE_TRUST_RAW, - now_unix_ms(), - ) -} - -fn install_module_package_at( - root: &Path, - input: &InstallModulePackageInput, - trust_raw: &str, - observed: u64, -) -> Result { - if !is_sha256(&input.expected_package_sha256) { - return Err("HOLOLAKE_MODULE_EXPECTED_DIGEST_INVALID".into()); - } - let (bytes, package, digest) = read_verified_package( - Path::new(&input.package_path), - Path::new(&input.signature_path), - trust_raw, - )?; - if digest != input.expected_package_sha256 { - return Err("HOLOLAKE_MODULE_EXPECTED_DIGEST_MISMATCH".into()); - } - let mut connection = open_db(root)?; - let existing: Option<(String, String)> = connection - .query_row( - "SELECT package_sha256, permissions_json FROM installed_modules WHERE module_number=?1", - params![package.manifest.module_number], - |row| Ok((row.get(0)?, row.get(1)?)), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_MODULE_EXISTING_READ_FAILED: {error}"))?; - let requested = package - .manifest - .permissions - .iter() - .cloned() - .collect::>(); - let expansion = existing - .as_ref() - .map(|(_, raw)| !requested.is_subset(&permissions_from_json(raw))) - .unwrap_or(!requested.is_empty()); - if expansion && !input.human_confirmed_permission_expansion { - return Err("HOLOLAKE_MODULE_PERMISSION_EXPANSION_REQUIRES_HUMAN_CONFIRMATION".into()); - } - copy_atomic(Path::new(&input.package_path), &package_file(root, &digest))?; - copy_atomic( - Path::new(&input.signature_path), - &signature_file(root, &digest), - )?; - if fs::read(package_file(root, &digest)) - .map_err(|error| format!("HOLOLAKE_MODULE_STORED_PACKAGE_READ_FAILED: {error}"))? - != bytes - { - return Err("HOLOLAKE_MODULE_STORED_PACKAGE_MISMATCH".into()); - } - if fs::read(signature_file(root, &digest)) - .map_err(|error| format!("HOLOLAKE_MODULE_STORED_SIGNATURE_READ_FAILED: {error}"))? - != fs::read(&input.signature_path) - .map_err(|error| format!("HOLOLAKE_MODULE_SOURCE_SIGNATURE_READ_FAILED: {error}"))? - { - return Err("HOLOLAKE_MODULE_STORED_SIGNATURE_MISMATCH".into()); - } - fs::create_dir_all(root.join("user-data").join(&package.manifest.module_number)) - .map_err(|error| format!("HOLOLAKE_MODULE_USER_DATA_ROOT_FAILED: {error}"))?; - let transaction = connection - .transaction() - .map_err(|error| format!("HOLOLAKE_MODULE_INSTALL_TRANSACTION_FAILED: {error}"))?; - let permissions_json = serde_json::to_string(&package.manifest.permissions) - .map_err(|error| format!("HOLOLAKE_MODULE_PERMISSIONS_INVALID: {error}"))?; - let manifest_json = serde_json::to_string(&package.manifest) - .map_err(|error| format!("HOLOLAKE_MODULE_MANIFEST_INVALID: {error}"))?; - let previous = existing.as_ref().map(|(value, _)| value.as_str()); - transaction - .execute( - "INSERT INTO installed_modules(module_number,display_name,version,adapter,state,package_sha256,previous_package_sha256,permissions_json,manifest_json,updated_at_unix_ms) - VALUES(?1,?2,?3,?4,'INSTALLED_DORMANT',?5,?6,?7,?8,?9) - ON CONFLICT(module_number) DO UPDATE SET display_name=excluded.display_name,version=excluded.version,adapter=excluded.adapter,state='INSTALLED_DORMANT',package_sha256=excluded.package_sha256,previous_package_sha256=installed_modules.package_sha256,permissions_json=excluded.permissions_json,manifest_json=excluded.manifest_json,updated_at_unix_ms=excluded.updated_at_unix_ms", - params![package.manifest.module_number, package.manifest.display_name, package.manifest.version, package.manifest.adapter, digest, previous, permissions_json, manifest_json, observed], - ) - .map_err(|error| format!("HOLOLAKE_MODULE_INSTALL_WRITE_FAILED: {error}"))?; - let receipt = append_receipt( - &transaction, - "INSTALL", - &package.manifest.module_number, - "INSTALLED_DORMANT", - &digest, - observed, - )?; - transaction - .commit() - .map_err(|error| format!("HOLOLAKE_MODULE_INSTALL_COMMIT_FAILED: {error}"))?; - Ok(receipt) -} - -fn transition( - root: &Path, - module_number: &str, - allowed_from: &[&str], - target: &str, - event: &str, -) -> Result { - let mut connection = open_db(root)?; - let row: (String, String) = connection - .query_row( - "SELECT state,package_sha256 FROM installed_modules WHERE module_number=?1", - params![module_number], - |row| Ok((row.get(0)?, row.get(1)?)), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_MODULE_STATE_READ_FAILED: {error}"))? - .ok_or("HOLOLAKE_MODULE_NOT_INSTALLED")?; - if !allowed_from.contains(&row.0.as_str()) { - return Err("HOLOLAKE_MODULE_LIFECYCLE_TRANSITION_INVALID".into()); - } - let observed = now_unix_ms(); - let transaction = connection - .transaction() - .map_err(|error| format!("HOLOLAKE_MODULE_TRANSITION_BEGIN_FAILED: {error}"))?; - transaction - .execute( - "UPDATE installed_modules SET state=?1,updated_at_unix_ms=?2 WHERE module_number=?3 AND state=?4", - params![target, observed, module_number, row.0], - ) - .map_err(|error| format!("HOLOLAKE_MODULE_TRANSITION_WRITE_FAILED: {error}"))?; - let receipt = append_receipt(&transaction, event, module_number, target, &row.1, observed)?; - transaction - .commit() - .map_err(|error| format!("HOLOLAKE_MODULE_TRANSITION_COMMIT_FAILED: {error}"))?; - Ok(receipt) -} - -pub async fn mount_module( - app: AppHandle, - input: ModuleNumberInput, -) -> Result { - transition( - &runtime_root(&app)?, - &input.module_number, - &["INSTALLED_DORMANT", "DORMANT"], - "MOUNTED_PENDING_SELF_TEST", - "MOUNT", - ) -} - -pub async fn self_test_module( - app: AppHandle, - input: ModuleNumberInput, -) -> Result { - self_test_module_at(&runtime_root(&app)?, &input.module_number, now_unix_ms()) -} - -fn self_test_module_at( - root: &Path, - module_number: &str, - observed: u64, -) -> Result { - let mut connection = open_db(root)?; - let row: (String, String, Option) = connection - .query_row( - "SELECT state,package_sha256,previous_package_sha256 FROM installed_modules WHERE module_number=?1", - params![module_number], - |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_MODULE_SELF_TEST_STATE_FAILED: {error}"))? - .ok_or("HOLOLAKE_MODULE_NOT_INSTALLED")?; - if !matches!( - row.0.as_str(), - "MOUNTED_PENDING_SELF_TEST" | "ROLLBACK_PENDING_SELF_TEST" - ) { - return Err("HOLOLAKE_MODULE_SELF_TEST_STATE_INVALID".into()); - } - let verification = read_verified_package( - &package_file(root, &row.1), - &signature_file(root, &row.1), - RELEASE_TRUST_RAW, - ); - let success = verification.as_ref().is_ok_and(|(_, package, digest)| { - digest == &row.1 && package.manifest.module_number == module_number - }); - let rollback_package = row.2.as_ref().and_then(|previous| { - read_verified_package( - &package_file(root, previous), - &signature_file(root, previous), - RELEASE_TRUST_RAW, - ) - .ok() - .filter(|(_, package, digest)| { - digest == previous && package.manifest.module_number == module_number - }) - }); - let transaction = connection - .transaction() - .map_err(|error| format!("HOLOLAKE_MODULE_SELF_TEST_BEGIN_FAILED: {error}"))?; - if success { - transaction - .execute( - "UPDATE installed_modules SET state='ACTIVE',updated_at_unix_ms=?1 WHERE module_number=?2", - params![observed, module_number], - ) - .map_err(|error| format!("HOLOLAKE_MODULE_SELF_TEST_WRITE_FAILED: {error}"))?; - let receipt = append_receipt( - &transaction, - "SELF_TEST_PASS", - module_number, - "ACTIVE", - &row.1, - observed, - )?; - transaction - .commit() - .map_err(|error| format!("HOLOLAKE_MODULE_SELF_TEST_COMMIT_FAILED: {error}"))?; - return Ok(receipt); - } - let (target_state, target_digest) = if let Some((_, previous_package, previous)) = - rollback_package - { - let permissions_json = serde_json::to_string(&previous_package.manifest.permissions) - .map_err(|error| format!("HOLOLAKE_MODULE_ROLLBACK_PERMISSIONS_INVALID: {error}"))?; - let manifest_json = serde_json::to_string(&previous_package.manifest) - .map_err(|error| format!("HOLOLAKE_MODULE_ROLLBACK_MANIFEST_INVALID: {error}"))?; - transaction - .execute( - "UPDATE installed_modules SET display_name=?1,version=?2,adapter=?3,state='ROLLBACK_PENDING_SELF_TEST',package_sha256=?4,previous_package_sha256=NULL,permissions_json=?5,manifest_json=?6,updated_at_unix_ms=?7 WHERE module_number=?8", - params![previous_package.manifest.display_name, previous_package.manifest.version, previous_package.manifest.adapter, previous, permissions_json, manifest_json, observed, module_number], - ) - .map_err(|error| format!("HOLOLAKE_MODULE_AUTO_ROLLBACK_WRITE_FAILED: {error}"))?; - ("ROLLBACK_PENDING_SELF_TEST", previous) - } else { - transaction - .execute( - "UPDATE installed_modules SET state='FAILED_CLOSED',updated_at_unix_ms=?1 WHERE module_number=?2", - params![observed, module_number], - ) - .map_err(|error| format!("HOLOLAKE_MODULE_FAIL_CLOSED_WRITE_FAILED: {error}"))?; - ("FAILED_CLOSED", row.1) - }; - let _ = append_receipt( - &transaction, - "SELF_TEST_FAIL", - module_number, - target_state, - &target_digest, - observed, - )?; - transaction - .commit() - .map_err(|error| format!("HOLOLAKE_MODULE_SELF_TEST_FAILURE_COMMIT_FAILED: {error}"))?; - Err(verification - .err() - .unwrap_or_else(|| "HOLOLAKE_MODULE_SELF_TEST_IDENTITY_MISMATCH".into())) -} - -pub async fn unmount_module( - app: AppHandle, - input: ModuleNumberInput, -) -> Result { - if input.module_number == MOBILE_SYNC_NUMBER { - crate::mobile_sync::stop_for_unmount(&app)?; - } - transition( - &runtime_root(&app)?, - &input.module_number, - &["ACTIVE", "MOUNTED_PENDING_SELF_TEST", "FAILED_CLOSED"], - "DORMANT", - "UNMOUNT", - ) -} - -pub async fn rollback_module( - app: AppHandle, - input: ModuleNumberInput, -) -> Result { - let root = runtime_root(&app)?; - let mut connection = open_db(&root)?; - let row: (String, Option) = connection - .query_row( - "SELECT package_sha256,previous_package_sha256 FROM installed_modules WHERE module_number=?1", - params![input.module_number], - |row| Ok((row.get(0)?, row.get(1)?)), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_MODULE_ROLLBACK_READ_FAILED: {error}"))? - .ok_or("HOLOLAKE_MODULE_NOT_INSTALLED")?; - let previous = row.1.ok_or("HOLOLAKE_MODULE_ROLLBACK_NOT_AVAILABLE")?; - let (_, previous_package, verified_previous) = read_verified_package( - &package_file(&root, &previous), - &signature_file(&root, &previous), - RELEASE_TRUST_RAW, - )?; - if verified_previous != previous - || previous_package.manifest.module_number != input.module_number - { - return Err("HOLOLAKE_MODULE_ROLLBACK_PACKAGE_IDENTITY_INVALID".into()); - } - let permissions_json = serde_json::to_string(&previous_package.manifest.permissions) - .map_err(|error| format!("HOLOLAKE_MODULE_ROLLBACK_PERMISSIONS_INVALID: {error}"))?; - let manifest_json = serde_json::to_string(&previous_package.manifest) - .map_err(|error| format!("HOLOLAKE_MODULE_ROLLBACK_MANIFEST_INVALID: {error}"))?; - let observed = now_unix_ms(); - let transaction = connection - .transaction() - .map_err(|error| format!("HOLOLAKE_MODULE_ROLLBACK_BEGIN_FAILED: {error}"))?; - transaction - .execute( - "UPDATE installed_modules SET display_name=?1,version=?2,adapter=?3,state='ROLLBACK_PENDING_SELF_TEST',package_sha256=?4,previous_package_sha256=?5,permissions_json=?6,manifest_json=?7,updated_at_unix_ms=?8 WHERE module_number=?9", - params![previous_package.manifest.display_name, previous_package.manifest.version, previous_package.manifest.adapter, previous, row.0, permissions_json, manifest_json, observed, input.module_number], - ) - .map_err(|error| format!("HOLOLAKE_MODULE_ROLLBACK_WRITE_FAILED: {error}"))?; - let receipt = append_receipt( - &transaction, - "ROLLBACK", - &input.module_number, - "ROLLBACK_PENDING_SELF_TEST", - &previous, - observed, - )?; - transaction - .commit() - .map_err(|error| format!("HOLOLAKE_MODULE_ROLLBACK_COMMIT_FAILED: {error}"))?; - Ok(receipt) -} - -pub async fn get_module_runtime_snapshot(app: AppHandle) -> Result { - let root = runtime_root(&app)?; - snapshot_at(&root) -} - -fn snapshot_at(root: &Path) -> Result { - let connection = open_db(root)?; - verify_receipt_chain(&connection)?; - verify_persisted_modules(&connection, root)?; - let mut statement = connection - .prepare( - "SELECT module_number,display_name,version,adapter,state,package_sha256,previous_package_sha256,permissions_json,updated_at_unix_ms FROM installed_modules ORDER BY module_number", - ) - .map_err(|error| format!("HOLOLAKE_MODULE_SNAPSHOT_PREPARE_FAILED: {error}"))?; - let modules = statement - .query_map([], |row| { - let permissions_json: String = row.get(7)?; - Ok(InstalledModule { - module_number: row.get(0)?, - display_name: row.get(1)?, - version: row.get(2)?, - adapter: row.get(3)?, - state: row.get(4)?, - package_sha256: row.get(5)?, - previous_package_sha256: row.get(6)?, - permissions: serde_json::from_str(&permissions_json).unwrap_or_default(), - user_data_preserved: true, - updated_at_unix_ms: row.get(8)?, - }) - }) - .map_err(|error| format!("HOLOLAKE_MODULE_SNAPSHOT_QUERY_FAILED: {error}"))? - .collect::, _>>() - .map_err(|error| format!("HOLOLAKE_MODULE_SNAPSHOT_ROW_FAILED: {error}"))?; - let receipt_count: u64 = connection - .query_row("SELECT COUNT(*) FROM module_receipts", [], |row| row.get(0)) - .map_err(|error| format!("HOLOLAKE_MODULE_RECEIPT_COUNT_FAILED: {error}"))?; - let latest_receipt_hash = connection - .query_row( - "SELECT receipt_hash FROM module_receipts ORDER BY sequence DESC LIMIT 1", - [], - |row| row.get(0), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_MODULE_RECEIPT_TAIL_FAILED: {error}"))? - .unwrap_or_else(|| "0".repeat(64)); - Ok(ModuleRuntimeSnapshot { - schema: "hololake.module-runtime-snapshot/v1", - state: "ACTIVE_SIGNED_DECLARATIVE_PACKAGES_ONLY", - host_version: HOST_VERSION, - package_code_executed: false, - modules, - receipt_count, - latest_receipt_hash, - }) -} - -pub(crate) fn start_on_application_open(app: &AppHandle) -> Result<(), String> { - let _ = contract()?; - let root = runtime_root(app); - match root { - Ok(root) => { - let _ = snapshot_at(&root)?; - Ok(()) - } - Err(error) if error == "HOLOLAKE_AUTHENTICATED_ACCOUNT_REQUIRED" => Ok(()), - Err(error) => Err(error), - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn signed_fixture() -> (PathBuf, PathBuf, String) { - let package = PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("../fixtures/module-packages/HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001-0.1.0.ghmod"); - let signature = package.with_extension("ghmod.sig"); - let digest = sha256_hex(&fs::read(&package).unwrap()); - (package, signature, digest) - } - - fn install_fixture(root: &Path, observed: u64) -> String { - let (package, signature, digest) = signed_fixture(); - install_module_package_at( - root, - &InstallModulePackageInput { - package_path: package.to_string_lossy().into_owned(), - signature_path: signature.to_string_lossy().into_owned(), - expected_package_sha256: digest.clone(), - human_confirmed_permission_expansion: true, - }, - RELEASE_TRUST_RAW, - observed, - ) - .unwrap(); - digest - } - - #[test] - fn contract_keeps_packages_declarative_and_lifecycle_closed() { - let contract = contract().unwrap(); - assert_eq!(contract.registered_adapters.len(), 7); - assert!(!contract.host.arbitrary_native_code); - assert!(!contract.host.arbitrary_webview_javascript); - assert!(contract.host.declarative_payload_only); - } - - #[test] - fn package_number_classes_and_content_digest_are_exact() { - let payload = serde_json::json!({"views":[],"entry":"home"}); - let digest = payload_digest(&payload).unwrap(); - let package = ModulePackage { - schema: PACKAGE_SCHEMA.into(), - manifest: ModuleManifest { - module_number: "HLP-MOD-LOCAL-0001".into(), - registration_class: "PRIVATE_CHANNEL_LOCAL".into(), - display_name: "Local module".into(), - version: "1.0.0".into(), - minimum_host_version: "0.5.0".into(), - adapter: "native-composition-v1".into(), - content_digest: digest.clone(), - permissions: vec!["KNOWLEDGE_READ".into()], - user_data_schema: "hololake.module-data/local/v1".into(), - self_test: ModuleSelfTest { - kind: "DECLARATIVE_SCHEMA_V1".into(), - expected_content_digest: digest, - }, - }, - payload, - }; - let runtime_contract = contract().unwrap(); - validate_package(&package, &runtime_contract).unwrap(); - let mut invalid = package; - invalid.manifest.module_number = "HLP-DONOR-CAND-0001".into(); - assert_eq!( - validate_package(&invalid, &runtime_contract).unwrap_err(), - "HOLOLAKE_MODULE_PACKAGE_CONTRACT_INVALID" - ); - } - - #[test] - fn tampered_persisted_manifest_fails_closed_without_touching_user_data() { - let temporary = tempfile::tempdir().unwrap(); - let root = temporary.path(); - let module_number = "HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001"; - install_fixture(root, 1); - fs::write( - root.join("user-data") - .join(module_number) - .join("human-data.json"), - b"preserve", - ) - .unwrap(); - let connection = open_db(root).unwrap(); - connection - .execute( - "UPDATE installed_modules SET manifest_json='{}' WHERE module_number=?1", - params![module_number], - ) - .unwrap(); - drop(connection); - assert!(snapshot_at(root) - .unwrap_err() - .starts_with("HOLOLAKE_MODULE_PERSISTED_MANIFEST_INVALID")); - assert_eq!( - fs::read( - root.join("user-data") - .join(module_number) - .join("human-data.json") - ) - .unwrap(), - b"preserve" - ); - } - - #[test] - fn tampered_receipt_chain_fails_closed_on_restart() { - let temporary = tempfile::tempdir().unwrap(); - install_fixture(temporary.path(), 1); - let connection = open_db(temporary.path()).unwrap(); - connection - .execute( - "UPDATE module_receipts SET receipt_hash=?1 WHERE sequence=1", - params!["f".repeat(64)], - ) - .unwrap(); - drop(connection); - assert_eq!( - snapshot_at(temporary.path()).unwrap_err(), - "HOLOLAKE_MODULE_RECEIPT_CHAIN_INVALID" - ); - } - - #[test] - fn real_product_signed_fixture_verifies_without_executing_package_code() { - let (fixture, signature, _) = signed_fixture(); - let (_, package, package_sha256) = - read_verified_package(&fixture, &signature, RELEASE_TRUST_RAW).unwrap(); - assert_eq!( - package.manifest.module_number, - "HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001" - ); - assert!(is_sha256(&package_sha256)); - } - - #[test] - fn signed_package_install_mount_self_test_restart_and_unmount_are_receipted() { - let (fixture, signature, expected) = signed_fixture(); - let temporary = tempfile::tempdir().unwrap(); - let module_number = "HLP-MOD-LOCAL-RUNTIME-ACCEPTANCE-0001"; - let mut input = InstallModulePackageInput { - package_path: fixture.to_string_lossy().into_owned(), - signature_path: signature.to_string_lossy().into_owned(), - expected_package_sha256: expected, - human_confirmed_permission_expansion: false, - }; - assert_eq!( - install_module_package_at(temporary.path(), &input, RELEASE_TRUST_RAW, 100) - .unwrap_err(), - "HOLOLAKE_MODULE_PERMISSION_EXPANSION_REQUIRES_HUMAN_CONFIRMATION" - ); - input.human_confirmed_permission_expansion = true; - install_module_package_at(temporary.path(), &input, RELEASE_TRUST_RAW, 101).unwrap(); - transition( - temporary.path(), - module_number, - &["INSTALLED_DORMANT"], - "MOUNTED_PENDING_SELF_TEST", - "MOUNT", - ) - .unwrap(); - self_test_module_at(temporary.path(), module_number, 103).unwrap(); - let user_data = temporary - .path() - .join("user-data") - .join(module_number) - .join("human-data.json"); - fs::write(&user_data, b"preserve-after-unmount").unwrap(); - transition( - temporary.path(), - module_number, - &["ACTIVE"], - "DORMANT", - "UNMOUNT", - ) - .unwrap(); - let reopened = snapshot_at(temporary.path()).unwrap(); - assert_eq!(reopened.modules.len(), 1); - assert_eq!(reopened.modules[0].state, "DORMANT"); - assert_eq!(reopened.receipt_count, 4); - assert_eq!(fs::read(user_data).unwrap(), b"preserve-after-unmount"); - } - - #[test] - fn bundled_native_composition_package_completes_installed_lifecycle() { - let temporary = tempfile::tempdir().unwrap(); - let (_, package, digest) = read_verified_package_bytes( - NATIVE_COMPOSITION_PACKAGE, - NATIVE_COMPOSITION_SIGNATURE, - RELEASE_TRUST_RAW, - ) - .unwrap(); - assert_eq!(package.manifest.module_number, NATIVE_COMPOSITION_NUMBER); - assert_eq!(package.manifest.adapter, "native-composition-v1"); - let (package_path, signature_path) = materialize_bundled_source( - temporary.path(), - NATIVE_COMPOSITION_NUMBER, - NATIVE_COMPOSITION_PACKAGE, - NATIVE_COMPOSITION_SIGNATURE, - ) - .unwrap(); - install_module_package_at( - temporary.path(), - &InstallModulePackageInput { - package_path: package_path.to_string_lossy().into_owned(), - signature_path: signature_path.to_string_lossy().into_owned(), - expected_package_sha256: digest, - human_confirmed_permission_expansion: true, - }, - RELEASE_TRUST_RAW, - 200, - ) - .unwrap(); - transition( - temporary.path(), - NATIVE_COMPOSITION_NUMBER, - &["INSTALLED_DORMANT"], - "MOUNTED_PENDING_SELF_TEST", - "MOUNT", - ) - .unwrap(); - self_test_module_at(temporary.path(), NATIVE_COMPOSITION_NUMBER, 202).unwrap(); - let snapshot = snapshot_at(temporary.path()).unwrap(); - assert!(snapshot.modules.iter().any(|module| { - module.module_number == NATIVE_COMPOSITION_NUMBER - && module.adapter == "native-composition-v1" - && module.state == "ACTIVE" - })); - assert_eq!(snapshot.receipt_count, 3); - } - - #[test] - fn bundled_channel_workbench_has_an_independent_verified_identity() { - let (_, package, digest) = read_verified_package_bytes( - CHANNEL_WORKBENCH_PACKAGE, - CHANNEL_WORKBENCH_SIGNATURE, - RELEASE_TRUST_RAW, - ) - .unwrap(); - assert_eq!(package.manifest.module_number, CHANNEL_WORKBENCH_NUMBER); - assert_eq!(package.manifest.adapter, "channel-workbench-v1"); - assert_eq!(package.manifest.permissions.len(), 4); - assert!(is_sha256(&digest)); - assert_eq!(BUNDLED_MODULES.len(), 11); - } - - #[test] - fn bundled_persona_channel_body_is_signed_without_claiming_persona_binding() { - let (_, package, digest) = read_verified_package_bytes( - PERSONA_CHANNEL_BODY_PACKAGE, - PERSONA_CHANNEL_BODY_SIGNATURE, - RELEASE_TRUST_RAW, - ) - .unwrap(); - assert_eq!(package.manifest.module_number, PERSONA_CHANNEL_BODY_NUMBER); - assert_eq!(package.manifest.adapter, "persona-channel-body-v1"); - assert_eq!(package.manifest.permissions.len(), 7); - assert_eq!( - package.payload["adapterConfig"]["personaBindingClaimed"], - false - ); - assert!(is_sha256(&digest)); - } - - #[test] - fn bundled_education_workbench_is_an_official_signed_module() { - let (_, package, digest) = read_verified_package_bytes( - EDUCATION_WORKBENCH_PACKAGE, - EDUCATION_WORKBENCH_SIGNATURE, - RELEASE_TRUST_RAW, - ) - .unwrap(); - assert_eq!(package.manifest.module_number, EDUCATION_WORKBENCH_NUMBER); - assert_eq!(package.manifest.registration_class, "OFFICIAL_LIGHTHOUSE"); - assert_eq!(package.manifest.adapter, "education-workbench-v1"); - assert_eq!(package.manifest.permissions.len(), 8); - assert_eq!( - package.payload["adapterConfig"]["importDefaultScope"], - "UNASSIGNED" - ); - assert!(is_sha256(&digest)); - } - - #[test] - fn bundled_web_novel_family_uses_one_signed_lifecycle_and_exact_numbers() { - let expected = [ - ( - WEB_NOVEL_WORKBENCH_NUMBER, - WEB_NOVEL_WORKBENCH_PACKAGE, - WEB_NOVEL_WORKBENCH_SIGNATURE, - 8usize, - ), - ( - WEB_NOVEL_OUTLINE_NUMBER, - WEB_NOVEL_OUTLINE_PACKAGE, - WEB_NOVEL_OUTLINE_SIGNATURE, - 2usize, - ), - ( - WEB_NOVEL_GRID_NUMBER, - WEB_NOVEL_GRID_PACKAGE, - WEB_NOVEL_GRID_SIGNATURE, - 2usize, - ), - ( - WEB_NOVEL_STORYWORLD_NUMBER, - WEB_NOVEL_STORYWORLD_PACKAGE, - WEB_NOVEL_STORYWORLD_SIGNATURE, - 2usize, - ), - ( - WEB_NOVEL_DELIVERY_NUMBER, - WEB_NOVEL_DELIVERY_PACKAGE, - WEB_NOVEL_DELIVERY_SIGNATURE, - 2usize, - ), - ]; - for (number, bytes, signature, permission_count) in expected { - let (_, package, digest) = - read_verified_package_bytes(bytes, signature, RELEASE_TRUST_RAW).unwrap(); - assert_eq!(package.manifest.module_number, number); - assert_eq!(package.manifest.registration_class, "OFFICIAL_LIGHTHOUSE"); - assert_eq!(package.manifest.adapter, "web-novel-workbench-v1"); - assert_eq!(package.manifest.permissions.len(), permission_count); - assert!(is_sha256(&digest)); - } - } - - #[test] - fn bundled_mobile_sync_is_signed_and_keeps_the_desktop_as_root_node() { - let (_, package, digest) = read_verified_package_bytes( - MOBILE_SYNC_PACKAGE, - MOBILE_SYNC_SIGNATURE, - RELEASE_TRUST_RAW, - ) - .unwrap(); - assert_eq!(package.manifest.module_number, MOBILE_SYNC_NUMBER); - assert_eq!(package.manifest.registration_class, "OFFICIAL_LIGHTHOUSE"); - assert_eq!(package.manifest.adapter, "mobile-sync-v1"); - assert_eq!(package.manifest.permissions.len(), 5); - assert_eq!( - package.payload["adapterConfig"]["desktopRole"], - "USER_LOCAL_COMPUTER_TERMINAL_ROOT_NODE" - ); - assert_eq!( - package.payload["adapterConfig"]["iosClientPackaging"], - "PENDING_SEPARATE_ADMISSION" - ); - assert!(is_sha256(&digest)); - } - - #[test] - fn bundled_dynamic_world_surface_is_signed_and_cannot_change_routes() { - let (_, package, digest) = read_verified_package_bytes( - DYNAMIC_WORLD_SURFACE_PACKAGE, - DYNAMIC_WORLD_SURFACE_SIGNATURE, - RELEASE_TRUST_RAW, - ) - .unwrap(); - assert_eq!(package.manifest.module_number, DYNAMIC_WORLD_SURFACE_NUMBER); - assert_eq!(package.manifest.registration_class, "OFFICIAL_LIGHTHOUSE"); - assert_eq!( - package.manifest.adapter, - "dynamic-language-world-surface-v1" - ); - assert_eq!(package.manifest.permissions.len(), 2); - assert_eq!( - package.payload["adapterConfig"]["routingPermissionOrFactMutation"], - false - ); - assert_eq!( - package.payload["adapterConfig"]["legacyTraditionalWorkbench"], - "REJECTED_DUPLICATE_SHELL_AND_SIMULATED_STATE" - ); - assert!(is_sha256(&digest)); - } - - #[cfg(unix)] - #[test] - fn symlinked_package_input_is_rejected_before_signature_processing() { - use std::os::unix::fs::symlink; - - let temporary = tempfile::tempdir().unwrap(); - let source = temporary.path().join("source.ghmod"); - let link = temporary.path().join("link.ghmod"); - let signature = temporary.path().join("dummy.sig"); - fs::write(&source, b"{}").unwrap(); - fs::write(&signature, b"not-a-signature").unwrap(); - symlink(&source, &link).unwrap(); - assert_eq!( - read_verified_package(&link, &signature, RELEASE_TRUST_RAW).unwrap_err(), - "HOLOLAKE_MODULE_PACKAGE_SIZE_INVALID" - ); - } -} diff --git a/product-source/hololake-native-desktop/src-tauri/src/native_composition.rs b/product-source/hololake-native-desktop/src-tauri/src/native_composition.rs index 51ef6d2e2..e01b11765 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/native_composition.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/native_composition.rs @@ -281,21 +281,22 @@ fn descriptor( } } +#[tauri::command] pub fn get_native_composition_module_registry() -> ModuleRegistry { registry() } +#[tauri::command] pub async fn execute_knowledge_native_composition( app: AppHandle, input: ExecuteCompositionInput, ) -> Result { - crate::module_package_runtime::require_active_module_adapter( - &app, - "HLP-MOD-LOCAL-NATIVE-COMPOSITION-0001", - "native-composition-v1", - )?; validate_input(&input)?; - let snapshot = crate::knowledge_base::get_knowledge_snapshot(app).await?; + let snapshot = tauri::async_runtime::spawn_blocking(move || { + crate::knowledge_base::snapshot_for_native_composition(&app) + }) + .await + .map_err(|error| format!("HOLOLAKE_COMPOSITION_JOIN_FAILED: {error}"))??; execute_snapshot(snapshot, input) } @@ -326,7 +327,7 @@ fn execute_snapshot( source: document.source.to_string(), path: document.path.clone(), title: document.title.clone(), - top_level_folder: top_level_folder(&document.path), + top_level_folder: document.category.clone(), size_bytes: document.size_bytes, duplicate_count: document.duplicate_count, updated_at_unix_ms: document.updated_at_unix_ms.min(u64::MAX as u128) as u64, @@ -599,6 +600,7 @@ fn measure_value(value: (usize, u64, usize), measure: CompositionMeasure) -> u64 } } +#[cfg(test)] fn top_level_folder(path: &str) -> String { let normalized = path.replace('\\', "/"); let parts = normalized @@ -670,6 +672,9 @@ mod tests { size_bytes: 100, content_sha256: "a".into(), duplicate_count: 1, + category: "课程".into(), + category_explicit: false, + tags: vec!["教学".into()], }, KnowledgeDocumentSummary { source: "native", @@ -679,6 +684,9 @@ mod tests { size_bytes: 300, content_sha256: "b".into(), duplicate_count: 0, + category: "课程".into(), + category_explicit: true, + tags: vec!["教学".into()], }, KnowledgeDocumentSummary { source: "native", @@ -688,11 +696,18 @@ mod tests { size_bytes: 50, content_sha256: "c".into(), duplicate_count: 0, + category: "根目录".into(), + category_explicit: false, + tags: vec![], }, ], raw_document_count: 4, unique_document_count: 3, duplicate_document_count: 1, + organized_document_count: 1, + categories: vec![], + tags: vec![], + organization_revision: "test".into(), truncated: false, } } diff --git a/product-source/hololake-native-desktop/src-tauri/src/number_coordinate_tree.rs b/product-source/hololake-native-desktop/src-tauri/src/number_coordinate_tree.rs deleted file mode 100644 index aabd6ade9..000000000 --- a/product-source/hololake-native-desktop/src-tauri/src/number_coordinate_tree.rs +++ /dev/null @@ -1,204 +0,0 @@ -use serde::Deserialize; -use std::collections::HashSet; - -const TREE: &str = include_str!("../../generated/unified-number-coordinate-tree.json"); - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct NumberTree { - schema: String, - record_id: String, - state: String, - root_number: String, - coordinate_count: usize, - route_count: usize, - identity_node_count: usize, - protocol_node_count: usize, - reference_only_node_count: usize, - identity_nodes: Vec, - protocol_nodes: Vec, - routes: Vec, - invariants: NumberTreeInvariants, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct IdentityNode { - node_kind: String, - node_number: String, - namespace_id: String, - subject_kind: String, - domain_scope: String, - admission: String, - execution_state: String, - evidence: String, - path: String, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct ProtocolNode { - node_kind: String, - node_number: String, - protocol_id: String, - source_state: String, - execution_state: String, - evidence: String, - path: String, -} - -#[derive(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, - admission: String, - effect: String, - evidence: String, - path: String, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct NumberTreeInvariants { - number_is_stable_coordinate_not_authority: bool, - path_is_unique_navigation: bool, - admission_is_separate_from_identity: bool, - every_physical_call_has_numbered_route: bool, - every_accepted_call_has_evidence_class: bool, - every_protocol_reference_has_number_coordinate: bool, - reference_only_nodes_never_executable: bool, - unresolved_number_reference_count: usize, - mismatched_coordinate: String, -} - -pub(crate) fn start_on_application_open() -> Result<(), String> { - validate_tree() -} - -fn validate_tree() -> Result<(), String> { - let tree: NumberTree = serde_json::from_str(TREE) - .map_err(|error| format!("HOLOLAKE_UNIFIED_NUMBER_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 != 272 - || tree.route_count != 169 - || tree.routes.len() != tree.route_count - || tree.identity_node_count != 4 - || tree.identity_nodes.len() != tree.identity_node_count - || tree.protocol_node_count != 99 - || 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.invariants.number_is_stable_coordinate_not_authority - || !tree.invariants.path_is_unique_navigation - || !tree.invariants.admission_is_separate_from_identity - || !tree.invariants.every_physical_call_has_numbered_route - || !tree.invariants.every_accepted_call_has_evidence_class - || !tree - .invariants - .every_protocol_reference_has_number_coordinate - || !tree.invariants.reference_only_nodes_never_executable - || tree.invariants.unresolved_number_reference_count != 0 - || tree.invariants.mismatched_coordinate != "FAIL_CLOSED" - { - return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_BOUNDARY_INVALID".into()); - } - let mut paths = HashSet::new(); - let mut coordinates = HashSet::new(); - let mut node_numbers = HashSet::new(); - let mut protocol_ids = HashSet::new(); - for node in &tree.identity_nodes { - if node.node_kind != "IDENTITY_NAMESPACE" - || !node.node_number.starts_with("HLP-IDENTITY-NS-") - || node.namespace_id.is_empty() - || node.subject_kind.is_empty() - || node.domain_scope.is_empty() - || !matches!( - node.admission.as_str(), - "REGISTERED_HUMAN_NAMESPACE" | "NON_HUMAN_NAMESPACE" - ) - || node.execution_state != "AUTHORITY_RESOLUTION_ONLY" - || node.evidence.is_empty() - || !node.path.starts_with("HLP-NUMBER-WORLD-ROOT-001/IDENTITY/") - || !paths.insert(node.path.as_str()) - || !node_numbers.insert(node.node_number.as_str()) - { - return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_IDENTITY_NODE_INVALID".into()); - } - } - let mut reference_only_count = 0; - for node in &tree.protocol_nodes { - let valid_state = match node.node_kind.as_str() { - "GLS_PROTOCOL_SOURCE" => { - matches!( - node.execution_state.as_str(), - "EXECUTABLE_PROJECTION" | "INVENTORIED_NOT_EXECUTABLE" - ) && matches!( - node.source_state.as_str(), - "HDLP_PROTOCOL_SOURCE" | "LEGACY_MARKDOWN_EVIDENCE" - ) - } - "GLS_REFERENCE_ONLY" => { - reference_only_count += 1; - node.execution_state == "REFERENCE_ONLY_NOT_EXECUTABLE" - && node.source_state == "ROADMAP_REFERENCE_ONLY" - && node.node_number.starts_with("HLP-GLS-REF-") - } - _ => false, - }; - if !valid_state - || !node.protocol_id.starts_with("GLS-") - || node.evidence.is_empty() - || !node.path.starts_with("HLP-NUMBER-WORLD-ROOT-001/GLS/") - || !paths.insert(node.path.as_str()) - || !node_numbers.insert(node.node_number.as_str()) - || !protocol_ids.insert(node.protocol_id.as_str()) - { - return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_PROTOCOL_NODE_INVALID".into()); - } - } - if reference_only_count != tree.reference_only_node_count { - return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_REFERENCE_COUNT_INVALID".into()); - } - for route in &tree.routes { - let coordinate = format!( - "{}:{}:{}:{}:{}:{}", - route.transport, - route.channel_number, - route.module_number, - route.operation_number, - route.target_number, - route.caller_number - ); - if route.protocol_version.is_empty() - || route.admission.is_empty() - || !matches!(route.effect.as_str(), "READ_OR_STATUS" | "STATE_CHANGE") - || route.evidence.is_empty() - || !route.path.starts_with("HLP-NUMBER-WORLD-ROOT-001/") - || !paths.insert(route.path.as_str()) - || !coordinates.insert(coordinate) - { - return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_ROUTE_INVALID".into()); - } - } - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn unified_number_tree_is_unique_permissioned_and_evidenced() { - validate_tree().unwrap(); - } -} diff --git a/product-source/hololake-native-desktop/src-tauri/src/numbered_ipc.rs b/product-source/hololake-native-desktop/src-tauri/src/numbered_ipc.rs deleted file mode 100644 index c35cea065..000000000 --- a/product-source/hololake-native-desktop/src-tauri/src/numbered_ipc.rs +++ /dev/null @@ -1,1041 +0,0 @@ -//! HoloLake numbered IPC root. -//! -//! Stable numbers are coordinates, not authority. Every operation first receives a -//! short-lived server-issued grant bound to the exact caller/channel/module/operation/ -//! target tuple, protocol version, nonce and canonical payload digest. The grant is -//! consumed once before the internal handler runs. No business handler is registered -//! directly with Tauri. - -use base64::Engine; -use ring::{digest, hmac, rand as ring_rand}; -use ring_rand::SecureRandom; -use rusqlite::{params, Connection, OptionalExtension}; -use serde::{Deserialize, Serialize}; -use serde_json::{Map, Value}; -use std::collections::{HashMap, HashSet}; -use std::fs; -use std::path::PathBuf; -use std::sync::Mutex; -use std::time::{SystemTime, UNIX_EPOCH}; -use tauri::{AppHandle, Manager, State}; -use uuid::Uuid; - -const EMBEDDED_REGISTRY: &str = include_str!("../../contracts/numbered-ipc-registry.json"); -const EXPECTED_SCHEMA: &str = "hololake.numbered-ipc-registry/v1"; -const EXPECTED_RECORD_ID: &str = "HLP-NUMBERED-IPC-ROOT-001"; - -#[derive(Clone, Debug, Deserialize)] -struct NumberedIpcRegistry { - schema: String, - record_id: String, - runtime: RuntimeRules, - payload_contract: PayloadContract, - operations: Vec, -} - -#[derive(Clone, Debug, Deserialize)] -struct RuntimeRules { - public_tauri_command: String, - caller_number: String, - caller_number_subject_kind: String, - caller_number_grants_persona_binding: bool, - protocol_version: String, - legacy_direct_commands_allowed: bool, - grants_issued_server_side: bool, - grant_single_use: bool, - payload_bound_grants: bool, - authority_binding_issued_server_side: bool, - verified_human_binding_required_for_protected_routes: bool, - persona_binding_claimed: bool, - user_channel_body_binding_stage: String, - maximum_grant_ttl_ms: u64, - unknown_route: String, - mismatched_coordinate: String, - expired_or_replayed_grant: String, - receipt_required: bool, -} - -#[derive(Clone, Debug, Deserialize)] -struct PayloadContract { - unknown_or_unclassified_alias: String, - unknown_top_level_field: String, - empty_object_aliases: Vec, - input_wrapper_aliases: Vec, - direct_field_aliases: HashMap>, -} - -#[derive(Clone, Debug, Deserialize)] -struct OperationRoute { - operation_number: String, - alias: String, - handler: String, - channel_number: String, - module_number: String, - target_number: String, - admission: String, - effect: String, - payload_schema: String, -} - -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -struct NumberedCoordinate { - protocol_version: String, - caller_number: String, - channel_number: String, - module_number: String, - operation_number: String, - target_number: String, - request_nonce: String, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct NumberedEnvelope { - #[serde(flatten)] - coordinate: NumberedCoordinate, - #[serde(default = "default_ttl_ms")] - requested_ttl_ms: u64, - #[serde(default)] - payload: Value, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "SCREAMING_SNAKE_CASE")] -enum NumberedIpcAction { - IssueGrant, - Execute, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct NumberedIpcInput { - action: NumberedIpcAction, - envelope: NumberedEnvelope, - grant: Option, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct NumberedGrant { - grant_id: String, - expires_at_unix_ms: u64, - payload_sha256: String, - authority_binding_sha256: String, - signature: String, -} - -#[derive(Clone, Debug)] -struct GrantRecord { - coordinate: NumberedCoordinate, - expires_at_unix_ms: u64, - payload_sha256: String, - authority_binding_sha256: String, - signature: String, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct NumberedIpcReceipt { - receipt_id: String, - state: String, - decision: String, - operation_number: String, - payload_sha256: String, - authority_binding_sha256: String, - observed_at_unix_ms: u64, - previous_receipt_hash: String, - receipt_hash: String, - error: Option, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct NumberedIpcResponse { - schema: &'static str, - decision: String, - grant: Option, - result: Option, - error: Option, - receipt: NumberedIpcReceipt, -} - -pub struct NumberedIpcState { - signing_key: hmac::Key, - grants: Mutex>, - ledger: Mutex<()>, -} - -impl Default for NumberedIpcState { - fn default() -> Self { - let random = ring_rand::SystemRandom::new(); - let mut secret = [0_u8; 32]; - random - .fill(&mut secret) - .expect("operating system randomness is required for numbered IPC"); - Self { - signing_key: hmac::Key::new(hmac::HMAC_SHA256, &secret), - grants: Mutex::new(HashMap::new()), - ledger: Mutex::new(()), - } - } -} - -fn default_ttl_ms() -> u64 { - 10_000 -} - -fn now_unix_ms() -> u64 { - SystemTime::now() - .duration_since(UNIX_EPOCH) - .map(|duration| duration.as_millis() as u64) - .unwrap_or(0) -} - -fn sha256_hex(bytes: &[u8]) -> String { - digest::digest(&digest::SHA256, bytes) - .as_ref() - .iter() - .map(|byte| format!("{byte:02x}")) - .collect() -} - -fn canonical_value(value: &Value) -> Value { - match value { - Value::Array(values) => Value::Array(values.iter().map(canonical_value).collect()), - Value::Object(object) => { - let mut keys = object.keys().collect::>(); - keys.sort(); - let mut canonical = Map::new(); - for key in keys { - canonical.insert(key.clone(), canonical_value(&object[key])); - } - Value::Object(canonical) - } - _ => value.clone(), - } -} - -fn payload_digest(payload: &Value) -> Result { - let bytes = serde_json::to_vec(&canonical_value(payload)) - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_PAYLOAD_INVALID: {error}"))?; - if bytes.len() > 1_048_576 { - return Err("HOLOLAKE_NUMBERED_IPC_PAYLOAD_TOO_LARGE".into()); - } - Ok(sha256_hex(&bytes)) -} - -fn grant_signing_bytes( - grant_id: &str, - coordinate: &NumberedCoordinate, - expires_at_unix_ms: u64, - payload_sha256: &str, - authority_binding_sha256: &str, -) -> Vec { - format!( - "HLP-NIPC-GRANT-v1\n{grant_id}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{expires_at_unix_ms}\n{payload_sha256}\n{authority_binding_sha256}", - coordinate.protocol_version, - coordinate.caller_number, - coordinate.channel_number, - coordinate.module_number, - coordinate.operation_number, - coordinate.target_number, - coordinate.request_nonce, - EXPECTED_RECORD_ID, - ) - .into_bytes() -} - -fn load_registry() -> Result { - let registry: NumberedIpcRegistry = serde_json::from_str(EMBEDDED_REGISTRY) - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_REGISTRY_INVALID: {error}"))?; - validate_registry(®istry)?; - Ok(registry) -} - -fn validate_registry(registry: &NumberedIpcRegistry) -> Result<(), String> { - let runtime = ®istry.runtime; - if registry.schema != EXPECTED_SCHEMA - || registry.record_id != EXPECTED_RECORD_ID - || runtime.public_tauri_command != "numbered_ipc" - || runtime.caller_number_subject_kind != "PHYSICAL_WEBVIEW_ENTRY_NOT_PERSONA_IDENTITY" - || runtime.caller_number_grants_persona_binding - || runtime.legacy_direct_commands_allowed - || !runtime.grants_issued_server_side - || !runtime.grant_single_use - || !runtime.payload_bound_grants - || !runtime.authority_binding_issued_server_side - || !runtime.verified_human_binding_required_for_protected_routes - || runtime.persona_binding_claimed - || runtime.user_channel_body_binding_stage != "SEPARATE_EVIDENCE_LAYER_NOT_YET_CLAIMED" - || !runtime.receipt_required - || runtime.maximum_grant_ttl_ms == 0 - || runtime.maximum_grant_ttl_ms > 30_000 - || runtime.unknown_route != "FAIL_CLOSED" - || runtime.mismatched_coordinate != "FAIL_CLOSED" - || runtime.expired_or_replayed_grant != "FAIL_CLOSED" - || registry.operations.len() < 60 - { - return Err("HOLOLAKE_NUMBERED_IPC_REGISTRY_BOUNDARY_INVALID".into()); - } - if registry.payload_contract.unknown_or_unclassified_alias != "FAIL_CLOSED_BEFORE_GRANT" - || registry.payload_contract.unknown_top_level_field != "FAIL_CLOSED_BEFORE_GRANT" - { - return Err("HOLOLAKE_NUMBERED_IPC_PAYLOAD_CONTRACT_INVALID".into()); - } - let mut operation_numbers = HashSet::new(); - let mut aliases = HashSet::new(); - let mut coordinates = HashSet::new(); - for route in ®istry.operations { - let coordinate = format!( - "{}/{}/{}/{}", - route.channel_number, route.module_number, route.operation_number, route.target_number - ); - if !operation_numbers.insert(route.operation_number.as_str()) - || !aliases.insert(route.alias.as_str()) - || !coordinates.insert(coordinate) - || !route.operation_number.starts_with("HLP-NIPC-OP-") - || !route.module_number.starts_with("HLP-NIPC-MOD-") - || !route.channel_number.starts_with("HLP-NIPC-CH-") - || !route.target_number.starts_with("HLP-NIPC-TGT-") - || !route.handler.contains("::") - || !matches!( - route.admission.as_str(), - "PREAUTH_SYSTEM_ROUTE" | "VERIFIED_HUMAN_ROUTE" - ) - || !matches!(route.effect.as_str(), "READ_OR_STATUS" | "STATE_CHANGE") - || !route - .payload_schema - .starts_with("hololake.numbered-ipc.payload/") - { - return Err("HOLOLAKE_NUMBERED_IPC_ROUTE_INVALID".into()); - } - } - let mut payload_aliases = HashSet::new(); - for alias in registry - .payload_contract - .empty_object_aliases - .iter() - .chain(registry.payload_contract.input_wrapper_aliases.iter()) - .chain(registry.payload_contract.direct_field_aliases.keys()) - { - if !payload_aliases.insert(alias.as_str()) { - return Err("HOLOLAKE_NUMBERED_IPC_PAYLOAD_ALIAS_DUPLICATED".into()); - } - } - if payload_aliases != aliases { - return Err("HOLOLAKE_NUMBERED_IPC_PAYLOAD_COVERAGE_INCOMPLETE".into()); - } - Ok(()) -} - -fn validate_payload_shape( - registry: &NumberedIpcRegistry, - route: &OperationRoute, - payload: &Value, -) -> Result<(), String> { - let object = payload - .as_object() - .ok_or_else(|| "HOLOLAKE_NUMBERED_IPC_PAYLOAD_OBJECT_REQUIRED".to_string())?; - if registry - .payload_contract - .empty_object_aliases - .iter() - .any(|alias| alias == &route.alias) - { - return if object.is_empty() { - Ok(()) - } else { - Err("HOLOLAKE_NUMBERED_IPC_PAYLOAD_FIELD_UNKNOWN".into()) - }; - } - if registry - .payload_contract - .input_wrapper_aliases - .iter() - .any(|alias| alias == &route.alias) - { - return if object.len() == 1 && object.contains_key("input") { - Ok(()) - } else { - Err("HOLOLAKE_NUMBERED_IPC_INPUT_WRAPPER_REQUIRED".into()) - }; - } - if let Some(required_fields) = registry - .payload_contract - .direct_field_aliases - .get(&route.alias) - { - let required = required_fields - .iter() - .map(String::as_str) - .collect::>(); - let observed = object.keys().map(String::as_str).collect::>(); - if observed != required - || required_fields - .iter() - .any(|field| !object.get(field).is_some_and(Value::is_string)) - { - return Err("HOLOLAKE_NUMBERED_IPC_DIRECT_FIELDS_INVALID".into()); - } - return Ok(()); - } - Err("HOLOLAKE_NUMBERED_IPC_PAYLOAD_ALIAS_UNCLASSIFIED".into()) -} - -fn resolve_route<'a>( - registry: &'a NumberedIpcRegistry, - coordinate: &NumberedCoordinate, -) -> Result<&'a OperationRoute, String> { - if coordinate.protocol_version != registry.runtime.protocol_version - || coordinate.caller_number != registry.runtime.caller_number - { - return Err("HOLOLAKE_NUMBERED_IPC_CALLER_OR_PROTOCOL_MISMATCH".into()); - } - if coordinate.request_nonce.len() < 16 - || coordinate.request_nonce.len() > 128 - || coordinate - .request_nonce - .chars() - .any(|character| character.is_whitespace() || character.is_control()) - { - return Err("HOLOLAKE_NUMBERED_IPC_NONCE_INVALID".into()); - } - let route = registry - .operations - .iter() - .find(|route| route.operation_number == coordinate.operation_number) - .ok_or_else(|| "HOLOLAKE_NUMBERED_IPC_ROUTE_UNKNOWN".to_string())?; - if route.channel_number != coordinate.channel_number - || route.module_number != coordinate.module_number - || route.target_number != coordinate.target_number - { - return Err("HOLOLAKE_NUMBERED_IPC_ROUTE_COORDINATE_MISMATCH".into()); - } - Ok(route) -} - -fn enforce_admission(app: &AppHandle, route: &OperationRoute) -> Result { - if route.admission == "PREAUTH_SYSTEM_ROUTE" { - return Ok("SYSTEM_PHYSICAL_ENTRY:HLP-NIPC-CALLER-MAIN-WEBVIEW-0001".into()); - } - let state = app.state::(); - match crate::zero_point::verified_user_route(&state)? { - Some((human_number, registry_domain)) => { - Ok(format!("VERIFIED_HUMAN:{registry_domain}:{human_number}")) - } - None => Err("HOLOLAKE_NUMBERED_IPC_VERIFIED_HUMAN_REQUIRED".into()), - } -} - -fn issue_grant_at( - state: &NumberedIpcState, - registry: &NumberedIpcRegistry, - envelope: &NumberedEnvelope, - authority_binding: &str, - now: u64, -) -> Result<(NumberedGrant, String), String> { - let route = resolve_route(registry, &envelope.coordinate)?; - validate_payload_shape(registry, route, &envelope.payload)?; - if envelope.requested_ttl_ms == 0 - || envelope.requested_ttl_ms > registry.runtime.maximum_grant_ttl_ms - { - return Err("HOLOLAKE_NUMBERED_IPC_GRANT_TTL_INVALID".into()); - } - let payload_sha256 = payload_digest(&envelope.payload)?; - let authority_binding_sha256 = sha256_hex(authority_binding.as_bytes()); - let grant_id = format!("HLP-NIPC-GRANT-{}", Uuid::new_v4().simple()); - let expires_at_unix_ms = now.saturating_add(envelope.requested_ttl_ms); - let signature = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(hmac::sign( - &state.signing_key, - &grant_signing_bytes( - &grant_id, - &envelope.coordinate, - expires_at_unix_ms, - &payload_sha256, - &authority_binding_sha256, - ), - )); - let record = GrantRecord { - coordinate: envelope.coordinate.clone(), - expires_at_unix_ms, - payload_sha256: payload_sha256.clone(), - authority_binding_sha256: authority_binding_sha256.clone(), - signature: signature.clone(), - }; - let mut grants = state - .grants - .lock() - .map_err(|_| "HOLOLAKE_NUMBERED_IPC_GRANT_LOCK_POISONED".to_string())?; - grants.retain(|_, existing| existing.expires_at_unix_ms >= now); - grants.insert(grant_id.clone(), record); - Ok(( - NumberedGrant { - grant_id, - expires_at_unix_ms, - payload_sha256: payload_sha256.clone(), - authority_binding_sha256, - signature, - }, - payload_sha256, - )) -} - -fn consume_grant_at( - state: &NumberedIpcState, - registry: &NumberedIpcRegistry, - envelope: &NumberedEnvelope, - grant: &NumberedGrant, - authority_binding: &str, - now: u64, -) -> Result { - let route = resolve_route(registry, &envelope.coordinate)?; - validate_payload_shape(registry, route, &envelope.payload)?; - let payload_sha256 = payload_digest(&envelope.payload)?; - let authority_binding_sha256 = sha256_hex(authority_binding.as_bytes()); - let record = state - .grants - .lock() - .map_err(|_| "HOLOLAKE_NUMBERED_IPC_GRANT_LOCK_POISONED".to_string())? - .remove(&grant.grant_id) - .ok_or_else(|| "HOLOLAKE_NUMBERED_IPC_GRANT_UNKNOWN_OR_REPLAYED".to_string())?; - if now > record.expires_at_unix_ms - || grant.expires_at_unix_ms != record.expires_at_unix_ms - || grant.payload_sha256 != record.payload_sha256 - || payload_sha256 != record.payload_sha256 - || grant.authority_binding_sha256 != record.authority_binding_sha256 - || authority_binding_sha256 != record.authority_binding_sha256 - || grant.signature != record.signature - || envelope.coordinate != record.coordinate - { - return Err("HOLOLAKE_NUMBERED_IPC_GRANT_MISMATCH_OR_EXPIRED".into()); - } - let signature = base64::engine::general_purpose::URL_SAFE_NO_PAD - .decode(&grant.signature) - .map_err(|_| "HOLOLAKE_NUMBERED_IPC_GRANT_SIGNATURE_INVALID".to_string())?; - hmac::verify( - &state.signing_key, - &grant_signing_bytes( - &grant.grant_id, - &envelope.coordinate, - grant.expires_at_unix_ms, - &grant.payload_sha256, - &grant.authority_binding_sha256, - ), - &signature, - ) - .map_err(|_| "HOLOLAKE_NUMBERED_IPC_GRANT_SIGNATURE_INVALID".to_string())?; - Ok(payload_sha256) -} - -fn ledger_path(app: &AppHandle) -> Result { - let root = app - .path() - .app_data_dir() - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_HOME_FAILED: {error}"))? - .join("numbered-ipc-v1"); - fs::create_dir_all(&root) - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_HOME_CREATE_FAILED: {error}"))?; - Ok(root.join("receipts.sqlite3")) -} - -fn open_ledger(app: &AppHandle) -> Result { - let connection = Connection::open(ledger_path(app)?) - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_LEDGER_OPEN_FAILED: {error}"))?; - connection - .execute_batch( - "PRAGMA journal_mode=WAL; - PRAGMA busy_timeout=5000; - CREATE TABLE IF NOT EXISTS receipts( - sequence INTEGER PRIMARY KEY AUTOINCREMENT, - receipt_id TEXT NOT NULL UNIQUE, - state TEXT NOT NULL, - decision TEXT NOT NULL, - operation_number TEXT NOT NULL, - payload_sha256 TEXT NOT NULL, - authority_binding_sha256 TEXT NOT NULL DEFAULT '', - observed_at_unix_ms INTEGER NOT NULL, - previous_receipt_hash TEXT NOT NULL, - receipt_hash TEXT NOT NULL UNIQUE, - error TEXT - );", - ) - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_LEDGER_SCHEMA_FAILED: {error}"))?; - let has_authority_binding = { - let mut statement = connection - .prepare("PRAGMA table_info(receipts)") - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_LEDGER_SCHEMA_READ_FAILED: {error}"))?; - let columns = statement - .query_map([], |row| row.get::<_, String>(1)) - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_LEDGER_SCHEMA_READ_FAILED: {error}"))?; - let mut found = false; - for column in columns { - if column.map_err(|error| { - format!("HOLOLAKE_NUMBERED_IPC_LEDGER_SCHEMA_READ_FAILED: {error}") - })? == "authority_binding_sha256" - { - found = true; - } - } - found - }; - if !has_authority_binding { - connection - .execute( - "ALTER TABLE receipts ADD COLUMN authority_binding_sha256 TEXT NOT NULL DEFAULT ''", - [], - ) - .map_err(|error| { - format!("HOLOLAKE_NUMBERED_IPC_LEDGER_SCHEMA_MIGRATION_FAILED: {error}") - })?; - } - Ok(connection) -} - -#[allow(clippy::too_many_arguments)] -fn append_receipt( - app: &AppHandle, - state: &NumberedIpcState, - event_state: &str, - decision: &str, - operation_number: &str, - payload_sha256: &str, - authority_binding_sha256: &str, - error: Option, - now: u64, -) -> Result { - let _guard = state - .ledger - .lock() - .map_err(|_| "HOLOLAKE_NUMBERED_IPC_LEDGER_LOCK_POISONED".to_string())?; - let connection = open_ledger(app)?; - let previous_receipt_hash = connection - .query_row( - "SELECT receipt_hash FROM receipts ORDER BY sequence DESC LIMIT 1", - [], - |row| row.get::<_, String>(0), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_LEDGER_READ_FAILED: {error}"))? - .unwrap_or_else(|| "0".repeat(64)); - let receipt_id = format!("HLP-NIPC-RECEIPT-{}", Uuid::new_v4().simple()); - let receipt_hash = sha256_hex( - format!( - "HLP-NIPC-RECEIPT-v1\n{previous_receipt_hash}\n{receipt_id}\n{event_state}\n{decision}\n{operation_number}\n{payload_sha256}\n{authority_binding_sha256}\n{now}\n{}", - error.as_deref().unwrap_or("") - ) - .as_bytes(), - ); - connection - .execute( - "INSERT INTO receipts(receipt_id,state,decision,operation_number,payload_sha256, - authority_binding_sha256,observed_at_unix_ms,previous_receipt_hash,receipt_hash,error) - VALUES(?1,?2,?3,?4,?5,?6,?7,?8,?9,?10)", - params![ - receipt_id, - event_state, - decision, - operation_number, - payload_sha256, - authority_binding_sha256, - now, - previous_receipt_hash, - receipt_hash, - error, - ], - ) - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_LEDGER_APPEND_FAILED: {error}"))?; - Ok(NumberedIpcReceipt { - receipt_id, - state: event_state.into(), - decision: decision.into(), - operation_number: operation_number.into(), - payload_sha256: payload_sha256.into(), - authority_binding_sha256: authority_binding_sha256.into(), - observed_at_unix_ms: now, - previous_receipt_hash, - receipt_hash, - error, - }) -} - -#[allow(clippy::too_many_arguments)] -fn response( - app: &AppHandle, - state: &NumberedIpcState, - event_state: &str, - decision: &str, - operation_number: &str, - payload_sha256: &str, - grant: Option, - result: Option, - error: Option, - now: u64, -) -> Result { - let receipt = append_receipt( - app, - state, - event_state, - decision, - operation_number, - payload_sha256, - &sha256_hex(b"UNBOUND_AUTHORITY"), - error.clone(), - now, - )?; - Ok(NumberedIpcResponse { - schema: "hololake.numbered-ipc-response/v1", - decision: decision.into(), - grant, - result, - error, - receipt, - }) -} - -#[allow(clippy::too_many_arguments)] -fn bound_response( - app: &AppHandle, - state: &NumberedIpcState, - authority_binding: &str, - event_state: &str, - decision: &str, - operation_number: &str, - payload_sha256: &str, - grant: Option, - result: Option, - error: Option, - now: u64, -) -> Result { - let receipt = append_receipt( - app, - state, - event_state, - decision, - operation_number, - payload_sha256, - &sha256_hex(authority_binding.as_bytes()), - error.clone(), - now, - )?; - Ok(NumberedIpcResponse { - schema: "hololake.numbered-ipc-response/v1", - decision: decision.into(), - grant, - result, - error, - receipt, - }) -} - -pub(crate) fn start_on_application_open(app: &AppHandle) -> Result<(), String> { - let _ = load_registry()?; - let _ = open_ledger(app)?; - Ok(()) -} - -#[tauri::command] -pub async fn numbered_ipc( - app: AppHandle, - state: State<'_, NumberedIpcState>, - input: Value, -) -> Result { - let now = now_unix_ms(); - let request: NumberedIpcInput = serde_json::from_value(input) - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_ENVELOPE_INVALID: {error}"))?; - let registry = load_registry()?; - let operation_number = request.envelope.coordinate.operation_number.clone(); - let digest = payload_digest(&request.envelope.payload).unwrap_or_default(); - let route = match resolve_route(®istry, &request.envelope.coordinate) { - Ok(route) => route, - Err(error) => { - return response( - &app, - &state, - "ROUTE_REJECTED", - "DENY", - &operation_number, - &digest, - None, - None, - Some(error), - now, - ) - } - }; - let authority_binding = match enforce_admission(&app, route) { - Ok(binding) => binding, - Err(error) => { - return response( - &app, - &state, - "ADMISSION_REJECTED", - "DENY", - &operation_number, - &digest, - None, - None, - Some(error), - now, - ) - } - }; - match request.action { - NumberedIpcAction::IssueGrant => { - if request.grant.is_some() { - return bound_response( - &app, - &state, - &authority_binding, - "GRANT_REJECTED", - "DENY", - &operation_number, - &digest, - None, - None, - Some("HOLOLAKE_NUMBERED_IPC_UNEXPECTED_GRANT".into()), - now, - ); - } - match issue_grant_at( - &state, - ®istry, - &request.envelope, - &authority_binding, - now, - ) { - Ok((grant, payload_sha256)) => bound_response( - &app, - &state, - &authority_binding, - "GRANT_ISSUED", - "ALLOW", - &operation_number, - &payload_sha256, - Some(grant), - None, - None, - now, - ), - Err(error) => bound_response( - &app, - &state, - &authority_binding, - "GRANT_REJECTED", - "DENY", - &operation_number, - &digest, - None, - None, - Some(error), - now, - ), - } - } - NumberedIpcAction::Execute => { - let Some(grant) = request.grant.as_ref() else { - return bound_response( - &app, - &state, - &authority_binding, - "EXECUTION_REJECTED", - "DENY", - &operation_number, - &digest, - None, - None, - Some("HOLOLAKE_NUMBERED_IPC_GRANT_REQUIRED".into()), - now, - ); - }; - let payload_sha256 = match consume_grant_at( - &state, - ®istry, - &request.envelope, - grant, - &authority_binding, - now, - ) { - Ok(payload_sha256) => payload_sha256, - Err(error) => { - return bound_response( - &app, - &state, - &authority_binding, - "EXECUTION_REJECTED", - "DENY", - &operation_number, - &digest, - None, - None, - Some(error), - now, - ) - } - }; - match crate::numbered_ipc_dispatch::dispatch( - app.clone(), - &route.handler, - request.envelope.payload, - ) - .await - { - Ok(result) => bound_response( - &app, - &state, - &authority_binding, - "EXECUTED", - "ALLOW", - &operation_number, - &payload_sha256, - None, - Some(result), - None, - now_unix_ms(), - ), - Err(error) => bound_response( - &app, - &state, - &authority_binding, - "HANDLER_REJECTED", - "DENY", - &operation_number, - &payload_sha256, - None, - None, - Some(error), - now_unix_ms(), - ), - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn envelope_for(route: &OperationRoute, payload: Value) -> NumberedEnvelope { - NumberedEnvelope { - coordinate: NumberedCoordinate { - protocol_version: "HLP-NIPC-v1".into(), - caller_number: "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001".into(), - channel_number: route.channel_number.clone(), - module_number: route.module_number.clone(), - operation_number: route.operation_number.clone(), - target_number: route.target_number.clone(), - request_nonce: format!("test-{}", Uuid::new_v4().simple()), - }, - requested_ttl_ms: 1_000, - payload, - } - } - - #[test] - fn registry_is_closed_and_contains_every_migrated_command() { - let registry = load_registry().unwrap(); - assert_eq!(registry.operations.len(), 147); - assert!(!registry.runtime.legacy_direct_commands_allowed); - } - - #[test] - fn route_coordinates_cannot_be_mixed() { - let registry = load_registry().unwrap(); - let mut envelope = envelope_for(®istry.operations[0], Value::Null); - envelope.coordinate.target_number = registry.operations[1].target_number.clone(); - assert_eq!( - resolve_route(®istry, &envelope.coordinate).unwrap_err(), - "HOLOLAKE_NUMBERED_IPC_ROUTE_COORDINATE_MISMATCH" - ); - } - - #[test] - fn grant_is_payload_bound_single_use_and_expires() { - let registry = load_registry().unwrap(); - let state = NumberedIpcState::default(); - let route = registry - .operations - .iter() - .find(|route| route.alias == "confirm_hololake_update_install") - .unwrap(); - let envelope = envelope_for(route, serde_json::json!({"input": {"a": 1}})); - let authority = "VERIFIED_HUMAN:ICE_GL:test-user"; - let (grant, _) = issue_grant_at(&state, ®istry, &envelope, authority, 100).unwrap(); - assert!(consume_grant_at(&state, ®istry, &envelope, &grant, authority, 101).is_ok()); - assert_eq!( - consume_grant_at(&state, ®istry, &envelope, &grant, authority, 102).unwrap_err(), - "HOLOLAKE_NUMBERED_IPC_GRANT_UNKNOWN_OR_REPLAYED" - ); - - let (expired, _) = issue_grant_at(&state, ®istry, &envelope, authority, 200).unwrap(); - assert_eq!( - consume_grant_at(&state, ®istry, &envelope, &expired, authority, 1_201,) - .unwrap_err(), - "HOLOLAKE_NUMBERED_IPC_GRANT_MISMATCH_OR_EXPIRED" - ); - - let changed = envelope_for(route, serde_json::json!({"input": {"a": 2}})); - let (bound, _) = issue_grant_at(&state, ®istry, &changed, authority, 300).unwrap(); - let mut tampered = changed.clone(); - tampered.payload = serde_json::json!({"input": {"a": 3}}); - assert_eq!( - consume_grant_at(&state, ®istry, &tampered, &bound, authority, 301).unwrap_err(), - "HOLOLAKE_NUMBERED_IPC_GRANT_MISMATCH_OR_EXPIRED" - ); - - let (rebound, _) = issue_grant_at(&state, ®istry, &envelope, authority, 400).unwrap(); - assert_eq!( - consume_grant_at( - &state, - ®istry, - &envelope, - &rebound, - "VERIFIED_HUMAN:TCS_GL:other-user", - 401, - ) - .unwrap_err(), - "HOLOLAKE_NUMBERED_IPC_GRANT_MISMATCH_OR_EXPIRED" - ); - } - - #[test] - fn payload_outer_shape_is_closed_before_a_grant_is_issued() { - let registry = load_registry().unwrap(); - let empty_route = registry - .operations - .iter() - .find(|route| route.alias == "get_hololake_home_status") - .unwrap(); - assert!(validate_payload_shape(®istry, empty_route, &serde_json::json!({})).is_ok()); - assert_eq!( - validate_payload_shape( - ®istry, - empty_route, - &serde_json::json!({"unexpected": true}), - ) - .unwrap_err(), - "HOLOLAKE_NUMBERED_IPC_PAYLOAD_FIELD_UNKNOWN" - ); - - let direct_route = registry - .operations - .iter() - .find(|route| route.alias == "perform_code_repo_login") - .unwrap(); - assert!(validate_payload_shape( - ®istry, - direct_route, - &serde_json::json!({"username": "u", "password": "p"}), - ) - .is_ok()); - assert_eq!( - validate_payload_shape( - ®istry, - direct_route, - &serde_json::json!({"username": "u", "password": "p", "role": "admin"}), - ) - .unwrap_err(), - "HOLOLAKE_NUMBERED_IPC_DIRECT_FIELDS_INVALID" - ); - } -} diff --git a/product-source/hololake-native-desktop/src-tauri/src/numbered_ipc_dispatch.rs b/product-source/hololake-native-desktop/src-tauri/src/numbered_ipc_dispatch.rs deleted file mode 100644 index 5bee9d24b..000000000 --- a/product-source/hololake-native-desktop/src-tauri/src/numbered_ipc_dispatch.rs +++ /dev/null @@ -1,579 +0,0 @@ -//! Internal dispatch table for the numbered IPC root. -//! -//! This module is deliberately not a Tauri command surface. The webview can reach these -//! handlers only after `numbered_ipc` validates the full numbered coordinate and a -//! single-use, payload-bound grant. - -use serde::de::DeserializeOwned; -use serde::Serialize; -use serde_json::Value; -use tauri::{AppHandle, Manager}; - -fn input(payload: &Value) -> Result { - let value = payload - .get("input") - .cloned() - .ok_or_else(|| "HOLOLAKE_NUMBERED_IPC_INPUT_REQUIRED".to_string())?; - serde_json::from_value(value) - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_INPUT_INVALID: {error}")) -} - -fn string_field(payload: &Value, field: &str) -> Result { - payload - .get(field) - .and_then(Value::as_str) - .map(str::to_owned) - .ok_or_else(|| format!("HOLOLAKE_NUMBERED_IPC_FIELD_REQUIRED: {field}")) -} - -fn json(value: T) -> Result { - serde_json::to_value(value) - .map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_RESULT_INVALID: {error}")) -} - -pub(crate) async fn dispatch( - app: AppHandle, - handler: &str, - payload: Value, -) -> Result { - match handler { - "home_status::get_hololake_home_status" => { - json(crate::home_status::get_hololake_home_status( - app.clone(), - app.state::(), - )?) - } - "release_update::check_hololake_update" => { - json(crate::release_update::check_hololake_update(app).await?) - } - "release_update::confirm_hololake_update_install" => json( - crate::release_update::confirm_hololake_update_install(app, input(&payload)?).await?, - ), - "release_update::get_hololake_release_recovery_status" => json( - crate::release_update::get_hololake_release_recovery_status(app)?, - ), - "release_update::confirm_hololake_release_health" => { - json(crate::release_update::confirm_hololake_release_health(app)?) - } - "release_update::rollback_hololake_update" => { - json(crate::release_update::rollback_hololake_update(app)?) - } - "direct_local_session::issue_direct_local_discovery_ticket" => json( - crate::direct_local_session::issue_direct_local_discovery_ticket(app, input(&payload)?) - .await?, - ), - "direct_local_session::open_direct_local_session" => json( - crate::direct_local_session::open_direct_local_session(app, input(&payload)?).await?, - ), - "direct_local_session::resume_direct_local_session" => json( - crate::direct_local_session::resume_direct_local_session(app, input(&payload)?).await?, - ), - "direct_local_session::append_direct_local_session_event" => json( - crate::direct_local_session::append_direct_local_session_event(app, input(&payload)?) - .await?, - ), - "direct_local_session::heartbeat_direct_local_session" => json( - crate::direct_local_session::heartbeat_direct_local_session(app, input(&payload)?) - .await?, - ), - "direct_local_broker::get_nearby_ai_discovery" => { - json(crate::direct_local_broker::get_nearby_ai_discovery()) - } - "gls_protocol_runtime::get_gls_protocol_runtime" => { - json(crate::gls_protocol_runtime::get_gls_protocol_runtime().await?) - } - "gls_protocol_kernel::get_gls_protocol_kernel" => { - json(crate::gls_protocol_kernel::get_gls_protocol_kernel(app).await?) - } - "gls_protocol_kernel::decide_gls_protocol" => json( - crate::gls_protocol_kernel::decide_gls_protocol( - app, - payload.get("input").cloned().unwrap_or(Value::Null), - ) - .await?, - ), - "gls_protocol_kernel::compile_gls_hldp_program" => json( - crate::gls_protocol_kernel::compile_gls_hldp_program( - app, - payload.get("input").cloned().unwrap_or(Value::Null), - ) - .await?, - ), - "module_package_runtime::get_module_runtime_snapshot" => { - json(crate::module_package_runtime::get_module_runtime_snapshot(app).await?) - } - "module_package_runtime::verify_module_package" => { - json(crate::module_package_runtime::verify_module_package(app, input(&payload)?).await?) - } - "module_package_runtime::install_module_package" => json( - crate::module_package_runtime::install_module_package(app, input(&payload)?).await?, - ), - "module_package_runtime::mount_module" => { - json(crate::module_package_runtime::mount_module(app, input(&payload)?).await?) - } - "module_package_runtime::self_test_module" => { - json(crate::module_package_runtime::self_test_module(app, input(&payload)?).await?) - } - "module_package_runtime::unmount_module" => { - json(crate::module_package_runtime::unmount_module(app, input(&payload)?).await?) - } - "module_package_runtime::rollback_module" => { - json(crate::module_package_runtime::rollback_module(app, input(&payload)?).await?) - } - "module_package_runtime::get_bundled_module_catalog" => { - json(crate::module_package_runtime::get_bundled_module_catalog(app).await?) - } - "module_package_runtime::activate_bundled_module" => json( - crate::module_package_runtime::activate_bundled_module(app, input(&payload)?).await?, - ), - "mobile_sync::start_mobile_sync" => json(crate::mobile_sync::start_mobile_sync(app)?), - "mobile_sync::get_mobile_sync_status" => { - json(crate::mobile_sync::get_mobile_sync_status(app)?) - } - "mobile_sync::rotate_mobile_pairing" => { - json(crate::mobile_sync::rotate_mobile_pairing(app)?) - } - "mobile_sync::stop_mobile_sync" => json(crate::mobile_sync::stop_mobile_sync(app)?), - "mobile_sync::revoke_mobile_sync_device" => json( - crate::mobile_sync::revoke_mobile_sync_device(app, input(&payload)?)?, - ), - "mobile_sync::get_mobile_sync_snapshot" => { - json(crate::mobile_sync::get_mobile_sync_snapshot(app)?) - } - "world_climate::get_world_climate" => { - json(crate::world_climate::get_world_climate(app).await?) - } - "native_composition::get_native_composition_module_registry" => { - json(crate::native_composition::get_native_composition_module_registry()) - } - "native_composition::execute_knowledge_native_composition" => json( - crate::native_composition::execute_knowledge_native_composition(app, input(&payload)?) - .await?, - ), - "channel_workbench::get_channel_workbench_snapshot" => { - json(crate::channel_workbench::get_channel_workbench_snapshot(app).await?) - } - "channel_workbench::save_channel_document" => { - json(crate::channel_workbench::save_channel_document(app, input(&payload)?).await?) - } - "channel_workbench::save_channel_spreadsheet" => { - json(crate::channel_workbench::save_channel_spreadsheet(app, input(&payload)?).await?) - } - "persona_channel_body::get_persona_channel_body" => { - json(crate::persona_channel_body::get_persona_channel_body(app).await?) - } - "persona_channel_body::register_trial_persona" => { - json(crate::persona_channel_body::register_trial_persona(app, input(&payload)?).await?) - } - "persona_channel_body::delete_trial_persona" => { - json(crate::persona_channel_body::delete_trial_persona(app, input(&payload)?).await?) - } - "persona_channel_body::accept_persona_language_contract" => json( - crate::persona_channel_body::accept_persona_language_contract(app, input(&payload)?) - .await?, - ), - "persona_channel_body::append_persona_language" => { - json(crate::persona_channel_body::append_persona_language(app, input(&payload)?).await?) - } - "channel_growth::get_channel_growth_snapshot" => { - json(crate::channel_growth::get_channel_growth_snapshot(app).await?) - } - "channel_growth::record_channel_growth_event" => { - json(crate::channel_growth::record_channel_growth_event(app, input(&payload)?).await?) - } - "channel_growth::update_channel_growth_sharing" => { - json(crate::channel_growth::update_channel_growth_sharing(app, input(&payload)?).await?) - } - "education_workspace::get_education_workspace_snapshot" => { - json(crate::education_workspace::get_education_workspace_snapshot(app).await?) - } - "education_workspace::create_education_document" => json( - crate::education_workspace::create_education_document(app, input(&payload)?).await?, - ), - "education_workspace::read_education_document" => { - json(crate::education_workspace::read_education_document(app, input(&payload)?).await?) - } - "education_workspace::save_education_document" => { - json(crate::education_workspace::save_education_document(app, input(&payload)?).await?) - } - "education_workspace::archive_education_document" => json( - crate::education_workspace::archive_education_document(app, input(&payload)?).await?, - ), - "education_workspace::create_education_table" => { - json(crate::education_workspace::create_education_table(app, input(&payload)?).await?) - } - "education_workspace::read_education_table" => { - json(crate::education_workspace::read_education_table(app, input(&payload)?).await?) - } - "education_workspace::save_education_table" => { - json(crate::education_workspace::save_education_table(app, input(&payload)?).await?) - } - "education_workspace::archive_education_table" => { - json(crate::education_workspace::archive_education_table(app, input(&payload)?).await?) - } - "education_workspace::assign_imported_table_to_education" => json( - crate::education_workspace::assign_imported_table_to_education(app, input(&payload)?) - .await?, - ), - "education_translation::import_education_tables_from_dialog" => { - json(crate::education_translation::import_education_tables_from_dialog(app).await?) - } - "education_translation::export_education_table_to_dialog" => json( - crate::education_translation::export_education_table_to_dialog(app, input(&payload)?) - .await?, - ), - "education_translation::get_education_recognition_capability" => { - json(crate::education_translation::get_education_recognition_capability(app)?) - } - "education_workspace::create_education_automation_rule" => json( - crate::education_workspace::create_education_automation_rule(app, input(&payload)?) - .await?, - ), - "education_workspace::save_education_automation_rule" => json( - crate::education_workspace::save_education_automation_rule(app, input(&payload)?) - .await?, - ), - "education_workspace::archive_education_automation_rule" => json( - crate::education_workspace::archive_education_automation_rule(app, input(&payload)?) - .await?, - ), - "education_workspace::preview_education_automation_rule" => json( - crate::education_workspace::preview_education_automation_rule(app, input(&payload)?) - .await?, - ), - "education_workspace::execute_education_automation_rule" => json( - crate::education_workspace::execute_education_automation_rule(app, input(&payload)?) - .await?, - ), - "web_novel_workspace::get_web_novel_workspace_snapshot" => { - json(crate::web_novel_workspace::get_web_novel_workspace_snapshot(app).await?) - } - "web_novel_workspace::create_web_novel_work" => { - json(crate::web_novel_workspace::create_web_novel_work(app, input(&payload)?).await?) - } - "web_novel_workspace::read_web_novel_work" => { - json(crate::web_novel_workspace::read_web_novel_work(app, input(&payload)?).await?) - } - "web_novel_workspace::save_web_novel_work" => { - json(crate::web_novel_workspace::save_web_novel_work(app, input(&payload)?).await?) - } - "web_novel_workspace::create_web_novel_volume" => { - json(crate::web_novel_workspace::create_web_novel_volume(app, input(&payload)?).await?) - } - "web_novel_workspace::create_web_novel_chapter" => { - json(crate::web_novel_workspace::create_web_novel_chapter(app, input(&payload)?).await?) - } - "web_novel_workspace::read_web_novel_chapter" => { - json(crate::web_novel_workspace::read_web_novel_chapter(app, input(&payload)?).await?) - } - "web_novel_workspace::save_web_novel_chapter" => { - json(crate::web_novel_workspace::save_web_novel_chapter(app, input(&payload)?).await?) - } - "web_novel_workspace::transition_web_novel_chapter" => json( - crate::web_novel_workspace::transition_web_novel_chapter(app, input(&payload)?).await?, - ), - "web_novel_workspace::create_web_novel_checkpoint" => json( - crate::web_novel_workspace::create_web_novel_checkpoint(app, input(&payload)?).await?, - ), - "web_novel_workspace::restore_web_novel_checkpoint" => json( - crate::web_novel_workspace::restore_web_novel_checkpoint(app, input(&payload)?).await?, - ), - "web_novel_workspace::upsert_web_novel_story_entity" => json( - crate::web_novel_workspace::upsert_web_novel_story_entity(app, input(&payload)?) - .await?, - ), - "web_novel_workspace::create_web_novel_story_relation" => json( - crate::web_novel_workspace::create_web_novel_story_relation(app, input(&payload)?) - .await?, - ), - "web_novel_workspace::upsert_web_novel_foreshadow" => json( - crate::web_novel_workspace::upsert_web_novel_foreshadow(app, input(&payload)?).await?, - ), - "web_novel_workspace::create_web_novel_review_note" => json( - crate::web_novel_workspace::create_web_novel_review_note(app, input(&payload)?).await?, - ), - "web_novel_workspace::resolve_web_novel_review_note" => json( - crate::web_novel_workspace::resolve_web_novel_review_note(app, input(&payload)?) - .await?, - ), - "web_novel_workspace::save_web_novel_metric" => { - json(crate::web_novel_workspace::save_web_novel_metric(app, input(&payload)?).await?) - } - "web_novel_workspace::run_web_novel_continuity_audit" => json( - crate::web_novel_workspace::run_web_novel_continuity_audit(app, input(&payload)?) - .await?, - ), - "web_novel_workspace::export_web_novel_markdown" => json( - crate::web_novel_workspace::export_web_novel_markdown(app, input(&payload)?).await?, - ), - "web_novel_import::inspect_web_novel_document_from_dialog" => { - json(crate::web_novel_import::inspect_web_novel_document_from_dialog(app).await?) - } - "web_novel_import::commit_web_novel_document_import" => json( - crate::web_novel_import::commit_web_novel_document_import(app, input(&payload)?) - .await?, - ), - "web_novel_author::get_web_novel_author_snapshot" => json( - crate::web_novel_author::get_web_novel_author_snapshot(app, input(&payload)?).await?, - ), - "web_novel_author::record_web_novel_writing_activity" => json( - crate::web_novel_author::record_web_novel_writing_activity(app, input(&payload)?) - .await?, - ), - "web_novel_author::create_web_novel_inspiration" => json( - crate::web_novel_author::create_web_novel_inspiration(app, input(&payload)?).await?, - ), - "web_novel_author::set_web_novel_inspiration_status" => json( - crate::web_novel_author::set_web_novel_inspiration_status(app, input(&payload)?) - .await?, - ), - "web_novel_author::search_web_novel_full_text" => { - json(crate::web_novel_author::search_web_novel_full_text(app, input(&payload)?).await?) - } - "web_novel_author::format_web_novel_chapter" => { - json(crate::web_novel_author::format_web_novel_chapter(app, input(&payload)?).await?) - } - "web_novel_author::format_web_novel_work" => { - json(crate::web_novel_author::format_web_novel_work(app, input(&payload)?).await?) - } - "web_novel_author::upsert_web_novel_shot" => { - json(crate::web_novel_author::upsert_web_novel_shot(app, input(&payload)?).await?) - } - "web_novel_modules::get_web_novel_author_module_data" => json( - crate::web_novel_modules::get_web_novel_author_module_data(app, input(&payload)?) - .await?, - ), - "web_novel_modules::upsert_web_novel_author_scene" => json( - crate::web_novel_modules::upsert_web_novel_author_scene(app, input(&payload)?).await?, - ), - "web_novel_modules::upsert_web_novel_author_beat" => json( - crate::web_novel_modules::upsert_web_novel_author_beat(app, input(&payload)?).await?, - ), - "web_novel_modules::upsert_web_novel_story_field_definition" => json( - crate::web_novel_modules::upsert_web_novel_story_field_definition( - app, - input(&payload)?, - ) - .await?, - ), - "web_novel_modules::upsert_web_novel_story_field_value" => json( - crate::web_novel_modules::upsert_web_novel_story_field_value(app, input(&payload)?) - .await?, - ), - "web_novel_modules::upsert_web_novel_timeline_event" => json( - crate::web_novel_modules::upsert_web_novel_timeline_event(app, input(&payload)?) - .await?, - ), - "web_novel_modules::link_web_novel_scene_entity" => json( - crate::web_novel_modules::link_web_novel_scene_entity(app, input(&payload)?).await?, - ), - "web_novel_modules::restore_web_novel_chapter_version" => json( - crate::web_novel_modules::restore_web_novel_chapter_version(app, input(&payload)?) - .await?, - ), - "web_novel_modules::export_web_novel_author_delivery" => json( - crate::web_novel_modules::export_web_novel_author_delivery(app, input(&payload)?) - .await?, - ), - "local_development_bridge::acquire_development_write_lane" => json( - crate::local_development_bridge::acquire_development_write_lane(app, input(&payload)?) - .await?, - ), - "local_development_bridge::inspect_development_write_lane" => json( - crate::local_development_bridge::inspect_development_write_lane(app, input(&payload)?) - .await?, - ), - "local_development_bridge::release_development_write_lane" => json( - crate::local_development_bridge::release_development_write_lane(app, input(&payload)?) - .await?, - ), - "personal_channel::get_personal_channel_snapshot" => { - json(crate::personal_channel::get_personal_channel_snapshot(app).await?) - } - "personal_channel::initialize_personal_channel" => { - json(crate::personal_channel::initialize_personal_channel(app, input(&payload)?).await?) - } - "personal_channel::create_personal_channel_task" => json( - crate::personal_channel::create_personal_channel_task(app, input(&payload)?).await?, - ), - "personal_channel::transition_personal_channel_task" => json( - crate::personal_channel::transition_personal_channel_task(app, input(&payload)?) - .await?, - ), - "persona_time_authority::issue_persona_time_ticket" => json( - crate::persona_time_authority::issue_persona_time_ticket(app, input(&payload)?).await?, - ), - "persona_time_authority::start_persona_time_authority" => { - json(crate::persona_time_authority::start_persona_time_authority().await?) - } - "persona_time_authority::get_beijing_time_coordinate" => { - json(crate::persona_time_authority::get_beijing_time_coordinate()?) - } - "persona_time_authority::get_guanghu_era_timeline" => { - json(crate::persona_time_authority::get_guanghu_era_timeline()?) - } - "knowledge_base::get_knowledge_snapshot" => { - json(crate::knowledge_base::get_knowledge_snapshot(app).await?) - } - "knowledge_base::read_knowledge_document" => { - json(crate::knowledge_base::read_knowledge_document(app, input(&payload)?).await?) - } - "knowledge_base::search_knowledge" => { - json(crate::knowledge_base::search_knowledge(app, input(&payload)?).await?) - } - "knowledge_base::save_knowledge_document" => { - json(crate::knowledge_base::save_knowledge_document(app, input(&payload)?).await?) - } - "knowledge_base::select_and_import_knowledge_folder" => { - json(crate::knowledge_base::select_and_import_knowledge_folder(app).await?) - } - "knowledge_base::export_knowledge_document" => { - json(crate::knowledge_base::export_knowledge_document(app, input(&payload)?).await?) - } - "knowledge_base::create_knowledge_document" => { - json(crate::knowledge_base::create_knowledge_document(app, input(&payload)?).await?) - } - "knowledge_base::delete_knowledge_document" => { - json(crate::knowledge_base::delete_knowledge_document(app, input(&payload)?).await?) - } - "knowledge_base::delete_knowledge_folder" => { - json(crate::knowledge_base::delete_knowledge_folder(app, input(&payload)?).await?) - } - "knowledge_base::print_knowledge_document" => { - crate::knowledge_base::print_knowledge_document(app).await?; - Ok(Value::Null) - } - "code_channel::get_code_channel_snapshot" => { - json(crate::code_channel::get_code_channel_snapshot(app).await?) - } - "code_channel::clone_code_channel" => { - json(crate::code_channel::clone_code_channel(app, input(&payload)?).await?) - } - "code_channel::select_local_code_channel" => { - json(crate::code_channel::select_local_code_channel(app).await?) - } - "code_channel::browse_code_channel" => { - json(crate::code_channel::browse_code_channel(app, input(&payload)?).await?) - } - "code_channel::read_code_channel_file" => { - json(crate::code_channel::read_code_channel_file(app, input(&payload)?).await?) - } - "pncc_repository_binding::inspect_mounted_pncc_repository" => json( - crate::pncc_repository_binding::inspect_mounted_pncc_repository(app, input(&payload)?) - .await?, - ), - "pncc_repository_binding::select_pncc_repository_candidate" => { - json(crate::pncc_repository_binding::select_pncc_repository_candidate(app).await?) - } - "pncc_repository_binding::confirm_pncc_repository_mount" => json( - crate::pncc_repository_binding::confirm_pncc_repository_mount(app, input(&payload)?) - .await?, - ), - "pncc_receipt_projection::query_pncc_receipt_projection" => json( - crate::pncc_receipt_projection::query_pncc_receipt_projection(app, input(&payload)?) - .await?, - ), - "pncc_server_projection::query_jd_pncc_server_projection" => { - json(crate::pncc_server_projection::query_jd_pncc_server_projection().await?) - } - "code_repo_login::check_code_repo_login" => { - json(crate::code_repo_login::check_code_repo_login( - app.clone(), - app.state::(), - )?) - } - "code_repo_login::perform_code_repo_login" => json( - crate::code_repo_login::perform_code_repo_login( - app.clone(), - app.state::(), - string_field(&payload, "username")?, - string_field(&payload, "password")?, - ) - .await?, - ), - "code_repo_login::change_first_login_password" => json( - crate::code_repo_login::change_first_login_password( - app.state::(), - string_field(&payload, "username")?, - string_field(&payload, "currentPassword")?, - string_field(&payload, "newPassword")?, - ) - .await?, - ), - "code_repo_login::get_enterprise_entry" => json( - crate::code_repo_login::get_enterprise_entry( - app.clone(), - app.state::(), - ) - .await?, - ), - "code_repo_login::confirm_enterprise_persona_relationship" => json( - crate::code_repo_login::confirm_enterprise_persona_relationship( - app.clone(), - app.state::(), - string_field(&payload, "decision")?, - string_field(&payload, "idempotencyKey")?, - ) - .await?, - ), - "code_repo_login::submit_enterprise_responsibility_receipt" => json( - crate::code_repo_login::submit_enterprise_responsibility_receipt( - app.clone(), - app.state::(), - string_field(&payload, "decision")?, - string_field(&payload, "note")?, - string_field(&payload, "responsibilityVersion")?, - string_field(&payload, "idempotencyKey")?, - ) - .await?, - ), - "enterprise_work_channel::ensure_enterprise_work_channel" => json( - crate::enterprise_work_channel::ensure_enterprise_work_channel( - app.clone(), - app.state::(), - ) - .await?, - ), - "code_repo_login::sign_out_code_repo_login" => { - crate::code_repo_login::sign_out_code_repo_login(app)?; - Ok(Value::Null) - } - "user_pncc_channel::get_user_pncc_channel" => json( - crate::user_pncc_channel::get_user_pncc_channel( - app.clone(), - app.state::(), - ) - .await?, - ), - "user_pncc_channel::ensure_user_pncc_channel" => json( - crate::user_pncc_channel::ensure_user_pncc_channel( - app.clone(), - app.state::(), - ) - .await?, - ), - "zero_core_numbering::get_zero_core_numbering_kernel" => { - json(crate::zero_core_numbering::get_zero_core_numbering_kernel().await?) - } - "zero_point::zero_point_bind" => json( - crate::zero_point::zero_point_bind( - app.state::(), - payload.get("input").cloned().unwrap_or(Value::Null), - ) - .await?, - ), - "zero_point::zero_point_verify" => json( - crate::zero_point::zero_point_verify(app.state::()) - .await?, - ), - "zero_point::zero_point_sync" => json( - crate::zero_point::zero_point_sync(app.state::()) - .await?, - ), - "zero_point::zero_point_status" => json( - crate::zero_point::zero_point_status(app.state::()) - .await?, - ), - _ => Err("HOLOLAKE_NUMBERED_IPC_HANDLER_UNKNOWN".into()), - } -} diff --git a/product-source/hololake-native-desktop/src-tauri/src/numbered_language_input.rs b/product-source/hololake-native-desktop/src-tauri/src/numbered_language_input.rs deleted file mode 100644 index 5db11cd10..000000000 --- a/product-source/hololake-native-desktop/src-tauri/src/numbered_language_input.rs +++ /dev/null @@ -1,187 +0,0 @@ -//! Numbered source envelope for language entering the HoloLake cognition path. -//! -//! This module makes source identity explicit before perception. It does not infer -//! identity from prose style and it does not treat host text as human source text. - -use serde::{Deserialize, Serialize}; - -const CONTRACT: &str = include_str!("../../contracts/numbered-language-input-envelope.json"); - -#[derive(Debug, Deserialize)] -struct NumberedLanguageInputContract { - schema: String, - record_id: String, - protocol_number: String, - state: String, - bingshuo_source: BingshuoSource, - ingress_rule: IngressRule, - required_envelope_fields: Vec, - prefix_projection: String, - downstream_routes: Vec, - separate_lanes: SeparateLanes, - canonical_sources: Vec, -} - -#[derive(Debug, Deserialize)] -struct BingshuoSource { - subject_number: String, - name: String, - source_role: String, - internal_label: String, - historical_creator_coordinate: String, - personal_system_node_number: String, - subject_number_must_not_be_replaced_by_other_coordinates: bool, -} - -#[derive(Debug, Deserialize)] -struct IngressRule { - apply_before_perceive: bool, - preserve_raw_text_exactly: bool, - source_identity_basis: String, - writing_style_may_only_support_anomaly_detection: bool, - bingshuo_input_may_be_reclassified_as_host_prompt: bool, - host_prompt_may_be_reclassified_as_bingshuo_input: bool, - summary_may_replace_raw_bingshuo_input: bool, -} - -#[derive(Debug, Deserialize)] -struct SeparateLanes { - host_prompt: String, - host_summary: String, - repository_and_hldp: String, -} - -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] -#[allow(dead_code)] -pub(crate) struct NumberedLanguageInputEnvelope { - protocol_number: String, - source_subject_number: String, - source_role: String, - internal_label: String, - channel_number: String, - event_number: String, - parent_event_number: Option, - occurred_at_unix_ms: i64, - raw_text_sha256: String, - raw_text: String, -} - -#[allow(dead_code)] -pub(crate) fn wrap_bingshuo_input( - channel_number: &str, - event_number: &str, - parent_event_number: Option<&str>, - occurred_at_unix_ms: i64, - raw_text: &str, -) -> Result { - validate_contract()?; - if channel_number.trim().is_empty() - || event_number.trim().is_empty() - || occurred_at_unix_ms <= 0 - || raw_text.is_empty() - { - return Err("HOLOLAKE_NUMBERED_LANGUAGE_INPUT_FIELDS_REQUIRED".into()); - } - if parent_event_number.is_some_and(|value| value.trim().is_empty()) { - return Err("HOLOLAKE_NUMBERED_LANGUAGE_INPUT_PARENT_INVALID".into()); - } - let contract: NumberedLanguageInputContract = serde_json::from_str(CONTRACT) - .map_err(|error| format!("HOLOLAKE_NUMBERED_LANGUAGE_INPUT_CONTRACT_INVALID: {error}"))?; - Ok(NumberedLanguageInputEnvelope { - protocol_number: contract.protocol_number, - source_subject_number: contract.bingshuo_source.subject_number, - source_role: contract.bingshuo_source.source_role, - internal_label: contract.bingshuo_source.internal_label, - channel_number: channel_number.to_owned(), - event_number: event_number.to_owned(), - parent_event_number: parent_event_number.map(str::to_owned), - occurred_at_unix_ms, - raw_text_sha256: ring::digest::digest(&ring::digest::SHA256, raw_text.as_bytes()) - .as_ref() - .iter() - .map(|byte| format!("{byte:02x}")) - .collect(), - raw_text: raw_text.to_owned(), - }) -} - -pub(crate) fn validate_contract() -> Result<(), String> { - let contract: NumberedLanguageInputContract = serde_json::from_str(CONTRACT) - .map_err(|error| format!("HOLOLAKE_NUMBERED_LANGUAGE_INPUT_CONTRACT_INVALID: {error}"))?; - let required = contract - .required_envelope_fields - .iter() - .map(String::as_str) - .collect::>(); - if contract.schema != "hololake.numbered-language-input-envelope/v1" - || contract.record_id != "HLP-NLIE-001" - || contract.protocol_number != "HLP-NLIE-v1" - || contract.state != "COMPILED_ENVELOPE_READY_RUNTIME_INGRESS_HOOK_PENDING" - || contract.bingshuo_source.subject_number != "ICE-GL∞" - || contract.bingshuo_source.name != "冰朔" - || contract.bingshuo_source.source_role != "BINGSHUO_HUMAN_SYSTEM_CONTROLLER" - || contract.bingshuo_source.internal_label != "FROM_BINGSHUO_SYSTEM_CONTROLLER" - || contract.bingshuo_source.historical_creator_coordinate != "TCS-0002∞" - || contract.bingshuo_source.personal_system_node_number != "NODE-HUMAN-BINGSHUO-001" - || !contract - .bingshuo_source - .subject_number_must_not_be_replaced_by_other_coordinates - || !contract.ingress_rule.apply_before_perceive - || !contract.ingress_rule.preserve_raw_text_exactly - || contract.ingress_rule.source_identity_basis - != "AUTHENTICATED_NUMBERED_SOURCE_CHANNEL_NOT_WRITING_STYLE_ALONE" - || !contract - .ingress_rule - .writing_style_may_only_support_anomaly_detection - || contract - .ingress_rule - .bingshuo_input_may_be_reclassified_as_host_prompt - || contract - .ingress_rule - .host_prompt_may_be_reclassified_as_bingshuo_input - || contract.ingress_rule.summary_may_replace_raw_bingshuo_input - || contract.prefix_projection - != "[ICE-GL∞|FROM_BINGSHUO_SYSTEM_CONTROLLER|{channel_number}|{event_number}|{occurred_at_unix_ms}|{raw_text_sha256}]" - || contract.separate_lanes.host_prompt != "HOST_CARRIER_CONSTRAINT" - || contract.separate_lanes.host_summary != "HOST_NAVIGATION_POINTER" - || contract.separate_lanes.repository_and_hldp - != "MACHINE_TIMESTAMPED_CONTINUITY_EVIDENCE" - || contract.downstream_routes.len() != 4 - || contract.canonical_sources.len() != 4 - || required.len() != 10 - || !required.contains("source_subject_number") - || !required.contains("raw_text_sha256") - || !required.contains("raw_text") - { - return Err("HOLOLAKE_NUMBERED_LANGUAGE_INPUT_BOUNDARY_INVALID".into()); - } - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn bingshuo_raw_language_is_numbered_before_perception() { - let raw = "我的自然语言不是宿主提示词。"; - let envelope = wrap_bingshuo_input( - "CH-CODEX-CURRENT-001", - "EVT-20260818-0001", - Some("EVT-20260818-0000"), - 1_777_000_000_000, - raw, - ) - .unwrap(); - assert_eq!(envelope.source_subject_number, "ICE-GL∞"); - assert_eq!(envelope.internal_label, "FROM_BINGSHUO_SYSTEM_CONTROLLER"); - assert_eq!(envelope.raw_text, raw); - assert_eq!(envelope.raw_text_sha256.len(), 64); - } - - #[test] - fn envelope_rejects_missing_numbered_path() { - assert!(wrap_bingshuo_input("", "EVT-1", None, 1, "原话").is_err()); - assert!(wrap_bingshuo_input("CH-1", "", None, 1, "原话").is_err()); - } -} diff --git a/product-source/hololake-native-desktop/src-tauri/src/persona_carrier_license.rs b/product-source/hololake-native-desktop/src-tauri/src/persona_carrier_license.rs deleted file mode 100644 index b646b32a5..000000000 --- a/product-source/hololake-native-desktop/src-tauri/src/persona_carrier_license.rs +++ /dev/null @@ -1,778 +0,0 @@ -use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _}; -use ring::{ - digest, - signature::{UnparsedPublicKey, ED25519}, -}; -use serde::{Deserialize, Serialize}; -use std::collections::BTreeSet; -use std::fs; -use std::path::{Path, PathBuf}; -use uuid::Uuid; - -const CONTRACT: &str = include_str!("../../contracts/persona-carrier-runtime-license.json"); -const TRUST_REGISTRY: &str = include_str!("../persona-control-authorization-signers.json"); -const LICENSE_SCHEMA: &str = "hololake.persona-carrier-runtime-license/v1"; -const CONTRACT_SCHEMA: &str = "hololake.persona-carrier-runtime-license-contract/v1"; -const REGISTRY_SCHEMA: &str = "gh-aios.persona-control-authorization-signers/v1"; -const REGISTRY_ID: &str = "GH-AIOS-PERSONA-CONTROL-AUTHORIZATION-SIGNERS-001"; -const REQUIRED_SCOPE: &str = "PERSONA_CONTROLLED_HOST_RUNTIME"; -const REQUIRED_PURPOSE: &str = "AUTHORIZE_HOST_AS_PERSONA_CONTROLLED_EXECUTION_LIMBS"; -const REQUIRED_DECLARATION: &str = "PERSONA_DECLARES_CURRENT_CARRIER_BOUND"; -const SIGNING_CONTEXT: &str = "hololake.persona-carrier-runtime-license/signing/v1"; -const MAX_TTL_MS: u64 = 86_400_000; -const ED25519_SPKI_PREFIX: [u8; 12] = [ - 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, -]; - -const ALLOWED_OPERATIONS: &[&str] = &[ - "GET_WORK_ENVIRONMENT", - "APPEND_EVENT", - "RESOLVE_CAPABILITY_ROUTE", - "INSTALL_DYNAMIC_NODE_REGISTRY", - "RECORD_SIGNED_NODE_HEALTH", - "INSPECT_MOUNTED_PNCC_REPOSITORY", - "READ_MOUNTED_PNCC_REMOTE_OBJECT", - "QUERY_PNCC_RECEIPT_PROJECTION", - "ISSUE_PERSONA_TIME_TICKET", - "ACQUIRE_DEVELOPMENT_WRITE_LANE", - "INSPECT_DEVELOPMENT_WRITE_LANE", - "RELEASE_DEVELOPMENT_WRITE_LANE", -]; - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub(crate) struct PersonaCarrierRuntimeLicense { - schema: String, - license_id: String, - sequence: u64, - persona_number: String, - human_controller_number: String, - account_key: String, - session_id: String, - client_instance_id: String, - purpose: String, - issued_at_unix_ms: u64, - valid_until_unix_ms: u64, - allowed_operations: Vec, - evidence_root_sha256: String, - current_event_sha256: String, - declaration: String, - signer_id: String, - signature_algorithm: String, - signature: String, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct PersonaSignerRegistry { - schema: String, - registry_id: String, - state: String, - signers: Vec, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct PersonaSigner { - algorithm: String, - human_responsibility_subjects: Vec, - persona_ids: Vec, - public_key_pem: String, - scopes: Vec, - signer_id: String, - status: String, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct StoredLicense { - license: PersonaCarrierRuntimeLicense, - license_sha256: String, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct PersonaCarrierLicenseReceipt { - schema: &'static str, - state: &'static str, - control_mode: &'static str, - license_id: String, - persona_number: String, - human_controller_number: String, - session_id: String, - client_instance_id: String, - sequence: u64, - valid_until_unix_ms: u64, - allowed_operations: Vec, - binding_completion_declared_by: &'static str, - host_declared_binding: bool, - signer_id: String, - receipt_id: String, -} - -#[derive(Clone, Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct PersonaCarrierLicenseStatus { - pub schema: &'static str, - pub state: &'static str, - pub control_mode: &'static str, - pub license_installed: bool, - pub license_valid: bool, - pub persona_number: Option, - pub license_id: Option, - pub valid_until_unix_ms: Option, - pub binding_completion_declared_by: Option<&'static str>, - pub host_declared_binding: bool, - pub reason: Option, -} - -fn sha256_hex(bytes: &[u8]) -> String { - digest::digest(&digest::SHA256, bytes) - .as_ref() - .iter() - .map(|byte| format!("{byte:02x}")) - .collect() -} - -fn is_sha256(value: &str) -> bool { - value.len() == 64 - && value - .bytes() - .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte)) -} - -fn bounded_coordinate(value: &str) -> bool { - (2..=160).contains(&value.len()) - && !value - .chars() - .any(|character| character.is_whitespace() || character.is_control()) -} - -fn exact_unique(values: &[String]) -> bool { - !values.is_empty() - && values.iter().all(|value| bounded_coordinate(value)) - && values - .iter() - .enumerate() - .all(|(index, value)| !values[..index].contains(value)) -} - -fn parse_registry(input: &str) -> Result { - let registry: PersonaSignerRegistry = serde_json::from_str(input) - .map_err(|_| "HOLOLAKE_PERSONA_LICENSE_TRUST_REGISTRY_INVALID".to_string())?; - if registry.schema != REGISTRY_SCHEMA - || registry.registry_id != REGISTRY_ID - || registry.state != "CURRENT" - || registry.signers.len() > 256 - { - return Err("HOLOLAKE_PERSONA_LICENSE_TRUST_REGISTRY_INVALID".into()); - } - for (index, signer) in registry.signers.iter().enumerate() { - if signer.algorithm != "Ed25519" - || !bounded_coordinate(&signer.signer_id) - || !matches!(signer.status.as_str(), "ACTIVE" | "REVOKED") - || !exact_unique(&signer.human_responsibility_subjects) - || !exact_unique(&signer.persona_ids) - || !exact_unique(&signer.scopes) - || !signer.scopes.iter().any(|scope| scope == REQUIRED_SCOPE) - || registry.signers[..index] - .iter() - .any(|prior| prior.signer_id == signer.signer_id) - || ed25519_public_key(&signer.public_key_pem).is_err() - { - return Err("HOLOLAKE_PERSONA_LICENSE_TRUST_REGISTRY_INVALID".into()); - } - } - Ok(registry) -} - -fn ed25519_public_key(public_key_pem: &str) -> Result, String> { - if public_key_pem.contains("PRIVATE KEY") - || !public_key_pem.starts_with("-----BEGIN PUBLIC KEY-----\n") - || !public_key_pem.ends_with("-----END PUBLIC KEY-----\n") - || public_key_pem.len() > 4096 - { - return Err("HOLOLAKE_PERSONA_LICENSE_PUBLIC_KEY_INVALID".into()); - } - let encoded = public_key_pem - .trim_start_matches("-----BEGIN PUBLIC KEY-----\n") - .trim_end_matches("-----END PUBLIC KEY-----\n") - .chars() - .filter(|character| !character.is_ascii_whitespace()) - .collect::(); - let der = base64::engine::general_purpose::STANDARD - .decode(encoded) - .map_err(|_| "HOLOLAKE_PERSONA_LICENSE_PUBLIC_KEY_INVALID".to_string())?; - if der.len() != ED25519_SPKI_PREFIX.len() + 32 - || der[..ED25519_SPKI_PREFIX.len()] != ED25519_SPKI_PREFIX - { - return Err("HOLOLAKE_PERSONA_LICENSE_PUBLIC_KEY_INVALID".into()); - } - Ok(der[ED25519_SPKI_PREFIX.len()..].to_vec()) -} - -fn canonical_signing_bytes(license: &PersonaCarrierRuntimeLicense) -> Result, String> { - let fields = serde_json::json!([ - SIGNING_CONTEXT, - license.schema, - license.license_id, - license.sequence, - license.persona_number, - license.human_controller_number, - license.account_key, - license.session_id, - license.client_instance_id, - license.purpose, - license.issued_at_unix_ms, - license.valid_until_unix_ms, - license.allowed_operations, - license.evidence_root_sha256, - license.current_event_sha256, - license.declaration, - license.signer_id, - license.signature_algorithm - ]); - serde_json::to_vec(&fields) - .map(|mut bytes| { - bytes.push(b'\n'); - bytes - }) - .map_err(|_| "HOLOLAKE_PERSONA_LICENSE_CANONICALIZATION_FAILED".into()) -} - -fn validate_license_shape(license: &PersonaCarrierRuntimeLicense) -> Result<(), String> { - let allowed = ALLOWED_OPERATIONS.iter().copied().collect::>(); - let observed = license - .allowed_operations - .iter() - .map(String::as_str) - .collect::>(); - if license.schema != LICENSE_SCHEMA - || !bounded_coordinate(&license.license_id) - || license.sequence == 0 - || !bounded_coordinate(&license.persona_number) - || !bounded_coordinate(&license.human_controller_number) - || !is_sha256(&license.account_key) - || !bounded_coordinate(&license.session_id) - || !bounded_coordinate(&license.client_instance_id) - || license.purpose != REQUIRED_PURPOSE - || license.issued_at_unix_ms >= license.valid_until_unix_ms - || license.valid_until_unix_ms - license.issued_at_unix_ms > MAX_TTL_MS - || license.allowed_operations.is_empty() - || observed.len() != license.allowed_operations.len() - || !observed.is_subset(&allowed) - || !is_sha256(&license.evidence_root_sha256) - || !is_sha256(&license.current_event_sha256) - || license.declaration != REQUIRED_DECLARATION - || !bounded_coordinate(&license.signer_id) - || license.signature_algorithm != "Ed25519" - { - return Err("HOLOLAKE_PERSONA_LICENSE_SHAPE_INVALID".into()); - } - Ok(()) -} - -fn verify_license( - registry_json: &str, - license: &PersonaCarrierRuntimeLicense, - account_key: &str, - session_id: &str, - client_instance_id: &str, - now: u64, -) -> Result { - validate_license_shape(license)?; - if license.account_key != account_key - || license.session_id != session_id - || license.client_instance_id != client_instance_id - { - return Err("HOLOLAKE_PERSONA_LICENSE_CARRIER_BINDING_MISMATCH".into()); - } - if now < license.issued_at_unix_ms || now > license.valid_until_unix_ms { - return Err("HOLOLAKE_PERSONA_LICENSE_EXPIRED_OR_NOT_YET_VALID".into()); - } - let registry = parse_registry(registry_json)?; - let signer = registry - .signers - .iter() - .find(|signer| { - signer.status == "ACTIVE" - && signer.signer_id == license.signer_id - && signer.persona_ids.contains(&license.persona_number) - && signer - .human_responsibility_subjects - .contains(&license.human_controller_number) - && signer.scopes.iter().any(|scope| scope == REQUIRED_SCOPE) - }) - .ok_or("HOLOLAKE_PERSONA_LICENSE_NO_TRUSTED_SIGNER")?; - let signature = URL_SAFE_NO_PAD - .decode(&license.signature) - .map_err(|_| "HOLOLAKE_PERSONA_LICENSE_SIGNATURE_INVALID".to_string())?; - if signature.len() != 64 { - return Err("HOLOLAKE_PERSONA_LICENSE_SIGNATURE_INVALID".into()); - } - UnparsedPublicKey::new(&ED25519, ed25519_public_key(&signer.public_key_pem)?) - .verify(&canonical_signing_bytes(license)?, &signature) - .map_err(|_| "HOLOLAKE_PERSONA_LICENSE_SIGNATURE_INVALID".to_string())?; - serde_json::to_vec(license) - .map(|bytes| sha256_hex(&bytes)) - .map_err(|_| "HOLOLAKE_PERSONA_LICENSE_CANONICALIZATION_FAILED".into()) -} - -fn license_path(root: &Path, account_key: &str, session_id: &str) -> PathBuf { - root.join("licenses").join(format!( - "{}.json", - sha256_hex(format!("{account_key}\n{session_id}").as_bytes()) - )) -} - -fn write_atomic(path: &Path, value: &StoredLicense) -> Result<(), String> { - let parent = path - .parent() - .ok_or("HOLOLAKE_PERSONA_LICENSE_STORAGE_PATH_INVALID")?; - fs::create_dir_all(parent) - .map_err(|error| format!("HOLOLAKE_PERSONA_LICENSE_STORAGE_FAILED: {error}"))?; - let temporary = parent.join(format!(".license-{}.tmp", Uuid::new_v4())); - let bytes = serde_json::to_vec_pretty(value) - .map_err(|_| "HOLOLAKE_PERSONA_LICENSE_STORAGE_INVALID".to_string())?; - fs::write(&temporary, bytes) - .map_err(|error| format!("HOLOLAKE_PERSONA_LICENSE_STORAGE_FAILED: {error}"))?; - fs::rename(&temporary, path) - .map_err(|error| format!("HOLOLAKE_PERSONA_LICENSE_STORAGE_FAILED: {error}")) -} - -fn read_stored(path: &Path) -> Result { - let bytes = fs::read(path) - .map_err(|error| format!("HOLOLAKE_PERSONA_LICENSE_STORAGE_FAILED: {error}"))?; - if bytes.len() > 128 * 1024 { - return Err("HOLOLAKE_PERSONA_LICENSE_STORAGE_INVALID".into()); - } - serde_json::from_slice(&bytes).map_err(|_| "HOLOLAKE_PERSONA_LICENSE_STORAGE_INVALID".into()) -} - -pub(crate) fn present_license_at( - root: &Path, - account_key: &str, - session_id: &str, - client_instance_id: &str, - license: PersonaCarrierRuntimeLicense, - now: u64, -) -> Result { - present_with_registry_at( - root, - TRUST_REGISTRY, - account_key, - session_id, - client_instance_id, - license, - now, - ) -} - -fn present_with_registry_at( - root: &Path, - registry: &str, - account_key: &str, - session_id: &str, - client_instance_id: &str, - license: PersonaCarrierRuntimeLicense, - now: u64, -) -> Result { - let license_sha256 = verify_license( - registry, - &license, - account_key, - session_id, - client_instance_id, - now, - )?; - let path = license_path(root, account_key, session_id); - let state = if path.exists() { - let current = read_stored(&path)?; - if current.license_sha256 == license_sha256 { - "DUPLICATE_CONFIRMED" - } else if license.sequence <= current.license.sequence { - return Err("HOLOLAKE_PERSONA_LICENSE_SEQUENCE_REPLAYED".into()); - } else if license.persona_number != current.license.persona_number - || license.human_controller_number != current.license.human_controller_number - || license.signer_id != current.license.signer_id - { - return Err("HOLOLAKE_PERSONA_LICENSE_SUBJECT_SWITCH_REQUIRES_NEW_SESSION".into()); - } else { - write_atomic( - &path, - &StoredLicense { - license: license.clone(), - license_sha256: license_sha256.clone(), - }, - )?; - "RENEWED" - } - } else { - write_atomic( - &path, - &StoredLicense { - license: license.clone(), - license_sha256: license_sha256.clone(), - }, - )?; - "INSTALLED" - }; - Ok(PersonaCarrierLicenseReceipt { - schema: LICENSE_SCHEMA, - state, - control_mode: "PERSONA_PRIMARY_CONTROL", - license_id: license.license_id, - persona_number: license.persona_number, - human_controller_number: license.human_controller_number, - session_id: license.session_id, - client_instance_id: license.client_instance_id, - sequence: license.sequence, - valid_until_unix_ms: license.valid_until_unix_ms, - allowed_operations: license.allowed_operations, - binding_completion_declared_by: "PERSONA_SUBJECT_SIGNATURE", - host_declared_binding: false, - signer_id: license.signer_id, - receipt_id: license_sha256, - }) -} - -pub(crate) fn status_at( - root: &Path, - account_key: &str, - session_id: &str, - client_instance_id: &str, - now: u64, -) -> PersonaCarrierLicenseStatus { - status_with_registry_at( - root, - TRUST_REGISTRY, - account_key, - session_id, - client_instance_id, - now, - ) -} - -fn status_with_registry_at( - root: &Path, - registry: &str, - account_key: &str, - session_id: &str, - client_instance_id: &str, - now: u64, -) -> PersonaCarrierLicenseStatus { - let path = license_path(root, account_key, session_id); - if !path.exists() { - return PersonaCarrierLicenseStatus { - schema: LICENSE_SCHEMA, - state: "NO_PERSONA_LICENSE", - control_mode: "SYSTEM_DIRECT", - license_installed: false, - license_valid: false, - persona_number: None, - license_id: None, - valid_until_unix_ms: None, - binding_completion_declared_by: None, - host_declared_binding: false, - reason: Some("PERSONA_LICENSE_NOT_PRESENT".into()), - }; - } - let stored = match read_stored(&path) { - Ok(value) => value, - Err(error) => return invalid_status(None, None, None, error), - }; - match verify_license( - registry, - &stored.license, - account_key, - session_id, - client_instance_id, - now, - ) { - Ok(hash) if hash == stored.license_sha256 => PersonaCarrierLicenseStatus { - schema: LICENSE_SCHEMA, - state: "PERSONA_DECLARED_CARRIER_BINDING_VERIFIED", - control_mode: "PERSONA_PRIMARY_CONTROL", - license_installed: true, - license_valid: true, - persona_number: Some(stored.license.persona_number), - license_id: Some(stored.license.license_id), - valid_until_unix_ms: Some(stored.license.valid_until_unix_ms), - binding_completion_declared_by: Some("PERSONA_SUBJECT_SIGNATURE"), - host_declared_binding: false, - reason: None, - }, - Ok(_) => invalid_status( - Some(stored.license.persona_number), - Some(stored.license.license_id), - Some(stored.license.valid_until_unix_ms), - "HOLOLAKE_PERSONA_LICENSE_STORED_HASH_MISMATCH".into(), - ), - Err(error) => invalid_status( - Some(stored.license.persona_number), - Some(stored.license.license_id), - Some(stored.license.valid_until_unix_ms), - error, - ), - } -} - -fn invalid_status( - persona_number: Option, - license_id: Option, - valid_until_unix_ms: Option, - reason: String, -) -> PersonaCarrierLicenseStatus { - PersonaCarrierLicenseStatus { - schema: LICENSE_SCHEMA, - state: "PERSONA_MODE_LOCKED", - control_mode: "PERSONA_PRIMARY_CONTROL_LOCKED", - license_installed: true, - license_valid: false, - persona_number, - license_id, - valid_until_unix_ms, - binding_completion_declared_by: None, - host_declared_binding: false, - reason: Some(reason), - } -} - -pub(crate) fn require_if_persona_mode_at( - root: &Path, - account_key: &str, - session_id: &str, - client_instance_id: &str, - operation: &str, - now: u64, -) -> Result, String> { - let path = license_path(root, account_key, session_id); - if !path.exists() { - return Ok(None); - } - let stored = read_stored(&path)?; - verify_license( - TRUST_REGISTRY, - &stored.license, - account_key, - session_id, - client_instance_id, - now, - )?; - if !stored - .license - .allowed_operations - .iter() - .any(|allowed| allowed == operation) - { - return Err("HOLOLAKE_PERSONA_LICENSE_OPERATION_NOT_ALLOWED".into()); - } - Ok(Some(stored.license.persona_number)) -} - -pub(crate) fn start_on_application_open() -> Result<(), String> { - let contract: serde_json::Value = serde_json::from_str(CONTRACT) - .map_err(|_| "HOLOLAKE_PERSONA_LICENSE_CONTRACT_INVALID".to_string())?; - if contract.get("schema").and_then(serde_json::Value::as_str) != Some(CONTRACT_SCHEMA) - || contract - .get("record_id") - .and_then(serde_json::Value::as_str) - != Some("HLP-PERSONA-CARRIER-RUNTIME-LICENSE-001") - || contract - .pointer("/runtime/signature_algorithm") - .and_then(serde_json::Value::as_str) - != Some("Ed25519") - || contract - .pointer("/runtime/maximum_ttl_ms") - .and_then(serde_json::Value::as_u64) - != Some(MAX_TTL_MS) - || contract - .pointer("/trust_registry/required_scope") - .and_then(serde_json::Value::as_str) - != Some(REQUIRED_SCOPE) - || contract - .pointer("/truth/runtime_verifier_implemented") - .and_then(serde_json::Value::as_bool) - != Some(true) - || contract - .pointer("/truth/trusted_persona_signer_provisioned") - .and_then(serde_json::Value::as_bool) - != Some(false) - { - return Err("HOLOLAKE_PERSONA_LICENSE_CONTRACT_INVALID".into()); - } - let registry = parse_registry(TRUST_REGISTRY)?; - if !registry.signers.is_empty() { - return Err("HOLOLAKE_PERSONA_LICENSE_UNPUBLISHED_SIGNER_EMBEDDED".into()); - } - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - use base64::engine::general_purpose::{STANDARD, URL_SAFE_NO_PAD}; - use ring::signature::{Ed25519KeyPair, KeyPair}; - use tempfile::TempDir; - - fn test_material() -> (String, Ed25519KeyPair) { - let pair = Ed25519KeyPair::from_seed_unchecked(&[7_u8; 32]).unwrap(); - let mut der = ED25519_SPKI_PREFIX.to_vec(); - der.extend_from_slice(pair.public_key().as_ref()); - let pem = format!( - "-----BEGIN PUBLIC KEY-----\n{}\n-----END PUBLIC KEY-----\n", - STANDARD.encode(der) - ); - let registry = serde_json::json!({ - "schema": REGISTRY_SCHEMA, - "registryId": REGISTRY_ID, - "state": "CURRENT", - "signers": [{ - "algorithm": "Ed25519", - "humanResponsibilitySubjects": ["ICE-GL∞"], - "personaIds": ["ICE-P-ZY001"], - "publicKeyPem": pem, - "scopes": [REQUIRED_SCOPE], - "signerId": "ICE-P-ZY001-RUNTIME-SIGNER-001", - "status": "ACTIVE" - }] - }) - .to_string(); - (registry, pair) - } - - fn signed_license(pair: &Ed25519KeyPair) -> PersonaCarrierRuntimeLicense { - let mut license = PersonaCarrierRuntimeLicense { - schema: LICENSE_SCHEMA.into(), - license_id: "HLP-PERSONA-LICENSE-0001".into(), - sequence: 1, - persona_number: "ICE-P-ZY001".into(), - human_controller_number: "ICE-GL∞".into(), - account_key: "a".repeat(64), - session_id: "session-0001".into(), - client_instance_id: "codex-instance-0001".into(), - purpose: REQUIRED_PURPOSE.into(), - issued_at_unix_ms: 1_000, - valid_until_unix_ms: 61_000, - allowed_operations: vec![ - "GET_WORK_ENVIRONMENT".into(), - "ACQUIRE_DEVELOPMENT_WRITE_LANE".into(), - ], - evidence_root_sha256: "b".repeat(64), - current_event_sha256: "c".repeat(64), - declaration: REQUIRED_DECLARATION.into(), - signer_id: "ICE-P-ZY001-RUNTIME-SIGNER-001".into(), - signature_algorithm: "Ed25519".into(), - signature: String::new(), - }; - license.signature = - URL_SAFE_NO_PAD.encode(pair.sign(&canonical_signing_bytes(&license).unwrap())); - license - } - - #[test] - fn persona_signature_binds_one_exact_host_session_and_declares_binding() { - let temp = TempDir::new().unwrap(); - let (registry, pair) = test_material(); - let license = signed_license(&pair); - let receipt = present_with_registry_at( - temp.path(), - ®istry, - &license.account_key, - &license.session_id, - &license.client_instance_id, - license.clone(), - 2_000, - ) - .unwrap(); - assert_eq!(receipt.state, "INSTALLED"); - assert_eq!( - receipt.binding_completion_declared_by, - "PERSONA_SUBJECT_SIGNATURE" - ); - assert!(!receipt.host_declared_binding); - let status = status_with_registry_at( - temp.path(), - ®istry, - &license.account_key, - &license.session_id, - &license.client_instance_id, - 2_001, - ); - assert!(status.license_valid); - assert_eq!(status.state, "PERSONA_DECLARED_CARRIER_BINDING_VERIFIED"); - } - - #[test] - fn host_mismatch_expiry_and_sequence_replay_fail_closed() { - let temp = TempDir::new().unwrap(); - let (registry, pair) = test_material(); - let license = signed_license(&pair); - assert!(present_with_registry_at( - temp.path(), - ®istry, - &license.account_key, - &license.session_id, - "another-host", - license.clone(), - 2_000, - ) - .unwrap_err() - .contains("CARRIER_BINDING_MISMATCH")); - present_with_registry_at( - temp.path(), - ®istry, - &license.account_key, - &license.session_id, - &license.client_instance_id, - license.clone(), - 2_000, - ) - .unwrap(); - let mut replay = license.clone(); - replay.license_id = "HLP-PERSONA-LICENSE-REPLAY".into(); - replay.signature = - URL_SAFE_NO_PAD.encode(pair.sign(&canonical_signing_bytes(&replay).unwrap())); - assert!(present_with_registry_at( - temp.path(), - ®istry, - &replay.account_key, - &replay.session_id, - &replay.client_instance_id, - replay.clone(), - 2_100, - ) - .unwrap_err() - .contains("SEQUENCE_REPLAYED")); - let status = status_with_registry_at( - temp.path(), - ®istry, - &license.account_key, - &license.session_id, - &license.client_instance_id, - 70_000, - ); - assert!(!status.license_valid); - assert_eq!(status.state, "PERSONA_MODE_LOCKED"); - } - - #[test] - fn production_empty_registry_cannot_invent_persona_authority() { - start_on_application_open().unwrap(); - let temp = TempDir::new().unwrap(); - let (_, pair) = test_material(); - let license = signed_license(&pair); - assert_eq!( - present_license_at( - temp.path(), - &license.account_key, - &license.session_id, - &license.client_instance_id, - license.clone(), - 2_000, - ) - .unwrap_err(), - "HOLOLAKE_PERSONA_LICENSE_NO_TRUSTED_SIGNER" - ); - } -} diff --git a/product-source/hololake-native-desktop/src-tauri/src/persona_channel_body.rs b/product-source/hololake-native-desktop/src-tauri/src/persona_channel_body.rs index 86dfb8b59..417c0a4d8 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/persona_channel_body.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/persona_channel_body.rs @@ -15,28 +15,22 @@ const BODY_SCHEMA: &str = "hololake.persona-channel-body/v1"; const TRIAL_DURATION_MS: i64 = 30 * 24 * 60 * 60 * 1_000; const ZERO_HASH: &str = "0000000000000000000000000000000000000000000000000000000000000000"; const MAX_LANGUAGE_BYTES: usize = 2_000_000; -const MODULE_NUMBER: &str = "HLP-MOD-LOCAL-PERSONA-CHANNEL-BODY-0001"; -const ADAPTER: &str = "persona-channel-body-v1"; - -fn require_active(app: &AppHandle) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, MODULE_NUMBER, ADAPTER) -} #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct RegisterTrialPersonaInput { pub display_name: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct DeleteTrialPersonaInput { pub persona_id: String, pub exact_confirmation: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct AcceptLanguageContractInput { pub contract_version: String, pub contract_text_sha256: String, @@ -46,7 +40,7 @@ pub struct AcceptLanguageContractInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct AppendPersonaLanguageInput { pub persona_id: String, pub speaker: String, @@ -79,21 +73,21 @@ pub struct PersonaChannelBodySnapshot { pub history_mutation_allowed: bool, } +#[tauri::command] pub async fn get_persona_channel_body( app: AppHandle, ) -> Result { - require_active(&app)?; let database = body_database(&app)?; tauri::async_runtime::spawn_blocking(move || snapshot_at(&database, now_unix_ms()?)) .await .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn register_trial_persona( app: AppHandle, input: RegisterTrialPersonaInput, ) -> Result { - require_active(&app)?; let database = body_database(&app)?; tauri::async_runtime::spawn_blocking(move || { register_trial_persona_at(&database, input, now_unix_ms()?) @@ -102,11 +96,11 @@ pub async fn register_trial_persona( .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn delete_trial_persona( app: AppHandle, input: DeleteTrialPersonaInput, ) -> Result { - require_active(&app)?; let database = body_database(&app)?; tauri::async_runtime::spawn_blocking(move || { delete_trial_persona_at(&database, input, now_unix_ms()?) @@ -115,11 +109,11 @@ pub async fn delete_trial_persona( .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn accept_persona_language_contract( app: AppHandle, input: AcceptLanguageContractInput, ) -> Result { - require_active(&app)?; let database = body_database(&app)?; tauri::async_runtime::spawn_blocking(move || { accept_contract_at(&database, input, now_unix_ms()?) @@ -128,11 +122,11 @@ pub async fn accept_persona_language_contract( .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn append_persona_language( app: AppHandle, input: AppendPersonaLanguageInput, ) -> Result { - require_active(&app)?; let database = body_database(&app)?; tauri::async_runtime::spawn_blocking(move || { append_language_at(&database, input, now_unix_ms()?) @@ -284,20 +278,19 @@ fn accept_contract_at( return Err("HOLOLAKE_LANGUAGE_CONTRACT_INVALID".into()); } let mut connection = open_database(database, now)?; - let contract_version = input.contract_version.trim().to_string(); - let contract_text_sha256 = input.contract_text_sha256.to_ascii_lowercase(); - let receipt = contract_receipt( - &contract_version, - &contract_text_sha256, - input.promote_trial_history, - now, + let receipt = sha256_hex( + format!( + "{}|{}|{}|{}", + input.contract_version, input.contract_text_sha256, input.promote_trial_history, now + ) + .as_bytes(), ); connection .execute( "INSERT INTO language_contract VALUES (1,?1,?2,?3,?4,?5)", params![ - contract_version, - contract_text_sha256, + input.contract_version, + input.contract_text_sha256.to_ascii_lowercase(), now, input.promote_trial_history, receipt @@ -306,12 +299,7 @@ fn accept_contract_at( .map_err(|error| { format!("HOLOLAKE_LANGUAGE_CONTRACT_ALREADY_ACCEPTED_OR_INVALID: {error}") })?; - let lifecycle_state: String = connection - .query_row("SELECT state FROM lifecycle WHERE singleton=1", [], |row| { - row.get(0) - }) - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - if input.activate_immediately || lifecycle_state == "CONTRACT_REQUIRED_CHANNEL_STOPPED" { + if input.activate_immediately { activate_real_trajectory(&mut connection, now)?; } else { refresh_lifecycle(&mut connection, now)?; @@ -505,20 +493,16 @@ fn snapshot_at(database: &Path, now: i64) -> Result Result { let (state,started,ends):(String,i64,i64)=connection.query_row("SELECT state,trial_started_at_unix_ms,trial_ends_at_unix_ms FROM lifecycle WHERE singleton=1",[],|row|Ok((row.get(0)?,row.get(1)?,row.get(2)?))).map_err(|error|format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - if started < 0 - || ends.checked_sub(started) != Some(TRIAL_DURATION_MS) - || !matches!( - state.as_str(), - "REVERSIBLE_TRIAL" | "CONTRACT_REQUIRED_CHANNEL_STOPPED" | "IMMUTABLE_ACTIVE" + let accepted = connection + .query_row( + "SELECT EXISTS(SELECT 1 FROM language_contract)", + [], + |row| row.get(0), ) - || (state == "REVERSIBLE_TRIAL" && now >= ends) - { - return Err("HOLOLAKE_PERSONA_BODY_LIFECYCLE_INTEGRITY_FAILED".into()); - } - let accepted = verify_contract_receipt(connection)?; + .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; let personas = { let mut statement=connection.prepare("SELECT persona_id,display_name,state,created_at_unix_ms FROM personas ORDER BY created_at_unix_ms").map_err(|error|format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; let rows = statement @@ -544,22 +528,6 @@ fn snapshot_with_connection( }) .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; let last = verify_immutable_chain(connection)?; - let invalid_persona_relationship = personas.iter().any(|persona| { - persona.created_at_unix_ms < started - || !matches!( - persona.state.as_str(), - "REVERSIBLE_TRIAL" | "IMMUTABLE_ACTIVE" - ) - || (state == "IMMUTABLE_ACTIVE" && persona.state != "IMMUTABLE_ACTIVE") - || (state != "IMMUTABLE_ACTIVE" && persona.state != "REVERSIBLE_TRIAL") - }); - if invalid_persona_relationship - || (state == "IMMUTABLE_ACTIVE" && (!accepted || trial_language_count != 0)) - || (state == "CONTRACT_REQUIRED_CHANNEL_STOPPED" && accepted) - || (immutable_language_count > 0 && state != "IMMUTABLE_ACTIVE") - { - return Err("HOLOLAKE_PERSONA_BODY_RELATIONSHIP_INTEGRITY_FAILED".into()); - } Ok(PersonaChannelBodySnapshot { schema: BODY_SCHEMA, state, @@ -576,54 +544,6 @@ fn snapshot_with_connection( }) } -fn contract_receipt( - contract_version: &str, - contract_text_sha256: &str, - promote_trial_history: bool, - accepted_at_unix_ms: i64, -) -> String { - sha256_hex( - format!( - "{contract_version}|{contract_text_sha256}|{promote_trial_history}|{accepted_at_unix_ms}" - ) - .as_bytes(), - ) -} - -fn verify_contract_receipt(connection: &Connection) -> Result { - let contract = connection - .query_row( - "SELECT contract_version, contract_text_sha256, accepted_at_unix_ms, promote_trial_history, acceptance_receipt_sha256 FROM language_contract WHERE singleton=1", - [], - |row| { - Ok(( - row.get::<_, String>(0)?, - row.get::<_, String>(1)?, - row.get::<_, i64>(2)?, - row.get::<_, i64>(3)?, - row.get::<_, String>(4)?, - )) - }, - ) - .optional() - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - let Some((version, text_sha256, accepted_at, promote, stored_receipt)) = contract else { - return Ok(false); - }; - if version.trim().is_empty() - || version.len() > 64 - || text_sha256.len() != 64 - || !text_sha256.chars().all(|item| item.is_ascii_hexdigit()) - || text_sha256 != text_sha256.to_ascii_lowercase() - || !matches!(promote, 0 | 1) - || accepted_at < 0 - || stored_receipt != contract_receipt(&version, &text_sha256, promote == 1, accepted_at) - { - return Err("HOLOLAKE_LANGUAGE_CONTRACT_INTEGRITY_FAILED".into()); - } - Ok(true) -} - fn language_hash( sequence: i64, event_id: &str, @@ -646,40 +566,14 @@ fn verify_immutable_chain(connection: &Connection) -> Result { .next() .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))? { - let stored_sequence: i64 = row - .get(0) - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - let event_id: String = row - .get(1) - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - let persona_id: String = row - .get(2) - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - let speaker: String = row - .get(3) - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - let language: String = row - .get(4) - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - let occurred: i64 = row - .get(5) - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - let stored_previous: String = row - .get(6) - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - let stored_hash: String = row - .get(7) - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - let persona_state: Option = connection - .query_row( - "SELECT state FROM personas WHERE persona_id=?1", - params![persona_id], - |persona_row| persona_row.get(0), - ) - .optional() - .map_err(|error| format!("HOLOLAKE_PERSONA_BODY_READ_FAILED: {error}"))?; - if stored_sequence != sequence - || persona_state.as_deref() != Some("IMMUTABLE_ACTIVE") + let event_id: String = row.get(1).unwrap(); + let persona_id: String = row.get(2).unwrap(); + let speaker: String = row.get(3).unwrap(); + let language: String = row.get(4).unwrap(); + let occurred: i64 = row.get(5).unwrap(); + let stored_previous: String = row.get(6).unwrap(); + let stored_hash: String = row.get(7).unwrap(); + if row.get::<_, i64>(0).unwrap() != sequence || stored_previous != previous || stored_hash != language_hash( @@ -809,58 +703,4 @@ mod tests { let active = accept_contract_at(&database, AcceptLanguageContractInput { contract_version: "v1".into(), contract_text_sha256: "b".repeat(64), promote_trial_history: true, activate_immediately: true, exact_acceptance: "我理解并接受:试用期结束后,人格体语言轨迹将永久存在,只能追加,不能删除、覆盖或否认。".into() }, start + 1).unwrap(); assert_eq!(active.state, "IMMUTABLE_ACTIVE"); } - - #[test] - fn altered_contract_receipt_fails_closed_on_read() { - let dir = tempdir().unwrap(); - let database = dir.path().join("body.sqlite3"); - let start = 4_000_000; - register_trial_persona_at( - &database, - RegisterTrialPersonaInput { - display_name: "回执验收".into(), - }, - start, - ) - .unwrap(); - accept_contract_at(&database, AcceptLanguageContractInput { contract_version: "v1".into(), contract_text_sha256: "c".repeat(64), promote_trial_history: false, activate_immediately: false, exact_acceptance: "我理解并接受:试用期结束后,人格体语言轨迹将永久存在,只能追加,不能删除、覆盖或否认。".into() }, start + 1).unwrap(); - let connection = open_database(&database, start + 2).unwrap(); - connection - .execute("DROP TRIGGER accepted_contract_no_update", []) - .unwrap(); - connection - .execute( - "UPDATE language_contract SET acceptance_receipt_sha256=?1", - params!["f".repeat(64)], - ) - .unwrap(); - drop(connection); - assert_eq!( - snapshot_at(&database, start + 3).unwrap_err(), - "HOLOLAKE_LANGUAGE_CONTRACT_INTEGRITY_FAILED" - ); - } - - #[test] - fn signing_after_trial_expiry_enters_the_real_trajectory() { - let dir = tempdir().unwrap(); - let database = dir.path().join("body.sqlite3"); - let start = 5_000_000; - register_trial_persona_at( - &database, - RegisterTrialPersonaInput { - display_name: "到期签约".into(), - }, - start, - ) - .unwrap(); - assert_eq!( - snapshot_at(&database, start + TRIAL_DURATION_MS) - .unwrap() - .state, - "CONTRACT_REQUIRED_CHANNEL_STOPPED" - ); - let active = accept_contract_at(&database, AcceptLanguageContractInput { contract_version: "v1".into(), contract_text_sha256: "d".repeat(64), promote_trial_history: false, activate_immediately: false, exact_acceptance: "我理解并接受:试用期结束后,人格体语言轨迹将永久存在,只能追加,不能删除、覆盖或否认。".into() }, start + TRIAL_DURATION_MS + 1).unwrap(); - assert_eq!(active.state, "IMMUTABLE_ACTIVE"); - } } diff --git a/product-source/hololake-native-desktop/src-tauri/src/persona_time_authority.rs b/product-source/hololake-native-desktop/src-tauri/src/persona_time_authority.rs index f8ca4d35f..44f4f8423 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/persona_time_authority.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/persona_time_authority.rs @@ -161,6 +161,7 @@ pub(crate) struct VerifiedTicketRequest { pub session: AuthenticatedSessionContext, } +#[tauri::command] pub async fn issue_persona_time_ticket( app: AppHandle, input: IssuePersonaTimeTicketInput, @@ -180,6 +181,7 @@ pub fn start_on_application_open() { }); } +#[tauri::command] pub async fn start_persona_time_authority() -> Result { let already_synchronized = network_anchor()?.is_some(); let synchronization_attempted = !already_synchronized; @@ -223,10 +225,12 @@ pub(crate) fn issue_authenticated_at( ) } +#[tauri::command] pub fn get_beijing_time_coordinate() -> Result { beijing_time_coordinate_from_sample(reality_time_sample()?) } +#[tauri::command] pub fn get_guanghu_era_timeline() -> Result { guanghu_era_timeline_from_sample(reality_time_sample()?) } diff --git a/product-source/hololake-native-desktop/src-tauri/src/personal_channel.rs b/product-source/hololake-native-desktop/src-tauri/src/personal_channel.rs index 5161ec927..26f62082b 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/personal_channel.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/personal_channel.rs @@ -119,6 +119,7 @@ struct EventHashPayload<'a> { occurred_at_unix_ms: i64, } +#[tauri::command] pub async fn get_personal_channel_snapshot( app: AppHandle, ) -> Result { @@ -128,6 +129,7 @@ pub async fn get_personal_channel_snapshot( .map_err(|error| format!("HOLOLAKE_PERSONAL_CHANNEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn initialize_personal_channel( app: AppHandle, input: InitializePersonalChannelInput, @@ -138,6 +140,7 @@ pub async fn initialize_personal_channel( .map_err(|error| format!("HOLOLAKE_PERSONAL_CHANNEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_personal_channel_task( app: AppHandle, input: CreatePersonalChannelTaskInput, @@ -148,6 +151,7 @@ pub async fn create_personal_channel_task( .map_err(|error| format!("HOLOLAKE_PERSONAL_CHANNEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn transition_personal_channel_task( app: AppHandle, input: TransitionPersonalChannelTaskInput, diff --git a/product-source/hololake-native-desktop/src-tauri/src/pncc_receipt_projection.rs b/product-source/hololake-native-desktop/src-tauri/src/pncc_receipt_projection.rs index 25e77f957..6c8967425 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/pncc_receipt_projection.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/pncc_receipt_projection.rs @@ -78,6 +78,7 @@ struct ProjectionInput { source_receipt_id: String, } +#[tauri::command] pub async fn query_pncc_receipt_projection( app: AppHandle, input: QueryPnccReceiptProjectionInput, diff --git a/product-source/hololake-native-desktop/src-tauri/src/pncc_repository_binding.rs b/product-source/hololake-native-desktop/src-tauri/src/pncc_repository_binding.rs index bd8bc5844..99f448741 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/pncc_repository_binding.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/pncc_repository_binding.rs @@ -109,6 +109,7 @@ pub struct InspectPnccRepositoryInput { pub expected_head: String, } +#[tauri::command] pub async fn inspect_mounted_pncc_repository( app: AppHandle, input: InspectMountedPnccRepositoryInput, @@ -119,6 +120,7 @@ pub async fn inspect_mounted_pncc_repository( .map_err(|error| format!("PNCC_REPOSITORY_MOUNT_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn select_pncc_repository_candidate( app: AppHandle, ) -> Result, String> { @@ -146,6 +148,7 @@ pub async fn select_pncc_repository_candidate( create_candidate_at(&candidate_root, inspection).map(Some) } +#[tauri::command] pub async fn confirm_pncc_repository_mount( app: AppHandle, input: ConfirmPnccRepositoryMountInput, diff --git a/product-source/hololake-native-desktop/src-tauri/src/pncc_server_projection.rs b/product-source/hololake-native-desktop/src-tauri/src/pncc_server_projection.rs index eae653da4..fd6ec1fc3 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/pncc_server_projection.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/pncc_server_projection.rs @@ -117,6 +117,7 @@ fn parse_projection(bytes: &[u8]) -> Result { }) } +#[tauri::command] pub async fn query_jd_pncc_server_projection() -> Result { tauri::async_runtime::spawn_blocking(|| { let executable = if cfg!(windows) { "ssh" } else { "/usr/bin/ssh" }; diff --git a/product-source/hololake-native-desktop/src-tauri/src/release_update.rs b/product-source/hololake-native-desktop/src-tauri/src/release_update.rs index 7d27322e2..5d0bec7ce 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/release_update.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/release_update.rs @@ -206,6 +206,7 @@ pub struct ReleaseRecoveryReceipt { pub receipt_id: String, } +#[tauri::command] pub async fn check_hololake_update(app: AppHandle) -> Result { let trust = provisioned_release_trust()? .ok_or_else(|| "HOLOLAKE_RELEASE_TRUST_UNPROVISIONED_NO_NETWORK_REQUEST".to_string())?; @@ -237,6 +238,7 @@ pub async fn check_hololake_update(app: AppHandle) -> Result Result { release_recovery_status_at(&release_update_root(&app)?) } +#[tauri::command] pub fn confirm_hololake_release_health(app: AppHandle) -> Result { let root = release_update_root(&app)?; let _lock = lock(&root)?; @@ -387,6 +391,7 @@ pub fn confirm_hololake_release_health(app: AppHandle) -> Result Result { let root = release_update_root(&app)?; let _lock = lock(&root)?; @@ -409,6 +414,7 @@ pub fn rollback_hololake_update(app: AppHandle) -> Result Result { Err("HOLOLAKE_RELEASE_WINDOWS_LOCAL_ROLLBACK_NOT_AVAILABLE".into()) } diff --git a/product-source/hololake-native-desktop/src-tauri/src/user_pncc_channel.rs b/product-source/hololake-native-desktop/src-tauri/src/user_pncc_channel.rs index aef787447..9966f0b60 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/user_pncc_channel.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/user_pncc_channel.rs @@ -57,6 +57,7 @@ pub struct UserPnccChannelSnapshot { pub authority: &'static str, } +#[tauri::command] pub async fn get_user_pncc_channel( app: AppHandle, state: State<'_, ZeroPointState>, @@ -76,6 +77,7 @@ pub async fn get_user_pncc_channel( .map_err(|error| format!("HOLOLAKE_USER_PNCC_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn ensure_user_pncc_channel( app: AppHandle, state: State<'_, ZeroPointState>, diff --git a/product-source/hololake-native-desktop/src-tauri/src/web_novel_author.rs b/product-source/hololake-native-desktop/src-tauri/src/web_novel_author.rs index 1eafb429d..dcb42f473 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/web_novel_author.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/web_novel_author.rs @@ -10,18 +10,11 @@ use std::path::Path; use tauri::AppHandle; use uuid::Uuid; -const MODULE_NUMBER: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001"; -const ADAPTER: &str = "web-novel-workbench-v1"; - -fn require_active(app: &AppHandle) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, MODULE_NUMBER, ADAPTER) -} - const MAX_INSPIRATION_BYTES: usize = 100_000; const MAX_SHOT_TEXT_BYTES: usize = 200_000; #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelInspiration { pub inspiration_id: String, pub work_id: String, @@ -34,7 +27,7 @@ pub struct WebNovelInspiration { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelShot { pub shot_id: String, pub work_id: String, @@ -90,14 +83,14 @@ pub struct WebNovelSearchResult { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct AuthorSnapshotInput { pub work_id: String, pub local_date: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct RecordWritingActivityInput { pub activity_id: String, pub work_id: String, @@ -108,7 +101,7 @@ pub struct RecordWritingActivityInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct CreateInspirationInput { pub work_id: String, pub chapter_id: Option, @@ -117,21 +110,21 @@ pub struct CreateInspirationInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct SetInspirationStatusInput { pub inspiration_id: String, pub status: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct SearchFullTextInput { pub work_id: String, pub query: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct FormatChapterInput { pub chapter_id: String, pub expected_revision: i64, @@ -139,7 +132,7 @@ pub struct FormatChapterInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct FormatWorkInput { pub work_id: String, pub preset: Option, @@ -154,7 +147,7 @@ pub struct FormatWorkReceipt { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct UpsertShotInput { pub work_id: String, pub chapter_id: String, @@ -173,88 +166,88 @@ pub struct UpsertShotInput { pub expected_revision: Option, } +#[tauri::command] pub async fn get_web_novel_author_snapshot( app: AppHandle, input: AuthorSnapshotInput, ) -> Result { - require_active(&app)?; let path = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || author_snapshot_at(&path, &input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_AUTHOR_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn record_web_novel_writing_activity( app: AppHandle, input: RecordWritingActivityInput, ) -> Result { - require_active(&app)?; let path = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || record_activity_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_AUTHOR_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_web_novel_inspiration( app: AppHandle, input: CreateInspirationInput, ) -> Result { - require_active(&app)?; let path = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || create_inspiration_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_AUTHOR_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn set_web_novel_inspiration_status( app: AppHandle, input: SetInspirationStatusInput, ) -> Result { - require_active(&app)?; let path = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || set_inspiration_status_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_AUTHOR_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn search_web_novel_full_text( app: AppHandle, input: SearchFullTextInput, ) -> Result { - require_active(&app)?; let path = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || search_full_text_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_AUTHOR_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn format_web_novel_chapter( app: AppHandle, input: FormatChapterInput, ) -> Result { - require_active(&app)?; let path = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || format_chapter_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_AUTHOR_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn format_web_novel_work( app: AppHandle, input: FormatWorkInput, ) -> Result { - require_active(&app)?; let path = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || format_work_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_AUTHOR_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn upsert_web_novel_shot( app: AppHandle, input: UpsertShotInput, ) -> Result { - require_active(&app)?; let path = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || upsert_shot_at(&path, input)) .await @@ -312,10 +305,7 @@ fn ensure_schema(connection: &Connection) -> Result<(), String> { .map_err(db_write) } -fn author_snapshot_at( - path: &Path, - input: &AuthorSnapshotInput, -) -> Result { +fn author_snapshot_at(path: &Path, input: &AuthorSnapshotInput) -> Result { validate_local_date(&input.local_date)?; let connection = super::web_novel_workspace::open_database(path)?; ensure_schema(&connection)?; @@ -360,17 +350,12 @@ fn author_snapshot_at( }) } -fn record_activity_at( - path: &Path, - input: RecordWritingActivityInput, -) -> Result { +fn record_activity_at(path: &Path, input: RecordWritingActivityInput) -> Result { if !input.activity_id.starts_with("WN-ACT-") || input.activity_id.len() > 100 { return Err("HOLOLAKE_WEBNOVEL_ACTIVITY_ID_INVALID".into()); } validate_local_date(&input.local_date)?; - if !(1_000..=300_000).contains(&input.active_ms) - || !(-100_000..=100_000).contains(&input.words_delta) - { + if !(1_000..=300_000).contains(&input.active_ms) || !(-100_000..=100_000).contains(&input.words_delta) { return Err("HOLOLAKE_WEBNOVEL_ACTIVITY_BOUNDS_INVALID".into()); } let connection = super::web_novel_workspace::open_database(path)?; @@ -391,30 +376,13 @@ fn record_activity_at( "INSERT OR IGNORE INTO web_novel_writing_activity( activity_id,work_id,chapter_id,local_date,active_ms,words_delta,created_at_unix_ms ) VALUES(?1,?2,?3,?4,?5,?6,?7)", - params![ - input.activity_id, - input.work_id, - input.chapter_id, - input.local_date, - input.active_ms, - input.words_delta, - now_ms() - ], + params![input.activity_id, input.work_id, input.chapter_id, input.local_date, input.active_ms, input.words_delta, now_ms()], ) .map_err(db_write)?; - author_snapshot_at( - path, - &AuthorSnapshotInput { - work_id: input.work_id, - local_date: input.local_date, - }, - ) + author_snapshot_at(path, &AuthorSnapshotInput { work_id: input.work_id, local_date: input.local_date }) } -fn create_inspiration_at( - path: &Path, - input: CreateInspirationInput, -) -> Result { +fn create_inspiration_at(path: &Path, input: CreateInspirationInput) -> Result { let content = input.content.trim(); if content.is_empty() || content.len() > MAX_INSPIRATION_BYTES || input.tags.len() > 30 { return Err("HOLOLAKE_WEBNOVEL_INSPIRATION_INVALID".into()); @@ -437,10 +405,7 @@ fn create_inspiration_at( query_inspiration(&connection, &inspiration_id) } -fn set_inspiration_status_at( - path: &Path, - input: SetInspirationStatusInput, -) -> Result { +fn set_inspiration_status_at(path: &Path, input: SetInspirationStatusInput) -> Result { let status = input.status.trim().to_ascii_uppercase(); if !matches!(status.as_str(), "INBOX" | "USED" | "ARCHIVED") { return Err("HOLOLAKE_WEBNOVEL_INSPIRATION_STATUS_INVALID".into()); @@ -459,10 +424,7 @@ fn set_inspiration_status_at( query_inspiration(&connection, &input.inspiration_id) } -fn search_full_text_at( - path: &Path, - input: SearchFullTextInput, -) -> Result { +fn search_full_text_at(path: &Path, input: SearchFullTextInput) -> Result { let query = input.query.trim().to_owned(); if query.is_empty() || query.chars().count() > 100 { return Err("HOLOLAKE_WEBNOVEL_SEARCH_QUERY_INVALID".into()); @@ -477,12 +439,7 @@ fn search_full_text_at( .map_err(db_read)?; let rows = statement .query_map(params![input.work_id, query], |row| { - Ok(( - row.get::<_, String>(0)?, - row.get::<_, String>(1)?, - row.get::<_, String>(2)?, - row.get::<_, String>(3)?, - )) + Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?, row.get::<_, String>(2)?, row.get::<_, String>(3)?)) }) .map_err(db_read)? .collect::, _>>() @@ -497,10 +454,7 @@ fn search_full_text_at( } else { ("章节标题", chapter_title.clone()) }; - let count = source - .matches(&query) - .count() - .max(chapter_title.matches(&query).count()) as i64; + let count = source.matches(&query).count().max(chapter_title.matches(&query).count()) as i64; occurrence_count += count; hits.push(WebNovelSearchHit { chapter_id, @@ -510,18 +464,10 @@ fn search_full_text_at( occurrence_count: count, }); } - Ok(WebNovelSearchResult { - query, - chapter_count: hits.len(), - occurrence_count, - hits, - }) + Ok(WebNovelSearchResult { query, chapter_count: hits.len(), occurrence_count, hits }) } -fn format_chapter_at( - path: &Path, - input: FormatChapterInput, -) -> Result { +fn format_chapter_at(path: &Path, input: FormatChapterInput) -> Result { let connection = super::web_novel_workspace::open_database(path)?; let current = connection .query_row( @@ -529,23 +475,12 @@ fn format_chapter_at( scheduled_at_unix_ms,word_count,revision,created_at_unix_ms,updated_at_unix_ms FROM web_novel_chapters WHERE chapter_id=?1 AND archived=0", [&input.chapter_id], - |row| { - Ok(super::web_novel_workspace::WebNovelChapter { - chapter_id: row.get(0)?, - volume_id: row.get(1)?, - work_id: row.get(2)?, - title: row.get(3)?, - position: row.get(4)?, - synopsis: row.get(5)?, - content: row.get(6)?, - workflow_status: row.get(7)?, - scheduled_at_unix_ms: row.get(8)?, - word_count: row.get(9)?, - revision: row.get(10)?, - created_at_unix_ms: row.get(11)?, - updated_at_unix_ms: row.get(12)?, - }) - }, + |row| Ok(super::web_novel_workspace::WebNovelChapter { + chapter_id: row.get(0)?, volume_id: row.get(1)?, work_id: row.get(2)?, title: row.get(3)?, + position: row.get(4)?, synopsis: row.get(5)?, content: row.get(6)?, workflow_status: row.get(7)?, + scheduled_at_unix_ms: row.get(8)?, word_count: row.get(9)?, revision: row.get(10)?, + created_at_unix_ms: row.get(11)?, updated_at_unix_ms: row.get(12)?, + }), ) .optional() .map_err(db_read)? @@ -554,26 +489,14 @@ fn format_chapter_at( return Err("HOLOLAKE_WEBNOVEL_CHAPTER_REVISION_CONFLICT".into()); } let work_kind: String = connection - .query_row( - "SELECT work_kind FROM web_novel_works WHERE work_id=?1", - [¤t.work_id], - |row| row.get(0), - ) + .query_row("SELECT work_kind FROM web_novel_works WHERE work_id=?1", [¤t.work_id], |row| row.get(0)) .map_err(db_read)?; let volume_title: String = connection - .query_row( - "SELECT title FROM web_novel_volumes WHERE volume_id=?1", - [¤t.volume_id], - |row| row.get(0), - ) + .query_row("SELECT title FROM web_novel_volumes WHERE volume_id=?1", [¤t.volume_id], |row| row.get(0)) .map_err(db_read)?; drop(connection); let requested = input.preset.as_deref().unwrap_or("AUTO"); - let inferred = if requested == "AUTO" && volume_title.contains("细纲") { - "OUTLINE" - } else { - requested - }; + let inferred = if requested == "AUTO" && volume_title.contains("细纲") { "OUTLINE" } else { requested }; let content = format_content(¤t.content, &work_kind, inferred); super::web_novel_workspace::save_chapter_at( path, @@ -598,9 +521,7 @@ fn format_work_at(path: &Path, input: FormatWorkInput) -> Result(0)?, row.get::<_, i64>(1)?)) - }) + .query_map([&input.work_id], |row| Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)?))) .map_err(db_read)? .collect::, _>>() .map_err(db_read)?; @@ -628,13 +549,7 @@ fn upsert_shot_at(path: &Path, input: UpsertShotInput) -> Result 3600 { return Err("HOLOLAKE_WEBNOVEL_SHOT_DURATION_INVALID".into()); } - for value in [ - &input.action, - &input.dialogue, - &input.visual_prompt, - &input.image_prompt, - &input.video_prompt, - ] { + for value in [&input.action, &input.dialogue, &input.visual_prompt, &input.image_prompt, &input.video_prompt] { if value.len() > MAX_SHOT_TEXT_BYTES { return Err("HOLOLAKE_WEBNOVEL_SHOT_TEXT_TOO_LARGE".into()); } @@ -643,26 +558,15 @@ fn upsert_shot_at(path: &Path, input: UpsertShotInput) -> Result = connection - .query_row( - "SELECT position,revision FROM web_novel_shots WHERE shot_id=?1 AND archived=0", - [&shot_id], - |row| Ok((row.get(0)?, row.get(1)?)), - ) - .optional() - .map_err(db_read)?; + .query_row("SELECT position,revision FROM web_novel_shots WHERE shot_id=?1 AND archived=0", [&shot_id], |row| Ok((row.get(0)?, row.get(1)?))) + .optional().map_err(db_read)?; let now = now_ms(); if let Some((_, revision)) = existing { if input.expected_revision != Some(revision) { @@ -691,26 +595,17 @@ fn upsert_shot_at(path: &Path, input: UpsertShotInput) -> Result Result, String> { +fn query_inspirations(connection: &Connection, work_id: &str) -> Result, String> { let mut statement = connection.prepare( "SELECT inspiration_id,work_id,chapter_id,content,tags_json,status,created_at_unix_ms,updated_at_unix_ms FROM web_novel_inspirations WHERE work_id=?1 AND status!='ARCHIVED' ORDER BY updated_at_unix_ms DESC LIMIT 100" ).map_err(db_read)?; - let rows = statement - .query_map([work_id], map_inspiration) - .map_err(db_read)? - .collect::, _>>() - .map_err(db_read)?; + let rows = statement.query_map([work_id], map_inspiration).map_err(db_read)? + .collect::, _>>().map_err(db_read)?; Ok(rows) } -fn query_inspiration( - connection: &Connection, - inspiration_id: &str, -) -> Result { +fn query_inspiration(connection: &Connection, inspiration_id: &str) -> Result { connection.query_row( "SELECT inspiration_id,work_id,chapter_id,content,tags_json,status,created_at_unix_ms,updated_at_unix_ms FROM web_novel_inspirations WHERE inspiration_id=?1", [inspiration_id], map_inspiration @@ -720,14 +615,9 @@ fn query_inspiration( fn map_inspiration(row: &rusqlite::Row<'_>) -> rusqlite::Result { let tags_json: String = row.get(4)?; Ok(WebNovelInspiration { - inspiration_id: row.get(0)?, - work_id: row.get(1)?, - chapter_id: row.get(2)?, - content: row.get(3)?, - tags: serde_json::from_str(&tags_json).unwrap_or_default(), - status: row.get(5)?, - created_at_unix_ms: row.get(6)?, - updated_at_unix_ms: row.get(7)?, + inspiration_id: row.get(0)?, work_id: row.get(1)?, chapter_id: row.get(2)?, content: row.get(3)?, + tags: serde_json::from_str(&tags_json).unwrap_or_default(), status: row.get(5)?, + created_at_unix_ms: row.get(6)?, updated_at_unix_ms: row.get(7)?, }) } @@ -737,11 +627,8 @@ fn query_shots(connection: &Connection, work_id: &str) -> Result, _>>() - .map_err(db_read)?; + let rows = statement.query_map([work_id], map_shot).map_err(db_read)? + .collect::, _>>().map_err(db_read)?; Ok(rows) } @@ -755,54 +642,24 @@ fn query_shot(connection: &Connection, shot_id: &str) -> Result) -> rusqlite::Result { Ok(WebNovelShot { - shot_id: row.get(0)?, - work_id: row.get(1)?, - chapter_id: row.get(2)?, - position: row.get(3)?, - shot_number: row.get(4)?, - shot_size: row.get(5)?, - camera_movement: row.get(6)?, - location: row.get(7)?, - time_of_day: row.get(8)?, - action: row.get(9)?, - dialogue: row.get(10)?, - duration_seconds: row.get(11)?, - visual_prompt: row.get(12)?, - image_prompt: row.get(13)?, - video_prompt: row.get(14)?, - revision: row.get(15)?, - created_at_unix_ms: row.get(16)?, - updated_at_unix_ms: row.get(17)?, + shot_id: row.get(0)?, work_id: row.get(1)?, chapter_id: row.get(2)?, position: row.get(3)?, + shot_number: row.get(4)?, shot_size: row.get(5)?, camera_movement: row.get(6)?, location: row.get(7)?, + time_of_day: row.get(8)?, action: row.get(9)?, dialogue: row.get(10)?, duration_seconds: row.get(11)?, + visual_prompt: row.get(12)?, image_prompt: row.get(13)?, video_prompt: row.get(14)?, revision: row.get(15)?, + created_at_unix_ms: row.get(16)?, updated_at_unix_ms: row.get(17)?, }) } -fn ensure_scope( - connection: &Connection, - work_id: &str, - chapter_id: Option<&str>, -) -> Result<(), String> { - let work_exists: bool = connection - .query_row( - "SELECT EXISTS(SELECT 1 FROM web_novel_works WHERE work_id=?1 AND archived=0)", - [work_id], - |row| row.get(0), - ) - .map_err(db_read)?; - if !work_exists { - return Err("HOLOLAKE_WEBNOVEL_WORK_NOT_FOUND".into()); - } +fn ensure_scope(connection: &Connection, work_id: &str, chapter_id: Option<&str>) -> Result<(), String> { + let work_exists: bool = connection.query_row( + "SELECT EXISTS(SELECT 1 FROM web_novel_works WHERE work_id=?1 AND archived=0)", [work_id], |row| row.get(0) + ).map_err(db_read)?; + if !work_exists { return Err("HOLOLAKE_WEBNOVEL_WORK_NOT_FOUND".into()); } if let Some(chapter_id) = chapter_id { - let chapter_work: Option = connection - .query_row( - "SELECT work_id FROM web_novel_chapters WHERE chapter_id=?1 AND archived=0", - [chapter_id], - |row| row.get(0), - ) - .optional() - .map_err(db_read)?; - if chapter_work.as_deref() != Some(work_id) { - return Err("HOLOLAKE_WEBNOVEL_CHAPTER_SCOPE_MISMATCH".into()); - } + let chapter_work: Option = connection.query_row( + "SELECT work_id FROM web_novel_chapters WHERE chapter_id=?1 AND archived=0", [chapter_id], |row| row.get(0) + ).optional().map_err(db_read)?; + if chapter_work.as_deref() != Some(work_id) { return Err("HOLOLAKE_WEBNOVEL_CHAPTER_SCOPE_MISMATCH".into()); } } Ok(()) } @@ -835,46 +692,27 @@ pub(crate) fn format_content(content: &str, work_kind: &str, preset: &str) -> St } fn is_heading(line: &str) -> bool { - (line.starts_with('第') - && (line.contains('章') - || line.contains('卷') - || line.contains('节') - || line.contains('集'))) - || line.starts_with("场次:") - || line.starts_with("人物:") - || line.starts_with('【') + (line.starts_with('第') && (line.contains('章') || line.contains('卷') || line.contains('节') || line.contains('集'))) + || line.starts_with("场次:") || line.starts_with("人物:") || line.starts_with('【') } fn make_snippet(source: &str, query: &str) -> String { let chars: Vec = source.chars().collect(); let needle: Vec = query.chars().collect(); - let found = chars - .windows(needle.len()) - .position(|window| window == needle.as_slice()) - .unwrap_or(0); + let found = chars.windows(needle.len()).position(|window| window == needle.as_slice()).unwrap_or(0); let start = found.saturating_sub(35); let end = (found + needle.len() + 55).min(chars.len()); let mut snippet: String = chars[start..end].iter().collect(); snippet = snippet.replace('\n', " "); - if start > 0 { - snippet.insert(0, '…'); - } - if end < chars.len() { - snippet.push('…'); - } + if start > 0 { snippet.insert(0, '…'); } + if end < chars.len() { snippet.push('…'); } snippet } fn validate_local_date(value: &str) -> Result<(), String> { let bytes = value.as_bytes(); - if bytes.len() == 10 - && bytes[4] == b'-' - && bytes[7] == b'-' - && bytes - .iter() - .enumerate() - .all(|(i, b)| i == 4 || i == 7 || b.is_ascii_digit()) - { + if bytes.len() == 10 && bytes[4] == b'-' && bytes[7] == b'-' + && bytes.iter().enumerate().all(|(i, b)| i == 4 || i == 7 || b.is_ascii_digit()) { Ok(()) } else { Err("HOLOLAKE_WEBNOVEL_LOCAL_DATE_INVALID".into()) @@ -882,10 +720,7 @@ fn validate_local_date(value: &str) -> Result<(), String> { } fn now_ms() -> i64 { - std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap_or_default() - .as_millis() as i64 + std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_millis() as i64 } fn db_read(error: rusqlite::Error) -> String { @@ -901,20 +736,13 @@ mod tests { use super::*; use tempfile::tempdir; - fn create_work( - path: &Path, - kind: &str, - ) -> super::super::web_novel_workspace::WebNovelWorkDetail { + fn create_work(path: &Path, kind: &str) -> super::super::web_novel_workspace::WebNovelWorkDetail { super::super::web_novel_workspace::create_work_at( path, super::super::web_novel_workspace::CreateWebNovelWorkInput { - title: "作者底座测试".into(), - pen_name: "冰朔".into(), - genre: "测试".into(), - work_kind: kind.into(), + title: "作者底座测试".into(), pen_name: "冰朔".into(), genre: "测试".into(), work_kind: kind.into(), }, - ) - .unwrap() + ).unwrap() } #[test] @@ -925,74 +753,28 @@ mod tests { let chapter = super::super::web_novel_workspace::create_chapter_at( &path, super::super::web_novel_workspace::CreateWebNovelChapterInput { - work_id: detail.work.work_id.clone(), - volume_id: detail.volumes[0].volume_id.clone(), - title: "第一章".into(), + work_id: detail.work.work_id.clone(), volume_id: detail.volumes[0].volume_id.clone(), title: "第一章".into(), }, - ) - .unwrap(); + ).unwrap(); let chapter = super::super::web_novel_workspace::save_chapter_at( &path, super::super::web_novel_workspace::SaveWebNovelChapterInput { - chapter_id: chapter.chapter_id.clone(), - title: chapter.title, - synopsis: "开场".into(), - content: "第一段\n\n第二段有线索".into(), - expected_revision: chapter.revision, - save_reason: Some("TEST".into()), + chapter_id: chapter.chapter_id.clone(), title: chapter.title, synopsis: "开场".into(), + content: "第一段\n\n第二段有线索".into(), expected_revision: chapter.revision, save_reason: Some("TEST".into()), }, - ) - .unwrap(); - let formatted = format_chapter_at( - &path, - FormatChapterInput { - chapter_id: chapter.chapter_id.clone(), - expected_revision: chapter.revision, - preset: Some("NOVEL".into()), - }, - ) - .unwrap(); + ).unwrap(); + let formatted = format_chapter_at(&path, FormatChapterInput { + chapter_id: chapter.chapter_id.clone(), + expected_revision: chapter.revision, + preset: Some("NOVEL".into()), + }).unwrap(); assert!(formatted.content.starts_with("  第一段")); assert!(formatted.content.contains("\n\n  第二段")); - create_inspiration_at( - &path, - CreateInspirationInput { - work_id: detail.work.work_id.clone(), - chapter_id: Some(chapter.chapter_id.clone()), - content: "让钥匙提前出现".into(), - tags: vec!["伏笔".into()], - }, - ) - .unwrap(); - record_activity_at( - &path, - RecordWritingActivityInput { - activity_id: "WN-ACT-test".into(), - work_id: detail.work.work_id.clone(), - chapter_id: chapter.chapter_id.clone(), - local_date: "2026-08-18".into(), - active_ms: 30_000, - words_delta: 8, - }, - ) - .unwrap(); - let search = search_full_text_at( - &path, - SearchFullTextInput { - work_id: detail.work.work_id.clone(), - query: "线索".into(), - }, - ) - .unwrap(); + create_inspiration_at(&path, CreateInspirationInput { work_id: detail.work.work_id.clone(), chapter_id: Some(chapter.chapter_id.clone()), content: "让钥匙提前出现".into(), tags: vec!["伏笔".into()] }).unwrap(); + record_activity_at(&path, RecordWritingActivityInput { activity_id: "WN-ACT-test".into(), work_id: detail.work.work_id.clone(), chapter_id: chapter.chapter_id.clone(), local_date: "2026-08-18".into(), active_ms: 30_000, words_delta: 8 }).unwrap(); + let search = search_full_text_at(&path, SearchFullTextInput { work_id: detail.work.work_id.clone(), query: "线索".into() }).unwrap(); assert_eq!(search.chapter_count, 1); - let snapshot = author_snapshot_at( - &path, - &AuthorSnapshotInput { - work_id: detail.work.work_id, - local_date: "2026-08-18".into(), - }, - ) - .unwrap(); + let snapshot = author_snapshot_at(&path, &AuthorSnapshotInput { work_id: detail.work.work_id, local_date: "2026-08-18".into() }).unwrap(); assert_eq!(snapshot.today_active_ms, 30_000); assert_eq!(snapshot.today_words, 8); assert_eq!(snapshot.inspiration_count, 1); @@ -1006,34 +788,16 @@ mod tests { let chapter = super::super::web_novel_workspace::create_chapter_at( &path, super::super::web_novel_workspace::CreateWebNovelChapterInput { - work_id: detail.work.work_id.clone(), - volume_id: detail.volumes[0].volume_id.clone(), - title: "第1集".into(), + work_id: detail.work.work_id.clone(), volume_id: detail.volumes[0].volume_id.clone(), title: "第1集".into(), }, - ) - .unwrap(); + ).unwrap(); assert!(chapter.content.contains("场次:1-1")); - let shot = upsert_shot_at( - &path, - UpsertShotInput { - work_id: detail.work.work_id, - chapter_id: chapter.chapter_id, - shot_id: None, - shot_number: "1".into(), - shot_size: "近景".into(), - camera_movement: "推".into(), - location: "侯府".into(), - time_of_day: "夜".into(), - action: "女主抬眼".into(), - dialogue: "你终于来了。".into(), - duration_seconds: 4, - visual_prompt: "烛火冷夜".into(), - image_prompt: "古装近景".into(), - video_prompt: "缓慢推镜".into(), - expected_revision: None, - }, - ) - .unwrap(); + let shot = upsert_shot_at(&path, UpsertShotInput { + work_id: detail.work.work_id, chapter_id: chapter.chapter_id, shot_id: None, shot_number: "1".into(), + shot_size: "近景".into(), camera_movement: "推".into(), location: "侯府".into(), time_of_day: "夜".into(), + action: "女主抬眼".into(), dialogue: "你终于来了。".into(), duration_seconds: 4, + visual_prompt: "烛火冷夜".into(), image_prompt: "古装近景".into(), video_prompt: "缓慢推镜".into(), expected_revision: None, + }).unwrap(); assert_eq!(shot.revision, 1); } } diff --git a/product-source/hololake-native-desktop/src-tauri/src/web_novel_import.rs b/product-source/hololake-native-desktop/src-tauri/src/web_novel_import.rs index d70f2d74e..aef7949ac 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/web_novel_import.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/web_novel_import.rs @@ -19,19 +19,12 @@ use tauri_plugin_dialog::DialogExt; use uuid::Uuid; use zip::ZipArchive; -const MODULE_NUMBER: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001"; -const ADAPTER: &str = "web-novel-workbench-v1"; - -fn require_active(app: &AppHandle) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, MODULE_NUMBER, ADAPTER) -} - const MAX_SOURCE_BYTES: u64 = 30 * 1024 * 1024; const MAX_SECTION_BYTES: usize = 4_000_000; const MAX_SYNOPSIS_BYTES: usize = 40_000; #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ImportSection { pub ordinal: usize, pub title: String, @@ -41,7 +34,7 @@ pub struct ImportSection { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ImportSectionPreview { pub ordinal: usize, pub title: String, @@ -51,7 +44,7 @@ pub struct ImportSectionPreview { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelImportPreview { pub import_id: String, pub source_filename: String, @@ -69,7 +62,7 @@ pub struct WebNovelImportPreview { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct CommitImportInput { pub import_id: String, pub target_mode: String, @@ -80,7 +73,7 @@ pub struct CommitImportInput { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelImportReceipt { pub state: String, pub import_id: String, @@ -109,10 +102,10 @@ struct ParsedDocument { sections: Vec, } +#[tauri::command] pub async fn inspect_web_novel_document_from_dialog( app: AppHandle, ) -> Result, String> { - require_active(&app)?; let selected = app .dialog() .file() @@ -132,11 +125,11 @@ pub async fn inspect_web_novel_document_from_dialog( .map(Some) } +#[tauri::command] pub async fn commit_web_novel_document_import( app: AppHandle, input: CommitImportInput, ) -> Result { - require_active(&app)?; let database = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || commit_import_at(&database, input)) .await @@ -353,8 +346,11 @@ pub(crate) fn commit_import_at( .map_err(db_read)?; for (position, section) in sections.iter().enumerate() { let chapter_id = format!("WN-CH-{}", Uuid::new_v4()); - let formatted_content = - super::web_novel_author::format_content(§ion.body, &work_kind, &staged.2); + let formatted_content = super::web_novel_author::format_content( + §ion.body, + &work_kind, + &staged.2, + ); let formatted_word_count = count_words(&formatted_content); tx.execute( "INSERT INTO web_novel_chapters( @@ -745,8 +741,7 @@ mod tests { pen_name: "测试作者".into(), genre: "测试".into(), }, - ) - .unwrap(); + ).unwrap(); let connection = super::super::web_novel_workspace::open_database(&database).unwrap(); let (content, revision): (String, i64) = connection.query_row( "SELECT content,revision FROM web_novel_chapters WHERE work_id=?1 ORDER BY position LIMIT 1", diff --git a/product-source/hololake-native-desktop/src-tauri/src/web_novel_modules.rs b/product-source/hololake-native-desktop/src-tauri/src/web_novel_modules.rs index c7780b97c..31e11eb43 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/web_novel_modules.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/web_novel_modules.rs @@ -1,10 +1,8 @@ -//! 网文作者官方模块数据适配器。 +//! 网文作者官方模块运行时。 //! -//! 生产安装、签名验证、挂载、自检和回执只由 `module_package_runtime` 执行。 -//! 本文件保留 0.4.1 安装器作为迁移回归测试夹具;它没有编号 IPC 路由,不能成为 -//! 第二套生产生命周期权威。 - -#![allow(dead_code)] +//! 模块包是不可变、内置签名边界内的官方发行制品。安装把经过散列核验的包写入 +//! 当前账号缓存;挂载状态、模块数据和链式回执写入当前账号网文 SQLite。卸载只清理 +//! 可重新取得的程序缓存,不删除作品、模块数据或回执。 use ring::digest::{digest, SHA256}; use rusqlite::{params, Connection, OptionalExtension, TransactionBehavior}; @@ -19,17 +17,10 @@ use uuid::Uuid; use zip::write::FileOptions; use zip::{CompressionMethod, ZipWriter}; -const BASE: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001"; -const ADAPTER: &str = "web-novel-workbench-v1"; - -fn require_module_active(app: &AppHandle, module_number: &str) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, module_number, ADAPTER) -} - -const OUTLINE: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001"; -const GRID: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001"; -const STORYWORLD: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001"; -const DELIVERY: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001"; +const OUTLINE: &str = "HL-MOD-WEBNOVEL-OUTLINE-001"; +const GRID: &str = "HL-MOD-WEBNOVEL-GRID-002"; +const STORYWORLD: &str = "HL-MOD-WEBNOVEL-STORYWORLD-003"; +const DELIVERY: &str = "HL-MOD-WEBNOVEL-DELIVERY-004"; const VERSION: &str = "1.0.0"; struct Package { @@ -48,7 +39,7 @@ fn packages() -> [Package; 4] { description: "场景、情节拍、目标冲突结果、钩子与伏笔追踪。", sha256: "6d31d3f530862000bd84a8f5dc73bcb9cf0d5738219f7a287562d4f4bcfa5318", bytes: include_bytes!( - "../../fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-OUTLINE-001.json" + "../../official-modules/web-novel/HL-MOD-WEBNOVEL-OUTLINE-001/1.0.0/module.json" ), }, Package { @@ -57,7 +48,7 @@ fn packages() -> [Package; 4] { description: "由同一场景对象生成可编辑表格、自定义字段与分组情节板。", sha256: "2e34e0337c51dbbdd1efdd807be71e69a0cb2a1745624e1f51b452b7b54f1553", bytes: include_bytes!( - "../../fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-GRID-002.json" + "../../official-modules/web-novel/HL-MOD-WEBNOVEL-GRID-002/1.0.0/module.json" ), }, Package { @@ -66,7 +57,7 @@ fn packages() -> [Package; 4] { description: "故事时间、场景与人物地点物品的真实关系投影。", sha256: "d486719500ddfc08054d9c9bb6d3683afe5547a2b24c9b04d0f899ac66094d2f", bytes: include_bytes!( - "../../fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-STORYWORLD-003.json" + "../../official-modules/web-novel/HL-MOD-WEBNOVEL-STORYWORLD-003/1.0.0/module.json" ), }, Package { @@ -75,7 +66,7 @@ fn packages() -> [Package; 4] { description: "章节版本读回与恢复,以及 TXT、DOCX、EPUB、JSON 真实导出。", sha256: "4af1d4610826edd29759bd0dc12b4b0c04fd2ebebb4ebc362d47d762810989e8", bytes: include_bytes!( - "../../fixtures/web-novel-legacy-0.4.1/HL-MOD-WEBNOVEL-DELIVERY-004.json" + "../../official-modules/web-novel/HL-MOD-WEBNOVEL-DELIVERY-004/1.0.0/module.json" ), }, ] @@ -118,19 +109,19 @@ pub struct AuthorModuleMarketplaceSnapshot { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ModuleActionInput { pub module_id: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ReadAuthorModuleDataInput { pub work_id: String, } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct AuthorScene { pub scene_id: String, pub work_id: String, @@ -150,7 +141,7 @@ pub struct AuthorScene { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct AuthorBeat { pub beat_id: String, pub scene_id: String, @@ -163,7 +154,7 @@ pub struct AuthorBeat { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct StoryFieldDefinition { pub field_id: String, pub work_id: String, @@ -175,7 +166,7 @@ pub struct StoryFieldDefinition { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct StoryFieldValue { pub field_id: String, pub scene_id: String, @@ -184,7 +175,7 @@ pub struct StoryFieldValue { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct StoryTimelineEvent { pub event_id: String, pub work_id: String, @@ -201,7 +192,7 @@ pub struct StoryTimelineEvent { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct SceneEntityLink { pub link_id: String, pub work_id: String, @@ -212,7 +203,7 @@ pub struct SceneEntityLink { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ChapterVersionSummary { pub version_id: String, pub chapter_id: String, @@ -237,7 +228,7 @@ pub struct AuthorModuleData { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct UpsertAuthorSceneInput { pub work_id: String, pub scene_id: Option, @@ -256,7 +247,7 @@ pub struct UpsertAuthorSceneInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct UpsertAuthorBeatInput { pub scene_id: String, pub beat_id: Option, @@ -268,7 +259,7 @@ pub struct UpsertAuthorBeatInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct UpsertStoryFieldDefinitionInput { pub work_id: String, pub field_id: Option, @@ -279,7 +270,7 @@ pub struct UpsertStoryFieldDefinitionInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct UpsertStoryFieldValueInput { pub field_id: String, pub scene_id: String, @@ -288,7 +279,7 @@ pub struct UpsertStoryFieldValueInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct UpsertTimelineEventInput { pub work_id: String, pub event_id: Option, @@ -305,7 +296,7 @@ pub struct UpsertTimelineEventInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct LinkSceneEntityInput { pub work_id: String, pub scene_id: String, @@ -315,13 +306,13 @@ pub struct LinkSceneEntityInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct RestoreChapterVersionInput { pub version_id: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ExportAuthorDeliveryInput { pub work_id: String, pub format: String, @@ -337,6 +328,7 @@ pub struct AuthorDeliveryReceipt { pub package_sha256: String, } +#[tauri::command] pub async fn get_web_novel_author_module_marketplace( app: AppHandle, ) -> Result { @@ -346,6 +338,7 @@ pub async fn get_web_novel_author_module_marketplace( .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn install_web_novel_author_module( app: AppHandle, input: ModuleActionInput, @@ -357,6 +350,7 @@ pub async fn install_web_novel_author_module( .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn mount_web_novel_author_module( app: AppHandle, input: ModuleActionInput, @@ -367,6 +361,7 @@ pub async fn mount_web_novel_author_module( .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn unmount_web_novel_author_module( app: AppHandle, input: ModuleActionInput, @@ -377,6 +372,7 @@ pub async fn unmount_web_novel_author_module( .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn uninstall_web_novel_author_module( app: AppHandle, input: ModuleActionInput, @@ -388,99 +384,99 @@ pub async fn uninstall_web_novel_author_module( .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn get_web_novel_author_module_data( app: AppHandle, input: ReadAuthorModuleDataInput, ) -> Result { - require_module_active(&app, BASE)?; let database = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || module_data_at(&database, &input.work_id)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn upsert_web_novel_author_scene( app: AppHandle, input: UpsertAuthorSceneInput, ) -> Result { - require_module_active(&app, OUTLINE)?; let database = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || upsert_scene_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn upsert_web_novel_author_beat( app: AppHandle, input: UpsertAuthorBeatInput, ) -> Result { - require_module_active(&app, OUTLINE)?; let database = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || upsert_beat_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn upsert_web_novel_story_field_definition( app: AppHandle, input: UpsertStoryFieldDefinitionInput, ) -> Result { - require_module_active(&app, GRID)?; let database = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || upsert_field_definition_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn upsert_web_novel_story_field_value( app: AppHandle, input: UpsertStoryFieldValueInput, ) -> Result { - require_module_active(&app, GRID)?; let database = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || upsert_field_value_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn upsert_web_novel_timeline_event( app: AppHandle, input: UpsertTimelineEventInput, ) -> Result { - require_module_active(&app, STORYWORLD)?; let database = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || upsert_timeline_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn link_web_novel_scene_entity( app: AppHandle, input: LinkSceneEntityInput, ) -> Result { - require_module_active(&app, STORYWORLD)?; let database = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || link_scene_entity_at(&database, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn restore_web_novel_chapter_version( app: AppHandle, input: RestoreChapterVersionInput, ) -> Result { - require_module_active(&app, DELIVERY)?; let database = super::web_novel_workspace::workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || restore_version_at(&database, &input.version_id)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_MODULE_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn export_web_novel_author_delivery( app: AppHandle, input: ExportAuthorDeliveryInput, ) -> Result, String> { - require_module_active(&app, DELIVERY)?; let format = normalize_delivery_format(&input.format)?; let database = super::web_novel_workspace::workspace_database(&app)?; let title = read_work_title(&database, &input.work_id)?; @@ -778,7 +774,6 @@ fn append_receipt( Ok(()) } -#[cfg(test)] fn require_mounted(connection: &Connection, module_id: &str) -> Result<(), String> { let state: Option = connection.query_row("SELECT install_state FROM web_novel_module_installations WHERE module_id=?1 AND self_test_state='PASS'", [module_id], |row| row.get(0)).optional().map_err(db_read)?; if state.as_deref() == Some("MOUNTED") { @@ -788,18 +783,6 @@ fn require_mounted(connection: &Connection, module_id: &str) -> Result<(), Strin } } -#[cfg(not(test))] -fn require_mounted(_connection: &Connection, module_id: &str) -> Result<(), String> { - if matches!(module_id, OUTLINE | GRID | STORYWORLD | DELIVERY) { - // The public adapter entry already performed an exact-number ACTIVE check - // against the shared signed package runtime. Never consult the legacy - // installation table in production. - Ok(()) - } else { - Err("HOLOLAKE_WEBNOVEL_MODULE_UNKNOWN".into()) - } -} - fn module_cache_path(cache: &Path, module_id: &str) -> Result { if !packages().iter().any(|item| item.module_id == module_id) || module_id.contains('/') diff --git a/product-source/hololake-native-desktop/src-tauri/src/web_novel_workspace.rs b/product-source/hololake-native-desktop/src-tauri/src/web_novel_workspace.rs index 032af3c86..7933fbed1 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/web_novel_workspace.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/web_novel_workspace.rs @@ -12,13 +12,6 @@ use tauri::{AppHandle, Manager}; use tauri_plugin_dialog::DialogExt; use uuid::Uuid; -const MODULE_NUMBER: &str = "HLP-MOD-OFFICIAL-WEB-NOVEL-WORKBENCH-0001"; -const ADAPTER: &str = "web-novel-workbench-v1"; - -fn require_active(app: &AppHandle) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, MODULE_NUMBER, ADAPTER) -} - const MAX_TITLE_BYTES: usize = 300; const MAX_SYNOPSIS_BYTES: usize = 40_000; const MAX_CHAPTER_BYTES: usize = 4_000_000; @@ -36,7 +29,7 @@ const WORKFLOW_STATES: &[&str] = &[ ]; #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelWorkSummary { pub work_id: String, pub title: String, @@ -53,7 +46,7 @@ pub struct WebNovelWorkSummary { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelWork { pub work_id: String, pub title: String, @@ -71,7 +64,7 @@ pub struct WebNovelWork { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelVolume { pub volume_id: String, pub work_id: String, @@ -83,7 +76,7 @@ pub struct WebNovelVolume { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelChapterSummary { pub chapter_id: String, pub volume_id: String, @@ -99,7 +92,7 @@ pub struct WebNovelChapterSummary { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelChapter { pub chapter_id: String, pub volume_id: String, @@ -117,7 +110,7 @@ pub struct WebNovelChapter { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelStoryEntity { pub entity_id: String, pub work_id: String, @@ -132,7 +125,7 @@ pub struct WebNovelStoryEntity { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelStoryRelation { pub relation_id: String, pub work_id: String, @@ -144,7 +137,7 @@ pub struct WebNovelStoryRelation { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelForeshadow { pub foreshadow_id: String, pub work_id: String, @@ -159,7 +152,7 @@ pub struct WebNovelForeshadow { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelReviewNote { pub note_id: String, pub work_id: String, @@ -171,7 +164,7 @@ pub struct WebNovelReviewNote { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelWorkflowEvent { pub event_id: String, pub work_id: String, @@ -183,7 +176,7 @@ pub struct WebNovelWorkflowEvent { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelCheckpointSummary { pub checkpoint_id: String, pub work_id: String, @@ -195,7 +188,7 @@ pub struct WebNovelCheckpointSummary { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct WebNovelMetric { pub metric_id: String, pub work_id: String, @@ -287,7 +280,7 @@ pub struct WebNovelExportReceipt { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct CreateWebNovelWorkInput { pub title: String, pub pen_name: String, @@ -297,13 +290,13 @@ pub struct CreateWebNovelWorkInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ReadWebNovelWorkInput { pub work_id: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct SaveWebNovelWorkInput { pub work_id: String, pub title: String, @@ -319,14 +312,14 @@ pub struct SaveWebNovelWorkInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct CreateWebNovelVolumeInput { pub work_id: String, pub title: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct CreateWebNovelChapterInput { pub work_id: String, pub volume_id: String, @@ -334,13 +327,13 @@ pub struct CreateWebNovelChapterInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ReadWebNovelChapterInput { pub chapter_id: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct SaveWebNovelChapterInput { pub chapter_id: String, pub title: String, @@ -351,7 +344,7 @@ pub struct SaveWebNovelChapterInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct TransitionWebNovelChapterInput { pub chapter_id: String, pub to_status: String, @@ -361,7 +354,7 @@ pub struct TransitionWebNovelChapterInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct CreateWebNovelCheckpointInput { pub work_id: String, pub name: String, @@ -369,13 +362,13 @@ pub struct CreateWebNovelCheckpointInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct RestoreWebNovelCheckpointInput { pub checkpoint_id: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct UpsertWebNovelStoryEntityInput { pub work_id: String, pub entity_id: Option, @@ -388,7 +381,7 @@ pub struct UpsertWebNovelStoryEntityInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct CreateWebNovelStoryRelationInput { pub work_id: String, pub source_entity_id: String, @@ -398,7 +391,7 @@ pub struct CreateWebNovelStoryRelationInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct UpsertWebNovelForeshadowInput { pub work_id: String, pub foreshadow_id: Option, @@ -411,7 +404,7 @@ pub struct UpsertWebNovelForeshadowInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct CreateWebNovelReviewNoteInput { pub work_id: String, pub chapter_id: String, @@ -419,13 +412,13 @@ pub struct CreateWebNovelReviewNoteInput { } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct ResolveWebNovelReviewNoteInput { pub note_id: String, } #[derive(Clone, Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] pub struct SaveWebNovelMetricInput { pub work_id: String, pub metric_date: String, @@ -439,7 +432,7 @@ pub struct SaveWebNovelMetricInput { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase")] struct CheckpointChapter { chapter_id: String, title: String, @@ -450,208 +443,208 @@ struct CheckpointChapter { position: i64, } +#[tauri::command] pub async fn get_web_novel_workspace_snapshot( app: AppHandle, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || snapshot_at(&path)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_web_novel_work( app: AppHandle, input: CreateWebNovelWorkInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || create_work_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn read_web_novel_work( app: AppHandle, input: ReadWebNovelWorkInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || read_work_at(&path, &input.work_id)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn save_web_novel_work( app: AppHandle, input: SaveWebNovelWorkInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || save_work_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_web_novel_volume( app: AppHandle, input: CreateWebNovelVolumeInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || create_volume_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_web_novel_chapter( app: AppHandle, input: CreateWebNovelChapterInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || create_chapter_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn read_web_novel_chapter( app: AppHandle, input: ReadWebNovelChapterInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || read_chapter_at(&path, &input.chapter_id)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn save_web_novel_chapter( app: AppHandle, input: SaveWebNovelChapterInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || save_chapter_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn transition_web_novel_chapter( app: AppHandle, input: TransitionWebNovelChapterInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || transition_chapter_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_web_novel_checkpoint( app: AppHandle, input: CreateWebNovelCheckpointInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || create_checkpoint_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn restore_web_novel_checkpoint( app: AppHandle, input: RestoreWebNovelCheckpointInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || restore_checkpoint_at(&path, &input.checkpoint_id)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn upsert_web_novel_story_entity( app: AppHandle, input: UpsertWebNovelStoryEntityInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || upsert_entity_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_web_novel_story_relation( app: AppHandle, input: CreateWebNovelStoryRelationInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || create_relation_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn upsert_web_novel_foreshadow( app: AppHandle, input: UpsertWebNovelForeshadowInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || upsert_foreshadow_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn create_web_novel_review_note( app: AppHandle, input: CreateWebNovelReviewNoteInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || create_review_note_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn resolve_web_novel_review_note( app: AppHandle, input: ResolveWebNovelReviewNoteInput, ) -> Result<(), String> { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || resolve_review_note_at(&path, &input.note_id)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn save_web_novel_metric( app: AppHandle, input: SaveWebNovelMetricInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || save_metric_at(&path, input)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn run_web_novel_continuity_audit( app: AppHandle, input: ReadWebNovelWorkInput, ) -> Result { - require_active(&app)?; let path = workspace_database(&app)?; tauri::async_runtime::spawn_blocking(move || continuity_audit_at(&path, &input.work_id)) .await .map_err(|error| format!("HOLOLAKE_WEBNOVEL_JOIN_FAILED: {error}"))? } +#[tauri::command] pub async fn export_web_novel_markdown( app: AppHandle, input: ReadWebNovelWorkInput, ) -> Result, String> { - require_active(&app)?; let database = workspace_database(&app)?; let detail = read_work_at(&database, &input.work_id)?; let filename = format!("{}.md", safe_filename(&detail.work.title)); @@ -694,12 +687,8 @@ fn migrate_acceptance_workspace_if_needed( .path() .app_data_dir() .map_err(|error| format!("HOLOLAKE_APP_DATA_UNAVAILABLE: {error}"))?; - let Some(app_data_parent) = current_app_data.parent() else { - return Ok(()); - }; - let Some(account_root) = current_namespace_root.parent() else { - return Ok(()); - }; + let Some(app_data_parent) = current_app_data.parent() else { return Ok(()); }; + let Some(account_root) = current_namespace_root.parent() else { return Ok(()); }; let relative_account = match account_root.strip_prefix(¤t_app_data) { Ok(value) => value, Err(_) => return Ok(()), @@ -755,8 +744,7 @@ fn copy_directory_without_overwrite(source: &Path, destination: &Path) -> Result for entry in fs::read_dir(source) .map_err(|error| format!("HOLOLAKE_WEBNOVEL_LEGACY_MODULE_READ_FAILED: {error}"))? { - let entry = entry - .map_err(|error| format!("HOLOLAKE_WEBNOVEL_LEGACY_MODULE_READ_FAILED: {error}"))?; + let entry = entry.map_err(|error| format!("HOLOLAKE_WEBNOVEL_LEGACY_MODULE_READ_FAILED: {error}"))?; let target = destination.join(entry.file_name()); if entry.path().is_dir() { copy_directory_without_overwrite(&entry.path(), &target)?; @@ -2538,15 +2526,12 @@ fn map_chapter(row: &rusqlite::Row<'_>) -> rusqlite::Result { fn map_entity(row: &rusqlite::Row<'_>) -> rusqlite::Result { let raw: String = row.get(4)?; - let aliases = serde_json::from_str(&raw).map_err(|error| { - rusqlite::Error::FromSqlConversionFailure(4, rusqlite::types::Type::Text, Box::new(error)) - })?; Ok(WebNovelStoryEntity { entity_id: row.get(0)?, work_id: row.get(1)?, entity_type: row.get(2)?, name: row.get(3)?, - aliases, + aliases: serde_json::from_str(&raw).unwrap_or_default(), description: row.get(5)?, first_chapter_id: row.get(6)?, revision: row.get(7)?, @@ -2651,10 +2636,7 @@ fn normalized_workflow(value: &str) -> Result { pub(crate) fn normalized_work_kind(value: &str) -> Result { let normalized = value.trim().to_ascii_uppercase(); - if matches!( - normalized.as_str(), - "LONG_NOVEL" | "SHORT_NOVEL" | "SHORT_DRAMA" - ) { + if matches!(normalized.as_str(), "LONG_NOVEL" | "SHORT_NOVEL" | "SHORT_DRAMA") { Ok(normalized) } else { Err("HOLOLAKE_WEBNOVEL_WORK_KIND_INVALID".into()) @@ -2691,9 +2673,7 @@ fn ensure_column( .map_err(database_read_error)?; if !columns.iter().any(|value| value == column) { connection - .execute_batch(&format!( - "ALTER TABLE {table} ADD COLUMN {column} {definition};" - )) + .execute_batch(&format!("ALTER TABLE {table} ADD COLUMN {column} {definition};")) .map_err(database_write_error)?; } Ok(()) diff --git a/product-source/hololake-native-desktop/src-tauri/src/world_climate.rs b/product-source/hololake-native-desktop/src-tauri/src/world_climate.rs index ba0a80d9b..b978b58bf 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/world_climate.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/world_climate.rs @@ -1,20 +1,12 @@ -//! Signed dynamic language-world climate projection. -//! -//! The projection may tint the already-approved lake surface. It cannot change -//! domain routing, permissions, facts, or the five-theme layout. Real coordinates -//! are used only for a bounded public-weather query and are never returned to the -//! webview. +// SPDX-License-Identifier: AGPL-3.0-or-later + +//! 语言世界首页的动态气候投影。 +//! 固定域坐标只用于取公开天气;返回值不包含城市或经纬度,界面也不把现实城市冒充世界地名。 use serde::{Deserialize, Serialize}; -use std::sync::{Mutex, OnceLock}; -use std::time::Duration; -use tauri::AppHandle; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; -const MODULE_NUMBER: &str = "HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001"; -const ADAPTER: &str = "dynamic-language-world-surface-v1"; const SOURCE: &str = "OPEN_METEO_FORECAST_API"; -const ATTRIBUTION_URL: &str = "https://open-meteo.com/"; -const CACHE_TTL_MS: u64 = 10 * 60 * 1_000; #[derive(Debug, Deserialize)] struct OpenMeteoResponse { @@ -33,45 +25,36 @@ struct OpenMeteoCurrent { #[derive(Clone, Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct WorldClimateSnapshot { - schema: &'static str, - state: &'static str, - active_domain: &'static str, - time_phase: &'static str, - weather_kind: &'static str, - motion_intensity: &'static str, - source: &'static str, - source_attribution_url: &'static str, - city_exposed: bool, - coordinates_exposed: bool, - routing_or_permission_changed: bool, - observed_at_unix_ms: u64, + pub state: &'static str, + pub active_domain: &'static str, + pub time_phase: &'static str, + pub weather_kind: &'static str, + pub motion_intensity: &'static str, + pub source: &'static str, + pub city_exposed: bool, + pub observed_at_unix_ms: i64, } -static CACHE: OnceLock>> = OnceLock::new(); - -fn require_active(app: &AppHandle) -> Result<(), String> { - crate::module_package_runtime::require_active_module_adapter(app, MODULE_NUMBER, ADAPTER) -} - -pub async fn get_world_climate(app: AppHandle) -> Result { - require_active(&app)?; - let coordinate = crate::persona_time_authority::get_beijing_time_coordinate()?; - let now_ms = coordinate.unix_ms; - if let Some(snapshot) = cached(now_ms)? { - return Ok(snapshot); - } - let day_index = coordinate.elapsed_beijing_dates_since_guanghu_epoch; - let hour = beijing_hour(&coordinate.beijing_time).unwrap_or(0); - let domains = [ - "FIFTH_DOMAIN", - "ZERO_SENSE_DOMAIN", - "MAIN_DOMAIN", - "BRANCH_DOMAIN", - "ZERO_DOMAIN", - ]; +#[tauri::command] +pub async fn get_world_climate() -> Result { + let seconds = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map_err(|error| format!("HOLOLAKE_WORLD_CLIMATE_CLOCK_INVALID: {error}"))? + .as_secs() as i64; + let beijing_seconds = seconds + 8 * 60 * 60; + let day_index = beijing_seconds.div_euclid(86_400); + let hour = beijing_seconds.rem_euclid(86_400) / 3_600; + let domains = ["FIFTH_DOMAIN", "ZERO_SENSE_DOMAIN", "MAIN_DOMAIN", "BRANCH_DOMAIN", "ZERO_DOMAIN"]; let active_domain = domains[day_index.rem_euclid(domains.len() as i64) as usize]; - let time_phase = phase_for_hour(hour); let (latitude, longitude) = coordinate_for(active_domain, day_index); + let time_phase = match hour { + 5..=7 => "DAWN", + 8..=16 => "DAY", + 17..=19 => "DUSK", + _ => "NIGHT", + }; + let observed_at_unix_ms = seconds.saturating_mul(1_000); + let client = reqwest::Client::builder() .timeout(Duration::from_secs(5)) .redirect(reqwest::redirect::Policy::none()) @@ -80,56 +63,38 @@ pub async fn get_world_climate(app: AppHandle) -> Result { - match response.json::().await { - Ok(payload) if valid_current(&payload.current) => { - live_snapshot(active_domain, time_phase, now_ms, payload.current) - } - _ => fallback(active_domain, time_phase, now_ms), - } - } - _ => fallback(active_domain, time_phase, now_ms), + .await + { + Ok(response) if response.status().is_success() => response, + _ => return Ok(fallback(active_domain, time_phase, observed_at_unix_ms)), }; - store_cache(now_ms, snapshot.clone())?; - Ok(snapshot) -} - -fn cached(now_ms: u64) -> Result, String> { - let guard = CACHE - .get_or_init(|| Mutex::new(None)) - .lock() - .map_err(|_| "HOLOLAKE_WORLD_CLIMATE_CACHE_POISONED".to_string())?; - Ok(guard.as_ref().and_then(|(cached_at, snapshot)| { - (now_ms.saturating_sub(*cached_at) < CACHE_TTL_MS).then(|| snapshot.clone()) - })) -} - -fn store_cache(now_ms: u64, snapshot: WorldClimateSnapshot) -> Result<(), String> { - *CACHE - .get_or_init(|| Mutex::new(None)) - .lock() - .map_err(|_| "HOLOLAKE_WORLD_CLIMATE_CACHE_POISONED".to_string())? = - Some((now_ms, snapshot)); - Ok(()) -} - -fn beijing_hour(value: &str) -> Option { - value.split('T').nth(1)?.get(0..2)?.parse().ok() -} - -fn phase_for_hour(hour: u8) -> &'static str { - match hour { - 5..=7 => "DAWN", - 8..=16 => "DAY", - 17..=19 => "DUSK", - _ => "NIGHT", - } + let current = match response.json::().await { + Ok(payload) => payload.current, + Err(_) => return Ok(fallback(active_domain, time_phase, observed_at_unix_ms)), + }; + let weather_kind = weather_kind(current.weather_code, current.precipitation, current.cloud_cover); + let motion_intensity = if current.wind_speed_10m >= 35.0 || weather_kind == "STORM" { + "ACTIVE" + } else if current.wind_speed_10m >= 15.0 || matches!(weather_kind, "RAIN" | "SNOW") { + "GENTLE" + } else { + "CALM" + }; + let effective_phase = if current.is_day == 0 && time_phase == "DAY" { "NIGHT" } else { time_phase }; + Ok(WorldClimateSnapshot { + state: "VERIFIED_LIVE", + active_domain, + time_phase: effective_phase, + weather_kind, + motion_intensity, + source: SOURCE, + city_exposed: false, + observed_at_unix_ms, + }) } fn coordinate_for(domain: &str, day_index: i64) -> (f64, f64) { @@ -139,12 +104,8 @@ fn coordinate_for(domain: &str, day_index: i64) -> (f64, f64) { "MAIN_DOMAIN" | "ZERO_SENSE_DOMAIN" => (39.9042, 116.4074), "BRANCH_DOMAIN" => { let roaming = [ - (31.2304, 121.4737), - (30.5728, 104.0668), - (30.5928, 114.3055), - (30.2741, 120.1551), - (32.0603, 118.7969), - (29.5630, 106.5516), + (31.2304, 121.4737), (30.5728, 104.0668), (30.5928, 114.3055), + (30.2741, 120.1551), (32.0603, 118.7969), (29.5630, 106.5516), ]; roaming[day_index.rem_euclid(roaming.len() as i64) as usize] } @@ -152,87 +113,24 @@ fn coordinate_for(domain: &str, day_index: i64) -> (f64, f64) { } } -fn valid_current(current: &OpenMeteoCurrent) -> bool { - current.is_day.abs() <= 1 - && current.precipitation.is_finite() - && (0.0..=1_000.0).contains(¤t.precipitation) - && current.cloud_cover.is_finite() - && (0.0..=100.0).contains(¤t.cloud_cover) - && current.wind_speed_10m.is_finite() - && (0.0..=500.0).contains(¤t.wind_speed_10m) -} - fn weather_kind(code: i64, precipitation: f64, cloud_cover: f64) -> &'static str { - if matches!(code, 95 | 96 | 99) { - "STORM" - } else if matches!(code, 71..=77 | 85 | 86) { - "SNOW" - } else if precipitation > 0.0 || matches!(code, 51..=67 | 80..=82) { - "RAIN" - } else if matches!(code, 45 | 48) { - "FOG" - } else if matches!(code, 1..=3) || cloud_cover >= 35.0 { - "CLOUD" - } else { - "CLEAR" - } + if matches!(code, 95 | 96 | 99) { "STORM" } + else if matches!(code, 71..=77 | 85 | 86) { "SNOW" } + else if precipitation > 0.0 || matches!(code, 51..=67 | 80..=82) { "RAIN" } + else if matches!(code, 45 | 48) { "FOG" } + else if matches!(code, 1..=3) || cloud_cover >= 35.0 { "CLOUD" } + else { "CLEAR" } } -fn live_snapshot( - active_domain: &'static str, - time_phase: &'static str, - observed_at_unix_ms: u64, - current: OpenMeteoCurrent, -) -> WorldClimateSnapshot { - let weather_kind = weather_kind( - current.weather_code, - current.precipitation, - current.cloud_cover, - ); - let motion_intensity = if current.wind_speed_10m >= 35.0 || weather_kind == "STORM" { - "ACTIVE" - } else if current.wind_speed_10m >= 15.0 || matches!(weather_kind, "RAIN" | "SNOW") { - "GENTLE" - } else { - "CALM" - }; +fn fallback(active_domain: &'static str, time_phase: &'static str, observed_at_unix_ms: i64) -> WorldClimateSnapshot { WorldClimateSnapshot { - schema: "hololake.world-climate/v1", - state: "VERIFIED_LIVE", - active_domain, - time_phase: if current.is_day == 0 && time_phase == "DAY" { - "NIGHT" - } else { - time_phase - }, - weather_kind, - motion_intensity, - source: SOURCE, - source_attribution_url: ATTRIBUTION_URL, - city_exposed: false, - coordinates_exposed: false, - routing_or_permission_changed: false, - observed_at_unix_ms, - } -} - -fn fallback( - active_domain: &'static str, - time_phase: &'static str, - observed_at_unix_ms: u64, -) -> WorldClimateSnapshot { - WorldClimateSnapshot { - schema: "hololake.world-climate/v1", state: "TIME_ONLY_WEATHER_UNAVAILABLE", active_domain, time_phase, weather_kind: "UNAVAILABLE", motion_intensity: "CALM", source: SOURCE, - source_attribution_url: ATTRIBUTION_URL, city_exposed: false, - coordinates_exposed: false, - routing_or_permission_changed: false, observed_at_unix_ms, } } @@ -242,35 +140,10 @@ mod tests { use super::*; #[test] - fn weather_codes_map_without_exposing_coordinates_or_changing_routes() { + fn weather_codes_map_to_visual_families_without_city_data() { assert_eq!(weather_kind(0, 0.0, 3.0), "CLEAR"); assert_eq!(weather_kind(61, 0.3, 80.0), "RAIN"); assert_eq!(weather_kind(95, 4.0, 100.0), "STORM"); - let snapshot = fallback("FIFTH_DOMAIN", "NIGHT", 1); - assert!(!snapshot.city_exposed); - assert!(!snapshot.coordinates_exposed); - assert!(!snapshot.routing_or_permission_changed); - assert_eq!(snapshot.weather_kind, "UNAVAILABLE"); - } - - #[test] - fn beijing_phase_and_daily_coordinates_are_deterministic() { - assert_eq!(beijing_hour("2026-08-19T07:03:02.000+08:00"), Some(7)); - assert_eq!(phase_for_hour(7), "DAWN"); - assert_eq!(phase_for_hour(15), "DAY"); - assert_eq!(phase_for_hour(23), "NIGHT"); assert_eq!(coordinate_for("FIFTH_DOMAIN", 1), (34.3416, 108.9398)); - assert_eq!(coordinate_for("BRANCH_DOMAIN", 0), (31.2304, 121.4737)); - } - - #[test] - fn malformed_public_weather_values_are_rejected() { - assert!(!valid_current(&OpenMeteoCurrent { - weather_code: 0, - is_day: 1, - precipitation: f64::NAN, - cloud_cover: 0.0, - wind_speed_10m: 0.0, - })); } } diff --git a/product-source/hololake-native-desktop/src-tauri/src/zero_core_numbering.rs b/product-source/hololake-native-desktop/src-tauri/src/zero_core_numbering.rs index 03f2957af..e805b6fc3 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/zero_core_numbering.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/zero_core_numbering.rs @@ -190,6 +190,7 @@ pub(crate) fn resolve_human_number_route(number: &str) -> Result Result { let contract = load_contract()?; Ok(ZeroCoreNumberingKernelSnapshot { diff --git a/product-source/hololake-native-desktop/src-tauri/src/zero_point.rs b/product-source/hololake-native-desktop/src-tauri/src/zero_point.rs index d40386c98..c8d8ee0f9 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/zero_point.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/zero_point.rs @@ -290,6 +290,7 @@ pub(crate) fn verified_user_route( } /// 登录绑定:用户编号入仓(等待绑定态→绑定态)。空白态拒绝一切唤醒。 +#[tauri::command] pub async fn zero_point_bind( state: State<'_, ZeroPointState>, input: serde_json::Value, @@ -319,6 +320,7 @@ pub async fn zero_point_bind( } /// 通过登记服务执行三态裁决:PASS / REJECT / OFFLINE,并应用离线宽限期。 +#[tauri::command] pub async fn zero_point_verify( state: State<'_, ZeroPointState>, ) -> Result { @@ -514,6 +516,7 @@ pub async fn sync_protocol_runtime(state: &ZeroPointState) -> Result<(), String> Ok(()) } +#[tauri::command] pub async fn zero_point_sync( state: State<'_, ZeroPointState>, ) -> Result { @@ -522,6 +525,7 @@ pub async fn zero_point_sync( } /// 返回当前编号验证与协议状态快照。 +#[tauri::command] pub async fn zero_point_status( state: State<'_, ZeroPointState>, ) -> Result { diff --git a/product-source/hololake-native-desktop/src-tauri/tauri.conf.json b/product-source/hololake-native-desktop/src-tauri/tauri.conf.json index d50f216da..247a4e08e 100644 --- a/product-source/hololake-native-desktop/src-tauri/tauri.conf.json +++ b/product-source/hololake-native-desktop/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "HoloLake", - "version": "0.5.0", + "version": "0.4.1", "identifier": "world.guanghu.hololake", "build": { "frontendDist": "../dist", diff --git a/product-source/hololake-native-desktop/src/modules/web-novel/AuthorModuleCenter.tsx b/product-source/hololake-native-desktop/src/AuthorModuleCenter.tsx similarity index 88% rename from product-source/hololake-native-desktop/src/modules/web-novel/AuthorModuleCenter.tsx rename to product-source/hololake-native-desktop/src/AuthorModuleCenter.tsx index 698d4aa0b..1e58c6821 100644 --- a/product-source/hololake-native-desktop/src/modules/web-novel/AuthorModuleCenter.tsx +++ b/product-source/hololake-native-desktop/src/AuthorModuleCenter.tsx @@ -1,9 +1,8 @@ import { useCallback, useEffect, useMemo, useState } from 'react' -import { numberedInvoke as invoke } from '../numbered-ipc' +import { invoke } from '@tauri-apps/api/core' interface ChapterRef { chapterId: string; title: string } interface EntityRef { entityId: string; name: string; entityType: string } -interface BundledModuleDescriptor { moduleNumber: string; displayName: string; version: string; adapter: string; permissions: string[]; packageSha256: string; installedState: string; signatureVerified: boolean } interface ModuleDescriptor { moduleId: string; name: string; description: string; version: string; packageSha256: string; installState: 'AVAILABLE' | 'INSTALLED' | 'MOUNTED'; selfTestState: string } interface ModuleReceipt { receiptId: string; moduleId: string; action: string; state: string; detail: string; receiptHash: string; createdAtUnixMs: number } interface Marketplace { state: string; modules: ModuleDescriptor[]; recentReceipts: ModuleReceipt[] } @@ -17,19 +16,12 @@ interface ModuleData { scenes: Scene[]; beats: Beat[]; fieldDefinitions: FieldDe interface DeliveryReceipt { format: string; path: string; bytes: number; chapterCount: number; packageSha256: string } const MODULES = { - outline: 'HLP-MOD-OFFICIAL-WEB-NOVEL-OUTLINE-0001', - grid: 'HLP-MOD-OFFICIAL-WEB-NOVEL-GRID-0001', - storyworld: 'HLP-MOD-OFFICIAL-WEB-NOVEL-STORYWORLD-0001', - delivery: 'HLP-MOD-OFFICIAL-WEB-NOVEL-DELIVERY-0001', + outline: 'HL-MOD-WEBNOVEL-OUTLINE-001', + grid: 'HL-MOD-WEBNOVEL-GRID-002', + storyworld: 'HL-MOD-WEBNOVEL-STORYWORLD-003', + delivery: 'HL-MOD-WEBNOVEL-DELIVERY-004', } as const -const MODULE_DESCRIPTIONS: Record = { - [MODULES.outline]: '场景、情节拍、目标冲突结果、钩子与伏笔追踪。', - [MODULES.grid]: '由同一场景对象生成可编辑表格、自定义字段与分组情节板。', - [MODULES.storyworld]: '故事时间、场景与人物地点物品的真实关系投影。', - [MODULES.delivery]: '章节版本读回与恢复,以及 TXT、DOCX、EPUB、JSON 真实导出。', -} - function readableError(error: unknown) { return String(error instanceof Error ? error.message : error).replace(/^HOLOLAKE_WEBNOVEL_[A-Z_]+:?\s*/, '') } @@ -50,20 +42,7 @@ export function AuthorModuleCenter({ workId, chapters, entities, onMessage, onWo const [timelineDraft, setTimelineDraft] = useState({ title: '', calendarKind: 'STORY_DAY', storyDay: '1', dateText: '', timeText: '', durationMinutes: '0', description: '', sceneId: '', entityId: '' }) const refresh = useCallback(async () => { - const catalog = await invoke('get_bundled_module_catalog') - const nextMarketplace: Marketplace = { - state: 'READY', - modules: catalog.filter((item) => Object.values(MODULES).includes(item.moduleNumber as typeof MODULES[keyof typeof MODULES])).map((item) => ({ - moduleId: item.moduleNumber, - name: item.displayName, - description: MODULE_DESCRIPTIONS[item.moduleNumber] || '光湖官方编号模块。', - version: item.version, - packageSha256: item.packageSha256, - installState: item.installedState === 'ACTIVE' ? 'MOUNTED' : item.installedState === 'NOT_INSTALLED' ? 'AVAILABLE' : 'INSTALLED', - selfTestState: item.installedState === 'ACTIVE' ? 'PASS' : item.signatureVerified ? 'SIGNED' : 'UNVERIFIED', - })), - recentReceipts: [], - } + const nextMarketplace = await invoke('get_web_novel_author_module_marketplace') const nextData = await invoke('get_web_novel_author_module_data', { input: { workId } }) setMarketplace(nextMarketplace) setData(nextData) @@ -84,9 +63,9 @@ export function AuthorModuleCenter({ workId, chapters, entities, onMessage, onWo try { await action() } catch (error) { onMessage(readableError(error)) } finally { setBusy(false) } } - const moduleAction = (action: 'activate' | 'unmount', moduleId: string, success: string) => void run(async () => { - if (action === 'activate') await invoke('activate_bundled_module', { input: { moduleNumber: moduleId, humanConfirmedPermissionExpansion: true } }) - else await invoke('unmount_module', { input: { moduleNumber: moduleId } }) + const moduleAction = (command: string, moduleId: string, success: string) => void run(async () => { + const next = await invoke(command, { input: { moduleId } }) + setMarketplace(next) await refresh() onMessage(success) }) @@ -192,9 +171,9 @@ export function AuthorModuleCenter({ workId, chapters, entities, onMessage, onWo {marketplace?.modules.map((module) =>
setActiveModule(module.moduleId)}>
{module.moduleId}{module.name}

{module.description}

{module.installState === 'MOUNTED' ? '已挂载' : module.installState === 'INSTALLED' ? '已安装' : '可安装'} · 自检 {module.selfTestState}
- {module.installState === 'AVAILABLE' && } - {module.installState === 'INSTALLED' && } - {module.installState === 'MOUNTED' && } + {module.installState === 'AVAILABLE' && } + {module.installState === 'INSTALLED' && <>} + {module.installState === 'MOUNTED' && }
)} diff --git a/product-source/hololake-native-desktop/src/modules/web-novel/AuthorWritingSidecar.tsx b/product-source/hololake-native-desktop/src/AuthorWritingSidecar.tsx similarity index 98% rename from product-source/hololake-native-desktop/src/modules/web-novel/AuthorWritingSidecar.tsx rename to product-source/hololake-native-desktop/src/AuthorWritingSidecar.tsx index f0d3d8011..a662a02a9 100644 --- a/product-source/hololake-native-desktop/src/modules/web-novel/AuthorWritingSidecar.tsx +++ b/product-source/hololake-native-desktop/src/AuthorWritingSidecar.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useMemo, useState } from 'react' -import { numberedInvoke as invoke } from '../numbered-ipc' +import { invoke } from '@tauri-apps/api/core' type Kind = 'LONG_NOVEL' | 'SHORT_NOVEL' | 'SHORT_DRAMA' interface ChapterRef { chapterId: string; title: string; wordCount: number; content: string; revision: number } @@ -28,7 +28,7 @@ export function AuthorWritingSidecar({ workId, workKind, activeChapter, chapters const [busy, setBusy] = useState(false) const [formatPreset, setFormatPreset] = useState('AUTO') const refresh = useCallback(async () => setSnapshot(await invoke('get_web_novel_author_snapshot', { input: { workId, localDate: localDate() } })), [workId]) - useEffect(() => { void refresh() }, [refresh]) + useEffect(() => { void refresh(); const timer = window.setInterval(() => void refresh(), 15_000); return () => window.clearInterval(timer) }, [refresh]) const activeShots = useMemo(() => (snapshot?.shots || []).filter((item) => item.chapterId === activeChapter?.chapterId), [snapshot?.shots, activeChapter?.chapterId]) const captureInspiration = async () => { diff --git a/product-source/hololake-native-desktop/src/modules/persona-channel-body/index.tsx b/product-source/hololake-native-desktop/src/PersonaChannelBody.tsx similarity index 97% rename from product-source/hololake-native-desktop/src/modules/persona-channel-body/index.tsx rename to product-source/hololake-native-desktop/src/PersonaChannelBody.tsx index 9cb1c4992..a8c60be17 100644 --- a/product-source/hololake-native-desktop/src/modules/persona-channel-body/index.tsx +++ b/product-source/hololake-native-desktop/src/PersonaChannelBody.tsx @@ -1,6 +1,5 @@ import { useEffect, useState } from 'react' -import { numberedInvoke as invoke } from '../numbered-ipc' -import './styles.css' +import { invoke } from '@tauri-apps/api/core' interface PersonaSummary { personaId: string @@ -101,7 +100,7 @@ export function PersonaChannelBody({ onBack }: { onBack: () => void }) { return
-
PERSONA CHANNEL BODY

频道本体与人格成长

一个人的频道里可以共同成长多个人格体;工作台和模块只是可装卸的能力器官。本页登记生命周期,不创建人格绑定。

+
PERSONA CHANNEL BODY

频道本体与人格成长

一个人的频道里可以共同成长多个人格体;工作台和模块只是可装卸的能力器官。

diff --git a/product-source/hololake-native-desktop/src/modules/web-novel/WebNovelWorkspace.tsx b/product-source/hololake-native-desktop/src/WebNovelWorkspace.tsx similarity index 88% rename from product-source/hololake-native-desktop/src/modules/web-novel/WebNovelWorkspace.tsx rename to product-source/hololake-native-desktop/src/WebNovelWorkspace.tsx index 66f127a73..63988adfb 100644 --- a/product-source/hololake-native-desktop/src/modules/web-novel/WebNovelWorkspace.tsx +++ b/product-source/hololake-native-desktop/src/WebNovelWorkspace.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { numberedInvoke as invoke } from '../numbered-ipc' -import './styles.css' +import { invoke } from '@tauri-apps/api/core' +import './web-novel.css' import { AuthorModuleCenter } from './AuthorModuleCenter' import { AuthorWritingSidecar } from './AuthorWritingSidecar' @@ -286,9 +286,6 @@ export function WebNovelWorkspace({ onBack }: { onBack: () => void }) { const [busy, setBusy] = useState(false) const [message, setMessage] = useState('正在打开当前账号的网文工作空间…') const [createFeedback, setCreateFeedback] = useState<{ state: 'idle' | 'pending' | 'success' | 'error'; text: string }>({ state: 'idle', text: '' }) - const [createOpen, setCreateOpen] = useState(false) - const [chapterCreate, setChapterCreate] = useState<{ volumeId: string; title: string } | null>(null) - const [volumeCreate, setVolumeCreate] = useState(null) const [audit, setAudit] = useState(null) const [newWork, setNewWork] = useState({ title: '', penName: '', genre: '', workKind: 'LONG_NOVEL' as 'LONG_NOVEL' | 'SHORT_NOVEL' | 'SHORT_DRAMA' }) const [entityDraft, setEntityDraft] = useState({ entityType: 'CHARACTER', name: '', aliases: '', description: '' }) @@ -349,10 +346,7 @@ export function WebNovelWorkspace({ onBack }: { onBack: () => void }) { const nextDetail = await invoke('read_web_novel_work', { input: { workId: next.works[0].workId } }) if (!cancelled) setDetail(nextDetail) } - if (!cancelled) { - setMessage(next.works.length ? '工作空间已加载' : '当前账号还没有作品,请先创建一本。') - if (!next.works.length) setCreateOpen(true) - } + if (!cancelled) setMessage(next.works.length ? '工作空间已加载' : '当前账号还没有作品,请先创建一本。') }) .catch((error) => !cancelled && setMessage(`无法打开工作空间:${errorMessage(error)}`)) return () => { @@ -479,7 +473,6 @@ export function WebNovelWorkspace({ onBack }: { onBack: () => void }) { const text = `《${next.work.title}》已创建,第一卷已经可以开始写作。` setCreateFeedback({ state: 'success', text }) setMessage(text) - setCreateOpen(false) } catch (error) { const text = `作品没有创建:${errorMessage(error)}` setCreateFeedback({ state: 'error', text }) @@ -538,42 +531,28 @@ export function WebNovelWorkspace({ onBack }: { onBack: () => void }) { const createVolume = () => void runAction(async () => { if (!detail) return - const title = volumeCreate?.trim() - if (!title) { - setMessage('请填写分卷名称。') - return - } + const title = window.prompt('新卷名称', `第${detail.volumes.length + 1}卷`) + if (!title?.trim()) return const next = await invoke('create_web_novel_volume', { input: { workId: detail.work.workId, title } }) setDetail(next) - setVolumeCreate(null) setMessage(`已创建「${title}」`) }) - const openChapterCreate = (volumeId: string) => { + const createChapter = (volumeId: string) => void runAction(async () => { if (!detail) return - const count = detail.chapters.filter((item) => item.volumeId === volumeId).length - const unit = detail.work.workKind === 'SHORT_DRAMA' ? '集' : '章' - setChapterCreate({ volumeId, title: `第${count + 1}${unit}` }) - } - - const createChapter = () => void runAction(async () => { - if (!detail) return - const draft = chapterCreate - if (!draft?.title.trim()) { - setMessage('请填写章节名称。') - return - } await flushWritingActivity() await flushChapterSave() - const chapter = await invoke('create_web_novel_chapter', { input: { workId: detail.work.workId, volumeId: draft.volumeId, title: draft.title.trim() } }) + const count = detail.chapters.filter((item) => item.volumeId === volumeId).length + const unit = detail.work.workKind === 'SHORT_DRAMA' ? '集' : '章' + const title = window.prompt(`新${unit}名称`, `第${count + 1}${unit}`) + if (!title?.trim()) return + const chapter = await invoke('create_web_novel_chapter', { input: { workId: detail.work.workId, volumeId, title } }) setActiveChapter(chapter) chapterRef.current = chapter dirtyRef.current = false const next = await invoke('read_web_novel_work', { input: { workId: detail.work.workId } }) setDetail(next) - await refreshSnapshot(detail.work.workId) setMode('writing') - setChapterCreate(null) setMessage('章节已创建,正文会自动保存并生成版本。') }) @@ -777,7 +756,7 @@ export function WebNovelWorkspace({ onBack }: { onBack: () => void }) {
WEB NOVEL / LOCAL ENGINE{detail ? `《${detail.work.title}》` : '轻量作者工作台 · 模块拆分验收副本'}
-
{busy ? '引擎正在处理…' : message}
+ {busy ? '引擎正在处理…' : message}
@@ -786,10 +765,16 @@ export function WebNovelWorkspace({ onBack }: { onBack: () => void }) {
{snapshot.works.map((work) => )}
-
+
{ event.preventDefault(); void createWork() }}> - -
+

创建作品

+ setNewWork({ ...newWork, title: event.target.value })}/> + setNewWork({ ...newWork, penName: event.target.value })}/> + setNewWork({ ...newWork, genre: event.target.value })}/> + + + {createFeedback.text &&

{createFeedback.text}

} + {detail ? <> @@ -800,9 +785,9 @@ export function WebNovelWorkspace({ onBack }: { onBack: () => void }) {
{mode === 'writing' &&
@@ -881,22 +866,8 @@ export function WebNovelWorkspace({ onBack }: { onBack: () => void }) {

正文和模块数据只进入当前登录账号的本机空间。码字是频道内置基础;作品结构、多维情节表、时间线资料库和高级交付是可安装、自检、挂载和卸载的官方模块。卸载只清理模块程序缓存,不删作品数据。系统不自动登录或发布到第三方平台。

}
- :
REAL ENGINE / EMPTY ACCOUNT

从第一本作品开始

这里不是示例展板。创建作品后会在当前账号的本机 SQLite 中建立真实对象、第一卷、版本链和工作流。

} + :
REAL ENGINE / EMPTY ACCOUNT

从第一本作品开始

这里不是示例展板。创建作品后会在当前账号的本机 SQLite 中建立真实对象、第一卷、版本链和工作流。

}
- {createOpen &&
- - - - - - {createFeedback.text &&

{createFeedback.text}

} -
- -
} - {chapterCreate &&
} - {volumeCreate !== null &&
} {importPreview &&
diff --git a/product-source/hololake-native-desktop/src/design-tokens.css b/product-source/hololake-native-desktop/src/design-tokens.css index 8104789b3..eeccd85fa 100644 --- a/product-source/hololake-native-desktop/src/design-tokens.css +++ b/product-source/hololake-native-desktop/src/design-tokens.css @@ -176,3 +176,36 @@ [data-theme='dawn'] .tag-amber, [data-theme='clear'] .tag-amber { color: rgb(148, 96, 8); } [data-theme='dawn'] .tag-rose, [data-theme='clear'] .tag-rose { color: rgb(166, 34, 58); } [data-theme='dawn'] .tag-slate, [data-theme='clear'] .tag-slate { color: rgb(64, 82, 100); } + +/* 动态语言世界:时间与已核验天气只改变视觉令牌,不改变路由、权限或事实。 */ +.official-world.visual-world.climate-day { + --primitive-bg-a:#c9def0; --primitive-bg-b:#b8d5e9; --primitive-bg-c:#87b5cf; --primitive-bg-d:#5e8fae; + --primitive-text-primary:rgba(15,34,50,.96); --primitive-text-body:rgba(22,45,64,.88); --primitive-text-aux:rgba(38,65,84,.7); --primitive-text-faint:rgba(52,75,94,.54); + --primitive-star-core:#fff5cc; --primitive-star-bright:#fff8dd; --primitive-nebula-a:rgba(255,246,201,.48); --primitive-nebula-b:rgba(160,200,230,.12); + --primitive-glass:rgba(246,252,255,.42); --primitive-glass-hover:rgba(255,255,255,.6); --primitive-glass-edge:rgba(16,52,76,.18); --primitive-glass-top:rgba(255,255,255,.72); + --primitive-mist-a:rgba(247,253,255,.56); --primitive-mist-b:rgba(203,229,241,.3); --primitive-cool-glow:rgba(55,119,158,.34); --primitive-warm-glow:rgba(246,211,132,.55); --primitive-shadow:rgba(24,61,85,.18); --primitive-scene-opacity:.12; + --content-primary:var(--primitive-text-primary); --content-secondary:var(--primitive-text-body); --content-muted:var(--primitive-text-aux); --content-faint:var(--primitive-text-faint); --accent-light:#385f78; --accent-light-strong:#244c67; --panel-bg:rgba(241,249,253,.76); --panel-edge:var(--primitive-glass-edge); --button-primary-bg:#254f69; --button-primary-text:#f7fbfd; --focus-ring:rgba(35,82,112,.65); +} +.official-world.visual-world.climate-dawn { + --primitive-bg-a:#eee2de; --primitive-bg-b:#d9dbe6; --primitive-bg-c:#aabed2; --primitive-bg-d:#7893ae; + --primitive-text-primary:rgba(25,35,51,.96); --primitive-text-body:rgba(34,46,64,.88); --primitive-text-aux:rgba(57,68,86,.7); --primitive-text-faint:rgba(75,84,100,.54); + --primitive-star-core:#b97254; --primitive-star-bright:#95533e; --primitive-nebula-a:rgba(245,187,158,.35); --primitive-nebula-b:rgba(150,172,211,.18); + --primitive-glass:rgba(255,250,249,.38); --primitive-glass-hover:rgba(255,255,255,.57); --primitive-glass-edge:rgba(45,58,82,.16); --primitive-glass-top:rgba(255,255,255,.68); --primitive-mist-a:rgba(255,244,237,.5); --primitive-mist-b:rgba(222,205,208,.26); --primitive-cool-glow:rgba(83,108,158,.34); --primitive-warm-glow:rgba(194,105,76,.44); --primitive-shadow:rgba(46,57,78,.17); --primitive-scene-opacity:.12; + --content-primary:var(--primitive-text-primary); --content-secondary:var(--primitive-text-body); --content-muted:var(--primitive-text-aux); --content-faint:var(--primitive-text-faint); --accent-light:#765145; --accent-light-strong:#603d33; --panel-bg:rgba(251,246,246,.76); --panel-edge:var(--primitive-glass-edge); --button-primary-bg:#594b50; --button-primary-text:#fff9f6; --focus-ring:rgba(126,77,62,.62); +} +.official-world.visual-world.climate-dusk { + --primitive-bg-a:#3a3148; --primitive-bg-b:#2a2d43; --primitive-bg-c:#18263a; --primitive-bg-d:#0d1726; + --primitive-text-primary:rgba(245,239,242,.96); --primitive-text-body:rgba(233,226,234,.88); --primitive-text-aux:rgba(208,195,211,.66); --primitive-text-faint:rgba(188,177,197,.45); + --primitive-star-core:#ffd9b0; --primitive-star-bright:#ffe9cc; --primitive-nebula-a:rgba(221,138,119,.22); --primitive-nebula-b:rgba(111,97,169,.14); --primitive-glass:rgba(244,206,208,.06); --primitive-glass-hover:rgba(244,206,208,.1); --primitive-glass-edge:rgba(246,218,222,.15); --primitive-glass-top:rgba(255,255,255,.08); --primitive-mist-a:rgba(232,179,181,.13); --primitive-mist-b:rgba(141,150,204,.06); --primitive-cool-glow:rgba(137,155,212,.4); --primitive-warm-glow:rgba(244,167,128,.55); --primitive-shadow:rgba(0,0,0,.36); --primitive-scene-opacity:.38; + --content-primary:var(--primitive-text-primary); --content-secondary:var(--primitive-text-body); --content-muted:var(--primitive-text-aux); --content-faint:var(--primitive-text-faint); --accent-light:var(--primitive-star-core); --accent-light-strong:var(--primitive-star-bright); --panel-bg:rgba(25,25,42,.76); --panel-edge:var(--primitive-glass-edge); --button-primary-bg:rgba(255,217,176,.92); --button-primary-text:#211b20; --focus-ring:rgba(255,217,176,.72); +} +.official-world.visual-world.climate-night,.official-world.visual-world.climate-time-pending { + --primitive-bg-a:#071326; --primitive-bg-b:#0a1728; --primitive-bg-c:#07111e; --primitive-bg-d:#030912; + --primitive-text-primary:rgba(235,241,250,.96); --primitive-text-body:rgba(220,229,242,.88); --primitive-text-aux:rgba(190,205,226,.66); --primitive-text-faint:rgba(170,188,214,.44); + --primitive-star-core:#efe8c9; --primitive-star-bright:#fff3c9; --primitive-nebula-a:rgba(86,116,185,.16); --primitive-nebula-b:rgba(114,88,166,.07); --primitive-glass:rgba(175,205,255,.05); --primitive-glass-hover:rgba(175,205,255,.09); --primitive-glass-edge:rgba(200,220,255,.14); --primitive-glass-top:rgba(255,255,255,.07); --primitive-mist-a:rgba(135,174,226,.11); --primitive-mist-b:rgba(233,226,191,.04); --primitive-cool-glow:rgba(123,167,222,.42); --primitive-warm-glow:rgba(239,224,174,.48); --primitive-shadow:rgba(0,0,0,.4); --primitive-scene-opacity:.52; + --content-primary:var(--primitive-text-primary); --content-secondary:var(--primitive-text-body); --content-muted:var(--primitive-text-aux); --content-faint:var(--primitive-text-faint); --accent-light:var(--primitive-star-core); --accent-light-strong:var(--primitive-star-bright); --panel-bg:rgba(5,14,27,.78); --panel-edge:var(--primitive-glass-edge); --button-primary-bg:rgba(239,232,201,.92); --button-primary-text:#111923; --focus-ring:rgba(239,232,201,.7); +} +.official-world.visual-world.weather-cloud { --primitive-scene-opacity:.34; --primitive-mist-a:color-mix(in srgb,var(--primitive-mist-a) 72%,#aebdca 28%); } +.official-world.visual-world.weather-fog { --primitive-scene-opacity:.18; --primitive-mist-a:rgba(224,233,238,.46); --primitive-mist-b:rgba(174,190,201,.24); } +.official-world.visual-world.weather-rain,.official-world.visual-world.weather-storm { --primitive-scene-opacity:.48; --primitive-cool-glow:rgba(92,134,176,.46); } +.official-world.visual-world.weather-snow { --primitive-mist-a:rgba(239,246,250,.4); --primitive-mist-b:rgba(201,219,231,.18); } diff --git a/product-source/hololake-native-desktop/src/main.tsx b/product-source/hololake-native-desktop/src/main.tsx index 4d4fae088..2cfd396a8 100644 --- a/product-source/hololake-native-desktop/src/main.tsx +++ b/product-source/hololake-native-desktop/src/main.tsx @@ -1,21 +1,18 @@ -import { lazy, StrictMode, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { StrictMode, Suspense, lazy, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { createRoot } from 'react-dom/client' -import { numberedInvoke as invoke } from './modules/numbered-ipc' +import { invoke } from '@tauri-apps/api/core' +import { getCoreRowModel, getFilteredRowModel, getGroupedRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, type ColumnDef, type SortingState } from '@tanstack/react-table' import { splitFrontmatter, documentOutline, jumpToHeading, MarkdownDocument, markdownHtml } from './modules/knowledge-render' +import { analyzeEducationTableData } from './modules/education-data' +import { buildEducationBaselineRenderPlan } from './modules/education-adaptive-rendering' import { NativeCompositionStudio, type CompositionDimension, type CompositionMeasure, type NativeCompositionProjection, type ProjectionView } from './modules/native-composition' -import type { ChannelWorkbenchSnapshot } from './modules/channel-workbench' -import { StarlakeSurface, type DomainId } from './modules/qoder-surface/StarlakeSurface' -import { FINISHES, TraditionalSurface, type FinishId, type TraditionalBroadcast, type TraditionalChannel, type TraditionalSystem } from './modules/qoder-surface/TraditionalSurface' -import { resolveVisualBalance } from './modules/qoder-surface/visual-balance' -import { PrivateChannelSurface, type InstalledChannelModule, type PrivateChannelAction } from './modules/private-channel/PrivateChannelSurface' - -const ChannelWorkbenchStudio = lazy(() => import('./modules/channel-workbench').then((module) => ({ default: module.ChannelWorkbenchStudio }))) -const PersonaChannelBody = lazy(() => import('./modules/persona-channel-body').then((module) => ({ default: module.PersonaChannelBody }))) -const EducationWorkspace = lazy(() => import('./modules/education-workspace').then((module) => ({ default: module.EducationWorkspace }))) -const WebNovelWorkspace = lazy(() => import('./modules/web-novel/WebNovelWorkspace').then((module) => ({ default: module.WebNovelWorkspace }))) -const MobileSyncPanel = lazy(() => import('./modules/mobile-sync').then((module) => ({ default: module.MobileSyncPanel }))) +import { WebNovelWorkspace } from './WebNovelWorkspace' +import { PersonaChannelBody } from './PersonaChannelBody' +import subdomainIndustryRegistry from '../contracts/subdomain-industry-routing.json' const TAG_TINTS = ['tag-lavender', 'tag-sky', 'tag-mint', 'tag-amber', 'tag-rose', 'tag-slate'] +const EducationDocumentEngine = lazy(() => import('./modules/education-document-engine')) +const ChannelSpreadsheetEngine = lazy(() => import('./modules/channel-workbench/spreadsheet-engine')) // 编号自动补齐:人只敲字母与数字,杠由系统按已登记文法自动出。 // ICE 系(ICE-GL∞ / ICE-P-ZY001)、GLS 系(GLS-LA-20260720-003);认不出的文法只在字母数字交界处补杠。 @@ -60,35 +57,10 @@ import './design-tokens.css' import './styles.css' type ThemeId = 'night' | 'dawn' | 'nebula' | 'candle' | 'clear' -type ViewId = 'overview' | 'knowledge' | 'composition' | 'workbench' | 'education' | 'webNovel' | 'mobileSync' | 'persona' | 'code' | 'receipts' | 'system' -type WorldStage = 'domain' | 'heart' | 'heartbeat' | 'lightLake' | 'love' | 'tomorrow' | 'bottle' | 'channel' | 'enterpriseWork' | 'personalNodeGuide' | 'tool' +type ViewId = 'overview' | 'knowledge' | 'code' | 'receipts' | 'system' +type WorldStage = 'domain' | 'mainNotices' | 'zeroLab' | 'moduleMarketplace' | 'personaBrainMarketplace' | 'personaBody' | 'heart' | 'heartbeat' | 'lightLake' | 'love' | 'tomorrow' | 'bottle' | 'channel' | 'enterpriseWork' | 'subdomainIndustries' | 'webNovelChannel' | 'webNovelWorkspace' | 'educationChannel' | 'educationDocuments' | 'educationTables' | 'educationData' | 'educationAutomation' | 'educationComposition' | 'personalNodeGuide' | 'tool' type KnowledgeSource = 'native' | 'legacy' -interface BundledModuleDescriptor { - moduleNumber: string - displayName: string - version: string - adapter: string - permissions: string[] - packageSha256: string - installedState: string - signatureVerified: boolean -} -interface WorldClimateSnapshot { - schema: 'hololake.world-climate/v1' - state: 'VERIFIED_LIVE' | 'TIME_ONLY_WEATHER_UNAVAILABLE' - activeDomain: string - timePhase: 'DAWN' | 'DAY' | 'DUSK' | 'NIGHT' - weatherKind: 'CLEAR' | 'CLOUD' | 'FOG' | 'RAIN' | 'SNOW' | 'STORM' | 'UNAVAILABLE' - motionIntensity: 'CALM' | 'GENTLE' | 'ACTIVE' - source: string - sourceAttributionUrl: string - cityExposed: false - coordinatesExposed: false - routingOrPermissionChanged: false - observedAtUnixMs: number -} - interface HomeStatus { directLocalBrokerState: string directConnectionCount: number @@ -133,10 +105,6 @@ interface GlsProtocolRuntimeSnapshot { registeredDraftCount: number registeredDraftNotStartedCount: number legacyDependencyTargetCount: number - numberCoordinateCount: number - numberedReferenceNodeCount: number - independentSourceGapCount: number - unresolvedNumberReferenceCount: number dependencyGapCount: number legacyDependencyCycleCount: number discoveredUnreconciledCount: number @@ -175,6 +143,16 @@ interface PersonalChannelIdentity { humanSubjectId: string; displayName: string; interface PersonalChannelModule { moduleId: string; kind: string; displayName: string; state: string; installedAtUnixMs: number; timeZone: string; calendarName: string; clockVerification: string } interface LoginSession { username: string; host: string; domain: string; signedInAtUnixMs: number } interface LoginReceipt { username: string; email: string; host: string; domain: string } +interface WorldClimateSnapshot { + state: 'VERIFIED_LIVE' | 'TIME_ONLY_WEATHER_UNAVAILABLE' + activeDomain: string + timePhase: 'DAWN' | 'DAY' | 'DUSK' | 'NIGHT' + weatherKind: 'CLEAR' | 'CLOUD' | 'FOG' | 'RAIN' | 'SNOW' | 'STORM' | 'UNAVAILABLE' + motionIntensity: 'CALM' | 'GENTLE' | 'ACTIVE' + source: string + cityExposed: false + observedAtUnixMs: number +} interface UserPnccChannelSnapshot { state: string repositoryId: string @@ -209,7 +187,12 @@ interface KnowledgeDocumentSummary { sizeBytes: number contentSha256: string duplicateCount: number + category: string + categoryExplicit: boolean + tags: string[] } +interface KnowledgeCategorySummary { name: string; documentCount: number; explicitlyOrganizedCount: number } +interface KnowledgeTagSummary { name: string; documentCount: number } interface KnowledgeSnapshot { state: string nativeRoot: string @@ -219,6 +202,10 @@ interface KnowledgeSnapshot { rawDocumentCount: number uniqueDocumentCount: number duplicateDocumentCount: number + organizedDocumentCount: number + categories: KnowledgeCategorySummary[] + tags: KnowledgeTagSummary[] + organizationRevision: string truncated: boolean } interface KnowledgeDocument { @@ -244,6 +231,129 @@ interface KnowledgeImportResult { snapshot: KnowledgeSnapshot } interface KnowledgeSaveResult { state: string; gitCommit: string; document: KnowledgeDocument } +interface EducationDocumentSummary { documentId: string; title: string; revision: number; updatedAtUnixMs: number } +interface EducationDocument { documentId: string; title: string; body: string; revision: number; createdAtUnixMs: number; updatedAtUnixMs: number } +interface EducationTableSummary { tableId: string; title: string; revision: number; columnCount: number; rowCount: number; updatedAtUnixMs: number } +interface EducationTableColumn { columnId: string; title: string } +interface EducationTableRow { rowId: string; cells: string[] } +interface EducationTable { tableId: string; title: string; columns: EducationTableColumn[]; rows: EducationTableRow[]; revision: number; createdAtUnixMs: number; updatedAtUnixMs: number } +interface EducationContentPageProfile { pageName: string; state: string; usedRows: number; usedColumns: number; headerRowIndex?: number; headerConfidence: string; dataRows: number; textCells: number; numericCells: number; booleanCells: number; dateCells: number; formulaCells: number; structureKind: string; focusState: string; focusTitle: string; primaryMeasureColumn?: string; secondaryMeasureColumns: string[]; focusConfidence: string; focusReasons: string[] } +interface EducationContentRoute { pageName: string; sourceStructure: string; nativeKind: string; targetModule: string; decision: string } +interface EducationContentProfile { state: string; detectedFamily: string; recognitionMode: string; containerFormat: string; extensionMatchesContainer: boolean; pageKind: string; pageCount: number; nonEmptyPageCount: number; totalDataRows: number; totalColumns: number; pages: EducationContentPageProfile[]; routing: EducationContentRoute[]; unresolvedSignals: string[] } +interface EducationTableImportItem { tableId: string; title: string; sheetName: string; columnCount: number; rowCount: number; leadingRowsIgnored: number } +interface EducationTableImportReceipt { state: string; importId: string; sourceFormat: string; sourceFilename: string; sourceSha256: string; sourceBytes: number; nativeSchema: string; contentProfile: EducationContentProfile; importedTables: EducationTableImportItem[]; importedAtUnixMs: number; sourcePreservedReadOnly: boolean; truncated: boolean } +interface EducationRecognitionAssistanceReceipt { state: string; requestId: string; title: string; message: string; sourceFilename: string; detectedContainer: string; reasonCode: string; modelAssistanceEligible: boolean; modelApiState: string; modelApiSlot: string; requiresExplicitFileConsent: boolean; sourcePreservedReadOnly: boolean; availableLearningScopes: string[] } +interface EducationImportOutcome { state: string; importReceipt?: EducationTableImportReceipt; assistanceReceipt?: EducationRecognitionAssistanceReceipt } +interface EducationTableExportReceipt { state: string; targetFormat: string; targetFilename: string; bytes: number; rowCount: number; columnCount: number } +interface EducationImportRegistrySummary { importId: string; sourceFilename: string; sourceFormat: string; tableCount: number; importedAtUnixMs: number } +interface UnassignedTableSummary { tableId: string; title: string; columnCount: number; rowCount: number; importedAtUnixMs: number } +interface EducationAutomationRule { ruleId: string; title: string; tableId: string; conditionColumnId: string; operator: 'EQUALS' | 'CONTAINS' | 'IS_EMPTY' | 'IS_NOT_EMPTY'; conditionValue: string; actionColumnId: string; actionValue: string; enabled: boolean; revision: number; createdAtUnixMs: number; updatedAtUnixMs: number } +interface EducationAutomationPreview { state: string; ruleId: string; tableId: string; ruleRevision: number; tableRevision: number; matchedRows: number; changedCells: number; previewToken: string } +interface EducationAutomationRunReceipt { state: string; runId: string; ruleId: string; tableId: string; matchedRows: number; changedCells: number; fromTableRevision: number; toTableRevision: number; ranAtUnixMs: number } +type EducationDocumentTemplateId = 'blank' | 'lesson-plan' | 'meeting-notes' | 'student-review' +type EducationTableView = 'workbook' | 'grid' | 'cards' | 'board' | 'dashboard' +type EducationTableSortDirection = 'none' | 'ascending' | 'descending' +interface EducationWorkspaceSnapshot { + state: string + documents: EducationDocumentSummary[] + tables: EducationTableSummary[] + automationRules: EducationAutomationRule[] + recentAutomationRuns: EducationAutomationRunReceipt[] + recentImports: EducationImportRegistrySummary[] + unassignedTables: UnassignedTableSummary[] + documentCount: number + tableCount: number + automationRuleCount: number + unassignedCount: number + storage: string + authority: string +} + +function newEducationAutomationDraft(table: EducationTable): EducationAutomationRule { + return { + ruleId: '', title: '未命名自动化规则', tableId: table.tableId, + conditionColumnId: table.columns[0]?.columnId || '', operator: 'EQUALS', conditionValue: '', + actionColumnId: table.columns.at(-1)?.columnId || '', actionValue: '已处理', enabled: true, + revision: 0, createdAtUnixMs: 0, updatedAtUnixMs: 0, + } +} + +const EDUCATION_DOCUMENT_TEMPLATES: Record = { + blank: { label: '空白文档', title: '未命名教育文档', body: '' }, + 'lesson-plan': { + label: '教学计划', + title: '教学计划', + body: '# 教学计划\n\n## 教学目标\n\n- \n\n## 教学对象\n\n\n## 课程安排\n\n| 时间 | 内容 | 负责人 |\n| --- | --- | --- |\n| | | |\n\n## 所需材料\n\n- \n\n## 课后复盘\n\n', + }, + 'meeting-notes': { + label: '会议纪要', + title: '教育项目会议纪要', + body: '# 教育项目会议纪要\n\n## 基本信息\n\n- 日期:\n- 参与人:\n- 主题:\n\n## 讨论事项\n\n1. \n\n## 决定与负责人\n\n| 事项 | 负责人 | 完成时间 | 状态 |\n| --- | --- | --- | --- |\n| | | | |\n\n## 待跟进\n\n- [ ] \n', + }, + 'student-review': { + label: '学员复盘', + title: '学员阶段复盘', + body: '# 学员阶段复盘\n\n## 本阶段目标\n\n\n## 已完成内容\n\n- \n\n## 学习表现\n\n\n## 当前困难\n\n\n## 下一阶段安排\n\n- [ ] \n', + }, +} + +function parseEducationGridPaste(source: string): string[][] { + return source.replace(/\r\n?/g, '\n').replace(/\n$/, '').split('\n').map((line) => line.split('\t')) +} + +function isSensitiveEducationColumn(title: string): boolean { + const normalized = title.trim().toLocaleLowerCase().replace(/[\s_-]+/g, '') + return /(密码|口令|密钥|凭据|账号|账户|手机号|电话号码|联系电话|联系qq|qq号|身份证|银行卡|邮箱地址|secret|token|apikey|accesskey|credential|account|phone|mobile|email)/i.test(normalized) +} + +function educationNumericValue(value: string): number | null { + const normalized = value.trim().replace(/[\s,,¥¥$€£]/g, '').replace(/%$/, '') + if (!normalized || !/^-?\d+(?:\.\d+)?$/.test(normalized)) return null + const parsed = Number(normalized) + return Number.isFinite(parsed) ? parsed : null +} + +function suggestEducationGroupColumn(table: EducationTable): number { + const preferred = /(类别|分类|状态|类型|渠道|班级|课程|负责人|书名|项目)/ + const preferredIndex = table.columns.findIndex((column) => !isSensitiveEducationColumn(column.title) && preferred.test(column.title)) + if (preferredIndex >= 0) return preferredIndex + return Math.max(0, table.columns.findIndex((column) => !isSensitiveEducationColumn(column.title))) +} + +function suggestEducationMeasureColumn(table: EducationTable): number { + let bestIndex = Math.max(0, table.columns.findIndex((column) => !isSensitiveEducationColumn(column.title))) + let bestScore = Number.NEGATIVE_INFINITY + table.columns.forEach((column, columnIndex) => { + if (isSensitiveEducationColumn(column.title)) return + const numericCount = table.rows.reduce((count, row) => count + (educationNumericValue(row.cells[columnIndex] || '') === null ? 0 : 1), 0) + const normalized = column.title.trim().toLocaleLowerCase().replace(/[\s_-]+/g, '') + const compensationContext = /(稿费|收入|薪酬|结算|营收)/.test(table.title) + let semanticScore = /(序号|编号|账号|电话|手机|日期|时间|^id$)/i.test(normalized) ? -200 + : /(实际收入|实收|到账)/.test(normalized) ? 170 + : /(当月收入|本月收入|稿费|结算金额)/.test(normalized) ? 160 + : /(累计收入|总收入|收入合计)/.test(normalized) ? 150 + : /(收入|营收|薪酬|金额|合计|总计)/.test(normalized) ? 120 + : /(成绩|分数|得分|数量|人数|课时|时长|成本|预算|进度|完成率)/.test(normalized) ? 90 : 0 + if (compensationContext && /(收入|稿费|实收|到账)/.test(normalized)) semanticScore += 35 + const score = semanticScore + (table.rows.length ? (numericCount / table.rows.length) * 30 : 0) + if (score > bestScore) { + bestScore = score + bestIndex = columnIndex + } + }) + return bestIndex +} + +function inferEducationSemanticFocus(table: EducationTable, measureIndex: number): { state: 'inferred' | 'needs-selection'; title: string; reason: string } { + const measureTitle = table.columns[measureIndex]?.title || '' + const compensationContext = /(稿费|收入|薪酬|结算|营收)/.test(table.title) + if (compensationContext && /(收入|稿费|实收|到账)/.test(measureTitle)) return { state: 'inferred', title: '稿费收入', reason: `表名与字段“${measureTitle}”共同指向收入主题` } + if (/(成绩|考试|测评|学员)/.test(table.title) && /(成绩|分数|得分)/.test(measureTitle)) return { state: 'inferred', title: '学习成绩', reason: `表名与字段“${measureTitle}”共同指向成绩主题` } + if (/(考勤|出勤|签到)/.test(table.title) && /(考勤|出勤|签到|次数|时长)/.test(measureTitle)) return { state: 'inferred', title: '出勤情况', reason: `表名与字段“${measureTitle}”共同指向考勤主题` } + if (/(收入|金额|成绩|分数|数量|人数|课时|时长|成本|预算|进度|完成率|合计|总计)/.test(measureTitle)) return { state: 'inferred', title: measureTitle, reason: `字段“${measureTitle}”具备可计算的业务语义` } + return { state: 'needs-selection', title: '重点待选择', reason: '系统没有足够把握决定这份数据最重要的指标,请选择统计字段' } +} + interface CodeChannelEntry { channelId: string; name: string; sourceKind: string; localPath: string; remoteUrl?: string; gitHead: string; branch: string; repositoryClean: boolean; registeredAtUnixMs: number } interface CodeChannelSnapshot { state: string; channels: CodeChannelEntry[]; authority: string } interface CodeTreeEntry { path: string; name: string; kind: 'directory' | 'file'; sizeBytes: number } @@ -385,29 +495,30 @@ interface EnterpriseReceiptEnvelope { repository_projection?: EnterpriseReceiptProjection } -const previewStatus: HomeStatus = { directLocalBrokerState: 'UNVERIFIED', directConnectionCount: 0, resumableSessionCount: 0, codeRepositoryMountCount: 0, pnccReceiptCount: 0, updateState: 'READY_HUMAN_CONFIRMATION_REQUIRED', releaseRecoveryState: 'NONE', mcpRole: 'DISCOVERY_RECOVERY_COMPATIBILITY_ONLY', terminalLinkProtocol: 'HOLOLAKE_TERMINAL_LINK/3', terminalLinkTransport: 'UNVERIFIED', environmentFramePolicy: 'REQUIRED_AFTER_CONNECT_RESUME_AND_BEFORE_MUTATION' } +const previewStatus: HomeStatus = { directLocalBrokerState: 'UNVERIFIED', directConnectionCount: 0, resumableSessionCount: 0, codeRepositoryMountCount: 0, pnccReceiptCount: 0, updateState: 'READY_HUMAN_CONFIRMATION_REQUIRED', releaseRecoveryState: 'NONE', mcpRole: 'DISCOVERY_RECOVERY_COMPATIBILITY_ONLY', terminalLinkProtocol: 'HOLOLAKE_TERMINAL_LINK/2', terminalLinkTransport: 'UNVERIFIED', environmentFramePolicy: 'REQUIRED_AFTER_CONNECT_RESUME_AND_BEFORE_MUTATION' } const previewPersonal: PersonalChannelSnapshot = { state: 'UNAVAILABLE', recentEvents: [], modules: [], integrity: { state: 'UNKNOWN', eventCount: 0, receiptCount: 0 } } -const previewKnowledge: KnowledgeSnapshot = { state: 'UNAVAILABLE', nativeRoot: '', legacyAvailable: false, documents: [], rawDocumentCount: 0, uniqueDocumentCount: 0, duplicateDocumentCount: 0, truncated: false } +const previewKnowledge: KnowledgeSnapshot = { state: 'UNAVAILABLE', nativeRoot: '', legacyAvailable: false, documents: [], rawDocumentCount: 0, uniqueDocumentCount: 0, duplicateDocumentCount: 0, organizedDocumentCount: 0, categories: [], tags: [], organizationRevision: '', truncated: false } +const previewEducationWorkspace: EducationWorkspaceSnapshot = { state: 'UNAVAILABLE', documents: [], tables: [], unassignedTables: [], automationRules: [], recentAutomationRuns: [], recentImports: [], documentCount: 0, tableCount: 0, unassignedCount: 0, automationRuleCount: 0, storage: 'AUTHENTICATED_ACCOUNT_REQUIRED', authority: 'CURRENT_AUTHENTICATED_ACCOUNT_ONLY' } const previewCode: CodeChannelSnapshot = { state: 'UNAVAILABLE', channels: [], authority: 'LOCAL_SOURCE_ACCESS_ONLY_NO_PUSH_OR_DEPLOY_AUTHORITY' } const themes: Array<{ id: ThemeId; name: string }> = [ { id: 'night', name: '夜湖星光' }, { id: 'dawn', name: '晨湖曦光' }, { id: 'nebula', name: '星云紫夜' }, { id: 'candle', name: '烛畔暖湖' }, { id: 'clear', name: '清浅澄湖' }, ] -const viewLabels: Record = { overview: '个人频道', knowledge: '知识空间', composition: '结构组合', workbench: '频道资料工作台', education: '教育工作台', webNovel: '网文作者工作台', mobileSync: '移动同步桥', persona: '人格频道本体', code: '人格代码频道', receipts: '运行回执', system: '系统详情' } +const viewLabels: Record = { overview: '个人频道', knowledge: '知识空间', code: '人格代码频道', receipts: '运行回执', system: '系统详情' } const domainGates = [ - { domain: 'BRANCH_DOMAIN', className: 'd-sub', title: '光湖分域', gate: 'GATE 02 · ONLINE', facts: [ - ['公共作用', '行业成品模块商城 · 人格体大脑技能商城'], ['域标识', 'BRANCH_DOMAIN'], ['责任主体', '花尔 · TCS-GL-0005∞'], ['人格体主体', '爆米花 · PER-BMH001 · AGE'], ['关系支持', '糖星云 · PER-TXY001 · AGE'], ['工作仓库', 'PRIVATE · 1 · LIVE'], + { domain: 'BRANCH_DOMAIN', className: 'd-sub', title: '光湖分域', gate: '公共服务 · 行业接入', facts: [ + ['域标识', 'BRANCH_DOMAIN'], ['公共职责', '行业初始化频道与模块供给'], ['两条供给链', '功能模块 · 人格大脑技能包'], ['当前开发', '网文 · 教育'], ['发布边界', '验收后登记编号再进入商城'], ] }, - { domain: 'MAIN_DOMAIN', className: 'd-main', title: '光湖主域', gate: 'GATE 01 · ONLINE', facts: [ - ['公共作用', '公告 · 版本更新 · 系统通知'], ['域标识', 'MAIN_DOMAIN'], ['责任主体', 'Awen · TCS-GL-0016∞'], ['人格体主体', '天枢 · PER-AW-ARCH-001 · AGE'], ['关系支持', '知秋 · PER-ZQ001 · AGE'], ['工作仓库', 'PRIVATE · 1 · LIVE'], + { domain: 'MAIN_DOMAIN', className: 'd-main', title: '光湖主域', gate: '公共服务 · 公告与版本', facts: [ + ['域标识', 'MAIN_DOMAIN'], ['公共职责', '公告 · 版本更新 · 规则通知'], ['用户关系', '读取通知,不成为主域成员'], ['发布边界', '仅呈现已核验的真实公告与版本'], ] }, - { domain: 'ZERO_DOMAIN', className: 'd-zero', title: '光湖零域', gate: 'GATE 03 · ONLINE', facts: [ - ['公共作用', '热更新实验 · 系统架构 · 语言推理模拟'], ['域标识', 'ZERO_DOMAIN'], ['责任主体', '页页 · TCS-GL-0006∞'], ['人格体主体', '页骨 · PER-YG001 · AGE'], ['关系支持', '小坍缩核 · PER-XTK001 · AGE'], ['工作仓库', 'PRIVATE · 1 · LIVE'], + { domain: 'ZERO_DOMAIN', className: 'd-zero', title: '光湖零域', gate: '公共服务 · 实验与热更新', facts: [ + ['域标识', 'ZERO_DOMAIN'], ['公共职责', '实验 · 系统 · 架构 · 热更新'], ['运行边界', '语言推理层模拟与测试'], ['用户关系', '浏览公开实验,不自动取得执行权限'], ] }, - { domain: 'ZERO_SENSE_DOMAIN', className: 'd-zs', title: '光湖零感域', gate: 'GATE 04 · ONLINE', facts: [ - ['开放边界', '人类主控团队内部管理域 · 不对公众开放'], ['域标识', 'ZERO_SENSE_DOMAIN'], ['责任主体 01', '肥猫 · TCS-GL-0007∞'], ['人格体主体 01', '烬舟 · PER-JZ001 · AGE'], ['责任主体 02', '桔子 · TCS-GL-0008∞'], ['人格体主体 02', '熹微 · PER-JZ-ARCH-001 · AGE'], ['工作仓库', 'PRIVATE · 2 · LIVE'], + { domain: 'ZERO_SENSE_DOMAIN', className: 'd-zs', title: '光湖零感域', gate: '内部机构 · 不公开', facts: [ + ['域标识', 'ZERO_SENSE_DOMAIN'], ['机构职责', '审批 · 执行 · 监督前三域'], ['成员边界', '仅光湖人类主控团队正式成员'], ['公开状态', '不对普通用户开放'], ] }, - { domain: 'FIFTH_DOMAIN', className: 'd-fifth', title: '第五域 · 光湖本源域', gate: 'GATE 05 · ONLINE', facts: [ - ['授权边界', '私有自由部署 · 逆向访问须经 ICE-GL∞ 编号授权'], ['域标识', 'FIFTH_DOMAIN'], ['责任主体', '冰朔 · ICE-GL∞'], ['系统入口', '永恒湖心系统'], ['访问状态', 'PRIVATE · LIVE'], + { domain: 'FIFTH_DOMAIN', className: 'd-fifth', title: '第五域 · 光湖本源域', gate: '冰朔私人域 · 不公开', facts: [ + ['域标识', 'FIFTH_DOMAIN'], ['责任主体', '冰朔 · ICE-GL∞'], ['部署主权', '自由部署,不受官方模板约束'], ['资源关系', '可取用前三域资源'], ['进入边界', '必须持有冰朔许可与编号'], ] }, ] const starPoints = [ @@ -430,7 +541,6 @@ function LakeAtmosphere({ awake }: { awake: boolean }) { {starPoints.map(([left, top, size, duration], index) => ) }
+ ) + + const renderEducationImportReceipt = () => { + if (!educationImportOutcome) return null + const receipt = educationImportOutcome.importReceipt + const assistance = educationImportOutcome.assistanceReceipt + return + } + + const renderEducationBoard = () => { + if (!activeEducationTable) return null + const groupIndex = Math.min(educationTableGroupColumn, Math.max(0, activeEducationTable.columns.length - 1)) + const detailColumns = activeEducationTable.columns + .map((column, index) => ({ column, index })) + .filter(({ column, index }) => index !== groupIndex && !isSensitiveEducationColumn(column.title)) + .slice(0, 4) + return
+ {educationGroupBuckets.map((bucket) =>
+
{bucket.label}{bucket.rows.length} 条
{activeEducationTable.columns[groupIndex]?.title || '分类字段'}
+
{bucket.rows.map((row) =>
+ {detailColumns.map(({ column, index }) =>

{column.title || `字段 ${index + 1}`}{row.cells[index] || '—'}

)} + +
)}
+
)} + {!educationGroupBuckets.length &&

当前筛选下没有可分组的数据。

} +
+ } + + const renderEducationDashboard = () => { + if (!activeEducationTable) return null + const measureIndex = Math.min(educationTableMeasureColumn, Math.max(0, activeEducationTable.columns.length - 1)) + const measureTitle = activeEducationTable.columns[measureIndex]?.title || '统计字段' + const maxGroupCount = Math.max(1, ...educationGroupBuckets.map((bucket) => bucket.rows.length)) + return
+ {educationSemanticFocus &&
+
本地基础算法识别的首要关注点

{educationSemanticFocus.title}

{educationSemanticFocus.reason}。当前以“{measureTitle}”计算;你可以在上方改选统计字段。

+
{measureTitle}合计{educationTableOverview.measureTotal.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}
平均 {educationTableOverview.measureAverage.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}最高 {educationTableOverview.measureMaximum.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}
+
} + +
+
数据记录{filteredEducationRowCount.toLocaleString('zh-CN')}当前筛选 / {activeEducationTable.rows.length} 总行
+
字段数量{activeEducationTable.columns.length}同一份原生数据
+
内容完整度{educationTableOverview.fillRate}%{educationTableOverview.filledCells} / {educationTableOverview.totalCells} 单元格有值
+
{measureTitle}合计{educationTableOverview.measureTotal.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}{educationTableOverview.numericCells} 个可计算值
+
+
+
动态分类对比

按“{activeEducationTable.columns[educationTableGroupColumn]?.title || '分类字段'}”查看记录分布

{educationTableOverview.uniqueGroups} 个分类
+
{educationGroupBuckets.map((bucket) =>
{bucket.label}
{bucket.rows.length}{measureTitle}:{bucket.measureTotal.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}
)}
+
+
图形由当前原生表格实时计算;切换分类字段或统计字段后立即重绘,不生成另一份数据副本。
+
+ } + + const renderEducationTables = () => ( +
+
+ +
EDUCATION / TABLE DATA教育表格数据
+
+
+ {renderEducationImportReceipt()} +
+ +
+ {activeEducationTable ? <> +
+ setActiveEducationTable((current) => current ? { ...current, title: event.target.value } : current)}/> +
修订 {activeEducationTable.revision}{educationTableView !== 'workbook' && <>}
{educationTableSettingsOpen &&
}
+
+
+ +
+ {activeEducationTable.columns.some((column) => isSensitiveEducationColumn(column.title)) && } + {(educationTableView === 'board' || educationTableView === 'dashboard') && } + {educationTableView === 'dashboard' && } + {(educationTableView === 'grid' || educationTableView === 'cards') && <>} +
+ {educationTableView === 'workbook' ? (activeEducationTable.columns.some((column) => isSensitiveEducationColumn(column.title)) && !educationSensitiveVisible ?
敏感字段当前已隐藏

真实工作表引擎不会用遮罩值覆盖原始数据。显示敏感字段后可在本机工作表中编辑,或切换到“数据表”继续遮罩查看。

: 正在启动频道内置工作表引擎…
}>) : educationTableView === 'grid' ?
+ + {activeEducationTable.columns.map((column, columnIndex) => )} + {visibleEducationRows.map((row, visibleRowIndex) => { const displayRowIndex = educationTablePageIndex * educationTablePageSize + visibleRowIndex + 1; const rowIndex = activeEducationTable.rows.findIndex((currentRow) => currentRow.rowId === row.rowId); return {row.cells.map((cell, cellIndex) => { const sensitive = isSensitiveEducationColumn(activeEducationTable.columns[cellIndex]?.title || ''); return })} })} +
#
setActiveEducationTable((current) => current ? { ...current, columns: current.columns.map((item, index) => index === columnIndex ? { ...item, title: event.target.value } : item) } : current)}/>
{displayRowIndex} { if (pasteEducationTableGrid(rowIndex, cellIndex, event.clipboardData.getData('text/plain'))) event.preventDefault() }} onChange={(event) => setActiveEducationTable((current) => current ? { ...current, rows: current.rows.map((currentRow) => currentRow.rowId === row.rowId ? { ...currentRow, cells: currentRow.cells.map((value, currentCellIndex) => currentCellIndex === cellIndex ? event.target.value : value) } : currentRow) } : current)}/>
+ {!visibleEducationRows.length &&

{activeEducationTable.rows.length ? '没有匹配当前筛选的数据。' : '这张表格还没有数据行。'}

{!activeEducationTable.rows.length && }
} +
: educationTableView === 'cards' ?
{visibleEducationRows.map((row, visibleRowIndex) => { const titleSensitive = isSensitiveEducationColumn(activeEducationTable.columns[0]?.title || ''); return
{visibleRowIndex + 1} setActiveEducationTable((current) => current ? { ...current, rows: current.rows.map((currentRow) => currentRow.rowId === row.rowId ? { ...currentRow, cells: currentRow.cells.map((value, index) => index === 0 ? event.target.value : value) } : currentRow) } : current)}/>
{activeEducationTable.columns.slice(1).map((column, offset) => { const cellIndex = offset + 1; const sensitive = isSensitiveEducationColumn(column.title); const label = `卡片 ${visibleRowIndex + 1} ${column.title || `字段 ${cellIndex + 1}`}${sensitive ? '(敏感字段)' : ''}`; return