fix: enforce one human one independent node

This commit is contained in:
冰朔 2026-08-10 21:07:30 +08:00
commit cec261174d
32 changed files with 474 additions and 75 deletions

View file

@ -20,7 +20,7 @@ const NOW = 1_786_291_200_000
function manifest(): VerifiedDomainManifest {
return {
public: {
accessModes: ['LOCAL_TERMINAL_NODE', 'CLOUD_RESIDENT_NODE'],
accessModes: ['LOCAL_TERMINAL_NODE', 'USER_OWNED_REMOTE_NODE'],
displayName: '第五域 · 光湖本源域',
domainId: 'DOM-FIFTH-0001',
formalName: '光湖本源域',
@ -104,7 +104,7 @@ describe('domain runtime contract', () => {
expect(() => assertVerifiedDomainManifest(candidate)).toThrow('domain_manifest_digest_invalid')
})
it.each(['LOCAL_TERMINAL_NODE', 'CLOUD_RESIDENT_NODE'] as const)(
it.each(['LOCAL_TERMINAL_NODE', 'USER_OWNED_REMOTE_NODE'] as const)(
'accepts %s as a user-owned access node type',
(nodeType) => {
const selected = selectPublicDomain(INITIAL_DOMAIN_ACCESS_STATE, manifest().public)
@ -143,16 +143,24 @@ describe('domain runtime contract', () => {
expect(() => acceptDomainSession(access, session({ domainId: 'DOMAIN-OTHER' }), NOW))
.toThrow('domain_session_domain_mismatch')
expect(() => acceptDomainSession(access, session({ nodeType: 'CLOUD_RESIDENT_NODE' }), NOW))
expect(() => acceptDomainSession(access, session({ nodeType: 'USER_OWNED_REMOTE_NODE' }), NOW))
.toThrow('domain_session_node_type_mismatch')
const withSession = acceptDomainSession(access, session(), NOW)
expect(() => acceptDomainConnectionReceipt(withSession, receipt({ domainId: 'DOMAIN-OTHER' })))
.toThrow('domain_connection_domain_mismatch')
expect(() => acceptDomainConnectionReceipt(withSession, receipt({ nodeType: 'CLOUD_RESIDENT_NODE' })))
expect(() => acceptDomainConnectionReceipt(withSession, receipt({ nodeType: 'USER_OWNED_REMOTE_NODE' })))
.toThrow('domain_connection_node_type_mismatch')
})
it('rejects the retired ambiguous cloud-resident node alias', () => {
const candidate = manifest()
candidate.public.accessModes = ['CLOUD_RESIDENT_NODE' as never]
expect(() => assertVerifiedDomainManifest(candidate))
.toThrow('domain_manifest_access_mode_invalid')
})
it('drops execution authority and keeps an explicit read-only scene after disconnect', () => {
const selected = selectPublicDomain(INITIAL_DOMAIN_ACCESS_STATE, manifest().public)
const access = beginDomainAccess(selected, manifest(), 'LOCAL_TERMINAL_NODE')

View file

@ -1,4 +1,4 @@
export type DomainNodeType = 'LOCAL_TERMINAL_NODE' | 'CLOUD_RESIDENT_NODE'
export type DomainNodeType = 'LOCAL_TERMINAL_NODE' | 'USER_OWNED_REMOTE_NODE'
export type PublicDomainStatus = 'PUBLIC_PREVIEW' | 'RESTRICTED_PREVIEW' | 'UNAVAILABLE'
@ -125,7 +125,9 @@ function publicDomain(domain: PublicDomainVestibule): PublicDomainVestibule {
if (!domain.accessModes.length) {
throw new DomainContractError('domain_manifest_access_modes_missing')
}
if (domain.accessModes.some(mode => mode !== 'LOCAL_TERMINAL_NODE' && mode !== 'CLOUD_RESIDENT_NODE')) {
if (domain.accessModes.some(
mode => mode !== 'LOCAL_TERMINAL_NODE' && mode !== 'USER_OWNED_REMOTE_NODE',
)) {
throw new DomainContractError('domain_manifest_access_mode_invalid')
}
if (domain.themePreview) {