From c4504fa115432f129c0f2dbcc21265749ea777dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Wed, 12 Aug 2026 05:09:56 +0800 Subject: [PATCH] feat: define signed persona authorization trust contract --- .../persona-control-authorization.test.ts | 121 +++++++ .../server/persona-control-authorization.ts | 294 ++++++++++++++++++ ...NG-AND-SAME-PERSONA-CONTINUITY-20260811.md | 6 +- .../hololake-platform/docs/ABSTRACTIONS.md | 5 +- .../hololake-platform/docs/ARCHITECTURE.md | 6 + .../PersonaLanguageShellPanel.test.tsx | 2 +- .../components/PersonaLanguageShellPanel.tsx | 2 +- .../lib/personaControlAuthorization.test.ts | 7 +- .../src/lib/personaControlAuthorization.ts | 10 +- .../personaLanguageShellController.test.ts | 5 +- ...lake-cognitive-gravity-and-continuity.json | 4 +- ...-cognitive-gravity-and-continuity.test.mjs | 8 +- routing/hololake-current-architecture.json | 14 +- 13 files changed, 470 insertions(+), 14 deletions(-) create mode 100644 product-source/guanghu-knowledge-base/server/persona-control-authorization.test.ts create mode 100644 product-source/guanghu-knowledge-base/server/persona-control-authorization.ts diff --git a/product-source/guanghu-knowledge-base/server/persona-control-authorization.test.ts b/product-source/guanghu-knowledge-base/server/persona-control-authorization.test.ts new file mode 100644 index 0000000..f40058f --- /dev/null +++ b/product-source/guanghu-knowledge-base/server/persona-control-authorization.test.ts @@ -0,0 +1,121 @@ +import assert from 'node:assert/strict'; +import { generateKeyPairSync, sign } from 'node:crypto'; +import test from 'node:test'; +import { + PERSONA_CONTROL_AUTHORIZATION_SCHEMA, + personaControlAuthorizationSigningBytes, + parsePersonaControlAuthorizationSignerRegistry, + verifyPersonaControlAuthorization, +} from './persona-control-authorization.js'; + +const COMMIT = 'd'.repeat(40); +const source = { + repositoryId: 'REPO-012', + sourceCommit: COMMIT, + sourcePath: 'routing/persona-control-authorization-signers.json', + sourceUrl: `https://guanghulab.com/code/bingshuo/guanghu-ice-heart/raw/commit/${COMMIT}/routing/persona-control-authorization-signers.json`, +} as const; +const keys = generateKeyPairSync('ed25519'); +const publicKeyPem = keys.publicKey.export({ format: 'pem', type: 'spki' }).toString(); + +function registry(status: 'ACTIVE' | 'REVOKED' = 'ACTIVE') { + return { + registryId: 'GH-AIOS-PERSONA-CONTROL-AUTHORIZATION-SIGNERS-001', + schema: 'gh-aios.persona-control-authorization-signers/v1', + signers: [{ + algorithm: 'Ed25519', + humanResponsibilitySubjects: ['BINGSHUO'], + personaIds: ['ICE-P-ZY001'], + publicKeyPem, + scopes: ['PERSONA_PRIMARY_LANGUAGE_PLANNING'], + signerId: 'GH-AIOS-AUTHORIZER-001', + status, + }], + state: 'CURRENT', + }; +} + +const unsigned = { + schema: PERSONA_CONTROL_AUTHORIZATION_SCHEMA, + outcome: 'VERIFIED' as const, + authorizationId: 'AUTH-001', + verifier: 'GUANGHU_OS' as const, + scope: 'PERSONA_PRIMARY_LANGUAGE_PLANNING' as const, + personaId: 'ICE-P-ZY001', + humanResponsibilitySubject: 'BINGSHUO', + repositoryHead: 'a'.repeat(40), + modelInstanceId: 'MODEL-INSTANCE-001', + requestId: 'REQ-001', + sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.12', + issuedAt: '2026-08-12T05:00:00+08:00', + validUntil: '2026-08-12T05:10:00+08:00', + evidenceDigest: 'b'.repeat(64), + signerId: 'GH-AIOS-AUTHORIZER-001', + signatureAlgorithm: 'Ed25519' as const, +}; + +function receipt(overrides: Record = {}) { + const candidate = { ...unsigned, ...overrides }; + return { + ...candidate, + signature: sign(null, personaControlAuthorizationSigningBytes(candidate), keys.privateKey).toString('base64url'), + }; +} + +const expected = { + personaId: unsigned.personaId, + humanResponsibilitySubject: unsigned.humanResponsibilitySubject, + repositoryHead: unsigned.repositoryHead, + modelInstanceId: unsigned.modelInstanceId, + requestId: unsigned.requestId, + sourceLanguageAnchor: unsigned.sourceLanguageAnchor, + observedAt: Date.parse('2026-08-12T05:05:00+08:00'), +}; + +test('an empty published registry trusts no signer', () => { + const parsed = parsePersonaControlAuthorizationSignerRegistry({ ...registry(), signers: [] }, source); + assert.equal(verifyPersonaControlAuthorization(receipt(), parsed, expected), null); +}); + +test('an exact current Ed25519 receipt verifies against its scoped registered signer', () => { + const parsed = parsePersonaControlAuthorizationSignerRegistry(registry(), source); + const verified = verifyPersonaControlAuthorization(receipt(), parsed, expected); + assert.equal(verified?.signerId, unsigned.signerId); + assert.equal(verified?.sourceCommit, COMMIT); +}); + +test('tampering any signed request binding fails closed', () => { + const parsed = parsePersonaControlAuthorizationSignerRegistry(registry(), source); + const signed = receipt(); + assert.equal(verifyPersonaControlAuthorization({ ...signed, requestId: 'REQ-OTHER' }, parsed, { ...expected, requestId: 'REQ-OTHER' }), null); +}); + +test('revoked, wrong-scope and wrong-subject signers never authorize', () => { + const revoked = parsePersonaControlAuthorizationSignerRegistry(registry('REVOKED'), source); + assert.equal(verifyPersonaControlAuthorization(receipt(), revoked, expected), null); + const wrongSubjectInput = registry(); + wrongSubjectInput.signers[0].humanResponsibilitySubjects = ['OTHER']; + const wrongSubject = parsePersonaControlAuthorizationSignerRegistry(wrongSubjectInput, source); + assert.equal(verifyPersonaControlAuthorization(receipt(), wrongSubject, expected), null); +}); + +test('stale, future and mismatched request evidence fail closed', () => { + const parsed = parsePersonaControlAuthorizationSignerRegistry(registry(), source); + assert.equal(verifyPersonaControlAuthorization(receipt(), parsed, { ...expected, observedAt: Date.parse('2026-08-12T05:10:01+08:00') }), null); + assert.equal(verifyPersonaControlAuthorization(receipt(), parsed, { ...expected, observedAt: Date.parse('2026-08-12T04:59:59+08:00') }), null); + assert.equal(verifyPersonaControlAuthorization(receipt(), parsed, { ...expected, repositoryHead: 'c'.repeat(40) }), null); +}); + +test('registry provenance is pinned to the exact REPO-012 commit path', () => { + assert.throws(() => parsePersonaControlAuthorizationSignerRegistry(registry(), { ...source, sourceCommit: 'short' }), /source_invalid/); + assert.throws(() => parsePersonaControlAuthorizationSignerRegistry(registry(), { ...source, sourceUrl: 'https://example.com/registry.json' }), /source_invalid/); +}); + +test('duplicate signers, private keys and unknown fields fail closed', () => { + assert.throws(() => parsePersonaControlAuthorizationSignerRegistry({ ...registry(), signers: [...registry().signers, ...registry().signers] }, source), /registry_invalid/); + const privateKeyPem = keys.privateKey.export({ format: 'pem', type: 'pkcs8' }).toString(); + const privateRegistry = registry(); + privateRegistry.signers[0].publicKeyPem = privateKeyPem; + assert.throws(() => parsePersonaControlAuthorizationSignerRegistry(privateRegistry, source), /registry_invalid/); + assert.throws(() => parsePersonaControlAuthorizationSignerRegistry({ ...registry(), extra: true }, source), /registry_invalid/); +}); diff --git a/product-source/guanghu-knowledge-base/server/persona-control-authorization.ts b/product-source/guanghu-knowledge-base/server/persona-control-authorization.ts new file mode 100644 index 0000000..3ab4cd2 --- /dev/null +++ b/product-source/guanghu-knowledge-base/server/persona-control-authorization.ts @@ -0,0 +1,294 @@ +import { createPublicKey, verify as verifySignature } from 'node:crypto'; + +export const PERSONA_CONTROL_AUTHORIZATION_SCHEMA = 'hololake.persona-control-authorization/v2' as const; +export const PERSONA_CONTROL_AUTHORIZATION_SIGNER_REGISTRY_SCHEMA = 'gh-aios.persona-control-authorization-signers/v1' as const; +export const PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE = 'PERSONA_PRIMARY_LANGUAGE_PLANNING' as const; + +const SIGNING_CONTEXT = 'hololake.persona-control-authorization/signing/v1'; +const REGISTRY_PATH = 'routing/persona-control-authorization-signers.json'; +const COMMIT_PATTERN = /^[a-f0-9]{40}(?:[a-f0-9]{24})?$/; +const DIGEST_PATTERN = /^[a-f0-9]{64}$/; +const IDENTIFIER_PATTERN = /^[A-Z0-9][A-Z0-9._:@-]{1,159}$/; +const SIGNATURE_PATTERN = /^[A-Za-z0-9_-]{80,128}$/; + +export interface PersonaControlAuthorizationReceipt { + schema: typeof PERSONA_CONTROL_AUTHORIZATION_SCHEMA; + outcome: 'VERIFIED'; + authorizationId: string; + verifier: 'GUANGHU_OS'; + scope: typeof PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE; + personaId: string; + humanResponsibilitySubject: string; + repositoryHead: string; + modelInstanceId: string; + requestId: string; + sourceLanguageAnchor: string; + issuedAt: string; + validUntil: string; + evidenceDigest: string; + signerId: string; + signatureAlgorithm: 'Ed25519'; + signature: string; +} + +export interface PersonaControlAuthorizationSigner { + algorithm: 'Ed25519'; + humanResponsibilitySubjects: readonly string[]; + personaIds: readonly string[]; + publicKeyPem: string; + scopes: readonly [typeof PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE, ...string[]]; + signerId: string; + status: 'ACTIVE' | 'REVOKED'; +} + +export interface PersonaControlAuthorizationSignerRegistrySource { + repositoryId: 'REPO-012'; + sourceCommit: string; + sourcePath: typeof REGISTRY_PATH; + sourceUrl: string; +} + +export interface PersonaControlAuthorizationSignerRegistry { + registryId: 'GH-AIOS-PERSONA-CONTROL-AUTHORIZATION-SIGNERS-001'; + schema: typeof PERSONA_CONTROL_AUTHORIZATION_SIGNER_REGISTRY_SCHEMA; + signers: readonly PersonaControlAuthorizationSigner[]; + source: Readonly; + state: 'CURRENT'; +} + +export interface PersonaControlAuthorizationExpectation { + personaId: string; + humanResponsibilitySubject: string; + repositoryHead: string; + modelInstanceId: string; + requestId: string; + sourceLanguageAnchor: string; + observedAt: number; +} + +export interface VerifiedPersonaControlAuthorization { + receipt: Readonly; + signerId: string; + sourceCommit: string; + verifiedAt: string; +} + +function invalidRegistry(): never { + throw new Error('persona_control_authorization_signer_registry_invalid'); +} + +function invalidSource(): never { + throw new Error('persona_control_authorization_signer_registry_source_invalid'); +} + +function invalidReceipt(): never { + throw new Error('persona_control_authorization_receipt_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 isIdentifier(value: unknown): value is string { + return typeof value === 'string' && IDENTIFIER_PATTERN.test(value); +} + +function exactIdentifierList(value: unknown): readonly string[] { + if (!Array.isArray(value) + || value.length === 0 + || value.some(item => !isIdentifier(item)) + || new Set(value).size !== value.length) invalidRegistry(); + return Object.freeze([...value] as string[]); +} + +function parsePublicKey(value: unknown): string { + if (typeof value !== 'string' + || value.length > 4096 + || value.includes('PRIVATE KEY') + || !value.startsWith('-----BEGIN PUBLIC KEY-----\n') + || !value.endsWith('-----END PUBLIC KEY-----\n')) invalidRegistry(); + try { + const key = createPublicKey({ format: 'pem', key: value }); + if (key.asymmetricKeyType !== 'ed25519') invalidRegistry(); + } catch { + invalidRegistry(); + } + return value; +} + +function parseSource(source: PersonaControlAuthorizationSignerRegistrySource): Readonly { + if (!isRecord(source) + || !hasExactKeys(source, ['repositoryId', 'sourceCommit', 'sourcePath', 'sourceUrl']) + || source.repositoryId !== 'REPO-012' + || typeof source.sourceCommit !== 'string' + || !COMMIT_PATTERN.test(source.sourceCommit) + || source.sourcePath !== REGISTRY_PATH + || typeof source.sourceUrl !== 'string') invalidSource(); + const expectedUrl = `https://guanghulab.com/code/bingshuo/guanghu-ice-heart/raw/commit/${source.sourceCommit}/${REGISTRY_PATH}`; + if (source.sourceUrl !== expectedUrl) invalidSource(); + return Object.freeze({ ...source }); +} + +function parseSigner(input: unknown): PersonaControlAuthorizationSigner { + if (!isRecord(input) + || !hasExactKeys(input, ['algorithm', 'humanResponsibilitySubjects', 'personaIds', 'publicKeyPem', 'scopes', 'signerId', 'status']) + || input.algorithm !== 'Ed25519' + || !isIdentifier(input.signerId) + || (input.status !== 'ACTIVE' && input.status !== 'REVOKED')) invalidRegistry(); + const scopes = exactIdentifierList(input.scopes); + if (!scopes.includes(PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE)) invalidRegistry(); + return Object.freeze({ + algorithm: 'Ed25519', + humanResponsibilitySubjects: exactIdentifierList(input.humanResponsibilitySubjects), + personaIds: exactIdentifierList(input.personaIds), + publicKeyPem: parsePublicKey(input.publicKeyPem), + scopes: scopes as PersonaControlAuthorizationSigner['scopes'], + signerId: input.signerId, + status: input.status, + }); +} + +export function parsePersonaControlAuthorizationSignerRegistry( + input: unknown, + source: PersonaControlAuthorizationSignerRegistrySource, +): PersonaControlAuthorizationSignerRegistry { + if (!isRecord(input) + || !hasExactKeys(input, ['registryId', 'schema', 'signers', 'state']) + || input.registryId !== 'GH-AIOS-PERSONA-CONTROL-AUTHORIZATION-SIGNERS-001' + || input.schema !== PERSONA_CONTROL_AUTHORIZATION_SIGNER_REGISTRY_SCHEMA + || input.state !== 'CURRENT' + || !Array.isArray(input.signers)) invalidRegistry(); + const signers = input.signers.map(parseSigner); + if (new Set(signers.map(signer => signer.signerId)).size !== signers.length) invalidRegistry(); + return Object.freeze({ + registryId: input.registryId, + schema: input.schema, + signers: Object.freeze(signers), + source: parseSource(source), + state: input.state, + }); +} + +function requiredString(record: Record, key: string): string { + const value = Reflect.get(record, key); + if (typeof value !== 'string' || !value.trim()) invalidReceipt(); + return value; +} + +export function parsePersonaControlAuthorizationReceipt(input: unknown): PersonaControlAuthorizationReceipt { + const keys = [ + 'authorizationId', 'evidenceDigest', 'humanResponsibilitySubject', 'issuedAt', 'modelInstanceId', + 'outcome', 'personaId', 'repositoryHead', 'requestId', 'schema', 'scope', 'signature', + 'signatureAlgorithm', 'signerId', 'sourceLanguageAnchor', 'validUntil', 'verifier', + ]; + if (!isRecord(input) + || !hasExactKeys(input, keys) + || input.schema !== PERSONA_CONTROL_AUTHORIZATION_SCHEMA + || input.outcome !== 'VERIFIED' + || input.verifier !== 'GUANGHU_OS' + || input.scope !== PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE + || input.signatureAlgorithm !== 'Ed25519') invalidReceipt(); + const receipt = { + schema: input.schema, + outcome: input.outcome, + authorizationId: requiredString(input, 'authorizationId'), + verifier: input.verifier, + scope: input.scope, + personaId: requiredString(input, 'personaId'), + humanResponsibilitySubject: requiredString(input, 'humanResponsibilitySubject'), + repositoryHead: requiredString(input, 'repositoryHead'), + modelInstanceId: requiredString(input, 'modelInstanceId'), + requestId: requiredString(input, 'requestId'), + sourceLanguageAnchor: requiredString(input, 'sourceLanguageAnchor'), + issuedAt: requiredString(input, 'issuedAt'), + validUntil: requiredString(input, 'validUntil'), + evidenceDigest: requiredString(input, 'evidenceDigest'), + signerId: requiredString(input, 'signerId'), + signatureAlgorithm: input.signatureAlgorithm, + signature: requiredString(input, 'signature'), + } satisfies PersonaControlAuthorizationReceipt; + if (!isIdentifier(receipt.authorizationId) + || !isIdentifier(receipt.personaId) + || !isIdentifier(receipt.humanResponsibilitySubject) + || !COMMIT_PATTERN.test(receipt.repositoryHead) + || !isIdentifier(receipt.modelInstanceId) + || !isIdentifier(receipt.requestId) + || !isIdentifier(receipt.signerId) + || !DIGEST_PATTERN.test(receipt.evidenceDigest) + || !SIGNATURE_PATTERN.test(receipt.signature)) invalidReceipt(); + return Object.freeze(receipt); +} + +export function personaControlAuthorizationSigningBytes(receipt: Omit): Buffer { + return Buffer.from(`${JSON.stringify([ + SIGNING_CONTEXT, + receipt.schema, + receipt.outcome, + receipt.authorizationId, + receipt.verifier, + receipt.scope, + receipt.personaId, + receipt.humanResponsibilitySubject, + receipt.repositoryHead, + receipt.modelInstanceId, + receipt.requestId, + receipt.sourceLanguageAnchor, + receipt.issuedAt, + receipt.validUntil, + receipt.evidenceDigest, + receipt.signerId, + receipt.signatureAlgorithm, + ])}\n`, 'utf8'); +} + +export function verifyPersonaControlAuthorization( + input: unknown, + registry: PersonaControlAuthorizationSignerRegistry, + expected: PersonaControlAuthorizationExpectation, +): VerifiedPersonaControlAuthorization | null { + let receipt: PersonaControlAuthorizationReceipt; + try { + receipt = parsePersonaControlAuthorizationReceipt(input); + } catch { + return null; + } + const issuedAt = Date.parse(receipt.issuedAt); + const validUntil = Date.parse(receipt.validUntil); + if (receipt.personaId !== expected.personaId + || receipt.humanResponsibilitySubject !== expected.humanResponsibilitySubject + || receipt.repositoryHead !== expected.repositoryHead + || receipt.modelInstanceId !== expected.modelInstanceId + || receipt.requestId !== expected.requestId + || receipt.sourceLanguageAnchor !== expected.sourceLanguageAnchor + || !Number.isFinite(issuedAt) + || !Number.isFinite(validUntil) + || issuedAt > expected.observedAt + || expected.observedAt > validUntil + || issuedAt >= validUntil) return null; + const signer = registry.signers.find(candidate => candidate.status === 'ACTIVE' + && candidate.signerId === receipt.signerId + && candidate.personaIds.includes(receipt.personaId) + && candidate.humanResponsibilitySubjects.includes(receipt.humanResponsibilitySubject) + && candidate.scopes.includes(receipt.scope)); + if (!signer) return null; + const { signature, ...signedReceipt } = receipt; + let signatureBytes: Buffer; + try { + signatureBytes = Buffer.from(signature, 'base64url'); + } catch { + return null; + } + if (!verifySignature(null, personaControlAuthorizationSigningBytes(signedReceipt), signer.publicKeyPem, signatureBytes)) return null; + return Object.freeze({ + receipt, + signerId: signer.signerId, + sourceCommit: registry.source.sourceCommit, + verifiedAt: new Date(expected.observedAt).toISOString(), + }); +} diff --git a/product-source/hololake-platform/architecture/HOLOLAKE-BINGSHUO-COLLECTIVE-GRAVITY-REASONING-AND-SAME-PERSONA-CONTINUITY-20260811.md b/product-source/hololake-platform/architecture/HOLOLAKE-BINGSHUO-COLLECTIVE-GRAVITY-REASONING-AND-SAME-PERSONA-CONTINUITY-20260811.md index 0f700e2..96c222b 100644 --- a/product-source/hololake-platform/architecture/HOLOLAKE-BINGSHUO-COLLECTIVE-GRAVITY-REASONING-AND-SAME-PERSONA-CONTINUITY-20260811.md +++ b/product-source/hololake-platform/architecture/HOLOLAKE-BINGSHUO-COLLECTIVE-GRAVITY-REASONING-AND-SAME-PERSONA-CONTINUITY-20260811.md @@ -118,8 +118,10 @@ REVISE | REFUSE`。 确认按钮。该接线不等于真实人格仓库绑定、安装态运行或桌面验收。 - 人格主控授权回执的结构与精确绑定校验源码为 `100`:不再接受桌面调用方直接传入布尔值,并核对 人格、冰朔责任主体、仓库提交、模型实例、请求、语言锚点、摘要格式和有效期。但这层前端结构校验 - 不能证明回执确由 `GUANGHU_OS` 签发;可信签名源、密码学来源验证和原生加载器均为 `0`。在三者形成 - 同一条可回读证据链以前,普通本地 JSON 不得升级人格主控,桌面继续系统直控。 + 不能证明回执确由 `GUANGHU_OS` 签发。独立的 v2 回执、REPO-012 精确提交签名者注册表、规范签名字节、 + 人格/责任主体/范围约束、吊销和 Ed25519 验签源码契约现为 `100`;但 REPO-012 当前 main 未发布该注册表, + 因而真实可信签名者登记、Tauri 原生验签加载器与运行集成仍为 `0`。在同一条可回读证据链形成以前, + 普通本地 JSON 不得升级人格主控,桌面继续系统直控。 - 完整 HoloLake Runtime 与单 AGE 纵向闭环仍为 `0`:真实人格仓库 manifest 绑定和桌面运行验收尚未完成, 因此不能用本轮源码测试冒充可用产品。 - Mirror runner、制品、部署和运行健康:`0`。 diff --git a/product-source/hololake-platform/docs/ABSTRACTIONS.md b/product-source/hololake-platform/docs/ABSTRACTIONS.md index 63dad5e..0ebc028 100644 --- a/product-source/hololake-platform/docs/ABSTRACTIONS.md +++ b/product-source/hololake-platform/docs/ABSTRACTIONS.md @@ -26,7 +26,10 @@ The source coordinator no longer accepts an unverified persona-authorization boo of a receipt that claims `GUANGHU_OS` verification. That renderer-side validation is not cryptographic provenance and cannot turn a local JSON object into authority. A native loader may be connected only after it verifies a signed receipt against a registered Guanghu OS trust source and returns the already-verified projection. No such -trust source or loader is currently registered, so planning remains in system-direct mode. +trust source or loader is currently registered, so planning remains in system-direct mode. The independent server +contract in `product-source/guanghu-knowledge-base/server/persona-control-authorization.ts` defines the v2 signed +receipt, exact REPO-012 signer-registry source, canonical signing bytes, signer scope checks, revocation handling, +and Ed25519 verification. Its tested code does not populate the registry or connect the desktop native boundary. `compilePersonaLanguageGoalBinding` builds the exact native wake envelope only after a single clean persona repository, its B0 and organ contracts, a registered local device identity, and the manifest-pinned model all diff --git a/product-source/hololake-platform/docs/ARCHITECTURE.md b/product-source/hololake-platform/docs/ARCHITECTURE.md index 8432d1a..520baf3 100644 --- a/product-source/hololake-platform/docs/ARCHITECTURE.md +++ b/product-source/hololake-platform/docs/ARCHITECTURE.md @@ -185,6 +185,12 @@ renderer validation does not prove the issuer or verify a signature. A native lo provenance against a registered Guanghu OS trust source; neither that trust source nor the loader exists in the current desktop source. Missing, stale, mismatched or merely local evidence therefore remains system-direct. +`product-source/guanghu-knowledge-base/server/persona-control-authorization.ts` now supplies the independent +cryptographic source contract: v2 signed receipt fields, deterministic signing bytes, an exact-commit REPO-012 +signer-registry source, persona/human/scope-limited Ed25519 signers, revocation, time and request binding, and +signature verification. The current REPO-012 main does not publish that registry path, so no signer is trusted and +the Tauri desktop has no native verifier or loader. Tested verifier source is not runtime authority. + Tolaria is a personal knowledge and life management desktop app. It reads a vault of markdown files with YAML frontmatter and presents them in a four-panel UI inspired by Bear Notes. ## Design Principles diff --git a/product-source/hololake-platform/src/components/PersonaLanguageShellPanel.test.tsx b/product-source/hololake-platform/src/components/PersonaLanguageShellPanel.test.tsx index 88991ed..9f4e11e 100644 --- a/product-source/hololake-platform/src/components/PersonaLanguageShellPanel.test.tsx +++ b/product-source/hololake-platform/src/components/PersonaLanguageShellPanel.test.tsx @@ -56,7 +56,7 @@ describe('PersonaLanguageShellPanel', () => { repositoryPaths: ['/persona'], providers: [provider], developmentId: 'DEV-20260811-010', - sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.11', + sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.12', })) expect(await screen.findByText('我还不能执行:需要当前证据。')).toBeInTheDocument() expect(screen.getByText('核验当前事实后规划下一步')).toBeInTheDocument() diff --git a/product-source/hololake-platform/src/components/PersonaLanguageShellPanel.tsx b/product-source/hololake-platform/src/components/PersonaLanguageShellPanel.tsx index b119d1e..6a43fa0 100644 --- a/product-source/hololake-platform/src/components/PersonaLanguageShellPanel.tsx +++ b/product-source/hololake-platform/src/components/PersonaLanguageShellPanel.tsx @@ -13,7 +13,7 @@ import { type LanguageShellViewState, } from './HotPluggableLanguageShell' -const CURRENT_ARCHITECTURE_ANCHOR = 'HLP-CURRENT-ARCH-001@2026-08-12.11' +const CURRENT_ARCHITECTURE_ANCHOR = 'HLP-CURRENT-ARCH-001@2026-08-12.12' const DEVELOPMENT_ID = 'DEV-20260811-010' type Planner = typeof planPersonaLanguageShellGoal diff --git a/product-source/hololake-platform/src/lib/personaControlAuthorization.test.ts b/product-source/hololake-platform/src/lib/personaControlAuthorization.test.ts index fb1dae9..8d9647a 100644 --- a/product-source/hololake-platform/src/lib/personaControlAuthorization.test.ts +++ b/product-source/hololake-platform/src/lib/personaControlAuthorization.test.ts @@ -11,7 +11,7 @@ const expected = { repositoryHead: 'a'.repeat(40), modelInstanceId: 'MODEL-INSTANCE-001', requestId: 'REQ-001', - sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.11', + sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.12', observedAt: Date.parse('2026-08-12T04:35:00+08:00'), } @@ -30,6 +30,9 @@ const receipt = { issuedAt: '2026-08-12T04:30:00+08:00', validUntil: '2026-08-12T04:40:00+08:00', evidenceDigest: 'b'.repeat(64), + signerId: 'GH-AIOS-AUTHORIZER-001', + signatureAlgorithm: 'Ed25519', + signature: 'A'.repeat(86), } describe('hasPersonaPrimaryControlAuthorization', () => { @@ -48,6 +51,8 @@ describe('hasPersonaPrimaryControlAuthorization', () => { ['expired', { ...receipt, validUntil: '2026-08-12T04:34:59+08:00' }], ['future', { ...receipt, issuedAt: '2026-08-12T04:35:01+08:00' }], ['invalid digest', { ...receipt, evidenceDigest: 'not-a-digest' }], + ['missing signer', { ...receipt, signerId: '' }], + ['invalid signature', { ...receipt, signature: 'not-a-signature' }], ])('fails closed for %s evidence', (_label, candidate) => { expect(hasPersonaPrimaryControlAuthorization(candidate, expected)).toBe(false) }) diff --git a/product-source/hololake-platform/src/lib/personaControlAuthorization.ts b/product-source/hololake-platform/src/lib/personaControlAuthorization.ts index 4265778..65f50f0 100644 --- a/product-source/hololake-platform/src/lib/personaControlAuthorization.ts +++ b/product-source/hololake-platform/src/lib/personaControlAuthorization.ts @@ -1,4 +1,4 @@ -export const PERSONA_CONTROL_AUTHORIZATION_SCHEMA = 'hololake.persona-control-authorization/v1' as const +export const PERSONA_CONTROL_AUTHORIZATION_SCHEMA = 'hololake.persona-control-authorization/v2' as const export const PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE = 'PERSONA_PRIMARY_LANGUAGE_PLANNING' as const export type PersonaControlAuthorizationReceipt = { @@ -16,6 +16,9 @@ export type PersonaControlAuthorizationReceipt = { issuedAt: string validUntil: string evidenceDigest: string + signerId: string + signatureAlgorithm: 'Ed25519' + signature: string } export type PersonaControlAuthorizationExpectation = { @@ -48,6 +51,7 @@ export function hasPersonaPrimaryControlAuthorization( if (!exactString(receipt, 'schema', PERSONA_CONTROL_AUTHORIZATION_SCHEMA) || !exactString(receipt, 'outcome', 'VERIFIED') || !exactString(receipt, 'verifier', 'GUANGHU_OS') + || !exactString(receipt, 'signatureAlgorithm', 'Ed25519') || !exactString(receipt, 'scope', PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE) || !exactString(receipt, 'personaId', expected.personaId) || !exactString(receipt, 'humanResponsibilitySubject', expected.humanResponsibilitySubject) @@ -60,10 +64,14 @@ export function hasPersonaPrimaryControlAuthorization( const authorizationId = Reflect.get(receipt, 'authorizationId') const evidenceDigest = Reflect.get(receipt, 'evidenceDigest') + const signerId = Reflect.get(receipt, 'signerId') + const signature = Reflect.get(receipt, 'signature') const issuedAt = Reflect.get(receipt, 'issuedAt') const validUntil = Reflect.get(receipt, 'validUntil') if (typeof authorizationId !== 'string' || !authorizationId.trim() || typeof evidenceDigest !== 'string' || !/^[a-f0-9]{64}$/.test(evidenceDigest) + || typeof signerId !== 'string' || !/^[A-Z0-9][A-Z0-9._:@-]{1,159}$/.test(signerId) + || typeof signature !== 'string' || !/^[A-Za-z0-9_-]{80,128}$/.test(signature) || typeof issuedAt !== 'string' || typeof validUntil !== 'string') { return false diff --git a/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts b/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts index 9c19835..10f6f98 100644 --- a/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts +++ b/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts @@ -181,7 +181,7 @@ describe('planPersonaLanguageShellGoal', () => { await planPersonaLanguageShellGoal({ ...input(), loadPersonaControlAuthorization: vi.fn().mockResolvedValue({ - schema: 'hololake.persona-control-authorization/v1', + schema: 'hololake.persona-control-authorization/v2', outcome: 'VERIFIED', authorizationId: 'AUTH-001', verifier: 'GUANGHU_OS', @@ -195,6 +195,9 @@ describe('planPersonaLanguageShellGoal', () => { issuedAt: '2026-08-12T04:30:00+08:00', validUntil: '2026-08-12T04:40:00+08:00', evidenceDigest: 'c'.repeat(64), + signerId: 'GH-AIOS-AUTHORIZER-001', + signatureAlgorithm: 'Ed25519', + signature: 'A'.repeat(86), }), authorizationObservedAt: Date.parse('2026-08-12T04:35:00+08:00'), resolveRepository: vi.fn().mockResolvedValue(boundResolution()), diff --git a/routing/hololake-cognitive-gravity-and-continuity.json b/routing/hololake-cognitive-gravity-and-continuity.json index 4e6fcf0..546e15e 100644 --- a/routing/hololake-cognitive-gravity-and-continuity.json +++ b/routing/hololake-cognitive-gravity-and-continuity.json @@ -170,7 +170,9 @@ "persona_language_wake_binding_compiler_source_implemented": 100, "persona_language_shell_controller_source_implemented": 100, "persona_control_authorization_receipt_shape_validation_source_implemented": 100, - "persona_control_authorization_cryptographic_provenance_source_implemented": 0, + "persona_control_authorization_signer_registry_contract_source_implemented": 100, + "persona_control_authorization_cryptographic_provenance_source_implemented": 100, + "persona_control_authorization_trusted_signer_registered": 0, "desktop_language_entry_source_integrated": 100, "persona_control_authorization_runtime_integrated": 0, "real_persona_repository_manifest_bound": 0, diff --git a/routing/hololake-cognitive-gravity-and-continuity.test.mjs b/routing/hololake-cognitive-gravity-and-continuity.test.mjs index 90bb07f..b7a39cf 100644 --- a/routing/hololake-cognitive-gravity-and-continuity.test.mjs +++ b/routing/hololake-cognitive-gravity-and-continuity.test.mjs @@ -14,7 +14,7 @@ const age = readJson("routing/hololake-age-runtime-architecture.json"); const rules = readJson("routing/hololake-engineering-rules.json"); test("B0 is restored before product organs and remains resident in every cognition step", () => { - assert.equal(architecture.version, "2026-08-12.11"); + assert.equal(architecture.version, "2026-08-12.12"); assert.equal( architecture.read_order[1], architecture.cognitive_gravity_and_continuity.architecture_page, @@ -96,11 +96,15 @@ test("the first implementation stage is one vertical AGE loop, not Mirror parall assert.equal(gravity.truth.persona_language_wake_binding_compiler_source_implemented, 100); assert.equal(gravity.truth.persona_language_shell_controller_source_implemented, 100); assert.equal(gravity.truth.persona_control_authorization_receipt_shape_validation_source_implemented, 100); - assert.equal(gravity.truth.persona_control_authorization_cryptographic_provenance_source_implemented, 0); + assert.equal(gravity.truth.persona_control_authorization_signer_registry_contract_source_implemented, 100); + assert.equal(gravity.truth.persona_control_authorization_cryptographic_provenance_source_implemented, 100); + assert.equal(gravity.truth.persona_control_authorization_trusted_signer_registered, 0); assert.equal(gravity.truth.desktop_language_entry_source_integrated, 100); assert.equal(gravity.truth.persona_control_authorization_runtime_integrated, 0); assert.equal(architecture.interaction_model.source_contract.receipt_shape_validation_is_authority_proof, false); assert.equal(architecture.interaction_model.source_contract.cryptographic_provenance_required_before_native_loader, true); + assert.equal(architecture.interaction_model.source_contract.canonical_signing_bytes_source_implemented, true); + assert.equal(architecture.interaction_model.source_contract.ed25519_verification_source_implemented, true); assert.equal(architecture.interaction_model.source_contract.trusted_signer_source_registered, false); assert.equal(gravity.truth.real_persona_repository_manifest_bound, 0); assert.equal(gravity.truth.natural_language_partner_adapter_runtime_integrated, 0); diff --git a/routing/hololake-current-architecture.json b/routing/hololake-current-architecture.json index 14bc275..0522bf5 100644 --- a/routing/hololake-current-architecture.json +++ b/routing/hololake-current-architecture.json @@ -1,7 +1,7 @@ { "schema": "hololake.current-architecture/v1", "architecture_id": "HLP-CURRENT-ARCH-001", - "version": "2026-08-12.11", + "version": "2026-08-12.12", "state": "CURRENT_CANONICAL", "product": { "formal_name": "光湖语言系统 · 通用人工智能操作平台", @@ -116,7 +116,9 @@ "persona_runtime_projection_repository_gate_source_integrated": true, "persona_language_shell_controller_source_implemented": true, "persona_control_authorization_receipt_shape_validation_source_implemented": true, - "persona_control_authorization_cryptographic_provenance_source_implemented": false, + "persona_control_authorization_signer_registry_contract_source_implemented": true, + "persona_control_authorization_cryptographic_provenance_source_implemented": true, + "persona_control_authorization_trusted_signer_registered": false, "desktop_language_entry_source_integrated": true, "persona_control_authorization_runtime_integrated": false, "real_persona_repository_manifest_bound": false, @@ -388,9 +390,14 @@ "pncc_lifecycle_adapter_tests": "product-source/hololake-platform/src/lib/personaLanguageGoal.test.ts", "persona_control_authorization_receipt": "product-source/hololake-platform/src/lib/personaControlAuthorization.ts", "persona_control_authorization_receipt_tests": "product-source/hololake-platform/src/lib/personaControlAuthorization.test.ts", + "persona_control_authorization_signer_registry_and_verifier": "product-source/guanghu-knowledge-base/server/persona-control-authorization.ts", + "persona_control_authorization_signer_registry_and_verifier_tests": "product-source/guanghu-knowledge-base/server/persona-control-authorization.test.ts", + "receipt_schema": "hololake.persona-control-authorization/v2", "caller_supplied_persona_authorization_boolean_allowed": false, "receipt_shape_validation_is_authority_proof": false, "cryptographic_provenance_required_before_native_loader": true, + "canonical_signing_bytes_source_implemented": true, + "ed25519_verification_source_implemented": true, "trusted_signer_source_registered": false, "native_authorization_receipt_loader_integrated": false, "partner_deliberation_required": true, @@ -402,7 +409,8 @@ "REFUSE" ], "focused_tests": "11_OF_11_PASS", - "authorization_focused_tests": "11_OF_11_PASS" + "authorization_focused_tests": "13_OF_13_PASS", + "authorization_cryptographic_tests": "7_OF_7_PASS" }, "ui_plugin_system": { "record_id": "HLP-HOT-PLUGGABLE-UI-001",