Bind runtime handoff to node proof

This commit is contained in:
冰朔 2026-08-10 08:25:34 +08:00
commit 46d19aeb45
7 changed files with 249 additions and 55 deletions

View file

@ -23,6 +23,7 @@ import {
createNodePossessionChallenge,
verifyNodePossessionResponse,
type NodePossessionProofSource,
type VerifiedNodePossession,
} from './node-possession-proof.js';
const IDENTIFIER_PATTERN = /^[A-Z0-9][A-Z0-9._:-]{1,159}$/;
@ -46,7 +47,7 @@ export interface DomainRuntimeHandoffCandidate {
}
export interface DomainRuntimeHandoffSource {
read(domainId: string, nodeId: string, nodeType: DomainNodeType): Promise<DomainRuntimeHandoffCandidate | null>;
read(possession: VerifiedNodePossession): Promise<DomainRuntimeHandoffCandidate | null>;
}
export interface DomainAccessProjection {
@ -102,6 +103,7 @@ export class DomainAccessOrchestrator {
]);
let nodeRegistrationVerified = false;
let nodePossessionVerified = false;
let possession: VerifiedNodePossession | null = null;
if (identity.accountVerified && nodeRegistrationSnapshot.receipt.status === 'CURRENT') {
try {
const loaded = assertLoadedNodeRegistrationSnapshot(nodeRegistrationSnapshot);
@ -126,7 +128,7 @@ export class DomainAccessOrchestrator {
const response = await this.nodePossessions.prove(challenge);
if (response) {
if (at === undefined) now = this.clock();
verifyNodePossessionResponse(response, challenge, registration, now);
possession = verifyNodePossessionResponse(response, challenge, registration, now);
nodePossessionVerified = true;
}
}
@ -144,10 +146,10 @@ export class DomainAccessOrchestrator {
nodeType,
};
if (identity.accountVerified && nodeRegistrationVerified && nodePossessionVerified) {
if (identity.accountVerified && nodeRegistrationVerified && nodePossessionVerified && possession) {
let candidate: DomainRuntimeHandoffCandidate | null = null;
try {
candidate = await this.handoffs.read(domainId, identity.nodeId, nodeType);
candidate = await this.handoffs.read(possession);
} catch {
candidate = null;
}