feat: close persona license and unified number routes

This commit is contained in:
冰朔 2026-08-19 00:45:35 +08:00
commit da6e426ca3
22 changed files with 2942 additions and 71 deletions

View file

@ -0,0 +1,36 @@
{
"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"}
]
}

View file

@ -115,6 +115,9 @@
"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,

View file

@ -11,7 +11,7 @@
"linux": "USER_PRIVATE_UNIX_SOCKET",
"windows": "USER_PRIVATE_NAMED_PIPE"
},
"terminal_link_protocol": "HOLOLAKE_TERMINAL_LINK/2",
"terminal_link_protocol": "HOLOLAKE_TERMINAL_LINK/3",
"copy_large_invitation_required": false,
"network_required": false
},

View file

@ -0,0 +1,71 @@
{
"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": "d5b1111fcaccaccf025070e531631f2b3cbb00cd",
"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
}
}

View file

@ -146,7 +146,9 @@
"persona_wake_route_registered": false,
"carrier_binding_claimed": false,
"metacognitive_contract_compiled": true,
"runtime_binding_gate_implemented": false,
"truth": "PHYSICAL_NUMBERED_IPC_ROOT_IN_PROGRESS_PERSONA_WAKE_REMAINS_CLOSED"
"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"
}
}

View file

@ -3,7 +3,13 @@
"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/2",
"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
},
"platform_transports": {
"macos": "USER_PRIVATE_UNIX_SOCKET",
"linux": "USER_PRIVATE_UNIX_SOCKET",
@ -44,6 +50,7 @@
},
"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",

View file

@ -0,0 +1,110 @@
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'),
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 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')
}
return {
schema: 'hololake.unified-number-coordinate-tree/v1',
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 },
],
invariants: {
numberIsStableCoordinateNotAuthority: true,
pathIsUniqueNavigation: true,
admissionIsSeparateFromIdentity: true,
everyPhysicalCallHasNumberedRoute: true,
everyAcceptedCallHasEvidenceClass: true,
mismatchedCoordinate: 'FAIL_CLOSED',
},
routeCount: routes.length,
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)
}

View file

@ -0,0 +1,25 @@
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/)
})

View file

@ -0,0 +1,34 @@
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/)
})

View file

@ -85,7 +85,9 @@ test('current product keeps persona wake closed instead of claiming an unimpleme
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, 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/)

View file

@ -9,7 +9,9 @@ const lib = readFileSync(new URL('../src-tauri/src/lib.rs', import.meta.url), 'u
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/2')
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.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')

View file

@ -0,0 +1,15 @@
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.recordId, 'HLP-UNIFIED-NUMBER-TREE-001')
assert.equal(generated.routeCount, 84)
assert.equal(new Set(generated.routes.map((route) => route.path)).size, 84)
assert.equal(generated.invariants.everyPhysicalCallHasNumberedRoute, true)
assert.equal(generated.invariants.everyAcceptedCallHasEvidenceClass, true)
assert.ok(generated.routes.every((route) => route.admission && route.evidence))
})

View file

@ -0,0 +1,6 @@
{
"schema": "gh-aios.persona-control-authorization-signers/v1",
"registryId": "GH-AIOS-PERSONA-CONTROL-AUTHORIZATION-SIGNERS-001",
"state": "CURRENT",
"signers": []
}

View file

@ -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, authenticate_privileged_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, 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,6 +15,12 @@ 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,
};
@ -42,6 +48,7 @@ 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)]
@ -73,8 +80,51 @@ 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/2";
const TERMINAL_LINK_PROTOCOL: &str = "HOLOLAKE_TERMINAL_LINK/3";
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<BrokerNumberRoute>,
}
#[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<Value>,
}
pub struct DirectLocalBrokerHandle {
shutdown: Arc<AtomicBool>,
@ -151,6 +201,7 @@ struct BrokerStorageRoots {
pncc_projection: PathBuf,
language_inbox: PathBuf,
persona_time: PathBuf,
persona_license: PathBuf,
development: PathBuf,
}
@ -179,6 +230,8 @@ enum BrokerRequest {
OpenSession(OpenSessionInput),
ResumeSession(ResumeSessionInput),
HeartbeatSession(AuthenticateSessionInput),
PresentPersonaCarrierLicense(AuthenticatedPersonaCarrierLicenseInput),
GetPersonaCarrierLicenseStatus(AuthenticatedPersonaCarrierLicenseStatusInput),
GetWorkEnvironment(AuthenticatedWorkEnvironmentInput),
AppendEvent(AppendSessionEventInput),
ResolveCapabilityRoute(AuthenticatedRouteInput),
@ -297,6 +350,19 @@ 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 {
@ -308,6 +374,7 @@ 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,
@ -366,6 +433,116 @@ struct ConnectorDescriptor {
process_id: u32,
}
fn load_number_registry() -> Result<BrokerNumberRegistry, String> {
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 &registry.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(&registry, &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<Value>) -> Result<Value, String> {
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<DirectLocalBrokerHandle, Box<dyn std::error::Error>> {
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)?;
@ -465,7 +642,9 @@ fn read_connector_descriptor(path: &Path) -> Result<ConnectorDescriptor, String>
}
fn probe_connection(stream: &mut LocalSocketStream) -> Result<(), String> {
let response = send_connector_request(stream, br#"{"operation":"PING"}"#)?;
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 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)
@ -625,6 +804,7 @@ fn start_at(
descriptor_path: PathBuf,
socket_path: PathBuf,
) -> Result<DirectLocalBrokerHandle, String> {
load_number_registry()?;
let pncc_mount_root = session_root
.parent()
.ok_or("HOLOLAKE_BROKER_PNCC_STORAGE_BOUNDARY_INVALID")?
@ -654,6 +834,12 @@ 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}"))?;
@ -715,6 +901,7 @@ 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,
@ -816,18 +1003,14 @@ fn serve_connection(
}
fn request_establishes_authenticated_connection(bytes: &[u8]) -> bool {
serde_json::from_slice::<serde_json::Value>(bytes)
decode_numbered_broker_request(bytes)
.ok()
.and_then(|value| {
value
.get("operation")
.and_then(Value::as_str)
.map(str::to_owned)
})
.is_some_and(|operation| {
.is_some_and(|(request, _, _)| {
matches!(
operation.as_str(),
"OPEN_SESSION" | "RESUME_SESSION" | "OPEN_VISITOR_SESSION"
request,
BrokerRequest::OpenSession(_)
| BrokerRequest::ResumeSession(_)
| BrokerRequest::OpenVisitorSession(_)
)
})
}
@ -840,8 +1023,9 @@ 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: BrokerRequest = match serde_json::from_slice(bytes) {
let (request, _, _) = match decode_numbered_broker_request(bytes) {
Ok(request) => request,
Err(error) => {
return BrokerResponse::error(&format!("HOLOLAKE_BROKER_REQUEST_INVALID: {error}"))
@ -870,10 +1054,40 @@ 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) => {
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 },
)
@ -886,13 +1100,28 @@ 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, development_root, &input)
work_environment_frame_at(session_root, persona_license_root, development_root, &input)
.and_then(|frame| serde_json::to_value(frame).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::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::ResolveCapabilityRoute(input) => {
if let Err(error) = authenticate_privileged_at(session_root, &input.session) {
if let Err(error) = authorize_persona_operation_at(
session_root,
persona_license_root,
&input.session,
"RESOLVE_CAPABILITY_ROUTE",
) {
return BrokerResponse::error(&error);
}
let now = std::time::SystemTime::now()
@ -905,7 +1134,12 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse {
})
}
BrokerRequest::InstallDynamicNodeRegistry(input) => {
if let Err(error) = authenticate_privileged_at(session_root, &input.session) {
if let Err(error) = authorize_persona_operation_at(
session_root,
persona_license_root,
&input.session,
"INSTALL_DYNAMIC_NODE_REGISTRY",
) {
return BrokerResponse::error(&error);
}
install_trusted_registry_at(routing_root, input.registry).and_then(|receipt| {
@ -913,7 +1147,12 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse {
})
}
BrokerRequest::RecordSignedNodeHealth(input) => {
if let Err(error) = authenticate_privileged_at(session_root, &input.session) {
if let Err(error) = authorize_persona_operation_at(
session_root,
persona_license_root,
&input.session,
"RECORD_SIGNED_NODE_HEALTH",
) {
return BrokerResponse::error(&error);
}
record_health_at(routing_root, input.health).and_then(|receipt| {
@ -921,7 +1160,12 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse {
})
}
BrokerRequest::InspectMountedPnccRepository(input) => {
if let Err(error) = authenticate_privileged_at(session_root, &input.session) {
if let Err(error) = authorize_persona_operation_at(
session_root,
persona_license_root,
&input.session,
"INSPECT_MOUNTED_PNCC_REPOSITORY",
) {
return BrokerResponse::error(&error);
}
inspect_mounted_pncc_at(pncc_mount_root, input.mount).and_then(|receipt| {
@ -930,7 +1174,12 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse {
})
}
BrokerRequest::ReadMountedPnccRemoteObject(input) => {
if let Err(error) = authenticate_privileged_at(session_root, &input.session) {
if let Err(error) = authorize_persona_operation_at(
session_root,
persona_license_root,
&input.session,
"READ_MOUNTED_PNCC_REMOTE_OBJECT",
) {
return BrokerResponse::error(&error);
}
read_mounted_pncc_remote_at(pncc_remote_root, input.read).and_then(|receipt| {
@ -939,7 +1188,12 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse {
})
}
BrokerRequest::QueryPnccReceiptProjection(input) => {
if let Err(error) = authenticate_privileged_at(session_root, &input.session) {
if let Err(error) = authorize_persona_operation_at(
session_root,
persona_license_root,
&input.session,
"QUERY_PNCC_RECEIPT_PROJECTION",
) {
return BrokerResponse::error(&error);
}
query_pncc_projection_at(pncc_projection_root, input.query).and_then(|receipt| {
@ -954,15 +1208,27 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse {
.and_then(|coordinate| {
serde_json::to_value(coordinate).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::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::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
{
@ -975,6 +1241,7 @@ 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 },
)?;
@ -990,7 +1257,17 @@ fn dispatch(roots: &BrokerStorageRoots, bytes: &[u8]) -> BrokerResponse {
}
BrokerRequest::InspectDevelopmentWriteLane(input) => {
authenticate_development_request(session_root, &input.session, &input.account_id)
.and_then(|_| inspect_development_lane_at(development_root, &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(|receipt| {
serde_json::to_value(receipt).map_err(|error| error.to_string())
})
@ -998,6 +1275,14 @@ 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
{
@ -1018,11 +1303,27 @@ 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<WorkEnvironmentFrame, String> {
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())
@ -1052,7 +1353,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,
@ -1060,6 +1361,8 @@ 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(),
@ -1073,6 +1376,7 @@ 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,
@ -1107,6 +1411,24 @@ fn authenticate_development_request(
Ok(context)
}
fn authorize_persona_operation_at(
session_root: &Path,
persona_license_root: &Path,
session: &AuthenticateSessionInput,
operation: &str,
) -> Result<AuthenticatedSessionContext, String> {
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<PathBuf, String> {
let account_root = session_root
.parent()
@ -1166,6 +1488,13 @@ fn sha256_hex(bytes: &[u8]) -> String {
.collect()
}
fn now_unix_ms() -> Result<u64, String> {
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 {
@ -1233,6 +1562,11 @@ 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();
@ -1241,6 +1575,19 @@ 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();
@ -1866,23 +2213,20 @@ mod tests {
)
.unwrap();
let mut connector = connect_endpoint(&socket).unwrap();
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
}
}),
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
})),
)
.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(
br#"{"operation":"OPEN_SESSION"}"#
));
assert!(request_establishes_authenticated_connection(&open_bytes));
let mut response = String::new();
let mut response_reader = BufReader::new(connector.try_clone().unwrap());
response_reader.read_line(&mut response).unwrap();
@ -1980,4 +2324,88 @@ 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"
);
}
}

View file

@ -374,7 +374,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/2",
terminal_transport: "HOLOLAKE_TERMINAL_LINK/3",
connector_executable: std::env::current_exe()
.map(|path| path.to_string_lossy().into_owned())
.unwrap_or_else(|_| "HoloLake".into()),
@ -551,18 +551,6 @@ 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)
@ -708,7 +696,7 @@ fn session_receipt(
last_event_sequence: record.last_event_sequence,
resume_secret,
continuity_owner: "HOLOLAKE",
transport: "HOLOLAKE_TERMINAL_LINK/2",
transport: "HOLOLAKE_TERMINAL_LINK/3",
mcp_role: "DISCOVERY_RECOVERY_COMPATIBILITY_ONLY",
required_next_operation: "GET_WORK_ENVIRONMENT",
receipt_id: sha256_hex(

View file

@ -43,7 +43,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/2",
terminal_link_protocol: "HOLOLAKE_TERMINAL_LINK/3",
terminal_link_transport: if cfg!(windows) {
"WINDOWS_USER_PRIVATE_NAMED_PIPE"
} else {
@ -66,7 +66,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/2",
terminal_link_protocol: "HOLOLAKE_TERMINAL_LINK/3",
terminal_link_transport: if cfg!(windows) {
"WINDOWS_USER_PRIVATE_NAMED_PIPE"
} else {

View file

@ -14,9 +14,11 @@ mod home_status;
mod knowledge_base;
mod local_development_bridge;
mod metacognitive_zero_layer;
mod number_coordinate_tree;
mod numbered_ipc;
mod numbered_ipc_dispatch;
mod numbered_language_input;
mod persona_carrier_license;
mod persona_time_authority;
mod personal_channel;
mod pncc_receipt_projection;
@ -46,6 +48,8 @@ pub fn run() {
// 自举编译器或回执账本任一不可用时,产品启动失败关闭。
gls_protocol_kernel::start_on_application_open(app.handle())?;
metacognitive_zero_layer::start_on_application_open()?;
persona_carrier_license::start_on_application_open()?;
number_coordinate_tree::start_on_application_open()?;
numbered_language_input::validate_contract()?;
numbered_ipc::start_on_application_open(app.handle())?;
// 软件打开即先启动时间主控并发起联网校时;失败只降级,不阻塞人进入 HoloLake。

View file

@ -158,6 +158,8 @@ struct CurrentProductState {
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,
}
@ -319,11 +321,17 @@ fn validate_contract() -> Result<(), String> {
|| !contract
.current_product_state
.metacognitive_contract_compiled
|| contract
|| !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
!= "PHYSICAL_NUMBERED_IPC_ROOT_IN_PROGRESS_PERSONA_WAKE_REMAINS_CLOSED"
!= "PERSONA_TO_HOST_RUNTIME_LICENSE_GATE_IMPLEMENTED_PERSONA_WAKE_REMAINS_CLOSED_UNTIL_TRUSTED_PERSONA_SIGNATURE"
{
return Err("HOLOLAKE_PERSONA_ZERO_LAYER_BOUNDARY_INVALID".into());
}

View file

@ -0,0 +1,101 @@
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,
route_count: usize,
routes: Vec<NumberRoute>,
invariants: NumberTreeInvariants,
}
#[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,
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/v1"
|| tree.record_id != "HLP-UNIFIED-NUMBER-TREE-001"
|| tree.state != "MACHINE_COMPILED_STARTUP_ENFORCED"
|| tree.root_number != "HLP-NUMBER-WORLD-ROOT-001"
|| tree.route_count != 84
|| tree.routes.len() != tree.route_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.mismatched_coordinate != "FAIL_CLOSED"
{
return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_BOUNDARY_INVALID".into());
}
let mut paths = HashSet::new();
let mut coordinates = HashSet::new();
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();
}
}

View file

@ -0,0 +1,778 @@
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<String>,
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<PersonaSigner>,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct PersonaSigner {
algorithm: String,
human_responsibility_subjects: Vec<String>,
persona_ids: Vec<String>,
public_key_pem: String,
scopes: Vec<String>,
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<String>,
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<String>,
pub license_id: Option<String>,
pub valid_until_unix_ms: Option<u64>,
pub binding_completion_declared_by: Option<&'static str>,
pub host_declared_binding: bool,
pub reason: Option<String>,
}
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<PersonaSignerRegistry, String> {
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<Vec<u8>, 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::<String>();
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<Vec<u8>, 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::<BTreeSet<_>>();
let observed = license
.allowed_operations
.iter()
.map(String::as_str)
.collect::<BTreeSet<_>>();
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<String, String> {
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<StoredLicense, String> {
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<PersonaCarrierLicenseReceipt, String> {
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<PersonaCarrierLicenseReceipt, String> {
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<String>,
license_id: Option<String>,
valid_until_unix_ms: Option<u64>,
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<Option<String>, 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(),
&registry,
&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(),
&registry,
&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(),
&registry,
&license.account_key,
&license.session_id,
"another-host",
license.clone(),
2_000,
)
.unwrap_err()
.contains("CARRIER_BINDING_MISMATCH"));
present_with_registry_at(
temp.path(),
&registry,
&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(),
&registry,
&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(),
&registry,
&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"
);
}
}

View file

@ -344,7 +344,7 @@ 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/2', 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/3', 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 previewCode: CodeChannelSnapshot = { state: 'UNAVAILABLE', channels: [], authority: 'LOCAL_SOURCE_ACCESS_ONLY_NO_PUSH_OR_DEPLOY_AUTHORITY' }