/** * Tracks the active 6-digit pairing-server session. * * While a token is active, `setupIncomingPairingSubscriber` auto-accepts the * first PAIR_REQUEST that arrives (the user's act of showing the code is the * consent — no banner). The token expires after `expiresAt` so a stale * pairing window cannot silently accept a peer minutes later. * * On a successful pairing while the popup is closed, the responder records a * `RecentPairing` so the next popup open can flash a "Paired with X" * confirmation. The record is read-once. */ const ACTIVE_TOKEN_KEY = "peach_active_pairing_token"; const RECENT_PAIRING_KEY = "peach_recent_pairing"; export interface ActivePairingToken { token: string; expiresAt: number; } export interface RecentPairing { deviceName: string; pairedAt: number; /** "showing" — we showed the code; "entering" — we typed a code. */ side: "showing" | "entering"; } export async function setActivePairingToken(value: ActivePairingToken | null): Promise { try { if (value === null) { await chrome.storage.session.remove(ACTIVE_TOKEN_KEY); } else { await chrome.storage.session.set({ [ACTIVE_TOKEN_KEY]: value }); } } catch { // session storage may be unavailable in test contexts } } export async function getActivePairingToken(): Promise { try { const result = await chrome.storage.session.get(ACTIVE_TOKEN_KEY); const value = (result as Record)[ACTIVE_TOKEN_KEY]; if (!value) return null; if (Date.now() >= value.expiresAt) { await chrome.storage.session.remove(ACTIVE_TOKEN_KEY); return null; } return value; } catch { return null; } } export async function setRecentPairing(value: RecentPairing): Promise { try { await chrome.storage.session.set({ [RECENT_PAIRING_KEY]: value }); } catch { // best-effort } } export async function consumeRecentPairing(): Promise { try { const result = await chrome.storage.session.get(RECENT_PAIRING_KEY); const value = (result as Record)[RECENT_PAIRING_KEY]; if (!value) return null; await chrome.storage.session.remove(RECENT_PAIRING_KEY); return value; } catch { return null; } }