import { FederationNode } from '../entities/federation-node.js'; import { FederationSession } from '../entities/federation-session.js'; export declare const HANDSHAKE_SIGNATURE_CONTEXT = "ruflo:federation:handshake:v1:"; export interface HandshakeChallenge { readonly challengeId: string; readonly nonce: string; readonly timestamp: string; readonly sourceNodeId: string; readonly targetNodeId: string; } export interface HandshakeChallengeResponse { readonly challengeId: string; readonly signedNonce: string; readonly publicKey: string; readonly capabilities: readonly string[]; } export interface HandshakeResult { readonly success: boolean; readonly session?: FederationSession; readonly error?: string; /** The peer answered with the key pinned for its node id. False means the key was only claimed. */ readonly pinned?: boolean; } export interface HandshakeServiceDeps { generateSessionId: () => string; generateSessionToken: () => string; generateNonce: () => string; /** Sign/verify the provided domain-bound bytes without adding another prefix. */ signChallenge: (payload: string) => Promise; verifySignature: (payload: string, signature: string, publicKey: string) => Promise; /** The Ed25519 key (hex) the operator pinned for a node id. Without a pin, a handshake proves nothing about who answered. */ pinnedKeyFor?: (nodeId: string) => string | undefined; getLocalNodeId: () => string; getLocalPublicKey: () => string; getLocalCapabilities: () => readonly string[]; } export interface HandshakeConfig { readonly sessionTtlMs: number; readonly maxSessionTtlMs: number; readonly heartbeatIntervalMs: number; readonly challengeTimeoutMs: number; } export declare class HandshakeService { private readonly deps; private readonly config; private readonly pendingChallenges; constructor(deps: HandshakeServiceDeps, config?: Partial); initiateHandshake(remoteNode: FederationNode): Promise; respondToHandshake(challenge: HandshakeChallenge): Promise; verifyChallenge(response: HandshakeChallengeResponse, remoteNode: FederationNode): Promise; /** * Establish a capability-limited session from discovery evidence. * * A signed manifest proves that the advertised key bound the protocol list; * it does not prove live challenge response, so this path never elevates * beyond VERIFIED. Endpoint-only peers remain UNTRUSTED with no negotiated * optional capabilities. A future wire handshake may elevate either session * after authenticating a response received from the remote process. */ establishDiscoverySession(remoteNode: FederationNode, verifiedManifest: boolean): FederationSession; renewSession(session: FederationSession): FederationSession; private cleanExpiredChallenges; } //# sourceMappingURL=handshake-service.d.ts.map