import { createHash, verify as verifySignature } from 'node:crypto'; import { assertRegisteredTrustedManifestSigner, resolveTrustedManifestSigner, type TrustedManifestSigner, type TrustedSignerLookup, } from './trusted-signer-registry.js'; import { assertLoadedTrustedSignerSnapshot, type TrustedSignerSnapshotReceipt, type TrustedSignerSnapshotResult, } from './trusted-signer-snapshot.js'; const MANIFEST_SCHEMA = 'gh-aios.domain-manifest/v1' as const; const SHA256_PATTERN = /^[a-f0-9]{64}$/; const COMMIT_PATTERN = /^[a-f0-9]{40}(?:[a-f0-9]{24})?$/; const POLICY_SCOPE_PATTERN = /^[a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?$/; const POLICY_REFERENCE_PATTERN = /^[a-z][a-z0-9+.-]*:\/\/[A-Za-z0-9._~:/-]{1,240}$/; const cryptographicallyVerifiedManifests = new WeakSet(); export type DomainNodeType = 'local-terminal' | 'cloud-resident'; export type DomainThemeOwner = 'domain-team' | 'fifth-domain'; export interface DomainRuntimeManifestPolicy { allowedSessionScopes: readonly string[]; forbiddenDataScopes: readonly string[]; permissionPolicyRef: string; routeRef: string; themeOwner: DomainThemeOwner; themePackageRef: string; } export interface DomainManifestEvidence { digest: string; domainId: string; repositoryId: string; runtimePolicy: DomainRuntimeManifestPolicy; schema: typeof MANIFEST_SCHEMA; signature: string; signerId: string; sourceCommit: string; verifierReceipt: { manifestDigest: string; signerId: string; state: 'verified'; verifiedAt: number; verifierId: string; }; } export interface DomainManifestSignedPayload { domainId: string; repositoryId: string; runtimePolicy: DomainRuntimeManifestPolicy; schema: typeof MANIFEST_SCHEMA; signerId: string; sourceCommit: string; } export interface DomainSessionCapability { capabilityId: string; domainId: string; expiresAt: number; nodeId: string; nodeType: DomainNodeType; scopes: string[]; } export interface DomainConnectionReceipt { connectionId: string; domainId: string; manifestDigest: string; nodeId: string; nodeType: DomainNodeType; receiptId: string; state: 'online'; } export interface DomainAccessHandoff { connectionReceipt: DomainConnectionReceipt; manifest: DomainManifestEvidence; sessionCapability: DomainSessionCapability; } export interface DomainAccessHandoffVerification { handoff: DomainAccessHandoff; trustSource: Readonly; } export interface DomainAccessEvidence { accountVerified: boolean; connectionReceipt?: DomainConnectionReceipt; domainId: string; manifest?: DomainManifestEvidence; nodeId: string; nodePossessionVerified: boolean; nodeRegistrationVerified: boolean; nodeType: DomainNodeType; sessionCapability?: DomainSessionCapability; } export interface DomainRuntimePolicyProjection { allowedSessionScopes: readonly string[]; forbiddenDataScopes: readonly string[]; manifestDigest: string; permissionPolicyRef: string; routeRef: string; themeOwner: DomainThemeOwner; themePackageRef: string; } export interface DomainAccessStatus { blockers: string[]; domainId: string; localWorkspaceAllowed: true; nodeId: string; nodeType: DomainNodeType; runtimePolicy?: DomainRuntimePolicyProjection; runtimeReady: boolean; stage: 'login-required' | 'identity-verified' | 'runtime-ready'; } function isRecord(value: unknown): value is Record { return typeof value === 'object' && value !== null && !Array.isArray(value); } function hasExactKeys(record: Record, keys: string[]): boolean { const actual = Object.keys(record).sort(); return actual.length === keys.length && actual.every((key, index) => key === [...keys].sort()[index]); } function isIdentifier(value: unknown): value is string { return typeof value === 'string' && value.length > 0 && value.length <= 160; } function isPolicyReference(value: unknown): value is string { return typeof value === 'string' && POLICY_REFERENCE_PATTERN.test(value); } function isPolicyScopeList(value: unknown): value is string[] { return Array.isArray(value) && value.length > 0 && value.length <= 64 && value.every((scope) => typeof scope === 'string' && POLICY_SCOPE_PATTERN.test(scope)) && new Set(value).size === value.length; } function invalidHandoff(): never { throw new Error('domain_access_handoff_invalid'); } export function domainManifestSigningBytes(payload: DomainManifestSignedPayload): Buffer { return Buffer.from(JSON.stringify({ domainId: payload.domainId, repositoryId: payload.repositoryId, runtimePolicy: { allowedSessionScopes: payload.runtimePolicy.allowedSessionScopes, forbiddenDataScopes: payload.runtimePolicy.forbiddenDataScopes, permissionPolicyRef: payload.runtimePolicy.permissionPolicyRef, routeRef: payload.runtimePolicy.routeRef, themeOwner: payload.runtimePolicy.themeOwner, themePackageRef: payload.runtimePolicy.themePackageRef, }, schema: payload.schema, signerId: payload.signerId, sourceCommit: payload.sourceCommit, }), 'utf8'); } /** * Validates the structure and binding of evidence returned by a trusted route. * Cryptographic signature verification is deliberately external: this boundary * only accepts a signer-bound verifier receipt and never treats a boolean as proof. */ export function parseDomainAccessHandoff( input: unknown, expectedDomainId: string, expectedNodeId: string, expectedNodeType: DomainNodeType, trustedSigner: TrustedManifestSigner, now = Date.now(), ): DomainAccessHandoff { assertRegisteredTrustedManifestSigner(trustedSigner); if (!isRecord(input) || !hasExactKeys(input, ['connectionReceipt', 'manifest', 'sessionCapability'])) invalidHandoff(); const manifest = input.manifest; const capability = input.sessionCapability; const connection = input.connectionReceipt; if (!isRecord(manifest) || !hasExactKeys(manifest, ['digest', 'domainId', 'repositoryId', 'runtimePolicy', 'schema', 'signature', 'signerId', 'sourceCommit'])) invalidHandoff(); if (!isRecord(capability) || !hasExactKeys(capability, ['capabilityId', 'domainId', 'expiresAt', 'nodeId', 'nodeType', 'scopes'])) invalidHandoff(); if (!isRecord(connection) || !hasExactKeys(connection, ['connectionId', 'domainId', 'manifestDigest', 'nodeId', 'nodeType', 'receiptId', 'state'])) invalidHandoff(); const runtimePolicy = manifest.runtimePolicy; if (!isRecord(runtimePolicy) || !hasExactKeys(runtimePolicy, ['allowedSessionScopes', 'forbiddenDataScopes', 'permissionPolicyRef', 'routeRef', 'themeOwner', 'themePackageRef'])) invalidHandoff(); const allowedSessionScopes = runtimePolicy.allowedSessionScopes; const forbiddenDataScopes = runtimePolicy.forbiddenDataScopes; const digest = manifest.digest; if (manifest.schema !== MANIFEST_SCHEMA || typeof digest !== 'string' || !SHA256_PATTERN.test(digest) || manifest.domainId !== expectedDomainId || manifest.repositoryId !== trustedSigner.repositoryId || manifest.signerId !== trustedSigner.signerId || trustedSigner.algorithm !== 'Ed25519' || !isIdentifier(trustedSigner.publicKeyPem) || !isIdentifier(manifest.signerId) || typeof manifest.sourceCommit !== 'string' || !COMMIT_PATTERN.test(manifest.sourceCommit) || typeof manifest.signature !== 'string') invalidHandoff(); if (!isPolicyScopeList(allowedSessionScopes) || !allowedSessionScopes.includes('domain:enter') || !isPolicyScopeList(forbiddenDataScopes) || !isPolicyReference(runtimePolicy.permissionPolicyRef) || !isPolicyReference(runtimePolicy.routeRef) || !isPolicyReference(runtimePolicy.themePackageRef) || (runtimePolicy.themeOwner !== 'domain-team' && runtimePolicy.themeOwner !== 'fifth-domain') || (expectedDomainId === 'DOM-FIFTH-0001' ? runtimePolicy.themeOwner !== 'fifth-domain' || !runtimePolicy.themePackageRef.startsWith('theme://origin-domain/') : runtimePolicy.themeOwner !== 'domain-team' || runtimePolicy.themePackageRef.startsWith('theme://origin-domain/'))) invalidHandoff(); const signedPayload = domainManifestSigningBytes({ domainId: manifest.domainId, repositoryId: manifest.repositoryId, runtimePolicy: runtimePolicy as unknown as DomainRuntimeManifestPolicy, schema: manifest.schema, signerId: manifest.signerId, sourceCommit: manifest.sourceCommit, }); if (createHash('sha256').update(signedPayload).digest('hex') !== digest) invalidHandoff(); let signature: Buffer; try { signature = Buffer.from(manifest.signature, 'base64'); if (signature.length !== 64 || signature.toString('base64') !== manifest.signature) invalidHandoff(); if (!verifySignature(null, signedPayload, trustedSigner.publicKeyPem, signature)) invalidHandoff(); } catch { invalidHandoff(); } if (!isIdentifier(capability.capabilityId) || capability.domainId !== expectedDomainId || capability.nodeId !== expectedNodeId || capability.nodeType !== expectedNodeType || typeof capability.expiresAt !== 'number' || !Number.isSafeInteger(capability.expiresAt) || capability.expiresAt <= now || !Array.isArray(capability.scopes) || capability.scopes.some((scope) => !isIdentifier(scope)) || new Set(capability.scopes).size !== capability.scopes.length || !capability.scopes.includes('domain:enter') || capability.scopes.some((scope) => !allowedSessionScopes.includes(scope))) invalidHandoff(); if (!isIdentifier(connection.connectionId) || !isIdentifier(connection.receiptId) || connection.domainId !== expectedDomainId || connection.nodeId !== expectedNodeId || connection.nodeType !== expectedNodeType || connection.manifestDigest !== digest || connection.state !== 'online') invalidHandoff(); const handoff: DomainAccessHandoff = { connectionReceipt: connection as unknown as DomainConnectionReceipt, manifest: { digest, domainId: manifest.domainId as string, repositoryId: manifest.repositoryId as string, runtimePolicy: Object.freeze({ allowedSessionScopes: Object.freeze([...allowedSessionScopes]), forbiddenDataScopes: Object.freeze([...forbiddenDataScopes]), permissionPolicyRef: runtimePolicy.permissionPolicyRef as string, routeRef: runtimePolicy.routeRef as string, themeOwner: runtimePolicy.themeOwner as DomainThemeOwner, themePackageRef: runtimePolicy.themePackageRef as string, }), schema: manifest.schema, signature: manifest.signature, signerId: manifest.signerId as string, sourceCommit: manifest.sourceCommit, verifierReceipt: { manifestDigest: digest, signerId: manifest.signerId, state: 'verified', verifiedAt: now, verifierId: 'HOLOLAKE-DESKTOP-ED25519', }, }, sessionCapability: capability as unknown as DomainSessionCapability, }; cryptographicallyVerifiedManifests.add(handoff.manifest); return handoff; } export function verifyDomainAccessHandoffFromSnapshot( input: unknown, expectedDomainId: string, expectedNodeId: string, expectedNodeType: DomainNodeType, signerLookup: Omit, snapshot: TrustedSignerSnapshotResult, now = Date.now(), ): DomainAccessHandoffVerification { try { const loaded = assertLoadedTrustedSignerSnapshot(snapshot); const registry = loaded.registry; const source = loaded.receipt; if (!registry || source.status === 'UNAVAILABLE' || source.sourceCommit !== registry.source.sourceCommit || source.registryVersion !== registry.version || source.signerCount !== registry.signers.length) invalidHandoff(); const trustedSigner = resolveTrustedManifestSigner(registry, { domainId: expectedDomainId, repositoryId: signerLookup.repositoryId, signerId: signerLookup.signerId, }); if (!trustedSigner) invalidHandoff(); return Object.freeze({ handoff: parseDomainAccessHandoff(input, expectedDomainId, expectedNodeId, expectedNodeType, trustedSigner, now), trustSource: source, }); } catch { invalidHandoff(); } } export function evaluateDomainAccess(evidence: DomainAccessEvidence, now = Date.now()): DomainAccessStatus { const blockers: string[] = []; if (!evidence.accountVerified) blockers.push('account_identity_missing'); if (!evidence.nodeRegistrationVerified || !evidence.nodeId) blockers.push('verified_node_registration_missing'); if (!evidence.nodePossessionVerified) blockers.push('verified_node_possession_missing'); const manifest = evidence.manifest; const verifier = manifest?.verifierReceipt; if (!manifest || !cryptographicallyVerifiedManifests.has(manifest) || manifest.schema !== MANIFEST_SCHEMA || manifest.domainId !== evidence.domainId || !SHA256_PATTERN.test(manifest.digest) || verifier?.state !== 'verified' || verifier.manifestDigest !== manifest.digest || verifier.signerId !== manifest.signerId) { blockers.push('verified_domain_manifest_missing'); } const capability = evidence.sessionCapability; if (!capability || !capability.capabilityId || capability.domainId !== evidence.domainId || capability.nodeId !== evidence.nodeId || capability.nodeType !== evidence.nodeType || capability.expiresAt <= now || !capability.scopes.includes('domain:enter') || capability.scopes.some((scope) => !manifest?.runtimePolicy.allowedSessionScopes.includes(scope))) { blockers.push('scoped_session_capability_missing'); } const receipt = evidence.connectionReceipt; if (!receipt || !receipt.connectionId || !receipt.receiptId || receipt.state !== 'online' || receipt.domainId !== evidence.domainId || receipt.nodeId !== evidence.nodeId || receipt.nodeType !== evidence.nodeType || receipt.manifestDigest !== evidence.manifest?.digest) { blockers.push('matching_connection_receipt_missing'); } const runtimeReady = blockers.length === 0; const runtimePolicy = runtimeReady && manifest ? Object.freeze({ allowedSessionScopes: Object.freeze([...manifest.runtimePolicy.allowedSessionScopes]), forbiddenDataScopes: Object.freeze([...manifest.runtimePolicy.forbiddenDataScopes]), manifestDigest: manifest.digest, permissionPolicyRef: manifest.runtimePolicy.permissionPolicyRef, routeRef: manifest.runtimePolicy.routeRef, themeOwner: manifest.runtimePolicy.themeOwner, themePackageRef: manifest.runtimePolicy.themePackageRef, }) : undefined; return { blockers, domainId: evidence.domainId, localWorkspaceAllowed: true, nodeId: evidence.nodeId, nodeType: evidence.nodeType, ...(runtimePolicy ? { runtimePolicy } : {}), runtimeReady, stage: runtimeReady ? 'runtime-ready' : evidence.accountVerified && evidence.nodeRegistrationVerified && evidence.nodePossessionVerified && Boolean(evidence.nodeId) ? 'identity-verified' : 'login-required', }; }