feat: enforce Guanghu-native HoloLake runtime laws
This commit is contained in:
parent
ccee303355
commit
67e6fcdd38
57 changed files with 1765 additions and 1504 deletions
|
|
@ -1430,8 +1430,6 @@ HoloLake Era is free and open source, and any kind of help is useful. Pick the p
|
|||
|
||||
HoloLake Era is supported by a panel of tools Luca uses every day to keep the project healthy, tested, and ready for AI-assisted development:
|
||||
|
||||
- [Codacy](https://www.codacy.com/)
|
||||
- [CodeScene](https://codescene.com/)
|
||||
- [CircleCI](https://circleci.com/)
|
||||
- [Unblocked](https://getunblocked.com/)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ HoloLake Era is free and open source, and any kind of help is useful. Pick the p
|
|||
|
||||
HoloLake Era is supported by a panel of tools Luca uses every day to keep the project healthy, tested, and ready for AI-assisted development:
|
||||
|
||||
- [Codacy](https://www.codacy.com/)
|
||||
- [CodeScene](https://codescene.com/)
|
||||
- [CircleCI](https://circleci.com/)
|
||||
- [Unblocked](https://getunblocked.com/)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ HoloLake Era is free and open source, and any kind of help is useful. Pick the p
|
|||
|
||||
HoloLake Era is supported by a panel of tools Luca uses every day to keep the project healthy, tested, and ready for AI-assisted development:
|
||||
|
||||
- [Codacy](https://www.codacy.com/)
|
||||
- [CodeScene](https://codescene.com/)
|
||||
- [CircleCI](https://circleci.com/)
|
||||
- [Unblocked](https://getunblocked.com/)
|
||||
|
||||
|
|
|
|||
|
|
@ -1430,8 +1430,6 @@ HoloLake Era is free and open source, and any kind of help is useful. Pick the p
|
|||
|
||||
HoloLake Era is supported by a panel of tools Luca uses every day to keep the project healthy, tested, and ready for AI-assisted development:
|
||||
|
||||
- [Codacy](https://www.codacy.com/)
|
||||
- [CodeScene](https://codescene.com/)
|
||||
- [CircleCI](https://circleci.com/)
|
||||
- [Unblocked](https://getunblocked.com/)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ HoloLake Era is free and open source, and any kind of help is useful. Pick the p
|
|||
|
||||
HoloLake Era is supported by a panel of tools Luca uses every day to keep the project healthy, tested, and ready for AI-assisted development:
|
||||
|
||||
- [Codacy](https://www.codacy.com/)
|
||||
- [CodeScene](https://codescene.com/)
|
||||
- [CircleCI](https://circleci.com/)
|
||||
- [Unblocked](https://getunblocked.com/)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ HoloLake Era is free and open source, and any kind of help is useful. Pick the p
|
|||
|
||||
HoloLake Era is supported by a panel of tools Luca uses every day to keep the project healthy, tested, and ready for AI-assisted development:
|
||||
|
||||
- [Codacy](https://www.codacy.com/)
|
||||
- [CodeScene](https://codescene.com/)
|
||||
- [CircleCI](https://circleci.com/)
|
||||
- [Unblocked](https://getunblocked.com/)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
use reqwest::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
#[cfg(desktop)]
|
||||
use std::path::PathBuf;
|
||||
#[cfg(desktop)]
|
||||
use std::sync::{Mutex, OnceLock};
|
||||
use std::time::Duration;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
|
@ -12,20 +8,16 @@ const LIGHTHOUSE_MODEL_URL: &str = "http://127.0.0.1:18077/v1/broadcast";
|
|||
const PERSONA_ID: &str = "ICE-P-ZY001";
|
||||
const CHANNEL_ID: &str = "HLP-HOLOLAKE-LIVING-SYSTEM";
|
||||
const MAX_EVENT_ID_BYTES: usize = 96;
|
||||
#[cfg(desktop)]
|
||||
const LIGHTHOUSE_SSH_ALIAS: &str = "guanghu-os-bs-sh-005";
|
||||
#[cfg(desktop)]
|
||||
static TUNNEL_LOCK: OnceLock<Mutex<()>> = OnceLock::new();
|
||||
|
||||
const SYSTEM_PROMPT: &str = concat!(
|
||||
"You are the non-conversational HoloLake living-system planner. ",
|
||||
"Return one compact JSON object only. Never chat, explain, use markdown, or call tools. ",
|
||||
"Keep eventId and intent unchanged. route must equal requestedRoute except world-login may be used as a safe gate. ",
|
||||
"Keep eventId and intent unchanged. ",
|
||||
"uiProjection.route and navigationAction.route must equal requestedRoute except world-login may be used as a safe gate. ",
|
||||
"requiredTruth may contain only receiptIds supplied by the event. ",
|
||||
"scene.depth: overview|focused|immersive. ",
|
||||
"scene.motion: quiet|responsive|active. ",
|
||||
"scene.starDensity: sparse|balanced|rich. ",
|
||||
"scene.connectionEmphasis: contextual|active-route|network. ",
|
||||
"Return typed uiProjection, navigationAction, capabilityCall, and receiptSchema fields. ",
|
||||
"capabilityCall must use an exact capability from capabilityRegistry and permissionBoundary. ",
|
||||
"receiptSchema must remain pending-evidence and cannot claim execution success. ",
|
||||
"Do not infer authorization, server state, identity, or execution success."
|
||||
);
|
||||
|
||||
|
|
@ -40,6 +32,12 @@ pub struct LivingSystemEvent {
|
|||
world_open: bool,
|
||||
receipt_ids: Vec<String>,
|
||||
occurred_at: u64,
|
||||
persona_system: Value,
|
||||
current_system_state: Value,
|
||||
knowledge_state: Value,
|
||||
permission_boundary: Value,
|
||||
responsibility_boundary: Value,
|
||||
capability_registry: Vec<Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
|
@ -69,90 +67,7 @@ pub async fn guanghu_living_system_plan(
|
|||
event: LivingSystemEvent,
|
||||
) -> Result<LivingSystemServerPlan, String> {
|
||||
let client = living_system_client()?;
|
||||
match plan_with_lighthouse(&event, LIGHTHOUSE_MODEL_URL, &client).await {
|
||||
Ok(plan) => Ok(plan),
|
||||
Err(error) if error.starts_with("guanghu_living_system_transport_failed:") => {
|
||||
ensure_lighthouse_tunnel().await?;
|
||||
plan_with_lighthouse(&event, LIGHTHOUSE_MODEL_URL, &client).await
|
||||
}
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(desktop)]
|
||||
async fn ensure_lighthouse_tunnel() -> Result<(), String> {
|
||||
tokio::task::spawn_blocking(|| {
|
||||
let _guard = TUNNEL_LOCK
|
||||
.get_or_init(|| Mutex::new(()))
|
||||
.lock()
|
||||
.map_err(|_| "guanghu_living_system_tunnel_lock_failed".to_owned())?;
|
||||
let (config, socket) = lighthouse_tunnel_paths()?;
|
||||
let check = crate::hidden_command("ssh")
|
||||
.args(lighthouse_tunnel_check_args(&config, &socket))
|
||||
.status();
|
||||
if check.is_ok_and(|status| status.success()) {
|
||||
return Ok(());
|
||||
}
|
||||
let status = crate::hidden_command("ssh")
|
||||
.args(lighthouse_tunnel_start_args(&config, &socket))
|
||||
.status()
|
||||
.map_err(|error| format!("guanghu_living_system_tunnel_start_failed: {error}"))?;
|
||||
if !status.success() {
|
||||
return Err("guanghu_living_system_tunnel_start_failed".to_owned());
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
.map_err(|error| format!("guanghu_living_system_tunnel_task_failed: {error}"))?
|
||||
}
|
||||
|
||||
#[cfg(not(desktop))]
|
||||
async fn ensure_lighthouse_tunnel() -> Result<(), String> {
|
||||
Err("guanghu_living_system_tunnel_desktop_required".to_owned())
|
||||
}
|
||||
|
||||
#[cfg(desktop)]
|
||||
fn lighthouse_tunnel_paths() -> Result<(PathBuf, PathBuf), String> {
|
||||
let ssh_root = dirs::home_dir()
|
||||
.ok_or_else(|| "guanghu_living_system_home_missing".to_owned())?
|
||||
.join(".ssh");
|
||||
let config = ssh_root.join("guanghu-os-bs-sh-005.conf");
|
||||
if !config.is_file() {
|
||||
return Err("guanghu_living_system_ssh_config_missing".to_owned());
|
||||
}
|
||||
Ok((config, ssh_root.join("guanghu-os-bs-sh-005-tunnel.sock")))
|
||||
}
|
||||
|
||||
#[cfg(desktop)]
|
||||
fn lighthouse_tunnel_check_args(config: &std::path::Path, socket: &std::path::Path) -> Vec<String> {
|
||||
vec![
|
||||
"-F".to_owned(),
|
||||
config.to_string_lossy().into_owned(),
|
||||
"-S".to_owned(),
|
||||
socket.to_string_lossy().into_owned(),
|
||||
"-O".to_owned(),
|
||||
"check".to_owned(),
|
||||
LIGHTHOUSE_SSH_ALIAS.to_owned(),
|
||||
]
|
||||
}
|
||||
|
||||
#[cfg(desktop)]
|
||||
fn lighthouse_tunnel_start_args(config: &std::path::Path, socket: &std::path::Path) -> Vec<String> {
|
||||
vec![
|
||||
"-F".to_owned(),
|
||||
config.to_string_lossy().into_owned(),
|
||||
"-M".to_owned(),
|
||||
"-S".to_owned(),
|
||||
socket.to_string_lossy().into_owned(),
|
||||
"-fN".to_owned(),
|
||||
"-o".to_owned(),
|
||||
"ExitOnForwardFailure=yes".to_owned(),
|
||||
"-L".to_owned(),
|
||||
"18077:127.0.0.1:8077".to_owned(),
|
||||
"-L".to_owned(),
|
||||
"13080:127.0.0.1:3080".to_owned(),
|
||||
LIGHTHOUSE_SSH_ALIAS.to_owned(),
|
||||
]
|
||||
plan_with_lighthouse(&event, LIGHTHOUSE_MODEL_URL, &client).await
|
||||
}
|
||||
|
||||
async fn plan_with_lighthouse(
|
||||
|
|
@ -251,6 +166,31 @@ fn validate_event(event: &LivingSystemEvent) -> Result<(), String> {
|
|||
if event.receipt_ids.len() > 32 || event.receipt_ids.iter().any(|value| value.len() > 160) {
|
||||
return Err("guanghu_living_system_receipts_invalid".to_owned());
|
||||
}
|
||||
if event.persona_system["personaSystemId"] != PERSONA_ID
|
||||
|| event.persona_system["humanAnchorId"] != "ICE-GL∞"
|
||||
{
|
||||
return Err("guanghu_living_system_persona_context_invalid".to_owned());
|
||||
}
|
||||
let runtime_receipt_id = event.current_system_state["runtimeBinding"]["issuedByReceiptId"]
|
||||
.as_str()
|
||||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(|| "guanghu_living_system_runtime_binding_invalid".to_owned())?;
|
||||
if event.current_system_state["runtimeBinding"]["status"] != "verified"
|
||||
|| event.current_system_state["runtimeBinding"]["personaSystemId"] != PERSONA_ID
|
||||
|| !event
|
||||
.receipt_ids
|
||||
.iter()
|
||||
.any(|receipt_id| receipt_id == runtime_receipt_id)
|
||||
{
|
||||
return Err("guanghu_living_system_runtime_binding_invalid".to_owned());
|
||||
}
|
||||
if !event.knowledge_state.is_object()
|
||||
|| !event.permission_boundary.is_object()
|
||||
|| !event.responsibility_boundary.is_object()
|
||||
|| event.capability_registry.is_empty()
|
||||
{
|
||||
return Err("guanghu_living_system_boundary_context_invalid".to_owned());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -276,8 +216,48 @@ mod tests {
|
|||
requested_route: "fifth-domain".to_owned(),
|
||||
appearance_theme: None,
|
||||
world_open: true,
|
||||
receipt_ids: vec!["truth-001".to_owned()],
|
||||
receipt_ids: vec!["truth-001".to_owned(), "runtime-binding-receipt".to_owned()],
|
||||
occurred_at: 1,
|
||||
persona_system: json!({
|
||||
"humanAnchorId": "ICE-GL∞",
|
||||
"personaSystemId": PERSONA_ID,
|
||||
"memoryProtocolRoot": "REPO-012",
|
||||
"modelInstanceId": "model-current"
|
||||
}),
|
||||
current_system_state: json!({
|
||||
"currentRoute": "world",
|
||||
"requestedRoute": "fifth-domain",
|
||||
"worldOpen": true,
|
||||
"receiptIds": ["truth-001", "runtime-binding-receipt"],
|
||||
"runtimeBinding": {
|
||||
"bindingId": "binding-current",
|
||||
"nodeId": "JD-FD-PRIMARY",
|
||||
"personaSystemId": PERSONA_ID,
|
||||
"modelInstanceId": "model-current",
|
||||
"issuedByReceiptId": "runtime-binding-receipt",
|
||||
"status": "verified"
|
||||
}
|
||||
}),
|
||||
knowledge_state: json!({
|
||||
"selectedLakeId": "lake-current",
|
||||
"mountedSources": ["REPO-012", "REPO-014"]
|
||||
}),
|
||||
permission_boundary: json!({
|
||||
"allowedCapabilities": ["navigation.apply"],
|
||||
"deniedCapabilities": []
|
||||
}),
|
||||
responsibility_boundary: json!({
|
||||
"controllerPersonaSystemId": PERSONA_ID,
|
||||
"humanAnchorId": "ICE-GL∞",
|
||||
"executorRule": "deterministic-host-only",
|
||||
"successRule": "evidence-required"
|
||||
}),
|
||||
capability_registry: vec![json!({
|
||||
"id": "navigation.apply",
|
||||
"inputType": "NavigationAction",
|
||||
"outputType": "ReceiptSchema",
|
||||
"requiresWorldOpen": false
|
||||
})],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -363,38 +343,19 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn tunnel_arguments_are_fixed_to_the_registered_loopback_routes() {
|
||||
let config = std::path::Path::new("/registered/ssh.conf");
|
||||
let socket = std::path::Path::new("/registered/tunnel.sock");
|
||||
fn rejects_server_planning_without_the_current_persona_runtime_binding() {
|
||||
let mut unbound = event();
|
||||
unbound.current_system_state["runtimeBinding"] = Value::Null;
|
||||
assert_eq!(
|
||||
lighthouse_tunnel_check_args(config, socket),
|
||||
[
|
||||
"-F",
|
||||
"/registered/ssh.conf",
|
||||
"-S",
|
||||
"/registered/tunnel.sock",
|
||||
"-O",
|
||||
"check",
|
||||
LIGHTHOUSE_SSH_ALIAS,
|
||||
]
|
||||
validate_event(&unbound).unwrap_err(),
|
||||
"guanghu_living_system_runtime_binding_invalid"
|
||||
);
|
||||
|
||||
let mut wrong_persona = event();
|
||||
wrong_persona.persona_system["personaSystemId"] = json!("OTHER-PERSONA");
|
||||
assert_eq!(
|
||||
lighthouse_tunnel_start_args(config, socket),
|
||||
[
|
||||
"-F",
|
||||
"/registered/ssh.conf",
|
||||
"-M",
|
||||
"-S",
|
||||
"/registered/tunnel.sock",
|
||||
"-fN",
|
||||
"-o",
|
||||
"ExitOnForwardFailure=yes",
|
||||
"-L",
|
||||
"18077:127.0.0.1:8077",
|
||||
"-L",
|
||||
"13080:127.0.0.1:3080",
|
||||
LIGHTHOUSE_SSH_ALIAS,
|
||||
]
|
||||
validate_event(&wrong_persona).unwrap_err(),
|
||||
"guanghu_living_system_persona_context_invalid"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue