diff --git a/deployment/receipts/GH-HOLOLAKE-NODE-REGISTRATION-TRANSPORT-20260810-001.json b/deployment/receipts/GH-HOLOLAKE-NODE-REGISTRATION-TRANSPORT-20260810-001.json deleted file mode 100644 index a81c20d7a..000000000 --- a/deployment/receipts/GH-HOLOLAKE-NODE-REGISTRATION-TRANSPORT-20260810-001.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "schema": "gh-aios.node-registration-transport-delivery/v1", - "receipt_id": "GH-HOLOLAKE-NODE-REGISTRATION-TRANSPORT-20260810-001", - "development_id": "DEV-20260809-007", - "generated_at": "2026-08-10T07:40:00+08:00", - "source": { - "repository_id": "REPO-014", - "branch": "main", - "implementation_commit": "27cd1645dac1676d10ddc0d031ca5aa402fad005", - "implementation_tree": "926da6bb1140bd9522c5dfb8711594f63533a4b3" - }, - "acceptance": { - "registered_endpoint_only": true, - "caller_supplied_url_rejected_before_network": true, - "credentials_omitted": true, - "redirects_rejected": true, - "timeout_ms": 5000, - "maximum_response_bytes": 65536, - "exact_request_response_binding": true, - "signed_claim_verified_after_transport": true, - "handoff_blocked_on_any_transport_or_claim_failure": true - }, - "verification": { - "targeted_node_registration_tests": "22/22 PASS", - "hololake_desktop_tests": "77/77 PASS", - "knowledge_base_production_build": "PASS", - "desktop_production_build": "PASS", - "ghnqg": "GHNQG_PASS_100", - "ghnqg_receipt": "/Users/bingshuolingdianyuanhe/Documents/Codex/2026-08-09/new-chat/outputs/quality/GHNQG-NODE-REGISTRATION-TRANSPORT-20260810.hldp", - "ghnqg_receipt_sha256": "e27a74bb243280c9e1096b9655d97c1a2c288fec5251dd2339f493195d669262", - "demo_vault_dirt": "NONE", - "localization": "NO_UI_COPY_CHANGES", - "analytics": "NO_EVENT_NEEDED_NON_USER_ACTION_TRANSPORT_BOUNDARY" - }, - "desktop_delivery": { - "candidate": "/Users/bingshuolingdianyuanhe/Documents/Codex/2026-08-09/new-chat/work/DEV-20260809-003/repo014/product-source/hololake-desktop/release/mac-arm64/HoloLake Era.app", - "installed": "/Users/bingshuolingdianyuanhe/Desktop/HoloLake Era.app", - "previous_bundle_backup": "/Users/bingshuolingdianyuanhe/Documents/Codex/2026-08-09/new-chat/work/DEV-20260809-007/desktop-backup-node-transport-20260810-0739/HoloLake Era.app", - "developer_id_signature": "PASS", - "notarization": "NOT_PERFORMED_OPTIONS_UNAVAILABLE", - "app_asar_sha256": "db22e77328b729c3d155f81b030dd4606e32be0c15e4a50fb0a33bc46a47da4a", - "executable_sha256": "2d7e6d6da66ac55d23b052612ef7384c6d48f2f780c355cb56e54e9048c93af4", - "installed_hashes_match_candidate": true, - "process_running_after_install": true - }, - "current_online_reality": { - "public_anchor_http": 200, - "repo_012_source_commit": "34e1949a113be8d4871e61c094f2ae06e0bc5a45", - "source_degraded": false, - "node_registration_endpoints_map": null, - "node_registration_endpoint_service_exists": false, - "node_registration_claim_exists": false, - "node_registration_capability": "NODE_REGISTRATION_NOT_EXISTS_0" - }, - "state": { - "code_complete": true, - "repository_published": false, - "desktop_installed": true, - "production_endpoint_deployed": false, - "production_runtime_healthy": false - } -} diff --git a/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.test.ts b/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.test.ts index 6157958c3..90afb4742 100644 --- a/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.test.ts +++ b/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.test.ts @@ -191,15 +191,11 @@ test('projects both trust-source states without asking for claims or handoff bef }); test('a signed node registration without a handoff remains identity-only', async () => { - let observedEndpointId = ''; const orchestrator = new DomainAccessOrchestrator( signerLoader(), registrationLoader(), loggedInIdentity, - { async read(request) { - observedEndpointId = request.endpoint.endpointId; - return validRegistrationClaim(); - } }, + validRegistrationSource, { async read() { return null; } }, ); @@ -207,7 +203,6 @@ test('a signed node registration without a handoff remains identity-only', async assert.equal(status.stage, 'identity-verified'); assert.equal(status.runtimeReady, false); - assert.equal(observedEndpointId, 'GH-NODE-REG-001'); assert.equal(status.blockers.includes('verified_node_registration_missing'), false); assert.ok(status.blockers.includes('verified_domain_manifest_missing')); }); @@ -251,14 +246,13 @@ test('current registries, signed node claim and verified handoff project runtime }); test('source failures are reduced to safe status without raw details', async () => { - let claimReads = 0; const unavailableSigner = new TrustedSignerSnapshotLoader({ async fetchJson() { throw new Error('secret signer detail'); } }); const unavailableRegistration = new NodeRegistrationSnapshotLoader({ async fetchJson() { throw new Error('secret registration detail'); } }); const orchestrator = new DomainAccessOrchestrator( unavailableSigner, unavailableRegistration, loggedInIdentity, - { async read() { claimReads += 1; throw new Error('secret claim detail'); } }, + { async read() { throw new Error('secret claim detail'); } }, { async read() { throw new Error('secret handoff detail'); } }, ); @@ -268,7 +262,6 @@ test('source failures are reduced to safe status without raw details', async () assert.equal(status.runtimeReady, false); assert.equal(status.nodeRegistrationSource.status, 'UNAVAILABLE'); assert.equal(status.trustSource.status, 'UNAVAILABLE'); - assert.equal(claimReads, 0); assert.equal(JSON.stringify(status).includes('secret'), false); }); diff --git a/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.ts b/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.ts index 1790bad57..323ab5651 100644 --- a/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.ts +++ b/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.ts @@ -18,7 +18,6 @@ import { NodeRegistrationSnapshotLoader, type NodeRegistrationSnapshotReceipt, } from './node-registration-snapshot.js'; -import type { NodeRegistrationClaimSource } from './node-registration-client.js'; const IDENTIFIER_PATTERN = /^[A-Z0-9][A-Z0-9._:-]{1,159}$/; @@ -32,6 +31,19 @@ export interface DomainIdentitySource { read(domainId: string, nodeType: DomainNodeType): Promise; } +export interface NodeRegistrationClaimRequest { + accountId: string; + domainId: string; + endpointId: string; + endpointUrl: string; + nodeId: string; + nodeType: DomainNodeType; +} + +export interface NodeRegistrationClaimSource { + read(request: Readonly): Promise; +} + export interface DomainRuntimeHandoffCandidate { handoff: unknown; signerLookup: { @@ -101,7 +113,8 @@ export class DomainAccessOrchestrator { const claim = await this.nodeRegistrations.read(Object.freeze({ accountId: identity.accountId, domainId, - endpoint, + endpointId: endpoint.endpointId, + endpointUrl: endpoint.url, nodeId: identity.nodeId, nodeType, })); diff --git a/product-source/guanghu-knowledge-base/server/node-registration-client.test.ts b/product-source/guanghu-knowledge-base/server/node-registration-client.test.ts deleted file mode 100644 index 9d89d92d8..000000000 --- a/product-source/guanghu-knowledge-base/server/node-registration-client.test.ts +++ /dev/null @@ -1,153 +0,0 @@ -import test from 'node:test'; -import assert from 'node:assert/strict'; -import { generateKeyPairSync } from 'node:crypto'; -import { HttpNodeRegistrationClaimSource } from './node-registration-client.js'; -import { - parseNodeRegistrationEndpointRegistry, - resolveNodeRegistrationEndpoint, -} from './node-registration.js'; - -const NOW = 1_786_291_200_000; -const COMMIT = 'a'.repeat(40); -const { publicKey } = generateKeyPairSync('ed25519'); - -function registeredEndpoint() { - const registry = parseNodeRegistrationEndpointRegistry({ - endpoints: [{ - algorithm: 'Ed25519', - domainIds: ['DOM-FIFTH-0001'], - endpointId: 'GH-NODE-REG-001', - nodeTypes: ['local-terminal'], - publicKeyPem: publicKey.export({ format: 'pem', type: 'spki' }).toString(), - signerId: 'GH-NODE-REG-SIGNER-001', - status: 'ACTIVE', - url: 'https://guanghulab.com/api/ai/v1/node-registrations/claims', - }], - registryId: 'GH-AIOS-NODE-REGISTRATION-ENDPOINTS-001', - schema: 'gh-aios.node-registration-endpoints/v1', - state: 'CURRENT', - version: '1.0.0', - }, { - repositoryId: 'REPO-012', - sourceCommit: COMMIT, - sourceUrl: `https://guanghulab.com/code/bingshuo/guanghu-ice-heart/raw/commit/${COMMIT}/routing/node-registration-endpoints.json`, - }); - const endpoint = resolveNodeRegistrationEndpoint(registry, { - domainId: 'DOM-FIFTH-0001', - nodeType: 'local-terminal', - }); - assert.ok(endpoint); - return endpoint; -} - -function lookup(endpoint = registeredEndpoint()) { - return { - accountId: 'bingshuo', - domainId: 'DOM-FIFTH-0001', - endpoint, - nodeId: 'LOCAL-001', - nodeType: 'local-terminal' as const, - }; -} - -function responseBody(status: 'ISSUED' | 'NOT_FOUND' = 'ISSUED', overrides: Record = {}) { - return { - claim: status === 'ISSUED' ? { signed: 'claim' } : null, - requestId: 'NODE-REQ-001', - schema: 'gh-aios.node-registration-claim-response/v1', - status, - ...overrides, - }; -} - -function jsonResponse(body: unknown, init: ResponseInit = {}) { - return new Response(JSON.stringify(body), { - status: 200, - ...init, - headers: { 'Content-Type': 'application/json', ...init.headers }, - }); -} - -test('posts an exact credentialless claim lookup only to the registered endpoint', async () => { - let observedUrl = ''; - let observedInit: RequestInit | undefined; - const source = new HttpNodeRegistrationClaimSource(async (url, init) => { - observedUrl = url; - observedInit = init; - return jsonResponse(responseBody()); - }, () => NOW, () => 'NODE-REQ-001'); - - const claim = await source.read(lookup()); - - assert.deepEqual(claim, { signed: 'claim' }); - assert.equal(observedUrl, 'https://guanghulab.com/api/ai/v1/node-registrations/claims'); - assert.equal(observedInit?.method, 'POST'); - assert.equal(observedInit?.credentials, 'omit'); - assert.equal(observedInit?.redirect, 'manual'); - assert.equal(observedInit?.cache, 'no-store'); - assert.equal(observedInit?.referrerPolicy, 'no-referrer'); - assert.deepEqual(JSON.parse(String(observedInit?.body)), { - accountId: 'bingshuo', - domainId: 'DOM-FIFTH-0001', - endpointId: 'GH-NODE-REG-001', - issuedAt: NOW, - nodeId: 'LOCAL-001', - nodeType: 'local-terminal', - requestId: 'NODE-REQ-001', - schema: 'gh-aios.node-registration-claim-request/v1', - }); - const headers = observedInit?.headers as Record; - assert.equal(headers.Authorization, undefined); - assert.equal(headers.Cookie, undefined); -}); - -test('returns null only for an exact NOT_FOUND response', async () => { - const source = new HttpNodeRegistrationClaimSource( - async () => jsonResponse(responseBody('NOT_FOUND')), - () => NOW, - () => 'NODE-REQ-001', - ); - assert.equal(await source.read(lookup()), null); -}); - -test('rejects caller-created endpoints before any network request', async () => { - let called = false; - const source = new HttpNodeRegistrationClaimSource(async () => { - called = true; - return jsonResponse(responseBody()); - }, () => NOW, () => 'NODE-REQ-001'); - const forged = { ...registeredEndpoint(), url: 'https://guanghulab.com/api/ai/v1/other' }; - - await assert.rejects(source.read(lookup(forged)), /transport_invalid/); - assert.equal(called, false); -}); - -test('rejects redirects, non-json responses, oversized bodies and mismatched envelopes', async () => { - const cases: Array<() => Response> = [ - () => new Response(null, { status: 302, headers: { Location: 'https://guanghulab.com/api/ai/v1/other' } }), - () => new Response('{}', { status: 200, headers: { 'Content-Type': 'text/plain' } }), - () => new Response('x', { status: 200, headers: { 'Content-Type': 'application/json', 'Content-Length': '65537' } }), - () => new Response(`"${'x'.repeat(65_536)}"`, { status: 200, headers: { 'Content-Type': 'application/json' } }), - () => jsonResponse(responseBody('ISSUED', { requestId: 'NODE-REQ-OTHER' })), - () => jsonResponse({ ...responseBody(), extra: true }), - () => jsonResponse(responseBody('NOT_FOUND', { claim: {} })), - ]; - for (const makeResponse of cases) { - const source = new HttpNodeRegistrationClaimSource( - async () => makeResponse(), - () => NOW, - () => 'NODE-REQ-001', - ); - await assert.rejects(source.read(lookup()), /transport_invalid/); - } -}); - -test('reduces network errors to one non-sensitive transport failure', async () => { - const source = new HttpNodeRegistrationClaimSource(async () => { - throw new Error('secret endpoint detail'); - }, () => NOW, () => 'NODE-REQ-001'); - await assert.rejects(source.read(lookup()), error => { - assert.equal((error as Error).message, 'node_registration_claim_transport_invalid'); - return true; - }); -}); diff --git a/product-source/guanghu-knowledge-base/server/node-registration-client.ts b/product-source/guanghu-knowledge-base/server/node-registration-client.ts deleted file mode 100644 index b1240b6a7..000000000 --- a/product-source/guanghu-knowledge-base/server/node-registration-client.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { randomUUID } from 'node:crypto'; -import type { DomainNodeType } from './domain-access.js'; -import { - assertRegisteredNodeRegistrationEndpoint, - type NodeRegistrationEndpoint, -} from './node-registration.js'; - -const REQUEST_SCHEMA = 'gh-aios.node-registration-claim-request/v1' as const; -const RESPONSE_SCHEMA = 'gh-aios.node-registration-claim-response/v1' as const; -const MAX_RESPONSE_BYTES = 64 * 1024; -const REQUEST_TIMEOUT_MS = 5_000; -const MAX_CLOCK_SKEW_MS = 5 * 60 * 1000; -const IDENTIFIER_PATTERN = /^[A-Z0-9][A-Z0-9._:-]{1,159}$/; -const ACCOUNT_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,79}$/; - -export interface NodeRegistrationClaimLookup { - accountId: string; - domainId: string; - endpoint: NodeRegistrationEndpoint; - nodeId: string; - nodeType: DomainNodeType; -} - -export interface NodeRegistrationClaimRequestBody { - accountId: string; - domainId: string; - endpointId: string; - issuedAt: number; - nodeId: string; - nodeType: DomainNodeType; - requestId: string; - schema: typeof REQUEST_SCHEMA; -} - -export interface NodeRegistrationClaimSource { - read(lookup: Readonly): Promise; -} - -type FetchImplementation = (input: string, init: RequestInit) => Promise; - -function invalidTransport(): never { - throw new Error('node_registration_claim_transport_invalid'); -} - -function isRecord(value: unknown): value is Record { - return typeof value === 'object' && value !== null && !Array.isArray(value); -} - -function hasExactKeys(record: Record, keys: string[]): boolean { - const expected = [...keys].sort(); - const actual = Object.keys(record).sort(); - return actual.length === expected.length && actual.every((key, index) => key === expected[index]); -} - -function buildRequest( - lookup: Readonly, - now: number, - requestId: string, -): Readonly { - let endpoint: NodeRegistrationEndpoint; - try { - endpoint = assertRegisteredNodeRegistrationEndpoint(lookup.endpoint); - } catch { - invalidTransport(); - } - if (endpoint.status !== 'ACTIVE' - || !endpoint.domainIds.includes(lookup.domainId) - || !endpoint.nodeTypes.includes(lookup.nodeType) - || !ACCOUNT_ID_PATTERN.test(lookup.accountId) - || !IDENTIFIER_PATTERN.test(lookup.domainId) - || !IDENTIFIER_PATTERN.test(lookup.nodeId) - || !IDENTIFIER_PATTERN.test(requestId) - || !Number.isSafeInteger(now)) invalidTransport(); - return Object.freeze({ - accountId: lookup.accountId, - domainId: lookup.domainId, - endpointId: endpoint.endpointId, - issuedAt: now, - nodeId: lookup.nodeId, - nodeType: lookup.nodeType, - requestId, - schema: REQUEST_SCHEMA, - }); -} - -async function readLimitedBody(response: Response): Promise { - if (!response.body) invalidTransport(); - const reader = response.body.getReader(); - const chunks: Uint8Array[] = []; - let total = 0; - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - total += value.byteLength; - if (total > MAX_RESPONSE_BYTES) invalidTransport(); - chunks.push(value); - } - } finally { - reader.releaseLock(); - } - const body = new Uint8Array(total); - let offset = 0; - for (const chunk of chunks) { - body.set(chunk, offset); - offset += chunk.byteLength; - } - return body; -} - -function parseResponse(input: unknown, request: NodeRegistrationClaimRequestBody): unknown | null { - if (!isRecord(input) - || !hasExactKeys(input, ['claim', 'requestId', 'schema', 'status']) - || input.schema !== RESPONSE_SCHEMA - || input.requestId !== request.requestId - || (input.status !== 'ISSUED' && input.status !== 'NOT_FOUND')) invalidTransport(); - if (input.status === 'NOT_FOUND') { - if (input.claim !== null) invalidTransport(); - return null; - } - if (!isRecord(input.claim)) invalidTransport(); - return input.claim; -} - -export class HttpNodeRegistrationClaimSource implements NodeRegistrationClaimSource { - constructor( - private readonly fetchImpl: FetchImplementation = fetch, - private readonly now: () => number = Date.now, - private readonly requestId: () => string = () => `NODE-REQ-${randomUUID().toUpperCase()}`, - ) {} - - async read(lookup: Readonly): Promise { - const issuedAt = this.now(); - const request = buildRequest(lookup, issuedAt, this.requestId()); - let response: Response; - try { - response = await this.fetchImpl(lookup.endpoint.url, { - body: JSON.stringify(request), - cache: 'no-store', - credentials: 'omit', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - method: 'POST', - redirect: 'manual', - referrerPolicy: 'no-referrer', - signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), - }); - } catch { - invalidTransport(); - } - if (response.status !== 200 - || response.redirected - || !response.headers.get('content-type')?.toLowerCase().startsWith('application/json')) { - invalidTransport(); - } - const contentLength = response.headers.get('content-length'); - if (contentLength && (!/^\d+$/.test(contentLength) || Number(contentLength) > MAX_RESPONSE_BYTES)) { - invalidTransport(); - } - let decoded: string; - try { - decoded = new TextDecoder('utf-8', { fatal: true }).decode(await readLimitedBody(response)); - } catch { - invalidTransport(); - } - let parsed: unknown; - try { - parsed = JSON.parse(decoded); - } catch { - invalidTransport(); - } - if (Math.abs(this.now() - issuedAt) > MAX_CLOCK_SKEW_MS) invalidTransport(); - return parseResponse(parsed, request); - } -} diff --git a/product-source/guanghu-knowledge-base/server/node-registration.ts b/product-source/guanghu-knowledge-base/server/node-registration.ts index 0cbb002c9..97f57540d 100644 --- a/product-source/guanghu-knowledge-base/server/node-registration.ts +++ b/product-source/guanghu-knowledge-base/server/node-registration.ts @@ -204,15 +204,6 @@ export function resolveNodeRegistrationEndpoint( return endpoint; } -export function assertRegisteredNodeRegistrationEndpoint( - endpoint: NodeRegistrationEndpoint, -): NodeRegistrationEndpoint { - if (!registeredEndpoints.has(endpoint)) { - throw new Error('node_registration_endpoint_unregistered'); - } - return endpoint; -} - export function nodeRegistrationClaimSigningBytes(payload: NodeRegistrationClaimPayload): Buffer { return Buffer.from(JSON.stringify({ accountId: payload.accountId, diff --git a/product-source/hololake-desktop/electron/main.ts b/product-source/hololake-desktop/electron/main.ts index d132b1763..22216ce02 100644 --- a/product-source/hololake-desktop/electron/main.ts +++ b/product-source/hololake-desktop/electron/main.ts @@ -21,7 +21,6 @@ import { importKnowledgeFolder } from './folder-import.js'; import { DomainAccessOrchestrator } from '../../guanghu-knowledge-base/server/domain-access-orchestrator.js'; import { TrustedSignerSnapshotLoader } from '../../guanghu-knowledge-base/server/trusted-signer-snapshot.js'; import { NodeRegistrationSnapshotLoader } from '../../guanghu-knowledge-base/server/node-registration-snapshot.js'; -import { HttpNodeRegistrationClaimSource } from '../../guanghu-knowledge-base/server/node-registration-client.js'; // ─── 配置 ─── @@ -337,8 +336,6 @@ const nodeRegistrationSnapshots = new NodeRegistrationSnapshotLoader({ }, }); -const nodeRegistrationClaims = new HttpNodeRegistrationClaimSource(); - const domainAccessOrchestrator = new DomainAccessOrchestrator( trustedSignerSnapshots, nodeRegistrationSnapshots, @@ -360,7 +357,13 @@ const domainAccessOrchestrator = new DomainAccessOrchestrator( } }, }, - nodeRegistrationClaims, + { + async read() { + // Current REPO-012 does not yet register a node-registration endpoint. + // Keep this transport absent until that public registry and service exist. + return null; + }, + }, { async read() { // 当前灯塔尚未发布签名运行体交接端点。保持关闭,不从账号身份推导运行体权限。 diff --git a/product-source/hololake-platform/architecture/HOLOLAKE-NODE-REGISTRATION-CONTRACT-20260810.md b/product-source/hololake-platform/architecture/HOLOLAKE-NODE-REGISTRATION-CONTRACT-20260810.md index 976dc9c05..e14bd4b15 100644 --- a/product-source/hololake-platform/architecture/HOLOLAKE-NODE-REGISTRATION-CONTRACT-20260810.md +++ b/product-source/hololake-platform/architecture/HOLOLAKE-NODE-REGISTRATION-CONTRACT-20260810.md @@ -44,17 +44,3 @@ - 当前桌面没有可调用的登记声明端点; - 当前没有生产节点登记签发公钥、登记声明或节点密钥挑战回执; - 因而 Forgejo 账号验证以后仍停留在“需要节点登记”,这是正确的失败关闭结果。 - -## 登记声明读取传输 · 阶段 002 - -登记声明读取不是“创建节点登记”,也不携带账号密码、访问令牌、验证码或节点私钥。客户端 -只在当前锚点注册表为 `CURRENT` 且解析出唯一活跃端点后,向该端点发送固定结构的无凭据 -`POST`:账号标识、域、节点编号、节点类型、端点编号、一次性请求编号与签发时间。 - -传输必须同时满足:禁止重定向、5 秒超时、`application/json`、响应不超过 64 KiB、响应 -请求编号与原请求一致。响应只允许 `ISSUED + claim` 或 `NOT_FOUND + null`;前者仍必须经过 -阶段 001 的 Ed25519 声明验证,后者不能升级任何权限。HTTP 错误、未知字段、超限、绑定不 -一致及解析失败全部关闭为“未验证节点登记”,并且不触发运行体交接。 - -当前公共锚点仍未登记端点,所以该传输在生产运行中不可达,也不会发出请求;实现存在不等于 -端点服务、节点登记或域运行体已经存在。 diff --git a/product-source/hololake-platform/architecture/README.md b/product-source/hololake-platform/architecture/README.md index f7979dc43..f4f606667 100644 --- a/product-source/hololake-platform/architecture/README.md +++ b/product-source/hololake-platform/architecture/README.md @@ -8,7 +8,7 @@ - [`HOLOLAKE-INTENT-REASONING-MAP-20260809.md`](HOLOLAKE-INTENT-REASONING-MAP-20260809.md):当前产品意图、纠正、思维推理与因果链。 - [`HOLOLAKE-SYSTEM-ARCHITECTURE-20260809.md`](HOLOLAKE-SYSTEM-ARCHITECTURE-20260809.md):`HLP-CURRENT-ARCH-001` 当前完整系统蓝图,覆盖 GH-AIOS 灯塔、五域独立入口、光湖本源域、节点登录与光湖桥。 - [`HOLOLAKE-DESKTOP-0.8.0-CURRENT-CAPABILITY-GAP-20260809.md`](HOLOLAKE-DESKTOP-0.8.0-CURRENT-CAPABILITY-GAP-20260809.md):桌面 0.8.0 已观察能力与最终规划的逐项差距;同时登记线上产品源码仍为 0.4.6 的分叉事实。 -- [`HOLOLAKE-NODE-REGISTRATION-CONTRACT-20260810.md`](HOLOLAKE-NODE-REGISTRATION-CONTRACT-20260810.md):账号验证与节点登记分离后的签名声明、端点注册表、无凭据声明读取传输、失败关闭和当前生产缺口验收基线。 +- [`HOLOLAKE-NODE-REGISTRATION-CONTRACT-20260810.md`](HOLOLAKE-NODE-REGISTRATION-CONTRACT-20260810.md):账号验证与节点登记分离后的签名声明、端点注册表、失败关闭和当前生产缺口验收基线。 - [`HOLOLAKE-LANGUAGE-PERSONA-OS.md`](HOLOLAKE-LANGUAGE-PERSONA-OS.md):HoloLake 作为 AI 语言人格驱动操作系统的当前正式产品定位、操作系统映射、原生应用边界与实现缺口。 - [`HOLOLAKE-INTENT-REASONING-MAP-20260807.md`](HOLOLAKE-INTENT-REASONING-MAP-20260807.md):2026-08-07 历史意图层,继续保存形成过程;不再作为当前默认入口。