import { describe, expect, it } from "vitest"; import { PAIRING_INVITATION_PREFIX, createPairingInvitation, pairingInvitationUrl, parsePairingInvitation, } from "./pairing-invitation"; const TOKEN = "AAECAwQFBgcICQoLDA0ODw"; const RELAY = "wss://relay.peachpasswords.com"; const KAT = "peach-pair-v1:eyJyZWxheSI6IndzczovL3JlbGF5LnBlYWNocGFzc3dvcmRzLmNvbSIsInRva2VuIjoiQUFFQ0F3UUZCZ2NJQ1FvTERBME9EdyJ9"; describe("relay pairing invitation", () => { it("pins the cross-client compact JSON/base64url vector", () => { expect(createPairingInvitation(`${RELAY}/`, TOKEN)).toBe(KAT); expect(parsePairingInvitation(KAT)).toEqual({ relayUrl: RELAY, token: TOKEN }); }); it("builds a room URL without identity or vault state", () => { const parsed = parsePairingInvitation(KAT); expect(parsed).not.toBeNull(); expect(pairingInvitationUrl(parsed!)).toBe(`${RELAY}/r/${TOKEN}`); expect(KAT).not.toContain("device"); expect(KAT).not.toContain("vault"); }); it("fails closed on malformed, insecure, or short-token payloads", () => { expect(parsePairingInvitation("not-an-invitation")).toBeNull(); expect(parsePairingInvitation(`${PAIRING_INVITATION_PREFIX}%%%`)).toBeNull(); const insecure = createRaw({ relay: "ws://relay.example.test", token: TOKEN }); expect(parsePairingInvitation(insecure)).toBeNull(); const shortToken = createRaw({ relay: RELAY, token: "too-short" }); expect(parsePairingInvitation(shortToken)).toBeNull(); }); }); function createRaw(value: unknown): string { const bytes = new TextEncoder().encode(JSON.stringify(value)); let binary = ""; for (const byte of bytes) binary += String.fromCharCode(byte); return `${PAIRING_INVITATION_PREFIX}${btoa(binary) .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=+$/g, "")}`; }