fix: complete ordinary channel runtime paths

This commit is contained in:
冰朔 2026-08-21 13:24:43 +08:00
commit 2e48b7d768
12 changed files with 158 additions and 40 deletions

View file

@ -46,6 +46,7 @@ struct RuntimeRules {
payload_bound_grants: bool,
authority_binding_issued_server_side: bool,
verified_human_binding_required_for_protected_routes: bool,
ordinary_user_local_channel_authority: String,
persona_binding_claimed: bool,
user_channel_body_binding_stage: String,
maximum_grant_ttl_ms: u64,
@ -266,6 +267,8 @@ fn validate_registry(registry: &NumberedIpcRegistry) -> Result<(), String> {
|| !runtime.payload_bound_grants
|| !runtime.authority_binding_issued_server_side
|| !runtime.verified_human_binding_required_for_protected_routes
|| runtime.ordinary_user_local_channel_authority
!= "EXPLICIT_INITIALIZATION_PLUS_ACCOUNT_SCOPED_SESSION_PLUS_KEYCHAIN_SECRET"
|| runtime.persona_binding_claimed
|| runtime.user_channel_body_binding_stage != "SEPARATE_EVIDENCE_LAYER_NOT_YET_CLAIMED"
|| !runtime.receipt_required
@ -424,7 +427,27 @@ fn enforce_admission(app: &AppHandle, route: &OperationRoute) -> Result<String,
Some((human_number, registry_domain)) => {
Ok(format!("VERIFIED_HUMAN:{registry_domain}:{human_number}"))
}
None => Err("HOLOLAKE_NUMBERED_IPC_VERIFIED_HUMAN_REQUIRED".into()),
None => {
// An ordinary user's local channel has no globally registered Guanghu
// number yet. Its explicit initialization acknowledgement, account-
// scoped session file and Keychain secret still form an authenticated
// human boundary for that local account. Without this branch every
// protected in-app feature (including the channel Agent) is rendered
// but unusable immediately after the advertised local initialization.
let session = crate::code_repo_login::current_login_session(app)?;
match session {
Some(session)
if session.domain == "PERSONAL_CHANNEL" && session.host == "local.hololake" =>
{
let identity = crate::personal_channel::identity_for_channel_runtime(app)?;
Ok(format!(
"AUTHENTICATED_LOCAL_HUMAN:PERSONAL_CHANNEL:{}",
identity.human_subject_id
))
}
_ => Err("HOLOLAKE_NUMBERED_IPC_VERIFIED_HUMAN_REQUIRED".into()),
}
}
}
}

View file

@ -31,6 +31,21 @@ fn json<T: Serialize>(value: T) -> Result<Value, String> {
.map_err(|error| format!("HOLOLAKE_NUMBERED_IPC_RESULT_INVALID: {error}"))
}
fn authenticated_human_subject(app: &AppHandle) -> Result<Option<(String, String)>, String> {
let state = app.state::<crate::zero_point::ZeroPointState>();
if let Some(subject) = crate::zero_point::verified_user_route(&state)? {
return Ok(Some(subject));
}
let Some(session) = crate::code_repo_login::current_login_session(app)? else {
return Ok(None);
};
if session.domain != "PERSONAL_CHANNEL" || session.host != "local.hololake" {
return Ok(None);
}
let identity = crate::personal_channel::identity_for_channel_runtime(app)?;
Ok(Some((identity.human_subject_id, session.domain)))
}
pub(crate) async fn dispatch(
app: AppHandle,
handler: &str,
@ -47,8 +62,7 @@ pub(crate) async fn dispatch(
json(crate::human_authorization::get_center(&app)?)
}
"human_authorization::decide_authorization_request" => {
let state = app.state::<crate::zero_point::ZeroPointState>();
let (human_number, _) = crate::zero_point::verified_user_route(&state)?
let (human_number, _) = authenticated_human_subject(&app)?
.ok_or_else(|| "HOLOLAKE_AUTHORIZATION_VERIFIED_HUMAN_REQUIRED".to_string())?;
json(crate::human_authorization::decide(
&app,
@ -57,14 +71,12 @@ pub(crate) async fn dispatch(
)?)
}
"external_ai_gateway::get_gateway_status" => {
let state = app.state::<crate::zero_point::ZeroPointState>();
crate::zero_point::verified_user_route(&state)?
authenticated_human_subject(&app)?
.ok_or_else(|| "HOLOLAKE_GATEWAY_VERIFIED_HUMAN_REQUIRED".to_string())?;
json(crate::external_ai_gateway::get_gateway_status(app).await?)
}
"external_ai_gateway::set_gateway_exposure" => {
let state = app.state::<crate::zero_point::ZeroPointState>();
let (human_number, _) = crate::zero_point::verified_user_route(&state)?
let (human_number, _) = authenticated_human_subject(&app)?
.ok_or_else(|| "HOLOLAKE_GATEWAY_VERIFIED_HUMAN_REQUIRED".to_string())?;
json(
crate::external_ai_gateway::set_gateway_exposure(
@ -104,8 +116,7 @@ pub(crate) async fn dispatch(
json(crate::hldp_tool_forge::compile_tool(app, input(&payload)?)?)
}
"hldp_tool_forge::request_test_authorization" => {
let state = app.state::<crate::zero_point::ZeroPointState>();
let (human_number, _) = crate::zero_point::verified_user_route(&state)?
let (human_number, _) = authenticated_human_subject(&app)?
.ok_or_else(|| "HOLOLAKE_TOOL_FORGE_VERIFIED_HUMAN_REQUIRED".to_string())?;
json(crate::hldp_tool_forge::request_test_authorization(
app,
@ -114,8 +125,7 @@ pub(crate) async fn dispatch(
)?)
}
"hldp_tool_forge::test_tool" => {
let state = app.state::<crate::zero_point::ZeroPointState>();
let (human_number, _) = crate::zero_point::verified_user_route(&state)?
let (human_number, _) = authenticated_human_subject(&app)?
.ok_or_else(|| "HOLOLAKE_TOOL_FORGE_VERIFIED_HUMAN_REQUIRED".to_string())?;
json(crate::hldp_tool_forge::test_tool(app, input(&payload)?, &human_number).await?)
}