fix(desktop): allow public world before account login

This commit is contained in:
冰朔 2026-08-16 22:11:08 +08:00
commit 466542ac93
6 changed files with 89 additions and 6 deletions

View file

@ -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"
}

View file

@ -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')

View file

@ -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<thread::JoinHandle<()>>,
}
/// Broker 在账号登录前保持休眠;登录后的状态刷新会按账号隔离根幂等启动。
/// 这避免为了展示公共五域首页而提前打开任何私人存储目录。
#[derive(Default)]
pub struct DirectLocalBrokerState {
handle: Mutex<Option<DirectLocalBrokerHandle>>,
}
impl DirectLocalBrokerState {
pub fn ensure_started(&self, app: &AppHandle) -> Result<bool, String> {
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)

View file

@ -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<HoloLakeHomeStatus, String> {
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)?;

View file

@ -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()) {