feat: embed complete GLS protocol kernel in HoloLake

This commit is contained in:
冰朔 2026-08-17 17:56:47 +08:00
commit b8d08fb620
15 changed files with 3515 additions and 485 deletions

View file

@ -0,0 +1,311 @@
//! GLS-0411 / GLS-0130 / GLS-0131 的受限 Bootstrap Compiler。
//!
//! 输入只能是类型化 HLDP-NP 对象;输出是确定性 GIR。这里不解释自然语言
//! 不执行生成代码,也不从输入中取得授权。
use ring::digest::{digest, SHA256};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::{BTreeMap, BTreeSet, HashMap};
const PROGRAM_SCHEMA: &str = "hololake.hldp-native-program/v1";
const GIR_SCHEMA: &str = "hololake.gir/v1";
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct HldpNativeProgram {
schema: String,
program_id: String,
version: String,
subject_id: String,
target_id: String,
scope: String,
permissions: Vec<String>,
resources: ProgramResources,
actions: Vec<ProgramAction>,
timeout_ms: u64,
stop_action: String,
cleanup_action: String,
rollback_action: String,
receipt_kinds: Vec<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct ProgramResources {
cpu_units: u64,
memory_bytes: u64,
storage_bytes: u64,
network_allowed: bool,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct ProgramAction {
id: String,
kind: String,
depends_on: Vec<String>,
input_digest: String,
permission: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct GirAction {
ordinal: usize,
id: String,
kind: String,
depends_on: Vec<String>,
input_digest: String,
permission: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct GirProgram {
pub schema: String,
pub compiler: String,
pub compiler_protocols: Vec<String>,
pub program_id: String,
pub source_sha256: String,
pub subject_id: String,
pub target_id: String,
pub scope: String,
pub permissions: Vec<String>,
pub resources: Value,
pub action_graph: Vec<GirAction>,
pub timeout_ms: u64,
pub stop_action: String,
pub cleanup_action: String,
pub rollback_action: String,
pub receipt_kinds: Vec<String>,
pub unresolved_natural_language: Vec<String>,
pub unresolved_permissions: Vec<String>,
pub gir_sha256: String,
}
fn sha256(bytes: &[u8]) -> String {
digest(&SHA256, bytes)
.as_ref()
.iter()
.map(|byte| format!("{byte:02x}"))
.collect()
}
fn valid_id(value: &str) -> bool {
!value.is_empty()
&& value.len() <= 128
&& value.bytes().all(|byte| {
byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_' | b'.' | b':' | b'/')
})
}
fn valid_digest(value: &str) -> bool {
value.len() == 64
&& value
.bytes()
.all(|byte| byte.is_ascii_hexdigit() && !byte.is_ascii_uppercase())
}
fn validate(program: &HldpNativeProgram) -> Result<(), String> {
if program.schema != PROGRAM_SCHEMA
|| !valid_id(&program.program_id)
|| !valid_id(&program.version)
|| !valid_id(&program.subject_id)
|| !valid_id(&program.target_id)
|| !valid_id(&program.scope)
|| program.permissions.is_empty()
|| program.actions.is_empty()
|| program.actions.len() > 256
|| program.timeout_ms == 0
|| program.resources.cpu_units == 0
|| program.resources.memory_bytes == 0
|| !valid_id(&program.stop_action)
|| !valid_id(&program.cleanup_action)
|| !valid_id(&program.rollback_action)
|| program.receipt_kinds.is_empty()
{
return Err("HOLOLAKE_GLC_HLDP_NP_CONTRACT_INVALID".into());
}
if program
.permissions
.iter()
.any(|permission| !valid_id(permission))
|| program.receipt_kinds.iter().any(|kind| !valid_id(kind))
{
return Err("HOLOLAKE_GLC_PERMISSION_OR_RECEIPT_INVALID".into());
}
let allowed_kinds = BTreeSet::from([
"VALIDATE",
"READ",
"TRANSFORM",
"ROUTE",
"STATE_TRANSITION",
"WRITE_RECEIPT",
"STOP",
"CLEANUP",
"ROLLBACK",
]);
let mut ids = BTreeSet::new();
for action in &program.actions {
if !ids.insert(action.id.as_str())
|| !valid_id(&action.id)
|| !allowed_kinds.contains(action.kind.as_str())
|| !valid_digest(&action.input_digest)
|| !program.permissions.contains(&action.permission)
{
return Err("HOLOLAKE_GLC_ACTION_INVALID".into());
}
}
for action in &program.actions {
if action
.depends_on
.iter()
.any(|dependency| dependency == &action.id || !ids.contains(dependency.as_str()))
{
return Err("HOLOLAKE_GLC_ACTION_DEPENDENCY_INVALID".into());
}
}
Ok(())
}
fn topological_actions(program: &HldpNativeProgram) -> Result<Vec<GirAction>, String> {
let by_id = program
.actions
.iter()
.map(|action| (action.id.as_str(), action))
.collect::<HashMap<_, _>>();
let mut indegree = BTreeMap::new();
let mut outgoing: BTreeMap<&str, Vec<&str>> = BTreeMap::new();
for action in &program.actions {
indegree.insert(action.id.as_str(), action.depends_on.len());
for dependency in &action.depends_on {
outgoing
.entry(dependency.as_str())
.or_default()
.push(action.id.as_str());
}
}
for targets in outgoing.values_mut() {
targets.sort();
}
let mut ready = indegree
.iter()
.filter_map(|(id, degree)| (*degree == 0).then_some(*id))
.collect::<BTreeSet<_>>();
let mut ordered = Vec::new();
while let Some(id) = ready.pop_first() {
let action = by_id[id];
ordered.push(GirAction {
ordinal: ordered.len(),
id: action.id.clone(),
kind: action.kind.clone(),
depends_on: {
let mut value = action.depends_on.clone();
value.sort();
value
},
input_digest: action.input_digest.clone(),
permission: action.permission.clone(),
});
for target in outgoing.get(id).into_iter().flatten() {
let degree = indegree.get_mut(target).expect("known target");
*degree -= 1;
if *degree == 0 {
ready.insert(target);
}
}
}
if ordered.len() != program.actions.len() {
return Err("HOLOLAKE_GLC_ACTION_GRAPH_CYCLE".into());
}
Ok(ordered)
}
pub(crate) fn compile_hldp_program(value: Value) -> Result<GirProgram, String> {
let program: HldpNativeProgram = serde_json::from_value(value)
.map_err(|error| format!("HOLOLAKE_GLC_STRICT_CODEC_REJECTED: {error}"))?;
validate(&program)?;
let canonical_source = serde_json::to_vec(&program)
.map_err(|error| format!("HOLOLAKE_GLC_SOURCE_SERIALIZE_FAILED: {error}"))?;
let action_graph = topological_actions(&program)?;
let mut permissions = program.permissions.clone();
permissions.sort();
permissions.dedup();
let mut receipt_kinds = program.receipt_kinds.clone();
receipt_kinds.sort();
receipt_kinds.dedup();
let resources = serde_json::to_value(&program.resources)
.map_err(|error| format!("HOLOLAKE_GLC_RESOURCE_SERIALIZE_FAILED: {error}"))?;
let mut gir = GirProgram {
schema: GIR_SCHEMA.into(),
compiler: "HOLOLAKE_BOOTSTRAP_GLC_V1".into(),
compiler_protocols: vec!["GLS-0411".into(), "GLS-0131".into(), "GLS-0130".into()],
program_id: program.program_id,
source_sha256: sha256(&canonical_source),
subject_id: program.subject_id,
target_id: program.target_id,
scope: program.scope,
permissions,
resources,
action_graph,
timeout_ms: program.timeout_ms,
stop_action: program.stop_action,
cleanup_action: program.cleanup_action,
rollback_action: program.rollback_action,
receipt_kinds,
unresolved_natural_language: vec![],
unresolved_permissions: vec![],
gir_sha256: String::new(),
};
gir.gir_sha256 = sha256(
&serde_json::to_vec(&gir)
.map_err(|error| format!("HOLOLAKE_GIR_SERIALIZE_FAILED: {error}"))?,
);
Ok(gir)
}
pub(crate) fn bootstrap_self_check() -> Result<String, String> {
let program = serde_json::json!({
"schema":PROGRAM_SCHEMA,"programId":"GLC-GOLDEN-001","version":"1.0.0","subjectId":"ICE-P-GOLDEN","targetId":"HOLOLAKE-KERNEL","scope":"TEST_ONLY",
"permissions":["READ_CONTRACT","WRITE_RECEIPT"],"resources":{"cpuUnits":1,"memoryBytes":1048576,"storageBytes":0,"networkAllowed":false},
"actions":[
{"id":"validate","kind":"VALIDATE","dependsOn":[],"inputDigest":sha256(b"input"),"permission":"READ_CONTRACT"},
{"id":"receipt","kind":"WRITE_RECEIPT","dependsOn":["validate"],"inputDigest":sha256(b"validated"),"permission":"WRITE_RECEIPT"}
],"timeoutMs":1000,"stopAction":"STOP","cleanupAction":"CLEANUP","rollbackAction":"ROLLBACK","receiptKinds":["VALIDATED"]
});
let first = compile_hldp_program(program.clone())?;
let second = compile_hldp_program(program)?;
if first != second {
return Err("HOLOLAKE_GLC_BOOTSTRAP_NON_DETERMINISTIC".into());
}
Ok(first.gir_sha256)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bootstrap_compiler_is_deterministic() {
assert_eq!(bootstrap_self_check().unwrap().len(), 64);
}
#[test]
fn unknown_fields_and_cycles_fail_closed() {
let unknown = serde_json::json!({"schema":PROGRAM_SCHEMA,"freeText":"run anything"});
assert!(compile_hldp_program(unknown)
.unwrap_err()
.contains("STRICT_CODEC"));
let cyclic = serde_json::json!({
"schema":PROGRAM_SCHEMA,"programId":"CYCLE","version":"1","subjectId":"S","targetId":"T","scope":"TEST","permissions":["P"],
"resources":{"cpuUnits":1,"memoryBytes":1,"storageBytes":0,"networkAllowed":false},
"actions":[{"id":"a","kind":"VALIDATE","dependsOn":["b"],"inputDigest":sha256(b"a"),"permission":"P"},{"id":"b","kind":"READ","dependsOn":["a"],"inputDigest":sha256(b"b"),"permission":"P"}],
"timeoutMs":1,"stopAction":"STOP","cleanupAction":"CLEAN","rollbackAction":"ROLLBACK","receiptKinds":["R"]
});
assert_eq!(
compile_hldp_program(cyclic).unwrap_err(),
"HOLOLAKE_GLC_ACTION_GRAPH_CYCLE"
);
}
}

File diff suppressed because it is too large Load diff

View file

@ -43,7 +43,7 @@ struct GlsCompilerBoundary {
arbitrary_protocol_code_allowed: bool,
executable_projection_requires_explicit_adapter: bool,
unprojected_protocol_behavior: String,
legacy_untyped_dependency_behavior: String,
source_dependency_behavior: String,
runtime_graph_source: String,
runtime_dependency_cycles: String,
unknown_protocol: String,
@ -61,6 +61,9 @@ struct GlsReconciliation {
dependencies_without_numbered_source: Vec<String>,
numbered_sources_not_in_protocol_registry: Vec<String>,
legacy_dependency_cycles: Vec<Vec<String>>,
source_reference_cycles: Vec<Vec<String>>,
typed_source_dependency_counts: HashMap<String, usize>,
unclassified_source_dependency_count: usize,
discovered_unreconciled_count: usize,
authority_conflict_count: usize,
}
@ -75,6 +78,7 @@ struct GlsDependencyEdge {
target: String,
edge_kind: String,
enters_runtime_graph: bool,
classification_basis: Option<String>,
}
#[derive(Clone, Debug, Deserialize)]
@ -83,6 +87,7 @@ struct GlsProtocol {
source_sha256: String,
registration: GlsRegistration,
projection_state: String,
implementation_stage: Option<String>,
adapter: Option<String>,
event_kinds: Vec<String>,
dependencies: Vec<String>,
@ -108,6 +113,9 @@ pub struct GlsProtocolRuntimeSnapshot {
pub legacy_dependency_cycle_count: usize,
pub discovered_unreconciled_count: usize,
pub authority_conflict_count: usize,
pub typed_source_dependency_count: usize,
pub unclassified_source_dependency_count: usize,
pub implementation_stage_count: usize,
pub active_adapters: Vec<String>,
pub raw_protocol_text_executed: bool,
pub arbitrary_protocol_code_allowed: bool,
@ -133,8 +141,7 @@ fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> {
.compiler
.executable_projection_requires_explicit_adapter
|| registry.compiler.unprojected_protocol_behavior != "INVENTORIED_NOT_EXECUTABLE"
|| registry.compiler.legacy_untyped_dependency_behavior
!= "AUDIT_ONLY_BLOCKS_NEW_ACTIVATION"
|| registry.compiler.source_dependency_behavior != "TYPED_AUDIT_ONLY_NEVER_ACTIVATES"
|| registry.compiler.runtime_graph_source != "EXPLICIT_EXECUTABLE_PROJECTIONS_ONLY"
|| registry.compiler.runtime_dependency_cycles != "REJECT"
|| registry.compiler.unknown_protocol != "FAIL_CLOSED"
@ -144,14 +151,25 @@ fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> {
|| registry.reconciliation.registered_draft_count != 33
|| registry.reconciliation.registered_draft_not_started_count != 21
|| registry.reconciliation.legacy_dependency_target_count != 57
|| registry.reconciliation.dependencies_not_in_protocol_registry.len() != 19
|| registry.reconciliation.dependencies_without_numbered_source.len() != 24
|| registry
.reconciliation
.dependencies_not_in_protocol_registry
.len()
!= 19
|| registry
.reconciliation
.dependencies_without_numbered_source
.len()
!= 24
|| registry
.reconciliation
.numbered_sources_not_in_protocol_registry
.len()
!= 31
|| registry.reconciliation.legacy_dependency_cycles.len() != 3
|| registry.reconciliation.source_reference_cycles
!= registry.reconciliation.legacy_dependency_cycles
|| registry.reconciliation.unclassified_source_dependency_count != 0
|| registry.reconciliation.discovered_unreconciled_count != 0
|| registry.reconciliation.authority_conflict_count != 0
|| registry.protocol_count != registry.protocols.len()
@ -215,10 +233,24 @@ fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> {
return Err("HOLOLAKE_GLS_REGISTRATION_NOT_RECONCILED".into());
}
for edge in &protocol.dependency_edges {
match edge.edge_kind.as_str() {
"RUNTIME_REQUIRES" if edge.enters_runtime_graph => {}
"LEGACY_UNTYPED_REFERENCE" if !edge.enters_runtime_graph => {}
_ => return Err("HOLOLAKE_GLS_DEPENDENCY_EDGE_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());
}
} else if matches!(
edge.edge_kind.as_str(),
"NORMATIVE_REFERENCE"
| "SCHEMA_IMPORT"
| "BUILD_REQUIRES"
| "BOOT_REQUIRES"
| "RECOVERY_REQUIRES"
| "EVIDENCE_ONLY"
) && !edge.enters_runtime_graph
&& edge.classification_basis.as_deref()
== Some("BOOTSTRAP_COMPILER_V1_FAMILY_AND_TARGET_RULE")
{
} else {
return Err("HOLOLAKE_GLS_DEPENDENCY_EDGE_INVALID".into());
}
}
let runtime_edges = protocol
@ -239,6 +271,23 @@ fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> {
if executable != registry.executable_projection_count {
return Err("HOLOLAKE_GLS_EXECUTABLE_COUNT_MISMATCH".into());
}
let stages = registry
.protocols
.iter()
.filter_map(|protocol| protocol.implementation_stage.as_deref())
.collect::<HashSet<_>>();
if stages != HashSet::from(["P0", "P1", "P2", "P3", "P4", "P5", "P6"])
|| registry.executable_projection_count != 25
|| registry.inventoried_not_executable_count != 50
|| registry
.reconciliation
.typed_source_dependency_counts
.values()
.sum::<usize>()
== 0
{
return Err("HOLOLAKE_GLS_IMPLEMENTATION_STAGE_SET_INVALID".into());
}
let by_id = registry
.protocols
@ -337,6 +386,20 @@ pub async fn get_gls_protocol_runtime() -> Result<GlsProtocolRuntimeSnapshot, St
legacy_dependency_cycle_count: registry.reconciliation.legacy_dependency_cycles.len(),
discovered_unreconciled_count: registry.reconciliation.discovered_unreconciled_count,
authority_conflict_count: registry.reconciliation.authority_conflict_count,
typed_source_dependency_count: registry
.reconciliation
.typed_source_dependency_counts
.values()
.sum(),
unclassified_source_dependency_count: registry
.reconciliation
.unclassified_source_dependency_count,
implementation_stage_count: registry
.protocols
.iter()
.filter_map(|protocol| protocol.implementation_stage.as_deref())
.collect::<HashSet<_>>()
.len(),
active_adapters,
raw_protocol_text_executed: registry.compiler.raw_protocol_text_executed,
arbitrary_protocol_code_allowed: registry.compiler.arbitrary_protocol_code_allowed,
@ -352,11 +415,23 @@ mod tests {
fn registry_is_pinned_and_never_executes_raw_protocol_text() {
let registry = load_registry().unwrap();
assert_eq!(registry.protocol_count, 75);
assert_eq!(registry.executable_projection_count, 4);
assert_eq!(registry.executable_projection_count, 25);
assert_eq!(registry.reconciliation.protocol_registry_id_count, 52);
assert_eq!(registry.reconciliation.legacy_dependency_target_count, 57);
assert_eq!(registry.reconciliation.legacy_dependency_cycles.len(), 3);
assert_eq!(registry.reconciliation.authority_conflict_count, 0);
assert_eq!(
registry.reconciliation.unclassified_source_dependency_count,
0
);
assert_eq!(
registry
.reconciliation
.typed_source_dependency_counts
.values()
.sum::<usize>(),
183
);
assert!(!registry.compiler.raw_protocol_text_executed);
assert!(!registry.compiler.arbitrary_protocol_code_allowed);
}
@ -394,7 +469,7 @@ mod tests {
.iter_mut()
.find(|protocol| protocol.id == "GLS-0253")
.unwrap();
numbering.dependency_edges[0].edge_kind = "LEGACY_UNTYPED_REFERENCE".into();
numbering.dependency_edges[0].edge_kind = "NORMATIVE_REFERENCE".into();
assert_eq!(
validate_registry(&dependency_tamper).unwrap_err(),
"HOLOLAKE_GLS_DEPENDENCY_EDGE_INVALID"

View file

@ -11,6 +11,8 @@ mod direct_local_session;
mod dynamic_capability_routing;
mod enterprise_work_channel;
mod glp_envelope;
mod gls_bootstrap_compiler;
mod gls_protocol_kernel;
mod gls_protocol_runtime;
mod home_status;
mod knowledge_base;
@ -50,6 +52,9 @@ pub fn run() {
direct_local_session::append_direct_local_session_event,
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,
@ -98,6 +103,9 @@ pub fn run() {
zero_point::zero_point_status,
])
.setup(|app| {
// GLS 是 HoloLake 产品内核,不是开发机旁路服务。合同、依赖闭包、
// 自举编译器或回执账本任一不可用时,产品启动失败关闭。
gls_protocol_kernel::start_on_application_open(app.handle())?;
// 软件打开即先启动时间主控并发起联网校时;失败只降级,不阻塞人进入 HoloLake。
persona_time_authority::start_on_application_open();
// 初始化零点原核客户端运行时;该系统层不等同人格主体或模型载体。

View file

@ -210,6 +210,7 @@ pub(crate) fn issue_authenticated_at(
session_root: &Path,
input: IssuePersonaTimeTicketInput,
) -> Result<PersonaTimeTicket, String> {
crate::gls_protocol_runtime::require_adapter("glp-continuity-kernel", "TIME_CONTINUITY")?;
let session = authenticate_context_at(session_root, &input.session)?;
issue_with_sample(
authority_root,