import { type PairingEmoji, type PairingServer } from "@gryt/crypto"; import type { HistoryProgress, HistorySink, PairedServerDevice, PairingClock, PairingDeviceInfo, PairingEndReason, PairingOidc, PairingStorage } from "./interfaces.js"; import type { PairingRelay } from "./relayClient.js"; export type NewDeviceState = { phase: "idle"; } | { phase: "opening"; } /** `renewed` says why this is a fresh QR: the last one ran out, or A never approved. */ | { phase: "showing"; qr: string; code: string; expiresAt: number; renewed?: "expired" | "timed_out"; } | { phase: "comparing"; emoji: readonly PairingEmoji[]; deadline: number; } | { phase: "signing_in"; username: string; from: string; } /** Everything is written. The app joins `servers`, publishes KeyPackages, then calls `ready`. */ | { phase: "joining"; servers: PairingServer[]; from: string; } | { phase: "linked"; from: string; } | { phase: "done"; from: string; } | { phase: "ended"; reason: PairingEndReason; }; export interface NewDeviceOptions { relay: PairingRelay; device: PairingDeviceInfo; storage: PairingStorage; oidc: PairingOidc; clock?: PairingClock; /** Only for a server with its own auth server: goes in the QR for A to check against its own. */ relayOrigin?: string; approvalMs?: number; /** N's archive. Without it, history A sends is left on the relay. */ history?: HistorySink; } export interface NewDevicePairing { readonly state: NewDeviceState; subscribe(listener: (state: NewDeviceState) => void): () => void; /** Null until the envelope brings a history key, or with no sink. */ readonly history: HistoryProgress | null; subscribeHistory(listener: (progress: HistoryProgress) => void): () => void; start(): void; /** In `joining`: N's device on each server, once its KeyPackages are up. */ ready(devices: PairedServerDevice[]): Promise; cancel(): Promise; /** "They don't match": the same as cancel, with a reason that says the link may be tampered with. */ mismatch(): Promise; } export declare const PAIRING_APPROVAL_MS = 60000; /** N: shows the QR and code, checks the emoji, opens the envelope, signs in, then says ready. */ export declare function createNewDevicePairing(options: NewDeviceOptions): NewDevicePairing;