| 1 | import { expect, it } from "@effect/vitest"; |
| 2 | import * as DateTime from "effect/DateTime"; |
| 3 | |
| 4 | import { |
| 5 | formatIssuedPairingCredential, |
| 6 | formatIssuedSession, |
| 7 | formatPairingCredentialList, |
| 8 | formatSessionList, |
| 9 | } from "./cliAuthFormat.ts"; |
| 10 | |
| 11 | it("formats issued pairing credentials with the secret and optional pair URL", () => { |
| 12 | const output = formatIssuedPairingCredential( |
| 13 | { |
| 14 | id: "pairing-1", |
| 15 | credential: "secret-pairing-token", |
| 16 | scopes: ["orchestration:read"], |
| 17 | subject: "one-time-token", |
| 18 | createdAt: DateTime.makeUnsafe("2026-04-08T09:00:00.000Z"), |
| 19 | expiresAt: DateTime.makeUnsafe("2026-04-08T10:00:00.000Z"), |
| 20 | }, |
| 21 | { baseUrl: "https://example.com", json: false }, |
| 22 | ); |
| 23 | |
| 24 | expect(output).toContain("secret-pairing-token"); |
| 25 | expect(output).toContain("https://example.com/pair#token=secret-pairing-token"); |
| 26 | expect(output).toContain("Expires at: 2026-04-08T10:00:00.000Z"); |
| 27 | expect(output).not.toContain("DateTime.Utc"); |
| 28 | }); |
| 29 | |
| 30 | it("formats pairing listings without exposing the secret token", () => { |
| 31 | const output = formatPairingCredentialList( |
| 32 | [ |
| 33 | { |
| 34 | id: "pairing-1", |
| 35 | subject: "one-time-token", |
| 36 | label: "Phone", |
| 37 | scopes: ["orchestration:read"], |
| 38 | createdAt: DateTime.makeUnsafe("2026-04-08T09:00:00.000Z"), |
| 39 | expiresAt: DateTime.makeUnsafe("2026-04-08T10:00:00.000Z"), |
| 40 | }, |
| 41 | ], |
| 42 | { json: false }, |
| 43 | ); |
| 44 | |
| 45 | expect(output).toContain("pairing-1"); |
| 46 | expect(output).not.toContain("secret-pairing-token"); |
| 47 | }); |
| 48 | |
| 49 | it("formats issued sessions with the bearer token but omits tokens from listings", () => { |
| 50 | const issuedOutput = formatIssuedSession( |
| 51 | { |
| 52 | sessionId: "session-1" as never, |
| 53 | token: "secret-session-token", |
| 54 | method: "bearer-access-token", |
| 55 | scopes: ["orchestration:read", "access:write"], |
| 56 | subject: "cli-issued-session", |
| 57 | client: { |
| 58 | label: "deploy-bot", |
| 59 | deviceType: "bot", |
| 60 | }, |
| 61 | expiresAt: DateTime.makeUnsafe("2026-04-08T10:00:00.000Z"), |
| 62 | }, |
| 63 | { json: false }, |
| 64 | ); |
| 65 | |
| 66 | const listedOutput = formatSessionList( |
| 67 | [ |
| 68 | { |
| 69 | sessionId: "session-1" as never, |
| 70 | method: "bearer-access-token", |
| 71 | scopes: ["orchestration:read", "access:write"], |
| 72 | subject: "cli-issued-session", |
| 73 | client: { |
| 74 | label: "deploy-bot", |
| 75 | deviceType: "bot", |
| 76 | }, |
| 77 | connected: false, |
| 78 | current: false, |
| 79 | issuedAt: DateTime.makeUnsafe("2026-04-08T09:00:00.000Z"), |
| 80 | expiresAt: DateTime.makeUnsafe("2026-04-08T10:00:00.000Z"), |
| 81 | lastConnectedAt: null, |
| 82 | }, |
| 83 | ], |
| 84 | { json: false }, |
| 85 | ); |
| 86 | |
| 87 | expect(issuedOutput).toContain("secret-session-token"); |
| 88 | expect(listedOutput).not.toContain("secret-session-token"); |
| 89 | }); |