Project live domain trust readiness

This commit is contained in:
冰朔 2026-08-10 05:01:32 +08:00
commit 7a90fad360
5 changed files with 120 additions and 4 deletions

View file

@ -43,8 +43,17 @@ interface ServerProfile {
interface DomainAccessStatus {
blockers: string[];
domainId?: string;
nodeId?: string;
runtimeReady: boolean;
stage: 'checking' | 'login-required' | 'identity-verified' | 'runtime-ready';
trustSource?: {
reason?: 'ANCHOR_INVALID' | 'REGISTRY_INVALID' | 'SOURCE_UNAVAILABLE';
registryVersion: string | null;
signerCount: number;
sourceCommit: string | null;
status: 'CURRENT' | 'DEGRADED_LAST_KNOWN_GOOD' | 'UNAVAILABLE';
};
}
function findFirstDocument(nodes: DocTreeNode[]): string | null {

View file

@ -1,5 +1,5 @@
import { Cloud, Laptop, ShieldCheck, X } from 'lucide-react';
import { projectDomainConnectionSteps, type DomainAccessProjection } from '../domain-connection';
import { projectDomainConnectionSteps, projectDomainTrustSource, type DomainAccessProjection } from '../domain-connection';
interface Props {
access: DomainAccessProjection;
@ -27,6 +27,7 @@ export function DomainConnectionSheet({ access, open, onClose, onEnterRuntime, o
</header>
<p className="domain-connection-lead">线</p>
<p className="domain-connection-boundary">{projectDomainTrustSource(access)}</p>
<div className="domain-node-modes" aria-label="支持的节点类型">
<article><Laptop aria-hidden="true" /><span><strong></strong><small>使</small></span></article>
@ -57,4 +58,3 @@ export function DomainConnectionSheet({ access, open, onClose, onEnterRuntime, o
</div>
);
}

View file

@ -1,6 +1,6 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { projectDomainConnectionSteps } from './domain-connection.js';
import { projectDomainConnectionSteps, projectDomainTrustSource } from './domain-connection.js';
test('code-channel account absence cannot be projected as a domain runtime login', () => {
const steps = projectDomainConnectionSteps({
@ -35,3 +35,37 @@ test('runtime-ready requires all four verified steps', () => {
assert.ok(steps.every(step => step.state === 'verified'));
});
test('a current empty signer registry is projected as a real manifest blocker', () => {
const access = {
blockers: ['verified_domain_manifest_missing'],
runtimeReady: false,
stage: 'identity-verified' as const,
trustSource: {
registryVersion: '1.0.0',
signerCount: 0,
sourceCommit: '34e1949a113be8d4871e61c094f2ae06e0bc5a45',
status: 'CURRENT' as const,
},
};
const manifest = projectDomainConnectionSteps(access)[1];
assert.equal(manifest.state, 'blocked');
assert.match(manifest.detail, /尚未登记任何目标域签名人/);
assert.match(projectDomainTrustSource(access), /当前.*v1\.0\.0.*34e1949a.*已登记签名人 0/);
});
test('an unavailable trust source remains closed without leaking raw transport details', () => {
const access = {
blockers: ['verified_domain_manifest_missing'],
runtimeReady: false,
stage: 'identity-verified' as const,
trustSource: {
reason: 'SOURCE_UNAVAILABLE' as const,
registryVersion: null,
signerCount: 0,
sourceCommit: null,
status: 'UNAVAILABLE' as const,
},
};
assert.match(projectDomainConnectionSteps(access)[1].detail, /系统保持关闭/);
assert.equal(projectDomainTrustSource(access), '可信清单来源不可用 · 域入口保持关闭');
});

View file

@ -2,8 +2,17 @@ export type DomainAccessStage = 'checking' | 'login-required' | 'identity-verifi
export interface DomainAccessProjection {
blockers: string[];
domainId?: string;
nodeId?: string;
runtimeReady: boolean;
stage: DomainAccessStage;
trustSource?: {
reason?: 'ANCHOR_INVALID' | 'REGISTRY_INVALID' | 'SOURCE_UNAVAILABLE';
registryVersion: string | null;
signerCount: number;
sourceCommit: string | null;
status: 'CURRENT' | 'DEGRADED_LAST_KNOWN_GOOD' | 'UNAVAILABLE';
};
}
export interface DomainConnectionStep {
@ -51,12 +60,31 @@ export function projectDomainConnectionSteps(access: DomainAccessProjection): Do
return ordered.map(id => {
const copy = stepCopy[id];
const verified = access.runtimeReady || (!blockers.has(id) && access.stage !== 'checking');
let detail = verified ? copy.verified : copy.pending;
if (!verified && id === 'manifest' && access.trustSource) {
if (access.trustSource.status === 'UNAVAILABLE') {
detail = '当前无法回读灯塔的可信签名人登记表;系统保持关闭,不使用缓存猜测域权限';
} else if (access.trustSource.status === 'DEGRADED_LAST_KNOWN_GOOD') {
detail = '当前只能回读上一次可信签名人快照;实时来源恢复前不签发新的域权限';
} else if (access.trustSource.signerCount === 0) {
detail = '灯塔登记表已回读为当前版本,但尚未登记任何目标域签名人';
}
}
return {
id,
label: copy.label,
state: access.stage === 'checking' ? 'checking' : verified ? 'verified' : 'blocked',
detail: access.stage === 'checking' ? '正在核对当前接入证据' : verified ? copy.verified : copy.pending,
detail: access.stage === 'checking' ? '正在核对当前接入证据' : detail,
};
});
}
export function projectDomainTrustSource(access: DomainAccessProjection): string {
const source = access.trustSource;
if (!source) return '可信清单来源尚未由桌面运行时回读';
if (source.status === 'UNAVAILABLE') return '可信清单来源不可用 · 域入口保持关闭';
const commit = source.sourceCommit ? source.sourceCommit.slice(0, 8) : '未知提交';
const version = source.registryVersion ?? '未知版本';
const health = source.status === 'CURRENT' ? '当前' : '上次可信快照';
return `可信清单 ${health} · v${version} · ${commit} · 已登记签名人 ${source.signerCount}`;
}