159 lines
5.9 KiB
TypeScript
159 lines
5.9 KiB
TypeScript
|
|
import { describe, expect, it } from 'vitest'
|
||
|
|
import {
|
||
|
|
INITIAL_DOMAIN_ACCESS_STATE,
|
||
|
|
acceptDomainConnectionReceipt,
|
||
|
|
acceptDomainSession,
|
||
|
|
assertVerifiedDomainManifest,
|
||
|
|
beginDomainAccess,
|
||
|
|
disconnectDomainRuntime,
|
||
|
|
enterDomainRuntime,
|
||
|
|
projectPublicDomainVestibule,
|
||
|
|
selectPublicDomain,
|
||
|
|
type DomainConnectionReceipt,
|
||
|
|
type DomainSessionCapability,
|
||
|
|
type VerifiedDomainManifest,
|
||
|
|
} from './domainRuntimeContract'
|
||
|
|
|
||
|
|
const DIGEST = 'a'.repeat(64)
|
||
|
|
const NOW = 1_786_291_200_000
|
||
|
|
|
||
|
|
function manifest(): VerifiedDomainManifest {
|
||
|
|
return {
|
||
|
|
public: {
|
||
|
|
accessModes: ['LOCAL_TERMINAL_NODE', 'CLOUD_RESIDENT_NODE'],
|
||
|
|
displayName: '第五域 · 光湖本源域',
|
||
|
|
domainId: 'DOM-FIFTH-0001',
|
||
|
|
formalName: '光湖本源域',
|
||
|
|
publicStatus: 'PUBLIC_PREVIEW',
|
||
|
|
purpose: '零点原核的工程本体与语言架构源点域',
|
||
|
|
responsibleParty: '第五域主控',
|
||
|
|
themePreview: {
|
||
|
|
assetRef: 'theme-preview://origin-domain/lake-reflects-stars',
|
||
|
|
description: '湖面映星公开预览',
|
||
|
|
},
|
||
|
|
},
|
||
|
|
provenance: {
|
||
|
|
digest: DIGEST,
|
||
|
|
repositoryId: 'REPO-012',
|
||
|
|
signature: 'signature-envelope-reference',
|
||
|
|
signerId: 'SIGNER-FIFTH-DOMAIN-001',
|
||
|
|
sourceCommit: '6e26d1f35439759542efb317c3ddd7661ba27d58',
|
||
|
|
},
|
||
|
|
runtime: {
|
||
|
|
backendVersion: 'not-published',
|
||
|
|
channelIds: ['CHANNEL-ZERO-CORE'],
|
||
|
|
forbiddenDataScopes: ['private-relationship-core'],
|
||
|
|
frontendVersion: 'not-published',
|
||
|
|
healthCheckRef: 'health://origin-domain/runtime',
|
||
|
|
moduleIds: ['MODULE-LANGUAGE-ARCHITECTURE'],
|
||
|
|
rollbackVersion: 'not-published',
|
||
|
|
routeRef: 'domain-route://origin-domain/runtime',
|
||
|
|
themePackageRef: 'theme://origin-domain/lake-reflects-stars',
|
||
|
|
},
|
||
|
|
schema: 'gh-aios.domain-manifest/v1',
|
||
|
|
verification: {
|
||
|
|
manifestDigest: DIGEST,
|
||
|
|
state: 'verified',
|
||
|
|
verifiedAt: NOW,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function session(overrides: Partial<DomainSessionCapability> = {}): DomainSessionCapability {
|
||
|
|
return {
|
||
|
|
capabilityId: 'CAP-001',
|
||
|
|
domainId: 'DOM-FIFTH-0001',
|
||
|
|
expiresAt: NOW + 60_000,
|
||
|
|
nodeId: 'LOCAL-NODE-001',
|
||
|
|
scopes: ['domain:enter'],
|
||
|
|
...overrides,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function receipt(overrides: Partial<DomainConnectionReceipt> = {}): DomainConnectionReceipt {
|
||
|
|
return {
|
||
|
|
connectionId: 'CONNECTION-001',
|
||
|
|
domainId: 'DOM-FIFTH-0001',
|
||
|
|
manifestDigest: DIGEST,
|
||
|
|
nodeId: 'LOCAL-NODE-001',
|
||
|
|
receiptId: 'RECEIPT-001',
|
||
|
|
state: 'online',
|
||
|
|
...overrides,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
describe('domain runtime contract', () => {
|
||
|
|
it('projects only public vestibule fields', () => {
|
||
|
|
const publicView = projectPublicDomainVestibule(manifest())
|
||
|
|
const serialized = JSON.stringify(publicView)
|
||
|
|
|
||
|
|
expect(publicView.displayName).toBe('第五域 · 光湖本源域')
|
||
|
|
expect(serialized).not.toContain('domain-route://')
|
||
|
|
expect(serialized).not.toContain('CHANNEL-ZERO-CORE')
|
||
|
|
expect(serialized).not.toContain('private-relationship-core')
|
||
|
|
expect(serialized).not.toContain('REPO-012')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('rejects a manifest that has not passed the external signature verifier', () => {
|
||
|
|
const candidate = manifest()
|
||
|
|
candidate.verification.state = 'verified'
|
||
|
|
candidate.verification.manifestDigest = 'b'.repeat(64)
|
||
|
|
|
||
|
|
expect(() => assertVerifiedDomainManifest(candidate)).toThrow('domain_manifest_digest_invalid')
|
||
|
|
})
|
||
|
|
|
||
|
|
it.each(['LOCAL_TERMINAL_NODE', 'CLOUD_RESIDENT_NODE'] as const)(
|
||
|
|
'accepts %s as a user-owned access node type',
|
||
|
|
(nodeType) => {
|
||
|
|
const selected = selectPublicDomain(INITIAL_DOMAIN_ACCESS_STATE, manifest().public)
|
||
|
|
const access = beginDomainAccess(selected, manifest(), nodeType)
|
||
|
|
|
||
|
|
expect(access).toMatchObject({ nodeType, stage: 'access' })
|
||
|
|
},
|
||
|
|
)
|
||
|
|
|
||
|
|
it('does not enter a runtime with only a selected vestibule or frontend login state', () => {
|
||
|
|
const selected = selectPublicDomain(INITIAL_DOMAIN_ACCESS_STATE, manifest().public)
|
||
|
|
const access = beginDomainAccess(selected, manifest(), 'LOCAL_TERMINAL_NODE')
|
||
|
|
|
||
|
|
expect(() => enterDomainRuntime(access, NOW)).toThrow('domain_runtime_session_missing')
|
||
|
|
const withSession = acceptDomainSession(access, session(), NOW)
|
||
|
|
expect(() => enterDomainRuntime(withSession, NOW)).toThrow('domain_runtime_connection_receipt_missing')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('enters only after a matching live session and connection receipt', () => {
|
||
|
|
const selected = selectPublicDomain(INITIAL_DOMAIN_ACCESS_STATE, manifest().public)
|
||
|
|
const access = beginDomainAccess(selected, manifest(), 'LOCAL_TERMINAL_NODE')
|
||
|
|
const withSession = acceptDomainSession(access, session(), NOW)
|
||
|
|
const connected = acceptDomainConnectionReceipt(withSession, receipt())
|
||
|
|
const runtime = enterDomainRuntime(connected, NOW)
|
||
|
|
|
||
|
|
expect(runtime).toMatchObject({
|
||
|
|
mode: 'connected',
|
||
|
|
nodeType: 'LOCAL_TERMINAL_NODE',
|
||
|
|
stage: 'runtime',
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
it('fails closed when the session or receipt belongs to another domain', () => {
|
||
|
|
const selected = selectPublicDomain(INITIAL_DOMAIN_ACCESS_STATE, manifest().public)
|
||
|
|
const access = beginDomainAccess(selected, manifest(), 'LOCAL_TERMINAL_NODE')
|
||
|
|
|
||
|
|
expect(() => acceptDomainSession(access, session({ domainId: 'DOMAIN-OTHER' }), NOW))
|
||
|
|
.toThrow('domain_session_domain_mismatch')
|
||
|
|
|
||
|
|
const withSession = acceptDomainSession(access, session(), NOW)
|
||
|
|
expect(() => acceptDomainConnectionReceipt(withSession, receipt({ domainId: 'DOMAIN-OTHER' })))
|
||
|
|
.toThrow('domain_connection_domain_mismatch')
|
||
|
|
})
|
||
|
|
|
||
|
|
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')
|
||
|
|
const withSession = acceptDomainSession(access, session(), NOW)
|
||
|
|
const connected = acceptDomainConnectionReceipt(withSession, receipt())
|
||
|
|
const runtime = enterDomainRuntime(connected, NOW)
|
||
|
|
|
||
|
|
expect(disconnectDomainRuntime(runtime).mode).toBe('disconnected-readonly')
|
||
|
|
})
|
||
|
|
})
|