diff --git a/deployment/receipts/GH-HOLOLAKE-HANDOFF-PROOF-BINDING-20260810-001.json b/deployment/receipts/GH-HOLOLAKE-HANDOFF-PROOF-BINDING-20260810-001.json deleted file mode 100644 index eb3b5c405..000000000 --- a/deployment/receipts/GH-HOLOLAKE-HANDOFF-PROOF-BINDING-20260810-001.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema": "gh-aios.handoff-proof-binding-deployment-receipt/v1", - "receipt_id": "GH-HOLOLAKE-HANDOFF-PROOF-BINDING-20260810-001", - "development_id": "DEV-20260809-007", - "repository_id": "REPO-014", - "branch": "main", - "repo012_main": "34e1949a113be8d4871e61c094f2ae06e0bc5a45", - "implementation": { - "commit": "46d19aeb459a9556f6478fe8353d19962833fdb0", - "tree": "f9fdaeca0c7feb3275d4be33e958da1eb41671e8", - "stage": "VERIFIED_NODE_POSSESSION_TO_DOMAIN_RUNTIME_HANDOFF_BINDING", - "private_key_published": false, - "password_token_or_code_published": false - }, - "verification": { - "targeted_tests": "PASS_17_OF_17", - "desktop_full_tests": "PASS_85_OF_85", - "desktop_build": "PASS_100", - "ghnqg": "PASS_100", - "ghnqg_receipt": "/Users/bingshuolingdianyuanhe/Documents/Codex/2026-08-09/new-chat/outputs/quality/GHNQG-HANDOFF-PROOF-BINDING-20260810.hldp", - "ghnqg_receipt_sha256": "e54fc87f01603b2a7146ecac4ba7b71a3cc81470e77d640b36b9e833d1a4ba10", - "candidate_codesign": "PASS_100", - "installed_codesign": "PASS_100", - "candidate_matches_installed": true, - "app_asar_sha256": "e226a11e4ab60717d83f2ae01069153cdf97e3f3fff49fdce11af3b061b4e050", - "executable_sha256": "b81fa712a8b55e22f8dd14a9e876b69368019113872a410e4ec887689a1ee9cf", - "macos_notarization": "SKIPPED_OPTIONS_UNAVAILABLE" - }, - "desktop_deployment": { - "installed_path": "/Users/bingshuolingdianyuanhe/Desktop/HoloLake Era.app", - "backup_path": "/Users/bingshuolingdianyuanhe/Documents/Codex/2026-08-09/new-chat/work/DEV-20260809-007/desktop-backup-handoff-proof-20260810T0843/HoloLake Era.app", - "pid": 23429, - "local_service": "http://127.0.0.1:3890/api/health", - "local_service_status": "online", - "local_service_version": "0.8.0" - }, - "runtime_boundary": { - "production_handoff_endpoint": "NOT_EXISTS_0", - "production_domain_session": "NOT_EXISTS_0", - "production_node_registry": "NOT_EXISTS_0", - "production_keystore_bridge": "NOT_EXISTS_0", - "desktop_handoff_source": "NULL_FAIL_CLOSED", - "notarized_artifact": false - }, - "publication": { - "remote_commit": "PENDING_FINAL_COMMIT_AND_PUBLICATION", - "fresh_clone_fsck": "PENDING", - "state": "READY_FOR_PUBLICATION" - } -} 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 53e21e8e2..ceeb2ae53 100644 --- a/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.ts +++ b/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.ts @@ -23,7 +23,6 @@ import { createNodePossessionChallenge, verifyNodePossessionResponse, type NodePossessionProofSource, - type VerifiedNodePossession, } from './node-possession-proof.js'; const IDENTIFIER_PATTERN = /^[A-Z0-9][A-Z0-9._:-]{1,159}$/; @@ -47,7 +46,7 @@ export interface DomainRuntimeHandoffCandidate { } export interface DomainRuntimeHandoffSource { - read(possession: VerifiedNodePossession): Promise; + read(domainId: string, nodeId: string, nodeType: DomainNodeType): Promise; } export interface DomainAccessProjection { @@ -103,7 +102,6 @@ export class DomainAccessOrchestrator { ]); let nodeRegistrationVerified = false; let nodePossessionVerified = false; - let possession: VerifiedNodePossession | null = null; if (identity.accountVerified && nodeRegistrationSnapshot.receipt.status === 'CURRENT') { try { const loaded = assertLoadedNodeRegistrationSnapshot(nodeRegistrationSnapshot); @@ -128,7 +126,7 @@ export class DomainAccessOrchestrator { const response = await this.nodePossessions.prove(challenge); if (response) { if (at === undefined) now = this.clock(); - possession = verifyNodePossessionResponse(response, challenge, registration, now); + verifyNodePossessionResponse(response, challenge, registration, now); nodePossessionVerified = true; } } @@ -146,10 +144,10 @@ export class DomainAccessOrchestrator { nodeType, }; - if (identity.accountVerified && nodeRegistrationVerified && nodePossessionVerified && possession) { + if (identity.accountVerified && nodeRegistrationVerified && nodePossessionVerified) { let candidate: DomainRuntimeHandoffCandidate | null = null; try { - candidate = await this.handoffs.read(possession); + candidate = await this.handoffs.read(domainId, identity.nodeId, nodeType); } catch { candidate = null; } diff --git a/product-source/guanghu-knowledge-base/server/domain-runtime-handoff-source.test.ts b/product-source/guanghu-knowledge-base/server/domain-runtime-handoff-source.test.ts index ddd15037a..bbf631e4b 100644 --- a/product-source/guanghu-knowledge-base/server/domain-runtime-handoff-source.test.ts +++ b/product-source/guanghu-knowledge-base/server/domain-runtime-handoff-source.test.ts @@ -1,163 +1,75 @@ import test from 'node:test'; import assert from 'node:assert/strict'; -import { createHash, generateKeyPairSync, sign } from 'node:crypto'; import { StrictDomainRuntimeHandoffSource } from './domain-runtime-handoff-source.js'; -import { - createNodePossessionChallenge, - nodePossessionChallengeSigningBytes, - verifyNodePossessionResponse, -} from './node-possession-proof.js'; -import { - nodeRegistrationClaimSigningBytes, - parseNodeRegistrationEndpointRegistry, - resolveNodeRegistrationEndpoint, - verifyNodeRegistrationClaim, -} from './node-registration.js'; -const NOW = 1_786_291_200_000; const DOMAIN_ID = 'DOM-FIFTH-0001'; const NODE_ID = 'JD-FD-PRIMARY'; const NODE_TYPE = 'cloud-resident' as const; -const registrationKeys = generateKeyPairSync('ed25519'); -const nodeKeys = generateKeyPairSync('ed25519'); -const publicKeyPem = nodeKeys.publicKey.export({ format: 'pem', type: 'spki' }).toString(); -const fingerprint = createHash('sha256') - .update(nodeKeys.publicKey.export({ format: 'der', type: 'spki' })) - .digest('hex'); -function verifiedPossession() { - const registry = parseNodeRegistrationEndpointRegistry({ - endpoints: [{ - algorithm: 'Ed25519', - domainIds: [DOMAIN_ID], - endpointId: 'GH-NODE-REG-001', - nodeTypes: [NODE_TYPE], - publicKeyPem: registrationKeys.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: 'a'.repeat(40), - sourceUrl: `https://guanghulab.com/code/bingshuo/guanghu-ice-heart/raw/commit/${'a'.repeat(40)}/routing/node-registration-endpoints.json`, - }); - const endpoint = resolveNodeRegistrationEndpoint(registry, { domainId: DOMAIN_ID, nodeType: NODE_TYPE }); - assert.ok(endpoint); - const payload = { - accountId: 'bingshuo', - claimId: 'NODE-CLAIM-001', - domainId: DOMAIN_ID, - endpointId: endpoint.endpointId, - expiresAt: NOW + 120_000, - issuedAt: NOW - 1_000, - nodeId: NODE_ID, - nodeKeyFingerprint: fingerprint, - nodeType: NODE_TYPE, - schema: 'gh-aios.node-registration-claim/v1' as const, - signerId: endpoint.signerId, - }; - const registration = verifyNodeRegistrationClaim({ - ...payload, - signature: sign(null, nodeRegistrationClaimSigningBytes(payload), registrationKeys.privateKey).toString('base64'), - }, { - accountId: payload.accountId, - domainId: DOMAIN_ID, - nodeId: NODE_ID, - nodeType: NODE_TYPE, - }, endpoint, NOW); - const challenge = createNodePossessionChallenge( - registration, - NOW, - 'NODE-CHALLENGE-001', - 'A'.repeat(43), - ); - const response = { - challengeId: challenge.challengeId, - publicKeyPem, - schema: 'gh-aios.node-possession-response/v1' as const, - signature: sign(null, nodePossessionChallengeSigningBytes(challenge), nodeKeys.privateKey).toString('base64'), - }; - return verifyNodePossessionResponse(response, challenge, registration, NOW + 1); -} - -function response(requestId: string, overrides: Record = {}) { +function response(overrides: Record = {}) { return { schema: 'gh-aios.domain-runtime-handoff-response/v1', handoff: { manifest: { digest: 'untrusted-until-orchestrator-verifies' } }, - request_id: requestId, signer_lookup: { repository_id: 'REPO-014', signer_id: 'GH-LIGHTHOUSE-001', }, - status: 'ISSUED', ...overrides, }; } -test('forwards one exact cryptographic authorization bundle without private material', async () => { +test('adapts one exact endpoint-neutral response without interpreting signed evidence', async () => { const requests: unknown[] = []; const source = new StrictDomainRuntimeHandoffSource({ async request(input) { requests.push(input); - return response(input.requestId); + return response(); }, - }, () => NOW + 2, () => 'HANDOFF-REQ-001'); + }); - const candidate = await source.read(verifiedPossession()); + const candidate = await source.read(DOMAIN_ID, NODE_ID, NODE_TYPE); - assert.equal(requests.length, 1); - assert.deepEqual(Object.keys(requests[0] as object).sort(), [ - 'accountId', 'challenge', 'domainId', 'issuedAt', 'nodeId', 'nodeType', - 'registration', 'requestId', 'response', 'schema', - ]); - assert.equal(JSON.stringify(requests[0]).includes('PRIVATE KEY'), false); + assert.deepEqual(requests, [{ domainId: DOMAIN_ID, nodeId: NODE_ID, nodeType: NODE_TYPE }]); assert.deepEqual(candidate, { handoff: { manifest: { digest: 'untrusted-until-orchestrator-verifies' } }, signerLookup: { repositoryId: 'REPO-014', signerId: 'GH-LIGHTHOUSE-001' }, }); + assert.equal(Object.isFrozen(candidate), true); + assert.equal(Object.isFrozen(candidate?.signerLookup), true); }); -test('binds the response to the generated request and rejects malformed envelopes', async () => { +test('rejects malformed, extended and self-authorizing response envelopes', async () => { const samples = [ null, - response('OTHER-REQ'), - response('HANDOFF-REQ-001', { extra: true }), - response('HANDOFF-REQ-001', { schema: 'other/v1' }), - response('HANDOFF-REQ-001', { signer_lookup: { repository_id: 'REPO-014', signer_id: 'bad signer' } }), - response('HANDOFF-REQ-001', { signer_lookup: { repository_id: 'REPO-014', signer_id: 'GH-LIGHTHOUSE-001', public_key: 'forbidden' } }), - response('HANDOFF-REQ-001', { handoff: null }), - response('HANDOFF-REQ-001', { handoff: null, signer_lookup: null, status: 'NOT_AUTHORIZED' }), + response({ extra: true }), + response({ schema: 'other/v1' }), + response({ signer_lookup: { repository_id: 'REPO-014', signer_id: 'bad signer' } }), + response({ signer_lookup: { repository_id: 'REPO-014', signer_id: 'GH-LIGHTHOUSE-001', public_key: 'forbidden' } }), + response({ handoff: null }), ]; - for (const sample of samples) { - const source = new StrictDomainRuntimeHandoffSource({ async request() { return sample; } }, () => NOW + 2, () => 'HANDOFF-REQ-001'); - assert.equal(await source.read(verifiedPossession()), null); + let index = 0; + const source = new StrictDomainRuntimeHandoffSource({ + async request() { return samples[index++]; }, + }); + + for (const _sample of samples) { + assert.equal(await source.read(DOMAIN_ID, NODE_ID, NODE_TYPE), null); } }); -test('rejects copied, expired and replayed possession authorizations before transport', async () => { +test('fails closed on invalid request identity and transport errors without leaking details', async () => { let requests = 0; - const possession = verifiedPossession(); const source = new StrictDomainRuntimeHandoffSource({ - async request(input) { requests += 1; return response(input.requestId); }, - }, () => NOW + 2, () => 'HANDOFF-REQ-001'); - assert.ok(await source.read(possession)); - assert.equal(await source.read(possession), null); - assert.equal(await source.read({ ...verifiedPossession() }), null); - const expired = new StrictDomainRuntimeHandoffSource({ - async request(input) { requests += 1; return response(input.requestId); }, - }, () => NOW + 60_000, () => 'HANDOFF-REQ-002'); - assert.equal(await expired.read(verifiedPossession()), null); + async request() { + requests += 1; + throw new Error('secret remote detail'); + }, + }); + + assert.equal(await source.read('bad domain', NODE_ID, NODE_TYPE), null); + assert.equal(requests, 0); + assert.equal(await source.read(DOMAIN_ID, NODE_ID, NODE_TYPE), null); + assert.equal(requests, 1); + assert.equal(await source.read(DOMAIN_ID, NODE_ID, 'invalid' as never), null); assert.equal(requests, 1); }); - -test('fails closed on transport errors without exposing remote details', async () => { - const source = new StrictDomainRuntimeHandoffSource({ - async request() { throw new Error('secret remote detail'); }, - }, () => NOW + 2, () => 'HANDOFF-REQ-001'); - assert.equal(await source.read(verifiedPossession()), null); -}); diff --git a/product-source/guanghu-knowledge-base/server/domain-runtime-handoff-source.ts b/product-source/guanghu-knowledge-base/server/domain-runtime-handoff-source.ts index 1d36698fa..30370c229 100644 --- a/product-source/guanghu-knowledge-base/server/domain-runtime-handoff-source.ts +++ b/product-source/guanghu-knowledge-base/server/domain-runtime-handoff-source.ts @@ -2,31 +2,14 @@ import type { DomainRuntimeHandoffCandidate, DomainRuntimeHandoffSource, } from './domain-access-orchestrator.js'; -import { - assertVerifiedNodePossession, - type NodePossessionChallenge, - type NodePossessionResponse, - type VerifiedNodePossession, -} from './node-possession-proof.js'; -import type { VerifiedNodeRegistration } from './node-registration.js'; -import { randomUUID } from 'node:crypto'; +import type { DomainNodeType } from './domain-access.js'; const IDENTIFIER_PATTERN = /^[A-Z0-9][A-Z0-9._:-]{1,159}$/; -const REQUEST_SCHEMA = 'gh-aios.domain-runtime-handoff-request/v1' as const; -const RESPONSE_SCHEMA = 'gh-aios.domain-runtime-handoff-response/v1' as const; -const consumedPossessions = new WeakSet(); export interface DomainRuntimeHandoffRequest { - accountId: string; - challenge: Readonly; domainId: string; - issuedAt: number; nodeId: string; - nodeType: VerifiedNodeRegistration['nodeType']; - registration: Readonly; - requestId: string; - response: Readonly; - schema: typeof REQUEST_SCHEMA; + nodeType: DomainNodeType; } export interface DomainRuntimeHandoffTransport { @@ -43,28 +26,19 @@ function hasExactKeys(value: Record, expected: readonly string[ return actual.length === keys.length && actual.every((key, index) => key === keys[index]); } -function parseResponse( - input: unknown, - request: DomainRuntimeHandoffRequest, -): Readonly | null { +function parseResponse(input: unknown): Readonly | null { if (!isRecord(input) - || !hasExactKeys(input, ['handoff', 'request_id', 'schema', 'signer_lookup', 'status']) - || input.schema !== RESPONSE_SCHEMA - || input.request_id !== request.requestId - || (input.status !== 'ISSUED' && input.status !== 'NOT_AUTHORIZED')) { - return null; - } - if (input.status === 'NOT_AUTHORIZED') { - if (input.handoff !== null || input.signer_lookup !== null) return null; - return null; - } - if (!isRecord(input.handoff) + || !hasExactKeys(input, ['handoff', 'schema', 'signer_lookup']) + || input.schema !== 'gh-aios.domain-runtime-handoff-response/v1' + || !isRecord(input.handoff) || !isRecord(input.signer_lookup) || !hasExactKeys(input.signer_lookup, ['repository_id', 'signer_id']) || typeof input.signer_lookup.repository_id !== 'string' || !IDENTIFIER_PATTERN.test(input.signer_lookup.repository_id) || typeof input.signer_lookup.signer_id !== 'string' - || !IDENTIFIER_PATTERN.test(input.signer_lookup.signer_id)) return null; + || !IDENTIFIER_PATTERN.test(input.signer_lookup.signer_id)) { + return null; + } return Object.freeze({ handoff: input.handoff, signerLookup: Object.freeze({ @@ -75,37 +49,13 @@ function parseResponse( } export class StrictDomainRuntimeHandoffSource implements DomainRuntimeHandoffSource { - constructor( - private readonly transport: DomainRuntimeHandoffTransport, - private readonly clock: () => number = Date.now, - private readonly requestId: () => string = () => `HANDOFF-REQ-${randomUUID().toUpperCase()}`, - ) {} + constructor(private readonly transport: DomainRuntimeHandoffTransport) {} - async read(possession: VerifiedNodePossession): Promise | null> { + async read(domainId: string, nodeId: string, nodeType: DomainNodeType): Promise | null> { + if (!IDENTIFIER_PATTERN.test(domainId) || !IDENTIFIER_PATTERN.test(nodeId)) return null; + if (nodeType !== 'local-terminal' && nodeType !== 'cloud-resident') return null; try { - const verified = assertVerifiedNodePossession(possession); - if (consumedPossessions.has(verified)) return null; - const issuedAt = this.clock(); - const requestId = this.requestId(); - if (!Number.isSafeInteger(issuedAt) - || issuedAt < verified.verifiedAt - || issuedAt >= verified.challenge.expiresAt - || issuedAt >= verified.registration.expiresAt - || !IDENTIFIER_PATTERN.test(requestId)) return null; - const request = Object.freeze({ - accountId: verified.registration.accountId, - challenge: verified.challenge, - domainId: verified.registration.domainId, - issuedAt, - nodeId: verified.registration.nodeId, - nodeType: verified.registration.nodeType, - registration: verified.registration, - requestId, - response: verified.response, - schema: REQUEST_SCHEMA, - }); - consumedPossessions.add(verified); - return parseResponse(await this.transport.request(request), request); + return parseResponse(await this.transport.request(Object.freeze({ domainId, nodeId, nodeType }))); } catch { return null; } diff --git a/product-source/guanghu-knowledge-base/server/node-possession-proof.test.ts b/product-source/guanghu-knowledge-base/server/node-possession-proof.test.ts index f5dd8e230..58b5618b2 100644 --- a/product-source/guanghu-knowledge-base/server/node-possession-proof.test.ts +++ b/product-source/guanghu-knowledge-base/server/node-possession-proof.test.ts @@ -91,10 +91,7 @@ test('verifies a fresh proof from the key fingerprint bound into the signed regi 'A'.repeat(43), ); const response = responseFor(challenge); - const possession = verifyNodePossessionResponse(response, challenge, registration, NOW + 1); - assert.equal(possession.registration, registration); - assert.equal(possession.challenge, challenge); - assert.deepEqual(possession.response, response); + assert.equal(verifyNodePossessionResponse(response, challenge, registration, NOW + 1), true); assert.throws(() => verifyNodePossessionResponse(response, challenge, registration, NOW + 2), /proof_invalid/); }); diff --git a/product-source/guanghu-knowledge-base/server/node-possession-proof.ts b/product-source/guanghu-knowledge-base/server/node-possession-proof.ts index 3315a6700..2cd568222 100644 --- a/product-source/guanghu-knowledge-base/server/node-possession-proof.ts +++ b/product-source/guanghu-knowledge-base/server/node-possession-proof.ts @@ -17,7 +17,6 @@ const IDENTIFIER_PATTERN = /^[A-Z0-9][A-Z0-9._:-]{1,159}$/; const NONCE_PATTERN = /^[A-Za-z0-9_-]{43}$/; const issuedChallenges = new WeakSet(); const consumedChallenges = new WeakSet(); -const verifiedPossessions = new WeakSet(); export interface NodePossessionChallenge { accountId: string; @@ -44,13 +43,6 @@ export interface NodePossessionProofSource { prove(challenge: Readonly): Promise; } -export interface VerifiedNodePossession { - challenge: Readonly; - registration: Readonly; - response: Readonly; - verifiedAt: number; -} - function invalidProof(): never { throw new Error('node_possession_proof_invalid'); } @@ -121,7 +113,7 @@ export function verifyNodePossessionResponse( challenge: NodePossessionChallenge, registration: VerifiedNodeRegistration, now = Date.now(), -): Readonly { +): true { try { assertVerifiedNodeRegistration(registration); } catch { @@ -148,11 +140,7 @@ export function verifyNodePossessionResponse( || input.publicKeyPem.includes('PRIVATE KEY') || typeof input.signature !== 'string') invalidProof(); - let publicKeyPem: string; - let signatureText: string; try { - publicKeyPem = input.publicKeyPem as string; - signatureText = input.signature as string; const publicKey = createPublicKey({ key: input.publicKeyPem, format: 'pem' }); if (publicKey.asymmetricKeyType !== 'ed25519') invalidProof(); const fingerprint = createHash('sha256') @@ -166,24 +154,5 @@ export function verifyNodePossessionResponse( invalidProof(); } consumedChallenges.add(challenge); - const verified = Object.freeze({ - challenge, - registration, - response: Object.freeze({ - challengeId: challenge.challengeId, - publicKeyPem: publicKeyPem!, - schema: RESPONSE_SCHEMA, - signature: signatureText!, - }), - verifiedAt: now, - }); - verifiedPossessions.add(verified); - return verified; -} - -export function assertVerifiedNodePossession( - possession: VerifiedNodePossession, -): VerifiedNodePossession { - if (!verifiedPossessions.has(possession)) invalidProof(); - return possession; + return true; } 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 0a660c392..ab72b5965 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 @@ -79,23 +79,3 @@ 运行体交接。当前桌面尚无生产节点密钥库桥,正式运行源固定返回无证明,因此即使未来出现一份 有效登记声明,也不能越过 `verified_node_possession_missing`。代码验证器存在不等于节点密钥、 生产密钥库桥、灯塔会话签发或域连接已经存在。 - -## 私钥证明到域交接的证据链 · 阶段 004 - -本地布尔值 `nodePossessionVerified=true` 不能作为灯塔签发域会话的请求证据。节点证明验证器 -现在生成进程内不可伪造的 `VerifiedNodePossession`:包含已验证登记声明、一次性挑战、节点 -签名响应和验证时间,并通过内部来源集合阻止调用方复制字段冒充验证结果。 - -域运行体交接源只接受这个验证对象,并构造固定 -`gh-aios.domain-runtime-handoff-request/v1` 请求包:账号、域、节点编号、节点类型、完整签名 -登记声明、挑战、节点响应、一次性请求编号和请求时间。它不包含账号密码、访问令牌、验证码 -或节点私钥。每份节点证明最多发起一次交接请求;失败重试必须重新完成新挑战,不能重放旧证明。 - -响应固定为 `gh-aios.domain-runtime-handoff-response/v1`,并必须回绑请求编号。只允许 -`ISSUED + handoff + signer_lookup` 或 `NOT_AUTHORIZED + null + null`。客户端仍须使用当前 -REPO-012 信任快照独立验证 handoff 中的域清单签名、短期会话能力和在线连接回执;服务端 -返回的 signer 名称、公钥字段或自授权布尔值都不能成为信任来源。 - -本阶段闭合的是“证明能够被带到交接边界”的客户端证据结构,不是生产 HTTP 端点。当前公共 -锚点没有域交接端点注册表,桌面运行源仍返回空结果,因此生产会话签发、域运行体连接与在线 -回执继续为 `NOT_EXISTS_0`。 diff --git a/product-source/hololake-platform/architecture/README.md b/product-source/hololake-platform/architecture/README.md index b59f51e8c..37241d6cc 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):账号、签名节点登记与当前节点私钥持有证明分离后的端点注册表、无凭据声明读取、60 秒一次性 Ed25519 挑战、不可伪造交接证据包、失败关闭和当前生产缺口验收基线。 +- [`HOLOLAKE-NODE-REGISTRATION-CONTRACT-20260810.md`](HOLOLAKE-NODE-REGISTRATION-CONTRACT-20260810.md):账号、签名节点登记与当前节点私钥持有证明分离后的端点注册表、无凭据声明读取、60 秒一次性 Ed25519 挑战、失败关闭和当前生产缺口验收基线。 - [`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 历史意图层,继续保存形成过程;不再作为当前默认入口。