import { type RelayKeyPair, type RelayPairingPayload } from '@pellux/goodvibes-transport-core/relay'; /** Structural client WebSocket the daemon uses to dial the relay. */ export interface RelayClientWebSocket { binaryType: string; send(data: string | Uint8Array | ArrayBuffer): void; close(code?: number, reason?: string): void; addEventListener(type: 'open' | 'message' | 'close' | 'error', listener: (event: unknown) => void): void; } /** Header set on every relay-tunneled request so downstream can tell it apart. */ export declare const RELAY_VIA_HEADER = "x-goodvibes-via-relay"; /** * Whether a request arrived over the relay (vs the trusted LAN). Surfaces and * policy hooks use this to show connections as "via relay" and to apply * relay-specific controls such as WebAuthn step-up on mutating calls. */ export declare function isRelayTunneledRequest(req: Request): boolean; /** Lifecycle status of the daemon's relay registration. */ export type RelayRegistrationStatus = 'idle' | 'connecting' | 'registered' | 'reconnecting' | 'stopped'; export interface RelayRegistrationLogger { info(message: string, fields?: Record): void; warn(message: string, fields?: Record): void; error(message: string, fields?: Record): void; } /** Options for {@link createRelayDaemonRegistration}. */ export interface RelayDaemonRegistrationOptions { /** The relay URL to dial (wss://…). */ readonly relayUrl: string; /** The unguessable rendezvous id this daemon registers under. */ readonly rid: string; /** The daemon's persistent relay identity key pair. */ readonly identity: RelayKeyPair; /** Base URL used to resolve tunneled request paths into local Requests. */ readonly localBaseUrl: string; /** Replay a reconstructed request against the daemon; returns null if unrouted. */ readonly dispatch: (req: Request) => Promise; /** WebSocket constructor override (defaults to globalThis.WebSocket). */ readonly webSocketImpl?: (url: string) => RelayClientWebSocket; /** Reconnect backoff base delay in ms (default 500). */ readonly reconnectBaseDelayMs?: number; /** Reconnect backoff cap in ms (default 30000). */ readonly reconnectMaxDelayMs?: number; /** Max concurrent event-subscription streams per pipe (default 8). */ readonly maxStreamsPerPipe?: number; /** Bounded per-stream send buffer, in chunks; overflow drops-with-notice (default 256). */ readonly streamBufferChunks?: number; /** * Max simultaneously-open secure-channel pipes retained in memory (default * 512). Each pipe holds a live secure channel derived from the connecting * surface's session; a relay that drops pipes WITHOUT sending a pipe-close * control frame (crash, network partition) would otherwise leave the channel * context, and the operator-token-authenticated requests riding it, pinned * forever. When the cap is hit the least-recently-used pipe is evicted (its * streams closed) so retained-context count stays bounded. */ readonly maxPipes?: number; /** * Max concurrently in-flight tunneled REQUESTS across all pipes (default * 1024). Each in-flight request retains its reconstructed Request, headers * (including the operator-token Authorization header) and any buffered body, * for the FULL lifetime: dispatch AND response buffering (the max-memory * phase). When the cap is hit a new request is refused with * an honest 503 `relay-overloaded` response instead of being retained, so a * dispatch stall (or a hot job-transition loop fanning requests) can never * accumulate request contexts without limit. */ readonly maxInFlightRequests?: number; readonly logger?: RelayRegistrationLogger; readonly onStatusChange?: (status: RelayRegistrationStatus) => void; } /** * Point-in-time footprint of the retained relay contexts. Exposed so ops * surfaces and regression tests can assert the caps hold under load. */ export interface RelayRegistrationStats { /** Open secure-channel pipes currently retained. */ readonly pipes: number; /** Tunneled requests currently mid-dispatch (contexts still retained). */ readonly inFlightRequests: number; /** Live event-subscription streams currently retained across all pipes. */ readonly streams: number; /** Pipes evicted because the maxPipes cap was exceeded (cumulative). */ readonly droppedPipes: number; /** Requests refused because the maxInFlightRequests cap was exceeded (cumulative). */ readonly droppedRequests: number; } /** A running daemon-side relay registration. */ export interface RelayDaemonRegistration { start(): void; stop(): void; readonly status: RelayRegistrationStatus; /** Mint a pairing payload a surface can scan to reach this daemon. */ mintPairing(label?: string): Promise; /** Retained-context footprint, for ops visibility and cap regression tests. */ stats(): RelayRegistrationStats; } export declare function createRelayDaemonRegistration(options: RelayDaemonRegistrationOptions): RelayDaemonRegistration; //# sourceMappingURL=relay-registration.d.ts.map