hololake-system-architecture/product-source/guanghu-knowledge-base/server/domain-access-orchestrator.ts

109 lines
3.2 KiB
TypeScript

import {
evaluateDomainAccess,
verifyDomainAccessHandoffFromSnapshot,
type DomainAccessEvidence,
type DomainAccessStatus,
} from './domain-access.js';
import {
TrustedSignerSnapshotLoader,
type TrustedSignerSnapshotReceipt,
} from './trusted-signer-snapshot.js';
const IDENTIFIER_PATTERN = /^[A-Z0-9][A-Z0-9._:-]{1,159}$/;
export interface DomainIdentityProjection {
accountVerified: boolean;
nodeId: string;
}
export interface DomainIdentitySource {
read(domainId: string): Promise<DomainIdentityProjection>;
}
export interface DomainRuntimeHandoffCandidate {
handoff: unknown;
signerLookup: {
repositoryId: string;
signerId: string;
};
}
export interface DomainRuntimeHandoffSource {
read(domainId: string, nodeId: string): Promise<DomainRuntimeHandoffCandidate | null>;
}
export interface DomainAccessProjection {
blockers: readonly string[];
domainId: string;
localWorkspaceAllowed: true;
nodeId: string;
runtimeReady: boolean;
stage: DomainAccessStatus['stage'];
trustSource: Readonly<TrustedSignerSnapshotReceipt>;
}
function safeIdentity(input: unknown): DomainIdentityProjection {
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
return { accountVerified: false, nodeId: '' };
}
const candidate = input as Record<string, unknown>;
const nodeId = typeof candidate.nodeId === 'string' && IDENTIFIER_PATTERN.test(candidate.nodeId)
? candidate.nodeId
: '';
return {
accountVerified: candidate.accountVerified === true && Boolean(nodeId),
nodeId,
};
}
export class DomainAccessOrchestrator {
constructor(
private readonly signerSnapshots: TrustedSignerSnapshotLoader,
private readonly identities: DomainIdentitySource,
private readonly handoffs: DomainRuntimeHandoffSource,
) {}
async domainAccess(domainId: string, now = Date.now()): Promise<Readonly<DomainAccessProjection>> {
if (!IDENTIFIER_PATTERN.test(domainId)) throw new Error('domain_access_domain_invalid');
const [snapshot, identity] = await Promise.all([
this.signerSnapshots.refresh(),
this.identities.read(domainId).then(safeIdentity, () => safeIdentity(null)),
]);
const evidence: DomainAccessEvidence = {
accountVerified: identity.accountVerified,
domainId,
nodeId: identity.nodeId,
};
if (identity.accountVerified) {
let candidate: DomainRuntimeHandoffCandidate | null = null;
try {
candidate = await this.handoffs.read(domainId, identity.nodeId);
} catch {
candidate = null;
}
if (candidate) {
try {
const verified = verifyDomainAccessHandoffFromSnapshot(
candidate.handoff,
domainId,
identity.nodeId,
candidate.signerLookup,
snapshot,
now,
);
Object.assign(evidence, verified.handoff);
} catch {
// Untrusted or incomplete handoffs remain absent from the projection.
}
}
}
const status = evaluateDomainAccess(evidence, now);
return Object.freeze({
...status,
blockers: Object.freeze([...status.blockers]),
trustSource: snapshot.receipt,
});
}
}