Bind domain access to registered node type
This commit is contained in:
parent
f3a1ee82a2
commit
8807b99d98
15 changed files with 168 additions and 63 deletions
|
|
@ -2,6 +2,7 @@ import {
|
|||
evaluateDomainAccess,
|
||||
verifyDomainAccessHandoffFromSnapshot,
|
||||
type DomainAccessEvidence,
|
||||
type DomainNodeType,
|
||||
type DomainAccessStatus,
|
||||
} from './domain-access.js';
|
||||
import {
|
||||
|
|
@ -14,10 +15,11 @@ const IDENTIFIER_PATTERN = /^[A-Z0-9][A-Z0-9._:-]{1,159}$/;
|
|||
export interface DomainIdentityProjection {
|
||||
accountVerified: boolean;
|
||||
nodeId: string;
|
||||
nodeRegistrationVerified: boolean;
|
||||
}
|
||||
|
||||
export interface DomainIdentitySource {
|
||||
read(domainId: string): Promise<DomainIdentityProjection>;
|
||||
read(domainId: string, nodeType: DomainNodeType): Promise<DomainIdentityProjection>;
|
||||
}
|
||||
|
||||
export interface DomainRuntimeHandoffCandidate {
|
||||
|
|
@ -29,7 +31,7 @@ export interface DomainRuntimeHandoffCandidate {
|
|||
}
|
||||
|
||||
export interface DomainRuntimeHandoffSource {
|
||||
read(domainId: string, nodeId: string): Promise<DomainRuntimeHandoffCandidate | null>;
|
||||
read(domainId: string, nodeId: string, nodeType: DomainNodeType): Promise<DomainRuntimeHandoffCandidate | null>;
|
||||
}
|
||||
|
||||
export interface DomainAccessProjection {
|
||||
|
|
@ -37,6 +39,7 @@ export interface DomainAccessProjection {
|
|||
domainId: string;
|
||||
localWorkspaceAllowed: true;
|
||||
nodeId: string;
|
||||
nodeType: DomainNodeType;
|
||||
runtimeReady: boolean;
|
||||
stage: DomainAccessStatus['stage'];
|
||||
trustSource: Readonly<TrustedSignerSnapshotReceipt>;
|
||||
|
|
@ -44,7 +47,7 @@ export interface DomainAccessProjection {
|
|||
|
||||
function safeIdentity(input: unknown): DomainIdentityProjection {
|
||||
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
|
||||
return { accountVerified: false, nodeId: '' };
|
||||
return { accountVerified: false, nodeId: '', nodeRegistrationVerified: false };
|
||||
}
|
||||
const candidate = input as Record<string, unknown>;
|
||||
const nodeId = typeof candidate.nodeId === 'string' && IDENTIFIER_PATTERN.test(candidate.nodeId)
|
||||
|
|
@ -53,6 +56,7 @@ function safeIdentity(input: unknown): DomainIdentityProjection {
|
|||
return {
|
||||
accountVerified: candidate.accountVerified === true && Boolean(nodeId),
|
||||
nodeId,
|
||||
nodeRegistrationVerified: candidate.nodeRegistrationVerified === true && Boolean(nodeId),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -63,22 +67,25 @@ export class DomainAccessOrchestrator {
|
|||
private readonly handoffs: DomainRuntimeHandoffSource,
|
||||
) {}
|
||||
|
||||
async domainAccess(domainId: string, now = Date.now()): Promise<Readonly<DomainAccessProjection>> {
|
||||
async domainAccess(domainId: string, nodeType: DomainNodeType, now = Date.now()): Promise<Readonly<DomainAccessProjection>> {
|
||||
if (!IDENTIFIER_PATTERN.test(domainId)) throw new Error('domain_access_domain_invalid');
|
||||
if (nodeType !== 'local-terminal' && nodeType !== 'cloud-resident') throw new Error('domain_access_node_type_invalid');
|
||||
const [snapshot, identity] = await Promise.all([
|
||||
this.signerSnapshots.refresh(),
|
||||
this.identities.read(domainId).then(safeIdentity, () => safeIdentity(null)),
|
||||
this.identities.read(domainId, nodeType).then(safeIdentity, () => safeIdentity(null)),
|
||||
]);
|
||||
const evidence: DomainAccessEvidence = {
|
||||
accountVerified: identity.accountVerified,
|
||||
domainId,
|
||||
nodeId: identity.nodeId,
|
||||
nodeRegistrationVerified: identity.nodeRegistrationVerified,
|
||||
nodeType,
|
||||
};
|
||||
|
||||
if (identity.accountVerified) {
|
||||
if (identity.accountVerified && identity.nodeRegistrationVerified) {
|
||||
let candidate: DomainRuntimeHandoffCandidate | null = null;
|
||||
try {
|
||||
candidate = await this.handoffs.read(domainId, identity.nodeId);
|
||||
candidate = await this.handoffs.read(domainId, identity.nodeId, nodeType);
|
||||
} catch {
|
||||
candidate = null;
|
||||
}
|
||||
|
|
@ -88,6 +95,7 @@ export class DomainAccessOrchestrator {
|
|||
candidate.handoff,
|
||||
domainId,
|
||||
identity.nodeId,
|
||||
nodeType,
|
||||
candidate.signerLookup,
|
||||
snapshot,
|
||||
now,
|
||||
|
|
|
|||
Loading…
Reference in a new issue