From 466542ac937e8effb81759671b6dc0f3882de4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Sun, 16 Aug 2026 22:11:08 +0800 Subject: [PATCH] fix(desktop): allow public world before account login --- .../enterprise-four-domain-entry.json | 1 + .../scripts/domain-number-routing.test.mjs | 15 ++++++ .../src-tauri/src/direct_local_broker.rs | 47 ++++++++++++++++++- .../src-tauri/src/home_status.rs | 19 +++++++- .../src-tauri/src/lib.rs | 4 +- routing/hololake-current-architecture.json | 9 +++- 6 files changed, 89 insertions(+), 6 deletions(-) diff --git a/product-source/hololake-native-desktop/contracts/enterprise-four-domain-entry.json b/product-source/hololake-native-desktop/contracts/enterprise-four-domain-entry.json index 62f37bebf..729a6d1cf 100644 --- a/product-source/hololake-native-desktop/contracts/enterprise-four-domain-entry.json +++ b/product-source/hololake-native-desktop/contracts/enterprise-four-domain-entry.json @@ -7,6 +7,7 @@ "persona_relationship_gate": {"shows_species":"AGE","shows_current_persona_identity":true,"shows_invalid_age_individual_numbers":false,"human_confirms_relationship_mapping":true,"human_confirmation_is_persona_acceptance":false,"responsibility_acceptance_is_separate":true}, "work_entry": {"domain":"DOMAIN-ZS","channel":"GUANGHU_CHANNEL","preserves_responsibility_domain":true}, "personal_route": {"separate_node_ownership_check":true,"enterprise_credentials_are_sufficient":false}, + "desktop_install_acceptance": {"mac_arm64":"PASS","mac_x86_64":"NOT_BUILT","windows":"NOT_BUILT","automatic_update_channel":"UNPROVISIONED_FAIL_CLOSED"}, "ui_template": "REPO-012@27d34dfdbf5df4c67b805402d442e5912c8f4c31:official-login-template-v0.4-locked+inner-screens-v0.1", "source": "routing/hololake-enterprise-four-domain-work-channel.json" } 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 6e9e62c87..2e0fbd567 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 @@ -60,12 +60,27 @@ test('the locked Qoder world template is the running client structure, not a ski const frontend = read('src/main.tsx') assert.equal(contract.state, 'SERVER_LIVE_CLIENT_UI_INTEGRATED') assert.match(contract.ui_template, /official-login-template-v0\.4-locked\+inner-screens-v0\.1/) + assert.equal(contract.desktop_install_acceptance.mac_arm64, 'PASS') + assert.equal(contract.desktop_install_acceptance.mac_x86_64, 'NOT_BUILT') + assert.equal(contract.desktop_install_acceptance.windows, 'NOT_BUILT') + assert.equal(contract.desktop_install_acceptance.automatic_update_channel, 'UNPROVISIONED_FAIL_CLOSED') assert.match(frontend, /number-nucleus/) assert.match(frontend, /worldStage === 'domain'/) assert.match(frontend, /worldStage === 'channel'/) assert.match(frontend, /worldStage === 'tool'/) }) +test('the public five-domain world starts before any private account storage is opened', () => { + const library = read('src-tauri/src/lib.rs') + const broker = read('src-tauri/src/direct_local_broker.rs') + const home = read('src-tauri/src/home_status.rs') + assert.match(library, /DirectLocalBrokerState::default\(\)/) + assert.match(broker, /HOLOLAKE_AUTHENTICATED_ACCOUNT_REQUIRED/) + assert.match(broker, /Ok\(false\)/) + assert.match(home, /WAITING_FOR_LOGIN/) + assert.doesNotMatch(library, /let broker = direct_local_broker::start\(app\.handle\(\)\)\?/) +}) + test('enterprise root uses a bounded lighthouse on the current Linux service node', () => { const contract = JSON.parse(read('contracts/domain-number-routing.json')) assert.equal(contract.server_runtime.enterprise_root, 'ENTERPRISE_LIGHTHOUSE_ON_CURRENT_LINUX_SERVICE_NODE') 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 fae0ad022..80ddc9fab 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 @@ -30,7 +30,7 @@ use std::os::unix::net::{UnixListener, UnixStream}; use std::path::{Path, PathBuf}; use std::sync::{ atomic::{AtomicBool, AtomicUsize, Ordering}, - mpsc, Arc, + mpsc, Arc, Mutex, }; use std::thread; use std::time::Duration; @@ -48,6 +48,51 @@ pub struct DirectLocalBrokerHandle { worker: Option>, } +/// Broker 在账号登录前保持休眠;登录后的状态刷新会按账号隔离根幂等启动。 +/// 这避免为了展示公共五域首页而提前打开任何私人存储目录。 +#[derive(Default)] +pub struct DirectLocalBrokerState { + handle: Mutex>, +} + +impl DirectLocalBrokerState { + pub fn ensure_started(&self, app: &AppHandle) -> Result { + let mut handle = self + .handle + .lock() + .map_err(|_| "HOLOLAKE_BROKER_STATE_LOCK_FAILED".to_string())?; + if handle.is_some() { + return Ok(true); + } + match start(app) { + Ok(started) => { + *handle = Some(started); + Ok(true) + } + Err(error) + if error + .to_string() + .contains("HOLOLAKE_AUTHENTICATED_ACCOUNT_REQUIRED") => + { + Ok(false) + } + Err(error) => Err(error.to_string()), + } + } + + pub fn active_connection_count(&self) -> usize { + self.handle + .lock() + .ok() + .and_then(|handle| { + handle + .as_ref() + .map(DirectLocalBrokerHandle::active_connection_count) + }) + .unwrap_or(0) + } +} + impl DirectLocalBrokerHandle { pub fn active_connection_count(&self) -> usize { self.authenticated_connections.load(Ordering::Acquire) diff --git a/product-source/hololake-native-desktop/src-tauri/src/home_status.rs b/product-source/hololake-native-desktop/src-tauri/src/home_status.rs index e98e6fb72..515607672 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/home_status.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/home_status.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later -use crate::direct_local_broker::DirectLocalBrokerHandle; +use crate::direct_local_broker::DirectLocalBrokerState; use crate::direct_local_session::{active_session_count_at, direct_session_root}; use crate::pncc_receipt_projection::{pncc_projection_root, projection_event_count_at}; use crate::pncc_repository_binding::{mounted_repository_count_at, pncc_repository_mount_root}; @@ -26,8 +26,23 @@ pub struct HoloLakeHomeStatus { #[tauri::command] pub fn get_hololake_home_status( app: AppHandle, - broker: State<'_, DirectLocalBrokerHandle>, + broker: State<'_, DirectLocalBrokerState>, ) -> Result { + let broker_ready = broker.ensure_started(&app)?; + if !broker_ready { + return Ok(HoloLakeHomeStatus { + schema: "hololake.home-status/v1", + direct_local_broker_state: "WAITING_FOR_LOGIN", + direct_connection_count: 0, + resumable_session_count: 0, + code_repository_mount_count: 0, + pncc_receipt_count: 0, + update_state: release_trust_state()?, + release_recovery_state: crate::release_update::release_recovery_state(&app)?, + automatic_upstream_updates: false, + mcp_role: "DISCOVERY_RECOVERY_COMPATIBILITY_ONLY", + }); + } let session_root = direct_session_root(&app)?; let mount_root = pncc_repository_mount_root(&app)?; let projection_root = pncc_projection_root(&app)?; 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 6527ff333..76aab18f8 100644 --- a/product-source/hololake-native-desktop/src-tauri/src/lib.rs +++ b/product-source/hololake-native-desktop/src-tauri/src/lib.rs @@ -96,7 +96,9 @@ pub fn run() { eprintln!("HoloLake zero-point protocol sync was not completed: {error}"); } }); - let broker = direct_local_broker::start(app.handle())?; + let broker = direct_local_broker::DirectLocalBrokerState::default(); + // 公共五域首页必须能在未登录时启动;私人 broker 只在已有账号会话时启动。 + broker.ensure_started(app.handle())?; app.manage(broker); release_trust::install_updater_if_provisioned(app.handle())?; if let Err(error) = release_update::observe_release_startup(app.handle()) { diff --git a/routing/hololake-current-architecture.json b/routing/hololake-current-architecture.json index 837325d10..8c1fe7425 100644 --- a/routing/hololake-current-architecture.json +++ b/routing/hololake-current-architecture.json @@ -1,7 +1,7 @@ { "schema": "hololake.current-architecture/v1", "architecture_id": "HLP-CURRENT-ARCH-001", - "version": "2026-08-16.12", + "version": "2026-08-16.13", "state": "CURRENT_CANONICAL", "product": { "formal_name": "光湖语言系统 · 通用人工智能操作平台", @@ -11,7 +11,7 @@ }, "current_native_edge": { "record_id": "HLP-NATIVE-DOMAIN-MEMBRANE-PNCC-20260816-001", - "state": "SOURCE_IMPLEMENTED_ENTERPRISE_IDENTITY_LIGHTHOUSE_LIVE_DESKTOP_INSTALL_ACCEPTANCE_PENDING", + "state": "MAC_ARM64_DESKTOP_INSTALLED_AND_LAUNCH_ACCEPTED_CROSS_PLATFORM_RELEASE_PENDING", "native_source": "product-source/hololake-native-desktop", "public_entry": "FIVE_DOMAIN_HOME_NUMBER_ROUTED_BEFORE_DOMAIN_LOGIN", "domain_selection_by_human_allowed": false, @@ -28,6 +28,11 @@ "enterprise_relationship_and_responsibility_client_commands": "SOURCE_INTEGRATED_QODER_UI_BOUND_MACOS_KEYCHAIN_SIGNING_READY", "qoder_official_ui_template": "REPO_012_27D34DF_OFFICIAL_LOGIN_V0_4_AND_INNER_SCREENS_V0_1_RUNTIME_INTEGRATED_BROWSER_VERIFIED", "client_world_navigation": "DOMAIN_HOME_TO_CHANNEL_OVERVIEW_TO_TOOL_PROJECTION_NO_TRADITIONAL_GLOBAL_SIDEBAR", + "prelogin_private_broker": "WAITING_FOR_LOGIN_NO_PRIVATE_STORAGE_OPENED", + "mac_arm64_desktop_install_acceptance": "PASS_DESKTOP_HOLOLAKE_APP_REAL_PROCESS_AND_FIVE_DOMAIN_UI_READBACK", + "mac_x86_64_installer": "NOT_BUILT", + "windows_installer": "NOT_BUILT", + "automatic_update_release_channel": "UNPROVISIONED_FAIL_CLOSED", "windows_secure_credential_bridge": "NOT_IMPLEMENTED_DO_NOT_CLAIM_PERSISTENT_SIGNING", "age_is_persona_species_not_individual_number_namespace": true, "enterprise_persona_identity_namespace": "PENDING_GUANGHU_TEAM_GOVERNANCE",