feat: bind persona control to authorization receipts

This commit is contained in:
冰朔 2026-08-12 04:36:45 +08:00
commit 099ed036b2
12 changed files with 248 additions and 15 deletions

View file

@ -116,6 +116,9 @@ REVISE | REFUSE`。
B0 伙伴审议的顺序失败关闭;成功只产生语言目标规划,不提供现实动作执行入口。桌面源码接线为 `100`
第五域入口只传入已挂载仓库与已配置模型元数据,并在没有桌面授权回执时保持系统直控、隐藏无法持久消费的
确认按钮。该接线不等于真实人格仓库绑定、安装态运行或桌面验收。
- 人格主控授权回执验证源码为 `100`:不再接受桌面调用方直接传入布尔值,而只接受由
`GUANGHU_OS` 核验、且与人格、冰朔责任主体、仓库提交、模型实例、请求和语言锚点精确绑定的
当前回执。桌面尚未接入原生回执加载器,因此人格主控运行集成仍为 `0`,缺少回执时继续系统直控。
- 完整 HoloLake Runtime 与单 AGE 纵向闭环仍为 `0`:真实人格仓库 manifest 绑定和桌面运行验收尚未完成,
因此不能用本轮源码测试冒充可用产品。
- Mirror runner、制品、部署和运行健康`0`

View file

@ -21,6 +21,11 @@ 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` requires one current `GUANGHU_OS` receipt bound to the exact persona,
human responsibility subject, repository head, model instance, request, and language anchor. Until a native
loader provides that evidence, planning remains in system-direct mode.
`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
agree. It materializes a catalog runtime endpoint into the native provider shape (`kind`, `base_url`, and

View file

@ -174,9 +174,14 @@ binding, and finally invokes B0 partner deliberation. Unavailable, unbound, ambi
binding, and cognition failures stop at their own boundary; later stages are not invoked. Its successful result
is still a language-goal projection, not permission to perform a reality action. `PersonaLanguageShellPanel`
is now mounted from the Fifth Domain desktop source and receives the app's already-mounted repository roots and
configured provider metadata. It keeps `personaAuthorized=false`, exposes no execution 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.
configured provider metadata. It has no native persona-control authorization receipt loader, exposes no execution
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 accepts only a current `GUANGHU_OS` verification receipt bound to the exact persona, human responsibility
subject, repository head, model instance, request and language anchor. Missing, stale or mismatched evidence
remains system-direct. This is a source contract; it does not claim persona-primary runtime control exists.
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.

View file

@ -55,9 +55,8 @@ describe('PersonaLanguageShellPanel', () => {
personaId: 'ICE-P-ZY001',
repositoryPaths: ['/persona'],
providers: [provider],
personaAuthorized: false,
developmentId: 'DEV-20260811-010',
sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.9',
sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.10',
}))
expect(await screen.findByText('我还不能执行:需要当前证据。')).toBeInTheDocument()
expect(screen.getByText('核验当前事实后规划下一步')).toBeInTheDocument()

View file

@ -13,7 +13,7 @@ import {
type LanguageShellViewState,
} from './HotPluggableLanguageShell'
const CURRENT_ARCHITECTURE_ANCHOR = 'HLP-CURRENT-ARCH-001@2026-08-12.9'
const CURRENT_ARCHITECTURE_ANCHOR = 'HLP-CURRENT-ARCH-001@2026-08-12.10'
const DEVELOPMENT_ID = 'DEV-20260811-010'
type Planner = typeof planPersonaLanguageShellGoal
@ -103,9 +103,8 @@ export function PersonaLanguageShellPanel({
personaId,
repositoryPaths,
providers,
// No desktop authorization receipt is wired yet, so this source slice
// must remain system-direct even after partner deliberation succeeds.
personaAuthorized: false,
// No native authorization receipt loader is wired yet. The controller
// therefore remains system-direct even after deliberation succeeds.
requestId: requestId(),
modelInstanceId: `hololake-desktop:${personaId}`,
developmentId: DEVELOPMENT_ID,

View file

@ -0,0 +1,54 @@
import { describe, expect, it } from 'vitest'
import {
PERSONA_CONTROL_AUTHORIZATION_SCHEMA,
PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE,
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.10',
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),
}
describe('hasPersonaPrimaryControlAuthorization', () => {
it('accepts only an exact, current, Guanghu OS verified planning receipt', () => {
expect(hasPersonaPrimaryControlAuthorization(receipt, expected)).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' }],
])('fails closed for %s evidence', (_label, candidate) => {
expect(hasPersonaPrimaryControlAuthorization(candidate, expected)).toBe(false)
})
})

View file

@ -0,0 +1,80 @@
export const PERSONA_CONTROL_AUTHORIZATION_SCHEMA = 'hololake.persona-control-authorization/v1' as const
export const PERSONA_PRIMARY_LANGUAGE_PLANNING_SCOPE = 'PERSONA_PRIMARY_LANGUAGE_PLANNING' as const
export type 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
}
export type PersonaControlAuthorizationExpectation = {
personaId: string
humanResponsibilitySubject: string
repositoryHead: string
modelInstanceId: string
requestId: string
sourceLanguageAnchor: string
observedAt?: number
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value)
}
function exactString(record: Record<string, unknown>, key: string, expected: string): boolean {
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.
*/
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, '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 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 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
}

View file

@ -96,7 +96,6 @@ function input() {
personaId: 'ICE-P-ZY001',
repositoryPaths: ['/persona/zhuyuan'],
providers: [provider],
personaAuthorized: true,
requestId: 'REQ-001',
modelInstanceId: 'MODEL-INSTANCE-001',
developmentId: 'DEV-20260811-010',
@ -173,6 +172,41 @@ describe('planPersonaLanguageShellGoal', () => {
})
expect(loadDeviceIdentity).toHaveBeenCalledTimes(1)
expect(planGoal).toHaveBeenCalledTimes(1)
expect(planGoal).toHaveBeenCalledWith(expect.objectContaining({ personaAuthorized: false }))
})
it('enables persona-primary planning only for an exact request-bound authorization receipt', async () => {
const planGoal = vi.fn().mockResolvedValue(plannedGoal)
await planPersonaLanguageShellGoal({
...input(),
loadPersonaControlAuthorization: vi.fn().mockResolvedValue({
schema: 'hololake.persona-control-authorization/v1',
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),
}),
authorizationObservedAt: Date.parse('2026-08-12T04:35:00+08:00'),
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: true }))
})
it('returns a stable binding error and never invokes cognition for invalid device evidence', async () => {

View file

@ -2,6 +2,7 @@ import { invoke } from '@tauri-apps/api/core'
import { isTauri, mockInvoke } from '../mock-tauri'
import type { AiModelProvider } from './aiTargets'
import type { LanguageGoalProjection, RealityBoundary } from './languageOperatingModel'
import { hasPersonaPrimaryControlAuthorization } from './personaControlAuthorization'
import {
planPersonaLanguageGoal,
type PersonaLanguageGoalBinding,
@ -34,6 +35,14 @@ export type PersonaLanguageShellPlan =
type RepositoryResolver = typeof resolvePersonaRepositoryBinding
type GoalPlanner = (input: PlanPersonaLanguageGoalInput) => Promise<LanguageGoalProjection>
type DeviceIdentityLoader = () => Promise<unknown>
type PersonaControlAuthorizationLoader = (input: {
personaId: string
humanResponsibilitySubject: string
repositoryHead: string
modelInstanceId: string
requestId: string
sourceLanguageAnchor: string
}) => Promise<unknown>
async function loadNativeDeviceIdentity(): Promise<unknown> {
return isTauri()
@ -41,6 +50,10 @@ async function loadNativeDeviceIdentity(): Promise<unknown> {
: mockInvoke<unknown>('guanghu_router_device_identity')
}
async function loadNoPersonaControlAuthorization(): Promise<null> {
return null
}
function errorCode(error: unknown, fallback: string): string {
return error instanceof Error && error.message.trim() ? error.message : fallback
}
@ -66,7 +79,7 @@ export async function planPersonaLanguageShellGoal({
personaId,
repositoryPaths,
providers,
personaAuthorized,
authorizationObservedAt,
detectedBoundaries,
requestId,
modelInstanceId,
@ -74,13 +87,14 @@ export async function planPersonaLanguageShellGoal({
sourceLanguageAnchor,
resolveRepository = resolvePersonaRepositoryBinding,
loadDeviceIdentity = loadNativeDeviceIdentity,
loadPersonaControlAuthorization = loadNoPersonaControlAuthorization,
planGoal = planPersonaLanguageGoal,
}: {
utterance: string
personaId: string
repositoryPaths: readonly string[]
providers: readonly AiModelProvider[]
personaAuthorized: boolean
authorizationObservedAt?: number
detectedBoundaries?: RealityBoundary[]
requestId: string
modelInstanceId: string
@ -88,6 +102,7 @@ export async function planPersonaLanguageShellGoal({
sourceLanguageAnchor: string
resolveRepository?: RepositoryResolver
loadDeviceIdentity?: DeviceIdentityLoader
loadPersonaControlAuthorization?: PersonaControlAuthorizationLoader
planGoal?: GoalPlanner
}): Promise<PersonaLanguageShellPlan> {
const repository = await resolveRepository({ personaId, repositoryPaths })
@ -121,6 +136,28 @@ export async function planPersonaLanguageShellGoal({
}
try {
const authorizationExpectation = {
personaId: repository.binding.personaId,
humanResponsibilitySubject: repository.binding.humanResponsibilitySubject,
repositoryHead: repository.binding.gitHead,
modelInstanceId,
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.
}
const personaAuthorized = hasPersonaPrimaryControlAuthorization(
personaAuthorizationReceipt,
{
...authorizationExpectation,
observedAt: authorizationObservedAt,
},
)
const goal = await planGoal({
utterance,
personaAuthorized,