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 4e51e4e..5a720d4 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 @@ -116,14 +116,14 @@ REVISE | REFUSE`。 B0 伙伴审议的顺序失败关闭;成功只产生语言目标规划,不提供现实动作执行入口。桌面源码接线为 `100`: 第五域入口只传入已挂载仓库与已配置模型元数据,并在没有桌面授权回执时保持系统直控、隐藏无法持久消费的 确认按钮。该接线不等于真实人格仓库绑定、安装态运行或桌面验收。 -- 人格主控授权回执的结构与精确绑定校验源码为 `100`:不再接受桌面调用方直接传入布尔值,并核对 - 人格、冰朔责任主体、仓库提交、模型实例、请求、语言锚点、摘要格式和有效期。但这层前端结构校验 - 不能证明回执确由 `GUANGHU_OS` 签发。独立的 v2 回执、REPO-012 精确提交签名者注册表、规范签名字节、 +- 人格主控授权的原生验签接线源码为 `100`:不再接受桌面调用方直接传入布尔值,也不把前端字段形状 + 当作权威。语言控制器把候选 v2 回执连同人格、冰朔责任主体、仓库提交、模型实例、请求、语言锚点和 + 观察时间一起交给原生边界;只有严格的原生成功投影才可能开启人格主控。独立的 v2 回执、REPO-012 精确提交签名者注册表、规范签名字节、 人格/责任主体/范围约束、吊销和 Ed25519 验签源码契约现为 `100`。REPO-012 main `21aec6f5042e32e34c892a7a212d8dec5f758437` 已发布锚定的空注册表,Tauri 原生只读加载器源码也为 `100`。原生 v2 签名回执解析、规范签名字节、Ed25519 SPKI 验签、签名者范围/吊销、请求绑定和有效期 - 校验源码也为 `100`。但真实可信签名者、密钥托管以及验签结果到人格语言控制器的运行接线仍为 `0`; - 当前空注册表只能产生拒绝,普通本地 JSON 不得升级人格主控,桌面继续系统直控。 + 校验源码也为 `100`,验签结果到人格语言控制器的源码接线亦为 `100`。但真实可信签名者和密钥托管仍为 `0`; + 当前空注册表只能产生 `NO_TRUSTED_SIGNER`,普通本地 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 a05e266..5624abf 100644 --- a/product-source/hololake-platform/docs/ABSTRACTIONS.md +++ b/product-source/hololake-platform/docs/ABSTRACTIONS.md @@ -21,14 +21,14 @@ then calls `compileLanguageGoal`. A failed, malformed, non-fact, or purpose-less still gated by a unique manifest-valid persona repository, the manifest-pinned configured model, and public device identity; it has no installed-desktop or live-product acceptance claim. -The source coordinator no longer accepts an unverified persona-authorization boolean from the desktop caller. -`hasPersonaPrimaryControlAuthorization` validates the shape, exact bindings, digest format, and validity window -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. REPO-012 -now publishes the exact registry source with zero signers, and the Tauri command loads only that exact commit-bound -empty state. The native verifier now validates the complete signed v2 contract, but no verified projection is wired -into the language controller and the authoritative registry has zero signers, so planning remains in system-direct mode. The independent server +The source coordinator no longer accepts an unverified persona-authorization boolean or treats a renderer-shaped +receipt as authority. When a candidate v2 receipt is present, the language controller sends that receipt and the +exact persona, human responsibility, repository, model, request, language-anchor, and observation-time expectation +to the native verifier. `hasPersonaPrimaryControlAuthorization` accepts only its strict five-field successful +projection; verifier errors, denials, extra fields, and locally claimed signed receipts remain system-direct. +REPO-012 publishes the exact registry source with zero signers, and the Tauri command loads only that exact +commit-bound empty state. The authoritative registry therefore still makes every current candidate return +`NO_TRUSTED_SIGNER`; source wiring is not live persona authority. 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 appoint a signer or enable the desktop persona-primary path. diff --git a/product-source/hololake-platform/docs/ARCHITECTURE.md b/product-source/hololake-platform/docs/ARCHITECTURE.md index 2946b9c..e3d552c 100644 --- a/product-source/hololake-platform/docs/ARCHITECTURE.md +++ b/product-source/hololake-platform/docs/ARCHITECTURE.md @@ -178,22 +178,22 @@ configured provider metadata. It has no native persona-control authorization rec callback, and hides the reality confirmation surface because no durable confirmation consumer is wired. This proves source integration, not a real persona manifest binding, installed desktop runtime, or acceptance. -`src/lib/personaControlAuthorization.ts` removes the desktop coordinator's caller-supplied authorization boolean. -It validates the structure and exact bindings of a current receipt that claims `GUANGHU_OS` verification: persona, -human responsibility subject, repository head, model instance, request and language anchor must all agree. This -renderer validation does not prove the issuer or verify a signature. A native loader must first verify signed -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. +`src/lib/personaControlAuthorization.ts` removes the desktop coordinator's caller-supplied authorization boolean +and no longer treats renderer-side receipt shape checks as authority. The language controller sends a candidate +receipt plus exact persona, human responsibility subject, repository head, model instance, request, language anchor, +and observation time to the native verifier. Only its strict successful projection can enable persona-primary +planning; a missing candidate, verifier error, denial, extra field, or merely local signed-looking object 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 now exposes a native read-only loader for the exact REPO-012 commit-bound registry. It accepts +signature verification. The current REPO-012 main publishes that registry path with zero signers, so no signer is +trusted and the Tauri desktop exposes a native read-only loader for the exact REPO-012 commit-bound registry. It accepts the current empty registry and keeps authorization disabled. The native verifier now implements strict v2 receipt parsing, canonical signing bytes, Ed25519 SPKI verification, signer scope/revocation checks, exact request bindings, -and validity windows. It is not wired into the language controller, and the authoritative registry still has zero -signers, so tested loader/verifier source is not runtime authority, deployment, or desktop acceptance. +and validity windows. Its verification projection is now wired into the language controller, but the authoritative +registry still has zero signers, so tested source wiring is not runtime authority, deployment, or desktop acceptance. 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. diff --git a/product-source/hololake-platform/src-tauri/src/persona_control_authorization.rs b/product-source/hololake-platform/src-tauri/src/persona_control_authorization.rs index a488690..ea15911 100644 --- a/product-source/hololake-platform/src-tauri/src/persona_control_authorization.rs +++ b/product-source/hololake-platform/src-tauri/src/persona_control_authorization.rs @@ -543,7 +543,7 @@ mod tests { repository_head: "a".repeat(40), model_instance_id: "MODEL-INSTANCE-001".into(), request_id: "REQ-001".into(), - source_language_anchor: "HLP-CURRENT-ARCH-001@2026-08-12.14".into(), + source_language_anchor: "HLP-CURRENT-ARCH-001@2026-08-12.15".into(), issued_at: "2026-08-12T05:00:00+08:00".into(), valid_until: "2026-08-12T05:10:00+08:00".into(), evidence_digest: "b".repeat(64), @@ -560,7 +560,7 @@ mod tests { repository_head: "a".repeat(40), model_instance_id: "MODEL-INSTANCE-001".into(), request_id: "REQ-001".into(), - source_language_anchor: "HLP-CURRENT-ARCH-001@2026-08-12.14".into(), + source_language_anchor: "HLP-CURRENT-ARCH-001@2026-08-12.15".into(), observed_at_milliseconds: chrono::DateTime::parse_from_rfc3339( "2026-08-12T05:05:00+08:00", ) diff --git a/product-source/hololake-platform/src/components/PersonaLanguageShellPanel.test.tsx b/product-source/hololake-platform/src/components/PersonaLanguageShellPanel.test.tsx index 546c850..0da8afe 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.14', + sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.15', })) 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 aa1af6d..615a99b 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.14' +const CURRENT_ARCHITECTURE_ANCHOR = 'HLP-CURRENT-ARCH-001@2026-08-12.15' const DEVELOPMENT_ID = 'DEV-20260811-010' type Planner = typeof planPersonaLanguageShellGoal @@ -103,9 +103,9 @@ export function PersonaLanguageShellPanel({ personaId, repositoryPaths, providers, - // Native registry loading and signed-receipt verification exist, but - // no verified projection is wired into this controller. The published - // registry is also empty, so this remains system-direct. + // The controller can verify a candidate receipt through the native + // boundary, but no candidate source is mounted here and the published + // signer registry is empty. This therefore remains system-direct. requestId: requestId(), modelInstanceId: `hololake-desktop:${personaId}`, developmentId: DEVELOPMENT_ID, diff --git a/product-source/hololake-platform/src/lib/personaControlAuthorization.test.ts b/product-source/hololake-platform/src/lib/personaControlAuthorization.test.ts index a33d58f..043ce29 100644 --- a/product-source/hololake-platform/src/lib/personaControlAuthorization.test.ts +++ b/product-source/hololake-platform/src/lib/personaControlAuthorization.test.ts @@ -1,59 +1,31 @@ import { describe, expect, it } from 'vitest' -import { - PERSONA_CONTROL_AUTHORIZATION_SCHEMA, - PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE, - hasPersonaPrimaryControlAuthorization, -} from './personaControlAuthorization' +import { hasPersonaPrimaryControlAuthorization } from './personaControlAuthorization' -const expected = { - 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.14', - observedAt: Date.parse('2026-08-12T04:35:00+08:00'), -} - -const receipt = { - schema: PERSONA_CONTROL_AUTHORIZATION_SCHEMA, - outcome: 'VERIFIED', - authorizationId: 'AUTH-001', - verifier: 'GUANGHU_OS', - scope: PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE, - personaId: expected.personaId, - humanResponsibilitySubject: expected.humanResponsibilitySubject, - repositoryHead: expected.repositoryHead, - modelInstanceId: expected.modelInstanceId, - requestId: expected.requestId, - sourceLanguageAnchor: expected.sourceLanguageAnchor, - issuedAt: '2026-08-12T04:30:00+08:00', - validUntil: '2026-08-12T04:40:00+08:00', - evidenceDigest: 'b'.repeat(64), +const verification = { + status: 'VERIFIED', + reason: null, + sourceCommit: 'a'.repeat(40), signerId: 'GH-AIOS-AUTHORIZER-001', - signatureAlgorithm: 'Ed25519', - signature: 'A'.repeat(86), + authorizationEnabled: true, } describe('hasPersonaPrimaryControlAuthorization', () => { - it('accepts only an exact, current, Guanghu OS verified planning receipt', () => { - expect(hasPersonaPrimaryControlAuthorization(receipt, expected)).toBe(true) + it('accepts only an exact native cryptographic verification projection', () => { + expect(hasPersonaPrimaryControlAuthorization(verification)).toBe(true) }) it.each([ ['missing', null], - ['wrong persona', { ...receipt, personaId: 'OTHER' }], - ['wrong repository head', { ...receipt, repositoryHead: 'c'.repeat(40) }], - ['wrong model instance', { ...receipt, modelInstanceId: 'OTHER' }], - ['wrong request', { ...receipt, requestId: 'OTHER' }], - ['wrong language anchor', { ...receipt, sourceLanguageAnchor: 'old' }], - ['unverified', { ...receipt, outcome: 'PENDING' }], - ['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' }], + ['self-claimed signed receipt', { schema: 'hololake.persona-control-authorization/v2', outcome: 'VERIFIED' }], + ['native denial', { ...verification, status: 'DENIED', authorizationEnabled: false }], + ['disabled projection', { ...verification, authorizationEnabled: false }], + ['reason present', { ...verification, reason: 'NO_TRUSTED_SIGNER' }], + ['missing signer', { ...verification, signerId: null }], + ['invalid signer', { ...verification, signerId: 'lowercase' }], + ['missing commit', { ...verification, sourceCommit: null }], + ['invalid commit', { ...verification, sourceCommit: 'not-a-commit' }], + ['unknown extra field', { ...verification, extra: true }], ])('fails closed for %s evidence', (_label, candidate) => { - expect(hasPersonaPrimaryControlAuthorization(candidate, expected)).toBe(false) + expect(hasPersonaPrimaryControlAuthorization(candidate)).toBe(false) }) }) diff --git a/product-source/hololake-platform/src/lib/personaControlAuthorization.ts b/product-source/hololake-platform/src/lib/personaControlAuthorization.ts index 65f50f0..c2dd212 100644 --- a/product-source/hololake-platform/src/lib/personaControlAuthorization.ts +++ b/product-source/hololake-platform/src/lib/personaControlAuthorization.ts @@ -31,6 +31,14 @@ export type PersonaControlAuthorizationExpectation = { observedAt?: number } +export type NativePersonaControlAuthorizationVerification = { + status: 'VERIFIED' + reason: null + sourceCommit: string + signerId: string + authorizationEnabled: true +} + function isRecord(value: unknown): value is Record { return typeof value === 'object' && value !== null && !Array.isArray(value) } @@ -39,50 +47,18 @@ function exactString(record: Record, key: string, expected: str return Reflect.get(record, key) === expected } -/** - * Accepts only a native-verifier receipt bound to this exact planning request. - * It does not issue authority and treats absent or stale evidence as system-direct. - */ +/** Accepts only the bounded result emitted after native cryptographic verification. */ export function hasPersonaPrimaryControlAuthorization( - receipt: unknown, - expected: PersonaControlAuthorizationExpectation, -): receipt is PersonaControlAuthorizationReceipt { - if (!isRecord(receipt)) return false - 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) - || !exactString(receipt, 'repositoryHead', expected.repositoryHead) - || !exactString(receipt, 'modelInstanceId', expected.modelInstanceId) - || !exactString(receipt, 'requestId', expected.requestId) - || !exactString(receipt, 'sourceLanguageAnchor', expected.sourceLanguageAnchor)) { - return false - } - - 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 - } - - const issuedAtMs = Date.parse(issuedAt) - const validUntilMs = Date.parse(validUntil) - const observedAt = expected.observedAt ?? Date.now() - return Number.isFinite(issuedAtMs) - && Number.isFinite(validUntilMs) - && issuedAtMs <= observedAt - && observedAt <= validUntilMs - && issuedAtMs < validUntilMs + verification: unknown, +): verification is NativePersonaControlAuthorizationVerification { + if (!isRecord(verification) || Object.keys(verification).length !== 5) return false + const sourceCommit = Reflect.get(verification, 'sourceCommit') + const signerId = Reflect.get(verification, 'signerId') + return exactString(verification, 'status', 'VERIFIED') + && Reflect.get(verification, 'reason') === null + && Reflect.get(verification, 'authorizationEnabled') === true + && typeof sourceCommit === 'string' + && /^[a-f0-9]{40}([a-f0-9]{24})?$/.test(sourceCommit) + && typeof signerId === 'string' + && /^[A-Z0-9][A-Z0-9._:@-]{1,159}$/.test(signerId) } diff --git a/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts b/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts index 10f6f98..bccbf50 100644 --- a/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts +++ b/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, vi } from 'vitest' +import { beforeEach, describe, expect, it, vi } from 'vitest' import type { AiModelProvider } from './aiTargets' import type { LanguageGoalProjection } from './languageOperatingModel' import type { PersonaLanguageGoalBinding } from './personaLanguageGoal' @@ -8,6 +8,11 @@ import type { } from './personaRepositoryBinding' import { planPersonaLanguageShellGoal } from './personaLanguageShellController' +const native = vi.hoisted(() => ({ invoke: vi.fn() })) + +vi.mock('@tauri-apps/api/core', () => ({ invoke: native.invoke })) +vi.mock('../mock-tauri', () => ({ isTauri: () => false, mockInvoke: native.invoke })) + const provider: AiModelProvider = { id: 'ollama-local', name: 'Local Ollama', @@ -104,6 +109,8 @@ function input() { } describe('planPersonaLanguageShellGoal', () => { + beforeEach(() => native.invoke.mockReset()) + it.each(['unavailable', 'unbound', 'ambiguous', 'error'] as const)( 'fails closed at repository phase %s before device identity or cognition', async (phase) => { @@ -175,30 +182,24 @@ describe('planPersonaLanguageShellGoal', () => { expect(planGoal).toHaveBeenCalledWith(expect.objectContaining({ personaAuthorized: false })) }) - it('enables persona-primary planning only for an exact request-bound authorization receipt', async () => { + it('enables persona-primary planning only after the native verifier accepts the exact receipt', async () => { const planGoal = vi.fn().mockResolvedValue(plannedGoal) + const candidateReceipt = { + schema: 'hololake.persona-control-authorization/v2', + outcome: 'VERIFIED', + authorizationId: 'AUTH-001', + } + native.invoke.mockResolvedValue({ + status: 'VERIFIED', + reason: null, + sourceCommit: 'c'.repeat(40), + signerId: 'GH-AIOS-AUTHORIZER-001', + authorizationEnabled: true, + }) await planPersonaLanguageShellGoal({ ...input(), - loadPersonaControlAuthorization: vi.fn().mockResolvedValue({ - schema: 'hololake.persona-control-authorization/v2', - outcome: 'VERIFIED', - authorizationId: 'AUTH-001', - verifier: 'GUANGHU_OS', - scope: 'PERSONA_PRIMARY_LANGUAGE_PLANNING', - personaId: repositoryBinding.personaId, - humanResponsibilitySubject: repositoryBinding.humanResponsibilitySubject, - repositoryHead: repositoryBinding.gitHead, - modelInstanceId: 'MODEL-INSTANCE-001', - requestId: 'REQ-001', - sourceLanguageAnchor: 'current-human-utterance', - 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), - }), + personaControlAuthorizationReceipt: candidateReceipt, authorizationObservedAt: Date.parse('2026-08-12T04:35:00+08:00'), resolveRepository: vi.fn().mockResolvedValue(boundResolution()), loadDeviceIdentity: vi.fn().mockResolvedValue({ @@ -209,9 +210,68 @@ describe('planPersonaLanguageShellGoal', () => { planGoal, }) + expect(native.invoke).toHaveBeenCalledWith( + 'verify_persona_control_authorization', + { + receipt: candidateReceipt, + expectation: { + personaId: repositoryBinding.personaId, + humanResponsibilitySubject: repositoryBinding.humanResponsibilitySubject, + repositoryHead: repositoryBinding.gitHead, + modelInstanceId: 'MODEL-INSTANCE-001', + requestId: 'REQ-001', + sourceLanguageAnchor: 'current-human-utterance', + observedAtMilliseconds: Date.parse('2026-08-12T04:35:00+08:00'), + }, + }, + ) expect(planGoal).toHaveBeenCalledWith(expect.objectContaining({ personaAuthorized: true })) }) + it('keeps system-direct planning for a native denial', async () => { + const planGoal = vi.fn().mockResolvedValue(plannedGoal) + native.invoke.mockResolvedValue({ + status: 'DENIED', + reason: 'NO_TRUSTED_SIGNER', + sourceCommit: 'c'.repeat(40), + signerId: null, + authorizationEnabled: false, + }) + + await planPersonaLanguageShellGoal({ + ...input(), + personaControlAuthorizationReceipt: { outcome: 'VERIFIED' }, + resolveRepository: vi.fn().mockResolvedValue(boundResolution()), + loadDeviceIdentity: vi.fn().mockResolvedValue({ + schema: 'guanghu.router-device/v1', + device_id: 'HL-DEVICE-001', + public_key: 'public-key', + }), + planGoal, + }) + + expect(planGoal).toHaveBeenCalledWith(expect.objectContaining({ personaAuthorized: false })) + }) + + it('keeps system-direct planning when the native verifier is unavailable', async () => { + const planGoal = vi.fn().mockResolvedValue(plannedGoal) + native.invoke.mockImplementationOnce(() => { throw new Error('SOURCE_UNAVAILABLE') }) + + await planPersonaLanguageShellGoal({ + ...input(), + personaControlAuthorizationReceipt: { outcome: 'VERIFIED' }, + resolveRepository: vi.fn().mockResolvedValue(boundResolution()), + loadDeviceIdentity: vi.fn().mockResolvedValue({ + schema: 'guanghu.router-device/v1', + device_id: 'HL-DEVICE-001', + public_key: 'public-key', + }), + planGoal, + }) + + expect(planGoal).toHaveBeenCalledWith(expect.objectContaining({ personaAuthorized: false })) + }) + it('returns a stable binding error and never invokes cognition for invalid device evidence', async () => { const planGoal = vi.fn() diff --git a/product-source/hololake-platform/src/lib/personaLanguageShellController.ts b/product-source/hololake-platform/src/lib/personaLanguageShellController.ts index caa31d1..486c5cf 100644 --- a/product-source/hololake-platform/src/lib/personaLanguageShellController.ts +++ b/product-source/hololake-platform/src/lib/personaLanguageShellController.ts @@ -35,14 +35,18 @@ export type PersonaLanguageShellPlan = type RepositoryResolver = typeof resolvePersonaRepositoryBinding type GoalPlanner = (input: PlanPersonaLanguageGoalInput) => Promise type DeviceIdentityLoader = () => Promise -type PersonaControlAuthorizationLoader = (input: { - personaId: string - humanResponsibilitySubject: string - repositoryHead: string - modelInstanceId: string - requestId: string - sourceLanguageAnchor: string -}) => Promise +type PersonaControlAuthorizationVerificationInput = { + receipt: unknown + expectation: { + personaId: string + humanResponsibilitySubject: string + repositoryHead: string + modelInstanceId: string + requestId: string + sourceLanguageAnchor: string + observedAtMilliseconds: number + } +} async function loadNativeDeviceIdentity(): Promise { return isTauri() @@ -50,8 +54,12 @@ async function loadNativeDeviceIdentity(): Promise { : mockInvoke('guanghu_router_device_identity') } -async function loadNoPersonaControlAuthorization(): Promise { - return null +async function verifyNativePersonaControlAuthorization( + input: PersonaControlAuthorizationVerificationInput, +): Promise { + return isTauri() + ? invoke('verify_persona_control_authorization', input) + : mockInvoke('verify_persona_control_authorization', input) } function errorCode(error: unknown, fallback: string): string { @@ -79,6 +87,7 @@ export async function planPersonaLanguageShellGoal({ personaId, repositoryPaths, providers, + personaControlAuthorizationReceipt, authorizationObservedAt, detectedBoundaries, requestId, @@ -87,13 +96,13 @@ export async function planPersonaLanguageShellGoal({ sourceLanguageAnchor, resolveRepository = resolvePersonaRepositoryBinding, loadDeviceIdentity = loadNativeDeviceIdentity, - loadPersonaControlAuthorization = loadNoPersonaControlAuthorization, planGoal = planPersonaLanguageGoal, }: { utterance: string personaId: string repositoryPaths: readonly string[] providers: readonly AiModelProvider[] + personaControlAuthorizationReceipt?: unknown authorizationObservedAt?: number detectedBoundaries?: RealityBoundary[] requestId: string @@ -102,7 +111,6 @@ export async function planPersonaLanguageShellGoal({ sourceLanguageAnchor: string resolveRepository?: RepositoryResolver loadDeviceIdentity?: DeviceIdentityLoader - loadPersonaControlAuthorization?: PersonaControlAuthorizationLoader planGoal?: GoalPlanner }): Promise { const repository = await resolveRepository({ personaId, repositoryPaths }) @@ -144,20 +152,22 @@ export async function planPersonaLanguageShellGoal({ requestId, sourceLanguageAnchor, } - let personaAuthorizationReceipt: unknown = null - try { - personaAuthorizationReceipt = await loadPersonaControlAuthorization(authorizationExpectation) - } catch { - // Authorization discovery is fail-closed but does not prevent safe, - // system-direct partner planning. + let nativeAuthorizationVerification: unknown = null + if (personaControlAuthorizationReceipt !== undefined) { + try { + nativeAuthorizationVerification = await verifyNativePersonaControlAuthorization({ + receipt: personaControlAuthorizationReceipt, + expectation: { + ...authorizationExpectation, + observedAtMilliseconds: authorizationObservedAt ?? Date.now(), + }, + }) + } catch { + // Native authorization verification is fail-closed but does not + // prevent safe, system-direct partner planning. + } } - const personaAuthorized = hasPersonaPrimaryControlAuthorization( - personaAuthorizationReceipt, - { - ...authorizationExpectation, - observedAt: authorizationObservedAt, - }, - ) + const personaAuthorized = hasPersonaPrimaryControlAuthorization(nativeAuthorizationVerification) const goal = await planGoal({ utterance, personaAuthorized, diff --git a/routing/hololake-cognitive-gravity-and-continuity.json b/routing/hololake-cognitive-gravity-and-continuity.json index 2d12fbd..2957cb0 100644 --- a/routing/hololake-cognitive-gravity-and-continuity.json +++ b/routing/hololake-cognitive-gravity-and-continuity.json @@ -143,7 +143,7 @@ }, "remaining_before_vertical_slice_acceptance": [ "REAL_PERSONA_REPOSITORY_MANIFEST_BINDING", - "NATIVE_PERSONA_CONTROL_AUTHORIZATION_RECEIPT_LOADER", + "TRUSTED_PERSONA_CONTROL_SIGNER_AND_KEY_CUSTODY", "DESKTOP_LIFECYCLE_RUNTIME_ACCEPTANCE" ], "next_after_vertical_slice": [ @@ -175,6 +175,7 @@ "persona_control_authorization_registry_source_published": 100, "native_persona_control_authorization_registry_loader_source_integrated": 100, "native_persona_control_authorization_receipt_verifier_source_integrated": 100, + "native_persona_control_authorization_verifier_wired_to_language_controller_source": 100, "persona_control_authorization_trusted_signer_registered": 0, "desktop_language_entry_source_integrated": 100, "persona_control_authorization_runtime_integrated": 0, diff --git a/routing/hololake-cognitive-gravity-and-continuity.test.mjs b/routing/hololake-cognitive-gravity-and-continuity.test.mjs index 96b572a..e82ce52 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.14"); + assert.equal(architecture.version, "2026-08-12.15"); assert.equal( architecture.read_order[1], architecture.cognitive_gravity_and_continuity.architecture_page, @@ -101,6 +101,7 @@ test("the first implementation stage is one vertical AGE loop, not Mirror parall assert.equal(gravity.truth.persona_control_authorization_registry_source_published, 100); assert.equal(gravity.truth.native_persona_control_authorization_registry_loader_source_integrated, 100); assert.equal(gravity.truth.native_persona_control_authorization_receipt_verifier_source_integrated, 100); + assert.equal(gravity.truth.native_persona_control_authorization_verifier_wired_to_language_controller_source, 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); @@ -111,7 +112,7 @@ test("the first implementation stage is one vertical AGE loop, not Mirror parall assert.equal(architecture.interaction_model.source_contract.trusted_signer_source_registered, false); assert.equal(architecture.interaction_model.source_contract.native_authorization_registry_loader_integrated, true); assert.equal(architecture.interaction_model.source_contract.native_authorization_receipt_loader_integrated, true); - assert.equal(architecture.interaction_model.source_contract.native_authorization_verifier_wired_to_language_controller, false); + assert.equal(architecture.interaction_model.source_contract.native_authorization_verifier_wired_to_language_controller, true); assert.equal(gravity.truth.real_persona_repository_manifest_bound, 0); assert.equal(gravity.truth.natural_language_partner_adapter_runtime_integrated, 0); assert.equal(gravity.truth.single_age_vertical_loop_implemented, 0); diff --git a/routing/hololake-current-architecture.json b/routing/hololake-current-architecture.json index 4668b17..0a1e55f 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.14", + "version": "2026-08-12.15", "state": "CURRENT_CANONICAL", "product": { "formal_name": "光湖语言系统 · 通用人工智能操作平台", @@ -121,6 +121,7 @@ "persona_control_authorization_registry_source_published": true, "native_persona_control_authorization_registry_loader_source_integrated": true, "native_persona_control_authorization_receipt_verifier_source_integrated": true, + "native_persona_control_authorization_verifier_wired_to_language_controller_source": true, "persona_control_authorization_trusted_signer_registered": false, "desktop_language_entry_source_integrated": true, "persona_control_authorization_runtime_integrated": false, @@ -409,7 +410,7 @@ "trusted_signer_source_registered": false, "native_authorization_registry_loader_integrated": true, "native_authorization_receipt_loader_integrated": true, - "native_authorization_verifier_wired_to_language_controller": false, + "native_authorization_verifier_wired_to_language_controller": true, "partner_deliberation_required": true, "human_utterance_is_direct_command": false, "allowed_dispositions": [ @@ -419,7 +420,8 @@ "REFUSE" ], "focused_tests": "11_OF_11_PASS", - "authorization_focused_tests": "13_OF_13_PASS", + "authorization_focused_tests": "11_OF_11_PASS", + "language_controller_authorization_wiring_tests": "10_OF_10_PASS", "authorization_cryptographic_tests": "7_OF_7_PASS", "native_authorization_registry_and_receipt_verifier_tests": "6_OF_6_PASS" },