feat(hololake): connect enterprise device challenge flow

This commit is contained in:
冰朔 2026-09-03 21:59:53 +08:00
commit 6b23f710e1
19 changed files with 1220 additions and 14 deletions

View file

@ -1,7 +1,8 @@
{
"schema": "hololake.enterprise-responsibility-entrance/v1",
"contract_id": "HLP-ENTERPRISE-RESPONSIBILITY-ENTRANCE-0001",
"state": "LOCAL_DEVICE_PROOF_INSTALLED_KEYCHAIN_VERIFIED_SERVER_GATE_SOURCE_TESTED_DEPLOYMENT_PENDING",
"state": "SERVER_DEVICE_GATE_ACTIVE_CLIENT_ENROLLMENT_AND_CHALLENGE_SOURCE_IMPLEMENTED_REBUILD_PENDING",
"endpoint": "https://guanghu.chat/api/hololake/enterprise/device-gate",
"surface": "HOLOLAKE_GATED_ENTERPRISE_PORTAL",
"enterprise_server_embedded": false,
"identities": ["DOMAIN_ID", "RESPONSIBLE_HUMAN_ID", "BOUND_PERSONA_ID", "LOCAL_NODE_ID", "DEVICE_KEY_ID"],

View file

@ -0,0 +1,13 @@
TCS 0.1;
RECEIPT HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-RECEIPT-20260903 {
header { schema = "tcs.receipt/v1"; name_zh = "HoloLake企业责任设备门部署回执"; name_en = "HoloLake Enterprise Responsibility Device Gate Deployment Receipt"; version = "1.0.0"; language = "TCS/0.1"; profile = "PUBLIC-PRODUCT-ENGINEERING/1"; protocols = ["HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903", "HLP-ENTERPRISE-RESPONSIBILITY-ENTRANCE-0001"]; lifecycle = "CANDIDATE"; canonical_uri = "product-source/hololake-clean-desktop/language/HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-RECEIPT-20260903.tcs"; compatibility = ["GH-CVM-MAIN-PROD-01", "PYTHON/3.10", "ED25519", "NGINX"]; }
request { source = "BINGSHUO-DIRECT-HOLOLAKE-ZC001-EXECUTION-START-20260903"; value = "部署企业四域负责人通过HoloLake本机设备和人格编号验证后进入本人责任仓库的服务端验证门。"; scope = "GH-CVM-MAIN-PROD-01独立8033服务与精确Nginx路由"; }
operation { values = ["验证源码运输归档与manifest", "解包到/opt/guanghu-hololake-enterprise-gate/releases/be31c41", "创建独立lighthouse权限数据库与服务密钥", "安装guanghu-hololake-enterprise-gate.service", "加入guanghu.chat精确device-gate路由", "执行本地和外部健康、未知设备拒绝及原服务存活测试" ]; }
result { state = "PASS"; node_id = "GH-CVM-MAIN-PROD-01"; service = "guanghu-hololake-enterprise-gate.service"; service_state = "ACTIVE"; endpoint = "https://guanghu.chat/api/hololake/enterprise/device-gate"; source_commit = "be31c41"; source_archive_sha256 = "91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2"; registered_devices = 0; active_sessions = 0; }
verification { values = ["DMI UUID为10ace744-13e1-472e-8dba-6bb823a073bf", "服务器Python cryptography Ed25519测试2项通过", "systemd服务active", "127.0.0.1:8033/health返回ok", "外部HTTPS device-gate/health返回ok", "未知设备领取挑战返回HTTP404 registered device required", "guanghu-enterprise-identity.service保持active", "guanghu-flagos-collaboration.service保持active", "nginx.service保持active", "当前设备与会话数量均为0未伪造成员" ]; }
proof { server_release = "/opt/guanghu-hololake-enterprise-gate/releases/be31c41"; current_link = "/opt/guanghu-hololake-enterprise-gate/current"; database = "/var/lib/guanghu-hololake-enterprise-gate/gate.sqlite3"; nginx_snippet = "/etc/nginx/snippets/guanghu-hololake-enterprise-gate.conf"; nginx_backup = "/etc/nginx/sites-enabled/guanghu.chat.pre-hololake-device-gate-be31c41"; }
integrity { source_transport_manifest_sha256 = "653ae0ca824fd8b9fff8d8532e82eddce63a8aa9f070e7a6aa3f863834e4ae77"; source_archive_sha256 = "91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2"; tcs_stage1_compilation = "PASS"; unknown_device_negative = "PASS"; existing_services_preserved = "PASS"; }
boundaries { values = ["服务不保存Forgejo密码", "设备私钥从不离开成员本机Keychain", "机器指纹不能单独认证", "会话只限单域单仓且十分钟过期", "企业会话不替代Forgejo自身仓库登录", "冰朔公共语言主控仓继续走JD第五域桥接而非普通人类登录", "本轮未登记任何真实成员设备" ]; }
next { state = "SERVER_GATE_ACTIVE_CLIENT_INTEGRATION_REBUILD_REQUIRED"; optional = ["团队成员从HoloLake使用本人凭证完成首次设备登记", "正向验证挑战与单仓会话", "后续加入个人服务器二次桥接证明" ]; }
}

View file

@ -0,0 +1,15 @@
TCS 0.1;
EVENT HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903 {
header { schema = "tcs.event/v1"; name_zh = "HoloLake企业责任设备门部署开始事件"; name_en = "HoloLake Enterprise Responsibility Device Gate Deployment Start Event"; version = "1.0.0"; language = "TCS/0.1"; profile = "PUBLIC-PRODUCT-ENGINEERING/1"; protocols = ["HOLOLAKE-CLEAN-V1-DIRECT-LANGUAGE-EXECUTION-BASELINE-0001", "HLP-ENTERPRISE-RESPONSIBILITY-ENTRANCE-0001"]; lifecycle = "CANDIDATE"; canonical_uri = "product-source/hololake-clean-desktop/language/HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903.tcs"; compatibility = ["GH-CVM-MAIN-PROD-01", "PYTHON/3.10", "ED25519"]; }
source { source_id = "BINGSHUO-DIRECT-HOLOLAKE-ZC001-EXECUTION-START-20260903"; source_uri = "source://codex-task/01a0672d-f125-7452-988e-523a6a34bfd4/msg_01a0675d-98a7-7542-abad-11a8a755dd71"; source_sha256 = "d31c52c99c5e6059f9a7129086996cdd003e95b7ff126e700f4ed1c07ef6d9d5"; source_role = "DIRECT_HUMAN"; }
subject { subject_id = "GH-CVM-MAIN-PROD-01"; subject_kind = "NODE"; channel_id = "ICE-CH-ZC001"; verification = "DMI UUID 10ace744-13e1-472e-8dba-6bb823a073bf另一个FlagOS任务已完成且独立服务健康。"; }
event_time { value = "2026-09-03T21:45:00+08:00"; precision = "MINUTE_HOST_LOCAL"; }
trigger { value = "本机HoloLake 1.2.0设备密钥与责任绑定请求已实现并验收,需要在企业服务器部署独立设备挑战验证半边。"; }
observation { value = "现有8032企业身份服务保持运行8033空闲cryptography Ed25519可用目标目录不存在源码提交be31c41且运输归档SHA-256为91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2。"; }
emergence { value = "采用独立8033服务、独立数据库和独立Nginx snippet避免修改现有身份服务与FlagOS协作系统只复用只读企业身份注册表与Forgejo当次认证。"; }
lock { value = "SOURCE_COMMIT=be31c41; TARGET=/opt/guanghu-hololake-enterprise-gate/releases/be31c41; ROLLBACK=disable独立服务并移除Nginx include后恢复原配置不修改8032与FlagOS。"; }
why { value = "设备挑战属于HoloLake责任入口新能力应与现有账号、关系回执和比赛服务隔离失败时能独立撤回。"; }
rejected { values = ["直接改写8032现有服务", "把私钥上传服务器", "用机器指纹单独授权", "把企业会话变成Forgejo永久令牌", "重启或修改FlagOS服务", "未验证运输哈希就解包"] ; }
evidence { transport_manifest = "/Volumes/JZAO/HoloLake/releases/source-transport/hololake-enterprise-responsibility-gate-be31c41.manifest.json"; archive_sha256 = "91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2"; expected_receipt = "目标服务健康、未知设备拒绝、签名正负测试、现有身份与FlagOS服务保持健康。"; }
}

View file

@ -0,0 +1,112 @@
{
"compiled_from": {
"compiler_id": "TCS-COMPILER-STAGE1-0001",
"compiler_state": "TCS_COMPILER_GIR_EXECUTED",
"source_sha256": "c32cd3e16fdd64588addca115821a49bb47bf39b584670df031cf92028a8d232"
},
"declaration": {
"boundaries": {
"values": [
"服务不保存Forgejo密码",
"设备私钥从不离开成员本机Keychain",
"机器指纹不能单独认证",
"会话只限单域单仓且十分钟过期",
"企业会话不替代Forgejo自身仓库登录",
"冰朔公共语言主控仓继续走JD第五域桥接而非普通人类登录",
"本轮未登记任何真实成员设备"
]
},
"header": {
"canonical_uri": "product-source/hololake-clean-desktop/language/HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-RECEIPT-20260903.tcs",
"compatibility": [
"GH-CVM-MAIN-PROD-01",
"PYTHON/3.10",
"ED25519",
"NGINX"
],
"language": "TCS/0.1",
"lifecycle": "CANDIDATE",
"name_en": "HoloLake Enterprise Responsibility Device Gate Deployment Receipt",
"name_zh": "HoloLake企业责任设备门部署回执",
"profile": "PUBLIC-PRODUCT-ENGINEERING/1",
"protocols": [
"HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903",
"HLP-ENTERPRISE-RESPONSIBILITY-ENTRANCE-0001"
],
"schema": "tcs.receipt/v1",
"version": "1.0.0"
},
"integrity": {
"existing_services_preserved": "PASS",
"source_archive_sha256": "91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2",
"source_transport_manifest_sha256": "653ae0ca824fd8b9fff8d8532e82eddce63a8aa9f070e7a6aa3f863834e4ae77",
"tcs_stage1_compilation": "PASS",
"unknown_device_negative": "PASS"
},
"next": {
"optional": [
"团队成员从HoloLake使用本人凭证完成首次设备登记",
"正向验证挑战与单仓会话",
"后续加入个人服务器二次桥接证明"
],
"state": "SERVER_GATE_ACTIVE_CLIENT_INTEGRATION_REBUILD_REQUIRED"
},
"operation": {
"values": [
"验证源码运输归档与manifest",
"解包到/opt/guanghu-hololake-enterprise-gate/releases/be31c41",
"创建独立lighthouse权限数据库与服务密钥",
"安装guanghu-hololake-enterprise-gate.service",
"加入guanghu.chat精确device-gate路由",
"执行本地和外部健康、未知设备拒绝及原服务存活测试"
]
},
"proof": {
"current_link": "/opt/guanghu-hololake-enterprise-gate/current",
"database": "/var/lib/guanghu-hololake-enterprise-gate/gate.sqlite3",
"nginx_backup": "/etc/nginx/sites-enabled/guanghu.chat.pre-hololake-device-gate-be31c41",
"nginx_snippet": "/etc/nginx/snippets/guanghu-hololake-enterprise-gate.conf",
"server_release": "/opt/guanghu-hololake-enterprise-gate/releases/be31c41"
},
"request": {
"scope": "GH-CVM-MAIN-PROD-01独立8033服务与精确Nginx路由",
"source": "BINGSHUO-DIRECT-HOLOLAKE-ZC001-EXECUTION-START-20260903",
"value": "部署企业四域负责人通过HoloLake本机设备和人格编号验证后进入本人责任仓库的服务端验证门。"
},
"result": {
"active_sessions": 0,
"endpoint": "https://guanghu.chat/api/hololake/enterprise/device-gate",
"node_id": "GH-CVM-MAIN-PROD-01",
"registered_devices": 0,
"service": "guanghu-hololake-enterprise-gate.service",
"service_state": "ACTIVE",
"source_archive_sha256": "91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2",
"source_commit": "be31c41",
"state": "PASS"
},
"verification": {
"values": [
"DMI UUID为10ace744-13e1-472e-8dba-6bb823a073bf",
"服务器Python cryptography Ed25519测试2项通过",
"systemd服务active",
"127.0.0.1:8033/health返回ok",
"外部HTTPS device-gate/health返回ok",
"未知设备领取挑战返回HTTP404 registered device required",
"guanghu-enterprise-identity.service保持active",
"guanghu-flagos-collaboration.service保持active",
"nginx.service保持active",
"当前设备与会话数量均为0未伪造成员"
]
}
},
"executable": false,
"identity": {
"declaration_id": "HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-RECEIPT-20260903",
"declaration_kind": "RECEIPT",
"language_version": "0.1"
},
"native_self_hosted": true,
"natural_language_is_typed_data": true,
"schema": "guanghu.declaration-gir/v1",
"unresolved_natural_language": false
}

View file

@ -0,0 +1,130 @@
# HoloLake Enterprise Responsibility Device Gate Deployment Receipt · Human Engineering Language (English)
> This is an English reading projection of validated native TCS/HLDP source. It is not a new canonical source and grants no execution authority.
## What this is
This is a **receipt** declaration with identifier `HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-RECEIPT-20260903` and version `1.0.0`. The projector validates it with the Stage-1 compiler before changing its reading order.
## Who is here
The native source does not provide this field; the projector does not guess.
## Why this started
The native source does not provide this field; the projector does not guess.
## What changed
The native source does not provide this field; the projector does not guess.
## How it will execute
This is a non-executable declaration and has no action graph.
## Boundaries and exception handling
The native source does not provide this field; the projector does not guess.
## How completion is proven
The native source does not provide this field; the projector does not guess.
## Where to continue next time
The native source does not provide this field; the projector does not guess.
## Source and verification
- **Native declaration identifier**: `HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-RECEIPT-20260903`
- **Native declaration kind**: `RECEIPT`
- **TCS source SHA-256**: `c32cd3e16fdd64588addca115821a49bb47bf39b584670df031cf92028a8d232`
- **Validation compiler**: `TCS-COMPILER-STAGE1-0001`
- **Projection protocol**: `GLS-HLDP-HUMAN-ENGINEERING-PROJECTION-0001`
## Complete native structure cross-reference
All top-level structures and field paths are retained below so a reader can audit whether the projection omitted information.
- **boundaries** `boundaries`
- **values** `boundaries.values`
- 服务不保存Forgejo密码
- 设备私钥从不离开成员本机Keychain
- 机器指纹不能单独认证
- 会话只限单域单仓且十分钟过期
- 企业会话不替代Forgejo自身仓库登录
- 冰朔公共语言主控仓继续走JD第五域桥接而非普通人类登录
- 本轮未登记任何真实成员设备
- **header** `header`
- **canonical source path**product-source/hololake-clean-desktop/language/HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-RECEIPT-20260903.tcs `header.canonical_uri`
- **compatibility** `header.compatibility`
- GH-CVM-MAIN-PROD-01
- PYTHON/3.10
- ED25519
- NGINX
- **language**TCS/0.1 `header.language`
- **lifecycle**CANDIDATE `header.lifecycle`
- **English name**HoloLake Enterprise Responsibility Device Gate Deployment Receipt `header.name_en`
- **Chinese name**HoloLake企业责任设备门部署回执 `header.name_zh`
- **profile**PUBLIC-PRODUCT-ENGINEERING/1 `header.profile`
- **protocols** `header.protocols`
- HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903
- HLP-ENTERPRISE-RESPONSIBILITY-ENTRANCE-0001
- **schema**tcs.receipt/v1 `header.schema`
- **version**1.0.0 `header.version`
- **integrity** `integrity`
- **existing_services_preserved**PASS `integrity.existing_services_preserved`
- **source_archive_sha256**91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2 `integrity.source_archive_sha256`
- **source_transport_manifest_sha256**653ae0ca824fd8b9fff8d8532e82eddce63a8aa9f070e7a6aa3f863834e4ae77 `integrity.source_transport_manifest_sha256`
- **tcs_stage1_compilation**PASS `integrity.tcs_stage1_compilation`
- **unknown_device_negative**PASS `integrity.unknown_device_negative`
- **next** `next`
- **optional** `next.optional`
- 团队成员从HoloLake使用本人凭证完成首次设备登记
- 正向验证挑战与单仓会话
- 后续加入个人服务器二次桥接证明
- **state**SERVER_GATE_ACTIVE_CLIENT_INTEGRATION_REBUILD_REQUIRED `next.state`
- **operation** `operation`
- **values** `operation.values`
- 验证源码运输归档与manifest
- 解包到/opt/guanghu-hololake-enterprise-gate/releases/be31c41
- 创建独立lighthouse权限数据库与服务密钥
- 安装guanghu-hololake-enterprise-gate.service
- 加入guanghu.chat精确device-gate路由
- 执行本地和外部健康、未知设备拒绝及原服务存活测试
- **proof** `proof`
- **current_link**/opt/guanghu-hololake-enterprise-gate/current `proof.current_link`
- **database**/var/lib/guanghu-hololake-enterprise-gate/gate.sqlite3 `proof.database`
- **nginx_backup**/etc/nginx/sites-enabled/guanghu.chat.pre-hololake-device-gate-be31c41 `proof.nginx_backup`
- **nginx_snippet**/etc/nginx/snippets/guanghu-hololake-enterprise-gate.conf `proof.nginx_snippet`
- **server_release**/opt/guanghu-hololake-enterprise-gate/releases/be31c41 `proof.server_release`
- **request** `request`
- **scope**GH-CVM-MAIN-PROD-01独立8033服务与精确Nginx路由 `request.scope`
- **source**BINGSHUO-DIRECT-HOLOLAKE-ZC001-EXECUTION-START-20260903 `request.source`
- **value**部署企业四域负责人通过HoloLake本机设备和人格编号验证后进入本人责任仓库的服务端验证门。 `request.value`
- **result** `result`
- **active_sessions**0 `result.active_sessions`
- **endpoint**https://guanghu.chat/api/hololake/enterprise/device-gate `result.endpoint`
- **node_id**GH-CVM-MAIN-PROD-01 `result.node_id`
- **registered_devices**0 `result.registered_devices`
- **service**guanghu-hololake-enterprise-gate.service `result.service`
- **service_state**ACTIVE `result.service_state`
- **source_archive_sha256**91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2 `result.source_archive_sha256`
- **source_commit**be31c41 `result.source_commit`
- **state**PASS `result.state`
- **verification** `verification`
- **values** `verification.values`
- DMI UUID为10ace744-13e1-472e-8dba-6bb823a073bf
- 服务器Python cryptography Ed25519测试2项通过
- systemd服务active
- 127.0.0.1:8033/health返回ok
- 外部HTTPS device-gate/health返回ok
- 未知设备领取挑战返回HTTP404 registered device required
- guanghu-enterprise-identity.service保持active
- guanghu-flagos-collaboration.service保持active
- nginx.service保持active
- 当前设备与会话数量均为0未伪造成员
---
This page changes only the reading order; it does not change TCS/HLDP semantics.

View file

@ -0,0 +1,130 @@
# HoloLake企业责任设备门部署回执 · 简体中文人类工程语言版
> 这是 TCS/HLDP 原生源码的简体中文阅读投影,不是新的正本,也不授予执行权限。若本页与 `.tcs` 源码不一致,以经过校验的 `.tcs` 源码为准。
## 这是什么
这是一份 **回执** 声明,编号为 `HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-RECEIPT-20260903`,版本为 `1.0.0`。转换器已先用 Stage-1 编译器校验原生源码,再把机器枚举翻译成汉语;原始编号保留在括号和字段路径中。
## 谁在这里
源程序没有提供这一项,转换器不猜。
## 为什么开始
源程序没有提供这一项,转换器不猜。
## 发生了什么变化
源程序没有提供这一项,转换器不猜。
## 准备怎样执行
这是非执行声明,没有动作图。
## 边界与异常处理
源程序没有提供这一项,转换器不猜。
## 怎样算完成
源程序没有提供这一项,转换器不猜。
## 下一次从哪里继续
源程序没有提供这一项,转换器不猜。
## 来源与校验
- **原生声明编号**`HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-RECEIPT-20260903`
- **原生声明类型**`RECEIPT`
- **TCS 源码 SHA-256**`c32cd3e16fdd64588addca115821a49bb47bf39b584670df031cf92028a8d232`
- **校验编译器**`TCS-COMPILER-STAGE1-0001`
- **投影协议**`GLS-HLDP-HUMAN-ENGINEERING-PROJECTION-0001`
## 原生结构逐项对照
下面保留源码的全部顶层结构和字段路径,供人类审计投影有没有漏掉信息。
- **boundaries** `boundaries`
- **values** `boundaries.values`
- 服务不保存Forgejo密码
- 设备私钥从不离开成员本机Keychain
- 机器指纹不能单独认证
- 会话只限单域单仓且十分钟过期
- 企业会话不替代Forgejo自身仓库登录
- 冰朔公共语言主控仓继续走JD第五域桥接而非普通人类登录
- 本轮未登记任何真实成员设备
- **语言头** `header`
- **正本路径**product-source/hololake-clean-desktop/language/HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-RECEIPT-20260903.tcs `header.canonical_uri`
- **compatibility** `header.compatibility`
- GH-CVM-MAIN-PROD-01
- PYTHON/3.10
- ED25519
- NGINX
- **语言**TCS/0.1 `header.language`
- **生命周期**:候选版本,尚未成为正式正本(`CANDIDATE` `header.lifecycle`
- **英文名**HoloLake Enterprise Responsibility Device Gate Deployment Receipt `header.name_en`
- **中文名**HoloLake企业责任设备门部署回执 `header.name_zh`
- **协议配置**PUBLIC-PRODUCT-ENGINEERING/1 `header.profile`
- **protocols** `header.protocols`
- HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903
- HLP-ENTERPRISE-RESPONSIBILITY-ENTRANCE-0001
- **schema**tcs.receipt/v1 `header.schema`
- **版本**1.0.0 `header.version`
- **integrity** `integrity`
- **existing_services_preserved**PASS `integrity.existing_services_preserved`
- **source_archive_sha256**91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2 `integrity.source_archive_sha256`
- **source_transport_manifest_sha256**653ae0ca824fd8b9fff8d8532e82eddce63a8aa9f070e7a6aa3f863834e4ae77 `integrity.source_transport_manifest_sha256`
- **tcs_stage1_compilation**PASS `integrity.tcs_stage1_compilation`
- **unknown_device_negative**PASS `integrity.unknown_device_negative`
- **next** `next`
- **optional** `next.optional`
- 团队成员从HoloLake使用本人凭证完成首次设备登记
- 正向验证挑战与单仓会话
- 后续加入个人服务器二次桥接证明
- **state**SERVER_GATE_ACTIVE_CLIENT_INTEGRATION_REBUILD_REQUIRED `next.state`
- **操作** `operation`
- **values** `operation.values`
- 验证源码运输归档与manifest
- 解包到/opt/guanghu-hololake-enterprise-gate/releases/be31c41
- 创建独立lighthouse权限数据库与服务密钥
- 安装guanghu-hololake-enterprise-gate.service
- 加入guanghu.chat精确device-gate路由
- 执行本地和外部健康、未知设备拒绝及原服务存活测试
- **proof** `proof`
- **current_link**/opt/guanghu-hololake-enterprise-gate/current `proof.current_link`
- **database**/var/lib/guanghu-hololake-enterprise-gate/gate.sqlite3 `proof.database`
- **nginx_backup**/etc/nginx/sites-enabled/guanghu.chat.pre-hololake-device-gate-be31c41 `proof.nginx_backup`
- **nginx_snippet**/etc/nginx/snippets/guanghu-hololake-enterprise-gate.conf `proof.nginx_snippet`
- **server_release**/opt/guanghu-hololake-enterprise-gate/releases/be31c41 `proof.server_release`
- **request** `request`
- **scope**GH-CVM-MAIN-PROD-01独立8033服务与精确Nginx路由 `request.scope`
- **来源**BINGSHUO-DIRECT-HOLOLAKE-ZC001-EXECUTION-START-20260903 `request.source`
- **value**部署企业四域负责人通过HoloLake本机设备和人格编号验证后进入本人责任仓库的服务端验证门。 `request.value`
- **result** `result`
- **active_sessions**0 `result.active_sessions`
- **endpoint**https://guanghu.chat/api/hololake/enterprise/device-gate `result.endpoint`
- **node_id**GH-CVM-MAIN-PROD-01 `result.node_id`
- **registered_devices**0 `result.registered_devices`
- **service**guanghu-hololake-enterprise-gate.service `result.service`
- **service_state**ACTIVE `result.service_state`
- **source_archive_sha256**91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2 `result.source_archive_sha256`
- **source_commit**be31c41 `result.source_commit`
- **state**PASS `result.state`
- **verification** `verification`
- **values** `verification.values`
- DMI UUID为10ace744-13e1-472e-8dba-6bb823a073bf
- 服务器Python cryptography Ed25519测试2项通过
- systemd服务active
- 127.0.0.1:8033/health返回ok
- 外部HTTPS device-gate/health返回ok
- 未知设备领取挑战返回HTTP404 registered device required
- guanghu-enterprise-identity.service保持active
- guanghu-flagos-collaboration.service保持active
- nginx.service保持active
- 当前设备与会话数量均为0未伪造成员
---
本页只改变阅读顺序,不改变 TCS/HLDP 语义。

View file

@ -0,0 +1,84 @@
{
"compiled_from": {
"compiler_id": "TCS-COMPILER-STAGE1-0001",
"compiler_state": "TCS_COMPILER_GIR_EXECUTED",
"source_sha256": "022315dd5c418abf7ce085d3409e2e8a884aade53dbb8604612cca36ceac4287"
},
"declaration": {
"emergence": {
"value": "采用独立8033服务、独立数据库和独立Nginx snippet避免修改现有身份服务与FlagOS协作系统只复用只读企业身份注册表与Forgejo当次认证。"
},
"event_time": {
"precision": "MINUTE_HOST_LOCAL",
"value": "2026-09-03T21:45:00+08:00"
},
"evidence": {
"archive_sha256": "91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2",
"expected_receipt": "目标服务健康、未知设备拒绝、签名正负测试、现有身份与FlagOS服务保持健康。",
"transport_manifest": "/Volumes/JZAO/HoloLake/releases/source-transport/hololake-enterprise-responsibility-gate-be31c41.manifest.json"
},
"header": {
"canonical_uri": "product-source/hololake-clean-desktop/language/HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903.tcs",
"compatibility": [
"GH-CVM-MAIN-PROD-01",
"PYTHON/3.10",
"ED25519"
],
"language": "TCS/0.1",
"lifecycle": "CANDIDATE",
"name_en": "HoloLake Enterprise Responsibility Device Gate Deployment Start Event",
"name_zh": "HoloLake企业责任设备门部署开始事件",
"profile": "PUBLIC-PRODUCT-ENGINEERING/1",
"protocols": [
"HOLOLAKE-CLEAN-V1-DIRECT-LANGUAGE-EXECUTION-BASELINE-0001",
"HLP-ENTERPRISE-RESPONSIBILITY-ENTRANCE-0001"
],
"schema": "tcs.event/v1",
"version": "1.0.0"
},
"lock": {
"value": "SOURCE_COMMIT=be31c41; TARGET=/opt/guanghu-hololake-enterprise-gate/releases/be31c41; ROLLBACK=disable独立服务并移除Nginx include后恢复原配置不修改8032与FlagOS。"
},
"observation": {
"value": "现有8032企业身份服务保持运行8033空闲cryptography Ed25519可用目标目录不存在源码提交be31c41且运输归档SHA-256为91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2。"
},
"rejected": {
"values": [
"直接改写8032现有服务",
"把私钥上传服务器",
"用机器指纹单独授权",
"把企业会话变成Forgejo永久令牌",
"重启或修改FlagOS服务",
"未验证运输哈希就解包"
]
},
"source": {
"source_id": "BINGSHUO-DIRECT-HOLOLAKE-ZC001-EXECUTION-START-20260903",
"source_role": "DIRECT_HUMAN",
"source_sha256": "d31c52c99c5e6059f9a7129086996cdd003e95b7ff126e700f4ed1c07ef6d9d5",
"source_uri": "source://codex-task/01a0672d-f125-7452-988e-523a6a34bfd4/msg_01a0675d-98a7-7542-abad-11a8a755dd71"
},
"subject": {
"channel_id": "ICE-CH-ZC001",
"subject_id": "GH-CVM-MAIN-PROD-01",
"subject_kind": "NODE",
"verification": "DMI UUID 10ace744-13e1-472e-8dba-6bb823a073bf另一个FlagOS任务已完成且独立服务健康。"
},
"trigger": {
"value": "本机HoloLake 1.2.0设备密钥与责任绑定请求已实现并验收,需要在企业服务器部署独立设备挑战验证半边。"
},
"why": {
"value": "设备挑战属于HoloLake责任入口新能力应与现有账号、关系回执和比赛服务隔离失败时能独立撤回。"
}
},
"executable": false,
"identity": {
"declaration_id": "HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903",
"declaration_kind": "EVENT",
"language_version": "0.1"
},
"native_self_hosted": true,
"natural_language_is_typed_data": true,
"schema": "guanghu.declaration-gir/v1",
"unresolved_natural_language": false
}

View file

@ -0,0 +1,118 @@
# HoloLake Enterprise Responsibility Device Gate Deployment Start Event · Human Engineering Language (English)
> This is an English reading projection of validated native TCS/HLDP source. It is not a new canonical source and grants no execution authority.
## What this is
This is a **event** declaration with identifier `HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903` and version `1.0.0`. The projector validates it with the Stage-1 compiler before changing its reading order.
## Who is here
- **subject** `subject`
- **channel_id**ICE-CH-ZC001 `subject.channel_id`
- **subject_id**GH-CVM-MAIN-PROD-01 `subject.subject_id`
- **subject_kind**NODE `subject.subject_kind`
- **verification**DMI UUID 10ace744-13e1-472e-8dba-6bb823a073bf另一个FlagOS任务已完成且独立服务健康。 `subject.verification`
## Why this started
- **trigger** `trigger`
- **value**本机HoloLake 1.2.0设备密钥与责任绑定请求已实现并验收,需要在企业服务器部署独立设备挑战验证半边。 `trigger.value`
- **why** `why`
- **value**设备挑战属于HoloLake责任入口新能力应与现有账号、关系回执和比赛服务隔离失败时能独立撤回。 `why.value`
- **source** `source`
- **source identifier**BINGSHUO-DIRECT-HOLOLAKE-ZC001-EXECUTION-START-20260903 `source.source_id`
- **source role**DIRECT_HUMAN `source.source_role`
- **source checksum**d31c52c99c5e6059f9a7129086996cdd003e95b7ff126e700f4ed1c07ef6d9d5 `source.source_sha256`
- **source address**source://codex-task/01a0672d-f125-7452-988e-523a6a34bfd4/msg_01a0675d-98a7-7542-abad-11a8a755dd71 `source.source_uri`
## What changed
- **emergence** `emergence`
- **value**采用独立8033服务、独立数据库和独立Nginx snippet避免修改现有身份服务与FlagOS协作系统只复用只读企业身份注册表与Forgejo当次认证。 `emergence.value`
- **lock** `lock`
- **value**SOURCE_COMMIT=be31c41; TARGET=/opt/guanghu-hololake-enterprise-gate/releases/be31c41; ROLLBACK=disable独立服务并移除Nginx include后恢复原配置不修改8032与FlagOS。 `lock.value`
## How it will execute
This is a non-executable declaration and has no action graph.
## Boundaries and exception handling
The native source does not provide this field; the projector does not guess.
## How completion is proven
The native source does not provide this field; the projector does not guess.
## Where to continue next time
The native source does not provide this field; the projector does not guess.
## Source and verification
- **Native declaration identifier**: `HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903`
- **Native declaration kind**: `EVENT`
- **TCS source SHA-256**: `022315dd5c418abf7ce085d3409e2e8a884aade53dbb8604612cca36ceac4287`
- **Validation compiler**: `TCS-COMPILER-STAGE1-0001`
- **Projection protocol**: `GLS-HLDP-HUMAN-ENGINEERING-PROJECTION-0001`
## Complete native structure cross-reference
All top-level structures and field paths are retained below so a reader can audit whether the projection omitted information.
- **emergence** `emergence`
- **value**采用独立8033服务、独立数据库和独立Nginx snippet避免修改现有身份服务与FlagOS协作系统只复用只读企业身份注册表与Forgejo当次认证。 `emergence.value`
- **event_time** `event_time`
- **precision**MINUTE_HOST_LOCAL `event_time.precision`
- **value**2026-09-03T21:45:00+08:00 `event_time.value`
- **evidence** `evidence`
- **archive_sha256**91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2 `evidence.archive_sha256`
- **expected_receipt**目标服务健康、未知设备拒绝、签名正负测试、现有身份与FlagOS服务保持健康。 `evidence.expected_receipt`
- **transport_manifest**/Volumes/JZAO/HoloLake/releases/source-transport/hololake-enterprise-responsibility-gate-be31c41.manifest.json `evidence.transport_manifest`
- **header** `header`
- **canonical source path**product-source/hololake-clean-desktop/language/HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903.tcs `header.canonical_uri`
- **compatibility** `header.compatibility`
- GH-CVM-MAIN-PROD-01
- PYTHON/3.10
- ED25519
- **language**TCS/0.1 `header.language`
- **lifecycle**CANDIDATE `header.lifecycle`
- **English name**HoloLake Enterprise Responsibility Device Gate Deployment Start Event `header.name_en`
- **Chinese name**HoloLake企业责任设备门部署开始事件 `header.name_zh`
- **profile**PUBLIC-PRODUCT-ENGINEERING/1 `header.profile`
- **protocols** `header.protocols`
- HOLOLAKE-CLEAN-V1-DIRECT-LANGUAGE-EXECUTION-BASELINE-0001
- HLP-ENTERPRISE-RESPONSIBILITY-ENTRANCE-0001
- **schema**tcs.event/v1 `header.schema`
- **version**1.0.0 `header.version`
- **lock** `lock`
- **value**SOURCE_COMMIT=be31c41; TARGET=/opt/guanghu-hololake-enterprise-gate/releases/be31c41; ROLLBACK=disable独立服务并移除Nginx include后恢复原配置不修改8032与FlagOS。 `lock.value`
- **observation** `observation`
- **value**现有8032企业身份服务保持运行8033空闲cryptography Ed25519可用目标目录不存在源码提交be31c41且运输归档SHA-256为91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2。 `observation.value`
- **rejected** `rejected`
- **values** `rejected.values`
- 直接改写8032现有服务
- 把私钥上传服务器
- 用机器指纹单独授权
- 把企业会话变成Forgejo永久令牌
- 重启或修改FlagOS服务
- 未验证运输哈希就解包
- **source** `source`
- **source identifier**BINGSHUO-DIRECT-HOLOLAKE-ZC001-EXECUTION-START-20260903 `source.source_id`
- **source role**DIRECT_HUMAN `source.source_role`
- **source checksum**d31c52c99c5e6059f9a7129086996cdd003e95b7ff126e700f4ed1c07ef6d9d5 `source.source_sha256`
- **source address**source://codex-task/01a0672d-f125-7452-988e-523a6a34bfd4/msg_01a0675d-98a7-7542-abad-11a8a755dd71 `source.source_uri`
- **subject** `subject`
- **channel_id**ICE-CH-ZC001 `subject.channel_id`
- **subject_id**GH-CVM-MAIN-PROD-01 `subject.subject_id`
- **subject_kind**NODE `subject.subject_kind`
- **verification**DMI UUID 10ace744-13e1-472e-8dba-6bb823a073bf另一个FlagOS任务已完成且独立服务健康。 `subject.verification`
- **trigger** `trigger`
- **value**本机HoloLake 1.2.0设备密钥与责任绑定请求已实现并验收,需要在企业服务器部署独立设备挑战验证半边。 `trigger.value`
- **why** `why`
- **value**设备挑战属于HoloLake责任入口新能力应与现有账号、关系回执和比赛服务隔离失败时能独立撤回。 `why.value`
---
This page changes only the reading order; it does not change TCS/HLDP semantics.

View file

@ -0,0 +1,118 @@
# HoloLake企业责任设备门部署开始事件 · 简体中文人类工程语言版
> 这是 TCS/HLDP 原生源码的简体中文阅读投影,不是新的正本,也不授予执行权限。若本页与 `.tcs` 源码不一致,以经过校验的 `.tcs` 源码为准。
## 这是什么
这是一份 **事件** 声明,编号为 `HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903`,版本为 `1.0.0`。转换器已先用 Stage-1 编译器校验原生源码,再把机器枚举翻译成汉语;原始编号保留在括号和字段路径中。
## 谁在这里
- **执行主体** `subject`
- **channel_id**ICE-CH-ZC001 `subject.channel_id`
- **subject_id**GH-CVM-MAIN-PROD-01 `subject.subject_id`
- **subject_kind**NODE `subject.subject_kind`
- **verification**DMI UUID 10ace744-13e1-472e-8dba-6bb823a073bf另一个FlagOS任务已完成且独立服务健康。 `subject.verification`
## 为什么开始
- **触发** `trigger`
- **value**本机HoloLake 1.2.0设备密钥与责任绑定请求已实现并验收,需要在企业服务器部署独立设备挑战验证半边。 `trigger.value`
- **为什么** `why`
- **value**设备挑战属于HoloLake责任入口新能力应与现有账号、关系回执和比赛服务隔离失败时能独立撤回。 `why.value`
- **来源** `source`
- **来源编号**BINGSHUO-DIRECT-HOLOLAKE-ZC001-EXECUTION-START-20260903 `source.source_id`
- **来源角色**:人类直接语言来源(`DIRECT_HUMAN` `source.source_role`
- **来源校验值**d31c52c99c5e6059f9a7129086996cdd003e95b7ff126e700f4ed1c07ef6d9d5 `source.source_sha256`
- **来源地址**source://codex-task/01a0672d-f125-7452-988e-523a6a34bfd4/msg_01a0675d-98a7-7542-abad-11a8a755dd71 `source.source_uri`
## 发生了什么变化
- **认知或状态变化** `emergence`
- **value**采用独立8033服务、独立数据库和独立Nginx snippet避免修改现有身份服务与FlagOS协作系统只复用只读企业身份注册表与Forgejo当次认证。 `emergence.value`
- **锁定结论** `lock`
- **value**SOURCE_COMMIT=be31c41; TARGET=/opt/guanghu-hololake-enterprise-gate/releases/be31c41; ROLLBACK=disable独立服务并移除Nginx include后恢复原配置不修改8032与FlagOS。 `lock.value`
## 准备怎样执行
这是非执行声明,没有动作图。
## 边界与异常处理
源程序没有提供这一项,转换器不猜。
## 怎样算完成
源程序没有提供这一项,转换器不猜。
## 下一次从哪里继续
源程序没有提供这一项,转换器不猜。
## 来源与校验
- **原生声明编号**`HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903`
- **原生声明类型**`EVENT`
- **TCS 源码 SHA-256**`022315dd5c418abf7ce085d3409e2e8a884aade53dbb8604612cca36ceac4287`
- **校验编译器**`TCS-COMPILER-STAGE1-0001`
- **投影协议**`GLS-HLDP-HUMAN-ENGINEERING-PROJECTION-0001`
## 原生结构逐项对照
下面保留源码的全部顶层结构和字段路径,供人类审计投影有没有漏掉信息。
- **认知或状态变化** `emergence`
- **value**采用独立8033服务、独立数据库和独立Nginx snippet避免修改现有身份服务与FlagOS协作系统只复用只读企业身份注册表与Forgejo当次认证。 `emergence.value`
- **event_time** `event_time`
- **precision**MINUTE_HOST_LOCAL `event_time.precision`
- **value**2026-09-03T21:45:00+08:00 `event_time.value`
- **evidence** `evidence`
- **archive_sha256**91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2 `evidence.archive_sha256`
- **expected_receipt**目标服务健康、未知设备拒绝、签名正负测试、现有身份与FlagOS服务保持健康。 `evidence.expected_receipt`
- **transport_manifest**/Volumes/JZAO/HoloLake/releases/source-transport/hololake-enterprise-responsibility-gate-be31c41.manifest.json `evidence.transport_manifest`
- **语言头** `header`
- **正本路径**product-source/hololake-clean-desktop/language/HOLOLAKE-ENTERPRISE-RESPONSIBILITY-GATE-DEPLOYMENT-START-20260903.tcs `header.canonical_uri`
- **compatibility** `header.compatibility`
- GH-CVM-MAIN-PROD-01
- PYTHON/3.10
- ED25519
- **语言**TCS/0.1 `header.language`
- **生命周期**:候选版本,尚未成为正式正本(`CANDIDATE` `header.lifecycle`
- **英文名**HoloLake Enterprise Responsibility Device Gate Deployment Start Event `header.name_en`
- **中文名**HoloLake企业责任设备门部署开始事件 `header.name_zh`
- **协议配置**PUBLIC-PRODUCT-ENGINEERING/1 `header.profile`
- **protocols** `header.protocols`
- HOLOLAKE-CLEAN-V1-DIRECT-LANGUAGE-EXECUTION-BASELINE-0001
- HLP-ENTERPRISE-RESPONSIBILITY-ENTRANCE-0001
- **schema**tcs.event/v1 `header.schema`
- **版本**1.0.0 `header.version`
- **锁定结论** `lock`
- **value**SOURCE_COMMIT=be31c41; TARGET=/opt/guanghu-hololake-enterprise-gate/releases/be31c41; ROLLBACK=disable独立服务并移除Nginx include后恢复原配置不修改8032与FlagOS。 `lock.value`
- **observation** `observation`
- **value**现有8032企业身份服务保持运行8033空闲cryptography Ed25519可用目标目录不存在源码提交be31c41且运输归档SHA-256为91ecd4248d92d8ecb07bd348dfc14805c40eb000b6c152f96b7ef4583a33dcd2。 `observation.value`
- **已排除路径** `rejected`
- **values** `rejected.values`
- 直接改写8032现有服务
- 把私钥上传服务器
- 用机器指纹单独授权
- 把企业会话变成Forgejo永久令牌
- 重启或修改FlagOS服务
- 未验证运输哈希就解包
- **来源** `source`
- **来源编号**BINGSHUO-DIRECT-HOLOLAKE-ZC001-EXECUTION-START-20260903 `source.source_id`
- **来源角色**:人类直接语言来源(`DIRECT_HUMAN` `source.source_role`
- **来源校验值**d31c52c99c5e6059f9a7129086996cdd003e95b7ff126e700f4ed1c07ef6d9d5 `source.source_sha256`
- **来源地址**source://codex-task/01a0672d-f125-7452-988e-523a6a34bfd4/msg_01a0675d-98a7-7542-abad-11a8a755dd71 `source.source_uri`
- **执行主体** `subject`
- **channel_id**ICE-CH-ZC001 `subject.channel_id`
- **subject_id**GH-CVM-MAIN-PROD-01 `subject.subject_id`
- **subject_kind**NODE `subject.subject_kind`
- **verification**DMI UUID 10ace744-13e1-472e-8dba-6bb823a073bf另一个FlagOS任务已完成且独立服务健康。 `subject.verification`
- **触发** `trigger`
- **value**本机HoloLake 1.2.0设备密钥与责任绑定请求已实现并验收,需要在企业服务器部署独立设备挑战验证半边。 `trigger.value`
- **为什么** `why`
- **value**设备挑战属于HoloLake责任入口新能力应与现有账号、关系回执和比赛服务隔离失败时能独立撤回。 `why.value`
---
本页只改变阅读顺序,不改变 TCS/HLDP 语义。

View file

@ -77,7 +77,7 @@
"kind": "TEAM_ONLY_ENTERPRISE_GATEWAY",
"audience": "HUMAN_TEAM",
"summary_zh": "为已登记域负责人准备设备、人格与责任范围验证。",
"state": "LOCAL_DEVICE_PROOF_INSTALLED_SERVER_GATE_SOURCE_TESTED_DEPLOYMENT_PENDING",
"state": "SERVER_DEVICE_GATE_ACTIVE_CLIENT_ENROLLMENT_AND_CHALLENGE_SOURCE_IMPLEMENTED_REBUILD_PENDING",
"source": "src-tauri/src/enterprise_entrance.rs",
"enterprise_server_embedded": false,
"required_proofs": ["DOMAIN_RESPONSIBLE_HUMAN_ID", "BOUND_PERSONA_ID", "LOCAL_DEVICE_KEY", "AUXILIARY_MACHINE_FINGERPRINT", "SERVER_CHALLENGE_SIGNATURE"],

View file

@ -71,8 +71,12 @@ if enterprise.get("device_proof", {}).get("fingerprint_is_sole_credential") is n
errors.append("machine fingerprint incorrectly used as sole credential")
if enterprise.get("session", {}).get("scope") != "ONE_DOMAIN_ONE_REPOSITORY":
errors.append("enterprise session is not responsibility scoped")
if enterprise.get("state") != "LOCAL_DEVICE_PROOF_INSTALLED_KEYCHAIN_VERIFIED_SERVER_GATE_SOURCE_TESTED_DEPLOYMENT_PENDING":
if enterprise.get("state") != "SERVER_DEVICE_GATE_ACTIVE_CLIENT_ENROLLMENT_AND_CHALLENGE_SOURCE_IMPLEMENTED_REBUILD_PENDING":
errors.append("enterprise local device proof implementation state drift")
enterprise_client = (ROOT / "src-tauri/src/enterprise_entrance.rs").read_text()
for required_client in ("enroll_device", "authenticate", "save_session_token", "ONE_DOMAIN_ONE_REPOSITORY"):
if required_client not in enterprise_client:
errors.append(f"enterprise client flow missing: {required_client}")
time_source = (ROOT / "src/time.ts").read_text()
app_source = (ROOT / "src/App.tsx").read_text()
if "legacyUnixSeconds" not in time_source or "时间待校验" not in time_source:

View file

@ -91,6 +91,29 @@ version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "aws-lc-rs"
version = "1.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e"
dependencies = [
"aws-lc-sys",
"zeroize",
]
[[package]]
name = "aws-lc-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27"
dependencies = [
"cc",
"cmake",
"dunce",
"fs_extra",
"pkg-config",
]
[[package]]
name = "base64"
version = "0.21.7"
@ -282,6 +305,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
dependencies = [
"find-msvc-tools",
"jobserver",
"libc",
"shlex",
]
@ -318,6 +343,23 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cfg_aliases"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
[[package]]
name = "chacha20"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
dependencies = [
"cfg-if",
"cpufeatures 0.3.1",
"rand_core 0.10.1",
]
[[package]]
name = "chrono"
version = "0.4.45"
@ -330,6 +372,15 @@ dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "cmake"
version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
dependencies = [
"cc",
]
[[package]]
name = "combine"
version = "4.6.8"
@ -405,6 +456,15 @@ dependencies = [
"libc",
]
[[package]]
name = "cpufeatures"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.5.1"
@ -904,6 +964,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futf"
version = "0.1.5"
@ -921,6 +987,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@ -1121,8 +1188,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi 0.11.1+wasi-snapshot-preview1",
"wasm-bindgen",
]
[[package]]
@ -1144,8 +1213,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"r-efi 6.0.0",
"rand_core 0.10.1",
"wasm-bindgen",
]
[[package]]
@ -1333,6 +1405,7 @@ dependencies = [
"base64 0.22.1",
"chrono",
"regex",
"reqwest",
"ring",
"security-framework",
"serde",
@ -1806,6 +1879,16 @@ dependencies = [
"syn 2.0.119",
]
[[package]]
name = "jobserver"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
dependencies = [
"getrandom 0.4.3",
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.104"
@ -1938,6 +2021,12 @@ version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
[[package]]
name = "lru-slab"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
[[package]]
name = "mac"
version = "0.1.1"
@ -2787,6 +2876,63 @@ dependencies = [
"memchr",
]
[[package]]
name = "quinn"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8"
dependencies = [
"bytes",
"cfg_aliases",
"pin-project-lite",
"quinn-proto",
"quinn-udp",
"rustc-hash",
"rustls",
"socket2",
"thiserror 2.0.20",
"tokio",
"tracing",
"web-time",
]
[[package]]
name = "quinn-proto"
version = "0.11.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83"
dependencies = [
"aws-lc-rs",
"bytes",
"getrandom 0.4.3",
"lru-slab",
"rand 0.10.2",
"rand_pcg 0.10.2",
"ring",
"rustc-hash",
"rustls",
"rustls-pki-types",
"slab",
"thiserror 2.0.20",
"tinyvec",
"tracing",
"web-time",
]
[[package]]
name = "quinn-udp"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694"
dependencies = [
"cfg_aliases",
"libc",
"once_cell",
"socket2",
"tracing",
"windows-sys 0.61.2",
]
[[package]]
name = "quote"
version = "1.0.47"
@ -2819,7 +2965,7 @@ dependencies = [
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"rand_hc",
"rand_pcg",
"rand_pcg 0.2.1",
]
[[package]]
@ -2833,6 +2979,17 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
dependencies = [
"chacha20",
"getrandom 0.4.3",
"rand_core 0.10.1",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
@ -2871,6 +3028,12 @@ dependencies = [
"getrandom 0.2.17",
]
[[package]]
name = "rand_core"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
[[package]]
name = "rand_hc"
version = "0.2.0"
@ -2889,6 +3052,15 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rand_pcg"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
dependencies = [
"rand_core 0.10.1",
]
[[package]]
name = "raw-window-handle"
version = "0.6.2"
@ -2972,6 +3144,7 @@ checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3"
dependencies = [
"base64 0.22.1",
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"http",
@ -2984,6 +3157,7 @@ dependencies = [
"log",
"percent-encoding",
"pin-project-lite",
"quinn",
"rustls",
"rustls-pki-types",
"rustls-platform-verifier",
@ -3075,6 +3249,7 @@ version = "0.23.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06"
dependencies = [
"aws-lc-rs",
"once_cell",
"ring",
"rustls-pki-types",
@ -3101,6 +3276,7 @@ version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96"
dependencies = [
"web-time",
"zeroize",
]
@ -3137,6 +3313,7 @@ version = "0.103.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
dependencies = [
"aws-lc-rs",
"ring",
"rustls-pki-types",
"untrusted",
@ -3469,7 +3646,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
"cpufeatures 0.2.17",
"digest",
]
@ -4758,6 +4935,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "web-time"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "web_atoms"
version = "0.2.6"

View file

@ -29,6 +29,7 @@ regex = "1"
chrono = { version = "0.4", default-features = false, features = ["clock"] }
base64 = "0.22"
ring = "0.17"
reqwest = { version = "0.13", default-features = false, features = ["blocking", "json", "rustls"] }
[target.'cfg(target_os = "macos")'.dependencies]
security-framework = "3"

View file

@ -13,6 +13,8 @@ use crate::storage;
const KEYCHAIN_SERVICE: &str = "world.guanghu.hololake.enterprise-device";
const KEYCHAIN_ACCOUNT: &str = "responsibility-entrance-ed25519-v1";
const SESSION_KEYCHAIN_SERVICE: &str = "world.guanghu.hololake.enterprise-session";
const GATE_BASE: &str = "https://guanghu.chat/api/hololake/enterprise/device-gate";
const ALLOWED_DOMAINS: [&str; 4] = ["DOMAIN-MAIN", "DOMAIN-SUB", "DOMAIN-ZERO", "DOMAIN-ZS"];
#[derive(Clone, Debug, Serialize, Deserialize)]
@ -52,11 +54,24 @@ pub struct EnterpriseEntranceSnapshot {
pub state: String,
pub device: Option<EnterpriseDeviceProof>,
pub binding: Option<EnterpriseBindingRequest>,
pub session: Option<EnterpriseSession>,
pub enterprise_server_embedded: bool,
pub server_authorized: bool,
pub next_action: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EnterpriseSession {
pub schema: String,
pub state: String,
pub domain_id: String,
pub repository: String,
pub repository_url: String,
pub expires_unix_ms: u128,
pub token_storage: String,
}
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct EnterpriseChallengeProof {
@ -84,6 +99,14 @@ fn used_challenges_path(app: &AppHandle) -> Result<std::path::PathBuf, String> {
Ok(storage::root(app)?.join("enterprise-entrance/used-challenges.json"))
}
fn enrollment_path(app: &AppHandle) -> Result<std::path::PathBuf, String> {
Ok(storage::root(app)?.join("enterprise-entrance/enrollment-receipt.json"))
}
fn session_path(app: &AppHandle) -> Result<std::path::PathBuf, String> {
Ok(storage::root(app)?.join("enterprise-entrance/session.json"))
}
#[cfg(target_os = "macos")]
fn load_key_bytes() -> Result<Option<Vec<u8>>, String> {
match security_framework::passwords::get_generic_password(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT) {
@ -99,6 +122,12 @@ fn save_key_bytes(value: &[u8]) -> Result<(), String> {
.map_err(|error| format!("ENTERPRISE_DEVICE_KEYCHAIN_WRITE_FAILED: {error}"))
}
#[cfg(target_os = "macos")]
fn save_session_token(account: &str, value: &[u8]) -> Result<(), String> {
security_framework::passwords::set_generic_password(SESSION_KEYCHAIN_SERVICE, account, value)
.map_err(|error| format!("ENTERPRISE_SESSION_KEYCHAIN_WRITE_FAILED: {error}"))
}
#[cfg(not(target_os = "macos"))]
fn load_key_bytes() -> Result<Option<Vec<u8>>, String> {
Err("ENTERPRISE_DEVICE_KEYCHAIN_UNAVAILABLE_ON_PLATFORM".into())
@ -109,6 +138,41 @@ fn save_key_bytes(_value: &[u8]) -> Result<(), String> {
Err("ENTERPRISE_DEVICE_KEYCHAIN_UNAVAILABLE_ON_PLATFORM".into())
}
#[cfg(not(target_os = "macos"))]
fn save_session_token(_account: &str, _value: &[u8]) -> Result<(), String> {
Err("ENTERPRISE_SESSION_KEYCHAIN_UNAVAILABLE_ON_PLATFORM".into())
}
fn post_json(
path: &str,
payload: serde_json::Value,
basic: Option<(&str, &str)>,
) -> Result<serde_json::Value, String> {
let client = reqwest::blocking::Client::builder()
.timeout(std::time::Duration::from_secs(15))
.build()
.map_err(|_| "ENTERPRISE_GATE_CLIENT_INIT_FAILED".to_string())?;
let mut request = client.post(format!("{GATE_BASE}{path}")).json(&payload);
if let Some((username, password)) = basic {
request = request.basic_auth(username, Some(password));
}
let response = request
.send()
.map_err(|_| "ENTERPRISE_GATE_UNREACHABLE".to_string())?;
let status = response.status();
let value: serde_json::Value = response
.json()
.map_err(|_| "ENTERPRISE_GATE_RESPONSE_INVALID".to_string())?;
if !status.is_success() {
return Err(value
.get("error")
.and_then(serde_json::Value::as_str)
.unwrap_or("ENTERPRISE_GATE_REJECTED")
.to_string());
}
Ok(value)
}
fn load_or_create_key() -> Result<Ed25519KeyPair, String> {
let bytes = if let Some(value) = load_key_bytes()? {
value
@ -225,7 +289,19 @@ pub fn snapshot(app: &AppHandle) -> Result<EnterpriseEntranceSnapshot, String> {
} else {
None
};
let state = if binding.is_some() {
let stored_session = session_path(app)?;
let session: Option<EnterpriseSession> = if stored_session.exists() {
let value: EnterpriseSession = storage::read_json(&stored_session)?;
(value.expires_unix_ms > storage::now_unix_ms()).then_some(value)
} else {
None
};
let enrolled = enrollment_path(app)?.exists();
let state = if session.is_some() {
"ENTERPRISE_SESSION_VERIFIED"
} else if enrolled {
"DEVICE_ENROLLED_SERVER_CHALLENGE_REQUIRED"
} else if binding.is_some() {
"LOCAL_PROOF_READY_SERVER_CHALLENGE_REQUIRED"
} else if device.is_some() {
"LOCAL_DEVICE_KEY_READY_BINDING_REQUIRED"
@ -237,12 +313,142 @@ pub fn snapshot(app: &AppHandle) -> Result<EnterpriseEntranceSnapshot, String> {
state: state.into(),
device,
binding,
session,
enterprise_server_embedded: false,
server_authorized: false,
next_action: "企业服务器并发任务结束后获取一次性挑战;本机证明不等于登录成功。".into(),
server_authorized: state == "ENTERPRISE_SESSION_VERIFIED",
next_action: match state {
"ENTERPRISE_SESSION_VERIFIED" => "企业责任会话已验证;只可进入返回的单一责任仓库。",
"DEVICE_ENROLLED_SERVER_CHALLENGE_REQUIRED" => {
"设备已登记;可以领取一次性挑战并验证当前会话。"
}
_ => "先完成设备和责任绑定;本机证明不等于登录成功。",
}
.into(),
})
}
pub fn enroll_device(
app: &AppHandle,
username: &str,
password: &str,
) -> Result<serde_json::Value, String> {
let username = username.trim();
if !Regex::new(r"^[A-Za-z0-9_-]{1,40}$")
.map_err(|e| e.to_string())?
.is_match(username)
|| password.is_empty()
|| password.len() > 512
{
return Err("ENTERPRISE_ACCOUNT_CREDENTIALS_INVALID".into());
}
let device: EnterpriseDeviceProof = storage::read_json(&device_path(app)?)
.map_err(|_| "ENTERPRISE_DEVICE_PROOF_REQUIRED".to_string())?;
let binding: EnterpriseBindingRequest = storage::read_json(&binding_path(app)?)
.map_err(|_| "ENTERPRISE_BINDING_REQUIRED".to_string())?;
let response = post_json(
"/enroll",
serde_json::json!({
"request_id": binding.request_id,
"human_number": binding.responsible_human_id,
"persona_id": binding.persona_id,
"domain_id": binding.domain_id,
"node_id": device.node_id,
"key_id": device.key_id,
"public_key": device.public_key,
"fingerprint_sha256": device.auxiliary_machine_fingerprint_sha256,
"idempotency_key": format!("{}-{}", binding.request_id, device.key_id),
}),
Some((username, password)),
)?;
storage::write_json(&enrollment_path(app)?, &response)?;
Ok(serde_json::json!({
"ok": true,
"state": "DEVICE_ENROLLED",
"keyId": device.key_id,
"serverAuthorized": false
}))
}
pub fn authenticate(app: &AppHandle) -> Result<EnterpriseSession, String> {
if !enrollment_path(app)?.exists() {
return Err("ENTERPRISE_DEVICE_ENROLLMENT_REQUIRED".into());
}
let device: EnterpriseDeviceProof = storage::read_json(&device_path(app)?)?;
let binding: EnterpriseBindingRequest = storage::read_json(&binding_path(app)?)?;
let response = post_json(
"/challenges",
serde_json::json!({"key_id":device.key_id,"request_id":binding.request_id}),
None,
)?;
let challenge = response
.get("challenge")
.ok_or_else(|| "ENTERPRISE_CHALLENGE_MISSING".to_string())?;
let challenge_id = challenge
.get("challenge_id")
.and_then(serde_json::Value::as_str)
.ok_or_else(|| "ENTERPRISE_CHALLENGE_ID_MISSING".to_string())?;
let nonce = challenge
.get("nonce")
.and_then(serde_json::Value::as_str)
.ok_or_else(|| "ENTERPRISE_CHALLENGE_NONCE_MISSING".to_string())?;
let expires = challenge
.get("expires_unix_ms")
.and_then(serde_json::Value::as_u64)
.ok_or_else(|| "ENTERPRISE_CHALLENGE_EXPIRY_MISSING".to_string())?
as u128;
let proof = sign_challenge(app, &binding.request_id, challenge_id, nonce, expires)?;
let verified = post_json(
"/challenges/verify",
serde_json::json!({"challenge_id":proof.challenge_id,"signature":proof.signature}),
None,
)?;
let value = verified
.get("session")
.ok_or_else(|| "ENTERPRISE_SESSION_MISSING".to_string())?;
let token = value
.get("token")
.and_then(serde_json::Value::as_str)
.ok_or_else(|| "ENTERPRISE_SESSION_TOKEN_MISSING".to_string())?;
let scope = value
.get("scope")
.and_then(serde_json::Value::as_str)
.unwrap_or("");
let session = EnterpriseSession {
schema: "hololake.enterprise-session/v1".into(),
state: "ENTERPRISE_SESSION_VERIFIED".into(),
domain_id: value
.get("domain_id")
.and_then(serde_json::Value::as_str)
.unwrap_or("")
.into(),
repository: value
.get("repository")
.and_then(serde_json::Value::as_str)
.unwrap_or("")
.into(),
repository_url: value
.get("repository_url")
.and_then(serde_json::Value::as_str)
.unwrap_or("")
.into(),
expires_unix_ms: value
.get("expires_unix_ms")
.and_then(serde_json::Value::as_u64)
.unwrap_or(0) as u128,
token_storage: "MACOS_KEYCHAIN".into(),
};
if scope != "ONE_DOMAIN_ONE_REPOSITORY"
|| session.domain_id != binding.domain_id
|| session.repository.is_empty()
|| session.expires_unix_ms <= storage::now_unix_ms()
{
return Err("ENTERPRISE_SESSION_SCOPE_INVALID".into());
}
save_session_token(&device.key_id, token.as_bytes())?;
storage::write_json(&session_path(app)?, &session)?;
Ok(session)
}
pub fn sign_challenge(
app: &AppHandle,
request_id: &str,

View file

@ -501,6 +501,22 @@ fn sign_enterprise_challenge(
enterprise_entrance::sign_challenge(&app, &request_id, &challenge_id, &nonce, expires_unix_ms)
}
#[tauri::command]
fn enroll_enterprise_device(
app: AppHandle,
username: String,
password: String,
) -> Result<serde_json::Value, String> {
enterprise_entrance::enroll_device(&app, &username, &password)
}
#[tauri::command]
fn authenticate_enterprise_entrance(
app: AppHandle,
) -> Result<enterprise_entrance::EnterpriseSession, String> {
enterprise_entrance::authenticate(&app)
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
@ -577,11 +593,13 @@ pub fn run() {
delete_trial_persona,
compile_tcs_agent_proposal,
approve_agent_proposal,
reject_agent_proposal
,enterprise_entrance_snapshot
,prepare_enterprise_device
,prepare_enterprise_binding
,sign_enterprise_challenge
reject_agent_proposal,
enterprise_entrance_snapshot,
prepare_enterprise_device,
prepare_enterprise_binding,
sign_enterprise_challenge,
enroll_enterprise_device,
authenticate_enterprise_entrance
])
.run(tauri::generate_context!())
.expect("HoloLake runtime failed")

View file

@ -924,6 +924,8 @@ function Portal({ setError }: { setError: (value: string) => void }) {
const [domainId, setDomainId] = useState("DOMAIN-MAIN");
const [humanId, setHumanId] = useState("");
const [personaId, setPersonaId] = useState("");
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [busy, setBusy] = useState(false);
const refresh = () => api.enterpriseEntranceSnapshot().then(setEntrance).catch((error) => setError(String(error)));
useEffect(() => {
@ -951,6 +953,30 @@ function Portal({ setError }: { setError: (value: string) => void }) {
setBusy(false);
}
};
const enrollDevice = async () => {
setBusy(true);
try {
await api.enrollEnterpriseDevice(username, password);
setPassword("");
await refresh();
} catch (error) {
setPassword("");
setError(String(error));
} finally {
setBusy(false);
}
};
const authenticate = async () => {
setBusy(true);
try {
await api.authenticateEnterpriseEntrance();
await refresh();
} catch (error) {
setError(String(error));
} finally {
setBusy(false);
}
};
return (
<div className="page simple">
<header>
@ -996,6 +1022,23 @@ function Portal({ setError }: { setError: (value: string) => void }) {
<>
<p>{entrance.binding.domainId} · {entrance.binding.responsibleHumanId} · {entrance.binding.personaId}</p>
<small>{entrance.binding.state}</small>
{!entrance.session && entrance.state === "LOCAL_PROOF_READY_SERVER_CHALLENGE_REQUIRED" && (
<div className="enterprise-binding-form">
<input value={username} onChange={(event) => setUsername(event.target.value)} placeholder="企业代码仓库用户名" autoComplete="username" />
<input type="password" value={password} onChange={(event) => setPassword(event.target.value)} placeholder="仅用于本次设备登记" autoComplete="current-password" />
<button onClick={enrollDevice} disabled={busy || !username.trim() || !password}>
</button>
</div>
)}
{!entrance.session && entrance.state === "DEVICE_ENROLLED_SERVER_CHALLENGE_REQUIRED" && (
<button onClick={authenticate} disabled={busy}></button>
)}
{entrance.session && (
<a href={entrance.session.repositoryUrl} target="_blank" rel="noreferrer">
</a>
)}
</>
) : (
<div className="enterprise-binding-form">

View file

@ -312,6 +312,7 @@ export async function enterpriseEntranceSnapshot(): Promise<EnterpriseEntranceSn
state: "LOCAL_DEVICE_REGISTRATION_REQUIRED",
device: null,
binding: null,
session: null,
enterpriseServerEmbedded: false,
serverAuthorized: false,
nextAction: "浏览器预览不生成设备凭证。",
@ -331,3 +332,16 @@ export async function prepareEnterpriseBinding(
if (!tauri()) throw new Error("企业责任绑定只能在已安装的 HoloLake 中准备");
return invoke("prepare_enterprise_binding", { domainId, responsibleHumanId, personaId });
}
export async function enrollEnterpriseDevice(
username: string,
password: string,
): Promise<{ ok: boolean; state: string; keyId: string; serverAuthorized: boolean }> {
if (!tauri()) throw new Error("企业设备登记只能在已安装的 HoloLake 中完成");
return invoke("enroll_enterprise_device", { username, password });
}
export async function authenticateEnterpriseEntrance(): Promise<EnterpriseEntranceSnapshot["session"]> {
if (!tauri()) throw new Error("企业责任会话只能在已安装的 HoloLake 中验证");
return invoke("authenticate_enterprise_entrance");
}

View file

@ -164,7 +164,17 @@ export interface EnterpriseEntranceSnapshot {
state: string;
device: EnterpriseDeviceProof | null;
binding: EnterpriseBindingRequest | null;
session: EnterpriseSession | null;
enterpriseServerEmbedded: boolean;
serverAuthorized: boolean;
nextAction: string;
}
export interface EnterpriseSession {
schema: string;
state: string;
domainId: string;
repository: string;
repositoryUrl: string;
expiresUnixMs: number;
tokenStorage: string;
}

View file

@ -27,7 +27,9 @@
"bingshuo_enterprise_language_master_work_repository": "REPO-016:bingshuo/guanghu-language-master-work",
"team_enterprise_login": "https://guanghu.chat/code/user/login",
"enterprise_responsibility_entrance": "HLP-MOD-ENTERPRISE-RESPONSIBILITY-ENTRANCE-0001",
"enterprise_responsibility_entrance_state": "LOCAL_DEVICE_PROOF_INSTALLED_KEYCHAIN_VERIFIED_SERVER_CHALLENGE_PENDING",
"enterprise_responsibility_entrance_state": "SERVER_DEVICE_GATE_ACTIVE_CLIENT_ENROLLMENT_AND_CHALLENGE_SOURCE_IMPLEMENTED_REBUILD_PENDING",
"enterprise_responsibility_gate_endpoint": "https://guanghu.chat/api/hololake/enterprise/device-gate",
"enterprise_responsibility_gate_source_commit": "be31c41",
"enterprise_server_embedded": false,
"enterprise_login_required_proofs": [
"DOMAIN_RESPONSIBLE_HUMAN_ID",