feat: compile GLS protocols into native runtime guards
This commit is contained in:
parent
96769846ac
commit
d6b1290e1c
13 changed files with 1909 additions and 6 deletions
|
|
@ -0,0 +1,252 @@
|
|||
//! GLS 协议运行注册表。
|
||||
//!
|
||||
//! 人类可读 GLS 正本先由仓库编译器固定为带来源摘要的协议清单;原生运行时只执行显式
|
||||
//! 登记的确定性适配器,不解释协议散文、不加载任意代码,也不把“已收录”冒充“已执行”。
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
const EMBEDDED_REGISTRY: &str = include_str!("../../contracts/gls-runtime-registry.json");
|
||||
const EXPECTED_SCHEMA: &str = "hololake.gls-protocol-runtime-registry/v1";
|
||||
const EXPECTED_SOURCE_COMMIT: &str = "2598fbfba8caf64c7ab9740a3036c5aab977502e";
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct GlsRuntimeRegistry {
|
||||
schema: String,
|
||||
source: GlsSource,
|
||||
compiler: GlsCompilerBoundary,
|
||||
protocol_count: usize,
|
||||
executable_projection_count: usize,
|
||||
inventoried_not_executable_count: usize,
|
||||
protocols: Vec<GlsProtocol>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct GlsSource {
|
||||
repository: String,
|
||||
commit: String,
|
||||
root: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct GlsCompilerBoundary {
|
||||
raw_protocol_text_executed: bool,
|
||||
arbitrary_protocol_code_allowed: bool,
|
||||
executable_projection_requires_explicit_adapter: bool,
|
||||
unprojected_protocol_behavior: String,
|
||||
dependency_cycles: String,
|
||||
unknown_protocol: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct GlsProtocol {
|
||||
id: String,
|
||||
source_sha256: String,
|
||||
projection_state: String,
|
||||
adapter: Option<String>,
|
||||
event_kinds: Vec<String>,
|
||||
dependencies: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GlsProtocolRuntimeSnapshot {
|
||||
pub state: String,
|
||||
pub source_repository: String,
|
||||
pub source_commit: String,
|
||||
pub source_root: String,
|
||||
pub protocol_count: usize,
|
||||
pub executable_projection_count: usize,
|
||||
pub inventoried_not_executable_count: usize,
|
||||
pub active_adapters: Vec<String>,
|
||||
pub raw_protocol_text_executed: bool,
|
||||
pub arbitrary_protocol_code_allowed: bool,
|
||||
pub unprojected_protocol_behavior: String,
|
||||
}
|
||||
|
||||
fn load_registry() -> Result<GlsRuntimeRegistry, String> {
|
||||
let registry: GlsRuntimeRegistry = serde_json::from_str(EMBEDDED_REGISTRY)
|
||||
.map_err(|error| format!("HOLOLAKE_GLS_RUNTIME_REGISTRY_INVALID: {error}"))?;
|
||||
validate_registry(®istry)?;
|
||||
Ok(registry)
|
||||
}
|
||||
|
||||
fn validate_registry(registry: &GlsRuntimeRegistry) -> Result<(), String> {
|
||||
if registry.schema != EXPECTED_SCHEMA
|
||||
|| registry.source.repository != "REPO-012"
|
||||
|| registry.source.commit != EXPECTED_SOURCE_COMMIT
|
||||
|| registry.source.root != "gls"
|
||||
|| registry.compiler.raw_protocol_text_executed
|
||||
|| registry.compiler.arbitrary_protocol_code_allowed
|
||||
|| !registry
|
||||
.compiler
|
||||
.executable_projection_requires_explicit_adapter
|
||||
|| registry.compiler.unprojected_protocol_behavior != "INVENTORIED_NOT_EXECUTABLE"
|
||||
|| registry.compiler.dependency_cycles != "REJECT"
|
||||
|| registry.compiler.unknown_protocol != "FAIL_CLOSED"
|
||||
|| registry.protocol_count != registry.protocols.len()
|
||||
|| registry.protocol_count
|
||||
!= registry.executable_projection_count + registry.inventoried_not_executable_count
|
||||
{
|
||||
return Err("HOLOLAKE_GLS_RUNTIME_BOUNDARY_INVALID".into());
|
||||
}
|
||||
|
||||
let mut ids = HashSet::new();
|
||||
let mut executable = 0;
|
||||
for protocol in ®istry.protocols {
|
||||
if !ids.insert(protocol.id.as_str())
|
||||
|| !protocol.id.starts_with("GLS-")
|
||||
|| protocol.source_sha256.len() != 64
|
||||
|| !protocol
|
||||
.source_sha256
|
||||
.chars()
|
||||
.all(|character| character.is_ascii_hexdigit())
|
||||
{
|
||||
return Err("HOLOLAKE_GLS_PROTOCOL_ENTRY_INVALID".into());
|
||||
}
|
||||
match protocol.projection_state.as_str() {
|
||||
"EXECUTABLE_PROJECTION" => {
|
||||
executable += 1;
|
||||
if protocol.adapter.as_deref().unwrap_or("").is_empty()
|
||||
|| protocol.event_kinds.is_empty()
|
||||
{
|
||||
return Err("HOLOLAKE_GLS_EXECUTABLE_ADAPTER_REQUIRED".into());
|
||||
}
|
||||
}
|
||||
"INVENTORIED_NOT_EXECUTABLE" => {
|
||||
if protocol.adapter.is_some()
|
||||
|| !protocol.event_kinds.is_empty()
|
||||
|| !protocol.dependencies.is_empty()
|
||||
{
|
||||
return Err("HOLOLAKE_GLS_INVENTORY_CANNOT_EXECUTE".into());
|
||||
}
|
||||
}
|
||||
_ => return Err("HOLOLAKE_GLS_PROJECTION_STATE_UNKNOWN".into()),
|
||||
}
|
||||
}
|
||||
if executable != registry.executable_projection_count {
|
||||
return Err("HOLOLAKE_GLS_EXECUTABLE_COUNT_MISMATCH".into());
|
||||
}
|
||||
|
||||
let by_id = registry
|
||||
.protocols
|
||||
.iter()
|
||||
.map(|protocol| (protocol.id.as_str(), protocol))
|
||||
.collect::<HashMap<_, _>>();
|
||||
for protocol in registry
|
||||
.protocols
|
||||
.iter()
|
||||
.filter(|protocol| protocol.projection_state == "EXECUTABLE_PROJECTION")
|
||||
{
|
||||
for dependency in &protocol.dependencies {
|
||||
if !matches!(
|
||||
by_id.get(dependency.as_str()),
|
||||
Some(entry) if entry.projection_state == "EXECUTABLE_PROJECTION"
|
||||
) {
|
||||
return Err("HOLOLAKE_GLS_EXECUTABLE_DEPENDENCY_INVALID".into());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn collect_protocol_set(
|
||||
id: &str,
|
||||
by_id: &HashMap<&str, &GlsProtocol>,
|
||||
visiting: &mut HashSet<String>,
|
||||
collected: &mut Vec<String>,
|
||||
) -> Result<(), String> {
|
||||
if collected.iter().any(|existing| existing == id) {
|
||||
return Ok(());
|
||||
}
|
||||
if !visiting.insert(id.to_string()) {
|
||||
return Err("HOLOLAKE_GLS_DEPENDENCY_CYCLE".into());
|
||||
}
|
||||
let protocol = by_id.get(id).ok_or("HOLOLAKE_GLS_PROTOCOL_UNKNOWN")?;
|
||||
if protocol.projection_state != "EXECUTABLE_PROJECTION" {
|
||||
return Err("HOLOLAKE_GLS_PROTOCOL_NOT_EXECUTABLE".into());
|
||||
}
|
||||
for dependency in &protocol.dependencies {
|
||||
collect_protocol_set(dependency, by_id, visiting, collected)?;
|
||||
}
|
||||
visiting.remove(id);
|
||||
collected.push(id.to_string());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn require_adapter(adapter: &str, event_kind: &str) -> Result<Vec<String>, String> {
|
||||
let registry = load_registry()?;
|
||||
let protocol = registry
|
||||
.protocols
|
||||
.iter()
|
||||
.find(|protocol| {
|
||||
protocol.projection_state == "EXECUTABLE_PROJECTION"
|
||||
&& protocol.adapter.as_deref() == Some(adapter)
|
||||
&& protocol.event_kinds.iter().any(|kind| kind == event_kind)
|
||||
})
|
||||
.ok_or("HOLOLAKE_GLS_EXECUTABLE_ADAPTER_NOT_REGISTERED")?;
|
||||
let by_id = registry
|
||||
.protocols
|
||||
.iter()
|
||||
.map(|entry| (entry.id.as_str(), entry))
|
||||
.collect::<HashMap<_, _>>();
|
||||
let mut collected = Vec::new();
|
||||
collect_protocol_set(&protocol.id, &by_id, &mut HashSet::new(), &mut collected)?;
|
||||
Ok(collected)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_gls_protocol_runtime() -> Result<GlsProtocolRuntimeSnapshot, String> {
|
||||
let registry = load_registry()?;
|
||||
let mut active_adapters = registry
|
||||
.protocols
|
||||
.iter()
|
||||
.filter_map(|protocol| protocol.adapter.clone())
|
||||
.collect::<Vec<_>>();
|
||||
active_adapters.sort();
|
||||
Ok(GlsProtocolRuntimeSnapshot {
|
||||
state: "ACTIVE_EXPLICIT_PROJECTIONS_ONLY".into(),
|
||||
source_repository: registry.source.repository,
|
||||
source_commit: registry.source.commit,
|
||||
source_root: registry.source.root,
|
||||
protocol_count: registry.protocol_count,
|
||||
executable_projection_count: registry.executable_projection_count,
|
||||
inventoried_not_executable_count: registry.inventoried_not_executable_count,
|
||||
active_adapters,
|
||||
raw_protocol_text_executed: registry.compiler.raw_protocol_text_executed,
|
||||
arbitrary_protocol_code_allowed: registry.compiler.arbitrary_protocol_code_allowed,
|
||||
unprojected_protocol_behavior: registry.compiler.unprojected_protocol_behavior,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
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!(!registry.compiler.raw_protocol_text_executed);
|
||||
assert!(!registry.compiler.arbitrary_protocol_code_allowed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numbering_adapter_resolves_a_dependency_closed_protocol_set() {
|
||||
let protocols = require_adapter("zero-core-numbering", "IDENTITY_ROUTE").unwrap();
|
||||
assert_eq!(protocols, ["GLS-0250", "GLS-0262", "GLS-0263", "GLS-0253"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unregistered_adapter_and_event_fail_closed() {
|
||||
assert_eq!(
|
||||
require_adapter("zero-core-numbering", "SHELL_EXECUTION").unwrap_err(),
|
||||
"HOLOLAKE_GLS_EXECUTABLE_ADAPTER_NOT_REGISTERED"
|
||||
);
|
||||
assert_eq!(
|
||||
require_adapter("invented-adapter", "IDENTITY_ROUTE").unwrap_err(),
|
||||
"HOLOLAKE_GLS_EXECUTABLE_ADAPTER_NOT_REGISTERED"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ mod direct_local_session;
|
|||
mod dynamic_capability_routing;
|
||||
mod enterprise_work_channel;
|
||||
mod glp_envelope;
|
||||
mod gls_protocol_runtime;
|
||||
mod home_status;
|
||||
mod knowledge_base;
|
||||
mod local_development_bridge;
|
||||
|
|
@ -23,6 +24,7 @@ mod pncc_server_projection;
|
|||
mod release_trust;
|
||||
mod release_update;
|
||||
mod user_pncc_channel;
|
||||
mod zero_core_numbering;
|
||||
mod zero_point;
|
||||
|
||||
use tauri::Manager;
|
||||
|
|
@ -47,6 +49,7 @@ pub fn run() {
|
|||
direct_local_session::resume_direct_local_session,
|
||||
direct_local_session::append_direct_local_session_event,
|
||||
direct_local_broker::get_nearby_ai_discovery,
|
||||
gls_protocol_runtime::get_gls_protocol_runtime,
|
||||
local_development_bridge::acquire_development_write_lane,
|
||||
local_development_bridge::inspect_development_write_lane,
|
||||
local_development_bridge::release_development_write_lane,
|
||||
|
|
@ -88,6 +91,7 @@ pub fn run() {
|
|||
code_repo_login::sign_out_code_repo_login,
|
||||
user_pncc_channel::get_user_pncc_channel,
|
||||
user_pncc_channel::ensure_user_pncc_channel,
|
||||
zero_core_numbering::get_zero_core_numbering_kernel,
|
||||
zero_point::zero_point_bind,
|
||||
zero_point::zero_point_verify,
|
||||
zero_point::zero_point_sync,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,263 @@
|
|||
//! 零点原核编号控制面第一段原生内核。
|
||||
//!
|
||||
//! 该内核把 REPO-012 当前身份权威图的可执行路由合同固定进本机二进制,先回答
|
||||
//! “这个编号属于哪类主体、应进入哪一个登记面”。编号形状本身不构成登记、人格绑定、
|
||||
//! 执行权或现实存在证明;未知编号和错误主体类型一律在联网与登录前失败关闭。
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
|
||||
const EMBEDDED_CONTRACT: &str = include_str!("../../contracts/zero-core-numbering-kernel.json");
|
||||
const EXPECTED_SCHEMA: &str = "hololake.zero-core-numbering-kernel/v1";
|
||||
const EXPECTED_MAP_ID: &str = "GH-IDENTITY-AUTHORITY-MAP-001";
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct NumberingContract {
|
||||
schema: String,
|
||||
authority: NumberingAuthority,
|
||||
runtime: NumberingRuntime,
|
||||
namespaces: Vec<NumberingNamespace>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct NumberingAuthority {
|
||||
source_commit: String,
|
||||
source_path: String,
|
||||
map_id: String,
|
||||
map_version: String,
|
||||
map_state: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct NumberingRuntime {
|
||||
state: String,
|
||||
number_shape_is_authority: bool,
|
||||
unknown_number: String,
|
||||
automatic_identity_issuance: bool,
|
||||
human_entry_requires_registered_human_namespace: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct NumberingNamespace {
|
||||
id: String,
|
||||
roots: Vec<String>,
|
||||
prefixes: Vec<String>,
|
||||
subject_kind: String,
|
||||
issuer: String,
|
||||
human_entry: bool,
|
||||
registry: String,
|
||||
domain_scope: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ZeroCoreNumberingKernelSnapshot {
|
||||
pub state: String,
|
||||
pub authority_map_id: String,
|
||||
pub authority_map_version: String,
|
||||
pub authority_map_state: String,
|
||||
pub source_commit: String,
|
||||
pub source_path: String,
|
||||
pub human_route_namespaces: Vec<String>,
|
||||
pub number_shape_is_authority: bool,
|
||||
pub automatic_identity_issuance: bool,
|
||||
pub unknown_number: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HumanNumberRoute {
|
||||
pub canonical_number: String,
|
||||
pub namespace: String,
|
||||
pub subject_kind: String,
|
||||
pub issuer: String,
|
||||
pub registry: String,
|
||||
pub domain_scope: String,
|
||||
pub protocol_set: Vec<String>,
|
||||
pub decision: String,
|
||||
}
|
||||
|
||||
fn load_contract() -> Result<NumberingContract, String> {
|
||||
let contract: NumberingContract = serde_json::from_str(EMBEDDED_CONTRACT)
|
||||
.map_err(|error| format!("HOLOLAKE_NUMBERING_CONTRACT_INVALID: {error}"))?;
|
||||
validate_contract(&contract)?;
|
||||
Ok(contract)
|
||||
}
|
||||
|
||||
fn validate_contract(contract: &NumberingContract) -> Result<(), String> {
|
||||
if contract.schema != EXPECTED_SCHEMA
|
||||
|| contract.authority.map_id != EXPECTED_MAP_ID
|
||||
|| contract.authority.source_commit.len() != 40
|
||||
|| !contract
|
||||
.authority
|
||||
.source_commit
|
||||
.chars()
|
||||
.all(|character| character.is_ascii_hexdigit())
|
||||
|| contract.authority.source_path.is_empty()
|
||||
|| contract.authority.map_version.is_empty()
|
||||
|| contract.authority.map_state.is_empty()
|
||||
|| contract.runtime.state != "ACTIVE_PINNED_AUTHORITY_MAP"
|
||||
|| contract.runtime.number_shape_is_authority
|
||||
|| contract.runtime.automatic_identity_issuance
|
||||
|| contract.runtime.unknown_number != "FAIL_CLOSED"
|
||||
|| !contract
|
||||
.runtime
|
||||
.human_entry_requires_registered_human_namespace
|
||||
{
|
||||
return Err("HOLOLAKE_NUMBERING_CONTRACT_BOUNDARY_INVALID".into());
|
||||
}
|
||||
|
||||
let mut ids = HashSet::new();
|
||||
for namespace in &contract.namespaces {
|
||||
if !ids.insert(namespace.id.as_str())
|
||||
|| namespace.id.is_empty()
|
||||
|| namespace.subject_kind.is_empty()
|
||||
|| namespace.issuer.is_empty()
|
||||
|| namespace.registry.is_empty()
|
||||
|| namespace.domain_scope.is_empty()
|
||||
|| (namespace.roots.is_empty() && namespace.prefixes.is_empty())
|
||||
|| namespace
|
||||
.roots
|
||||
.iter()
|
||||
.chain(namespace.prefixes.iter())
|
||||
.any(|value| value.is_empty())
|
||||
{
|
||||
return Err("HOLOLAKE_NUMBERING_NAMESPACE_CONTRACT_INVALID".into());
|
||||
}
|
||||
}
|
||||
for required in ["ICE_GL", "ICE_P", "ICE_BB", "TCS_GL"] {
|
||||
if !ids.contains(required) {
|
||||
return Err("HOLOLAKE_NUMBERING_NAMESPACE_REQUIRED".into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_number_input(number: &str) -> Result<&str, String> {
|
||||
let number = number.trim();
|
||||
if number.is_empty() || number.len() > 96 {
|
||||
return Err("HOLOLAKE_NUMBERING_IDENTIFIER_INVALID".into());
|
||||
}
|
||||
if number
|
||||
.chars()
|
||||
.any(|character| character.is_control() || character.is_whitespace())
|
||||
{
|
||||
return Err("HOLOLAKE_NUMBERING_IDENTIFIER_INVALID".into());
|
||||
}
|
||||
Ok(number)
|
||||
}
|
||||
|
||||
fn matching_namespace<'a>(
|
||||
contract: &'a NumberingContract,
|
||||
number: &str,
|
||||
) -> Result<&'a NumberingNamespace, String> {
|
||||
let matches = contract
|
||||
.namespaces
|
||||
.iter()
|
||||
.filter(|namespace| {
|
||||
namespace.roots.iter().any(|root| root == number)
|
||||
|| namespace
|
||||
.prefixes
|
||||
.iter()
|
||||
.any(|prefix| number.starts_with(prefix))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
match matches.as_slice() {
|
||||
[namespace] => Ok(namespace),
|
||||
[] => Err("HOLOLAKE_NUMBERING_NAMESPACE_UNKNOWN".into()),
|
||||
_ => Err("HOLOLAKE_NUMBERING_NAMESPACE_AMBIGUOUS".into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_human_number_route(number: &str) -> Result<HumanNumberRoute, String> {
|
||||
let number = validate_number_input(number)?;
|
||||
let protocol_set =
|
||||
crate::gls_protocol_runtime::require_adapter("zero-core-numbering", "IDENTITY_ROUTE")?;
|
||||
let contract = load_contract()?;
|
||||
let namespace = matching_namespace(&contract, number)?;
|
||||
if !namespace.human_entry {
|
||||
return Err("HOLOLAKE_NUMBERING_HUMAN_ENTRY_SUBJECT_KIND_REJECTED".into());
|
||||
}
|
||||
Ok(HumanNumberRoute {
|
||||
canonical_number: number.to_string(),
|
||||
namespace: namespace.id.clone(),
|
||||
subject_kind: namespace.subject_kind.clone(),
|
||||
issuer: namespace.issuer.clone(),
|
||||
registry: namespace.registry.clone(),
|
||||
domain_scope: namespace.domain_scope.clone(),
|
||||
protocol_set,
|
||||
decision: "ALLOW_REGISTRY_RESOLUTION".into(),
|
||||
})
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_zero_core_numbering_kernel() -> Result<ZeroCoreNumberingKernelSnapshot, String> {
|
||||
let contract = load_contract()?;
|
||||
Ok(ZeroCoreNumberingKernelSnapshot {
|
||||
state: contract.runtime.state,
|
||||
authority_map_id: contract.authority.map_id,
|
||||
authority_map_version: contract.authority.map_version,
|
||||
authority_map_state: contract.authority.map_state,
|
||||
source_commit: contract.authority.source_commit,
|
||||
source_path: contract.authority.source_path,
|
||||
human_route_namespaces: contract
|
||||
.namespaces
|
||||
.into_iter()
|
||||
.filter(|namespace| namespace.human_entry)
|
||||
.map(|namespace| namespace.id)
|
||||
.collect(),
|
||||
number_shape_is_authority: contract.runtime.number_shape_is_authority,
|
||||
automatic_identity_issuance: contract.runtime.automatic_identity_issuance,
|
||||
unknown_number: contract.runtime.unknown_number,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn embedded_authority_map_contract_is_valid_and_fail_closed() {
|
||||
let contract = load_contract().unwrap();
|
||||
assert_eq!(contract.authority.map_id, EXPECTED_MAP_ID);
|
||||
assert!(!contract.runtime.number_shape_is_authority);
|
||||
assert!(!contract.runtime.automatic_identity_issuance);
|
||||
assert_eq!(contract.runtime.unknown_number, "FAIL_CLOSED");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn registered_human_namespaces_select_their_authoritative_registry() {
|
||||
let bingshuo = resolve_human_number_route("ICE-GL∞").unwrap();
|
||||
assert_eq!(bingshuo.namespace, "ICE_GL");
|
||||
assert_eq!(bingshuo.domain_scope, "FIFTH_DOMAIN");
|
||||
let zhizhi = resolve_human_number_route("ICE-GL-ZHI∞").unwrap();
|
||||
assert_eq!(zhizhi.namespace, "ICE_GL");
|
||||
let feimao = resolve_human_number_route("TCS-GL-0007∞").unwrap();
|
||||
assert_eq!(feimao.namespace, "TCS_GL");
|
||||
assert_eq!(feimao.domain_scope, "ENTERPRISE_FOUR_DOMAINS");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn persona_and_unknown_numbers_cannot_enter_a_human_route() {
|
||||
assert_eq!(
|
||||
resolve_human_number_route("ICE-P-ZY001").unwrap_err(),
|
||||
"HOLOLAKE_NUMBERING_HUMAN_ENTRY_SUBJECT_KIND_REJECTED"
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_human_number_route("ICE-BB-YM001").unwrap_err(),
|
||||
"HOLOLAKE_NUMBERING_HUMAN_ENTRY_SUBJECT_KIND_REJECTED"
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_human_number_route("UNKNOWN-001").unwrap_err(),
|
||||
"HOLOLAKE_NUMBERING_NAMESPACE_UNKNOWN"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed_identifiers_are_rejected_before_namespace_resolution() {
|
||||
assert_eq!(
|
||||
resolve_human_number_route("ICE-GL- bad").unwrap_err(),
|
||||
"HOLOLAKE_NUMBERING_IDENTIFIER_INVALID"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -394,13 +394,15 @@ fn resolver_url_for_number(
|
|||
protocol: &ZeroPointProtocol,
|
||||
number: &str,
|
||||
) -> Result<reqwest::Url, String> {
|
||||
let mut url = if number.starts_with("TCS-GL-") {
|
||||
reqwest::Url::parse(&protocol.enterprise_resolve_url)
|
||||
let route = crate::zero_core_numbering::resolve_human_number_route(number)?;
|
||||
let enterprise = route.namespace == "TCS_GL";
|
||||
let mut url = reqwest::Url::parse(if enterprise {
|
||||
&protocol.enterprise_resolve_url
|
||||
} else {
|
||||
reqwest::Url::parse(&protocol.lighthouse_resolve_url)
|
||||
}
|
||||
&protocol.lighthouse_resolve_url
|
||||
})
|
||||
.map_err(|_| "HOLOLAKE_ZP_RESOLVER_URL_INVALID".to_string())?;
|
||||
if number.starts_with("TCS-GL-") {
|
||||
if enterprise {
|
||||
url.query_pairs_mut().append_pair("id", number);
|
||||
} else {
|
||||
// 第五域旧协议以 `?id=` 结尾;使用 URL 查询构造器避免把编号中的字符裸拼入地址。
|
||||
|
|
|
|||
Loading…
Reference in a new issue