@insureco/bio 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -35,6 +35,7 @@ __export(index_exports, {
35
35
  BioError: () => BioError,
36
36
  EmbedClient: () => EmbedClient,
37
37
  GraphClient: () => GraphClient,
38
+ PassportClient: () => PassportClient,
38
39
  decodeToken: () => decodeToken,
39
40
  generatePKCE: () => generatePKCE,
40
41
  isTokenExpired: () => isTokenExpired,
@@ -172,6 +173,23 @@ var BioAuth = class _BioAuth {
172
173
  codeChallenge
173
174
  };
174
175
  }
176
+ /**
177
+ * Build an authorization URL with prompt=none for silent authentication.
178
+ *
179
+ * Useful for checking if the user has an existing session without showing
180
+ * a login screen. If the user is not authenticated, Bio-ID redirects back
181
+ * with an `error=login_required` query parameter instead of showing UI.
182
+ */
183
+ silentAuth(opts) {
184
+ const result = this.getAuthorizationUrl({
185
+ redirectUri: opts.redirectUri,
186
+ scopes: opts.scopes,
187
+ state: opts.state
188
+ });
189
+ const url = new URL(result.url);
190
+ url.searchParams.set("prompt", "none");
191
+ return { ...result, url: url.toString() };
192
+ }
175
193
  /**
176
194
  * Exchange an authorization code for tokens.
177
195
  *
@@ -1050,7 +1068,48 @@ var GraphClient = class _GraphClient {
1050
1068
  async matchAppetite(input) {
1051
1069
  return this.post("/api/graph/appetite/match", input, { requiresAuth: true });
1052
1070
  }
1071
+ // ─── Verification Routes (auth required, gas-metered) ─────────────────────
1072
+ /**
1073
+ * Verify an agent's license for a given state and line of business.
1074
+ * Returns validity, license number, expiry, and a Septor proof hash.
1075
+ */
1076
+ async verifyLicense(input) {
1077
+ return this.post("/api/graph/verify/license", input, { requiresAuth: true });
1078
+ }
1079
+ /**
1080
+ * Verify an agent's appointment with a carrier.
1081
+ * Returns validity, appointed date, states, and a Septor proof hash.
1082
+ */
1083
+ async verifyAppointment(input) {
1084
+ return this.post("/api/graph/verify/appointment", input, { requiresAuth: true });
1085
+ }
1086
+ /**
1087
+ * Get the distribution chain for an entity (agent → agency → MGA → carrier).
1088
+ * Requires an accessToken (auth: required).
1089
+ */
1090
+ async getChain(entityId) {
1091
+ return this.getAuth(`/api/graph/chain/${encodeURIComponent(entityId)}`);
1092
+ }
1093
+ /**
1094
+ * Search across Agent, Agency, MGA, and Carrier nodes.
1095
+ * Public route — no auth required.
1096
+ */
1097
+ async search(query, options) {
1098
+ const params = new URLSearchParams({ q: query });
1099
+ if (options?.limit) params.set("limit", String(options.limit));
1100
+ if (options?.types?.length) params.set("types", options.types.join(","));
1101
+ return this.get(`/api/graph/search?${params.toString()}`);
1102
+ }
1053
1103
  // ─── Internal ─────────────────────────────────────────────────────────────
1104
+ async getAuth(path) {
1105
+ if (!this.accessToken) {
1106
+ throw new BioError(
1107
+ `bio-graph ${path} requires an accessToken \u2014 pass it in the GraphClient constructor`,
1108
+ "config_error"
1109
+ );
1110
+ }
1111
+ return this.get(path);
1112
+ }
1054
1113
  async get(path, attempt = 0) {
1055
1114
  const url = `${this.graphUrl}${path}`;
1056
1115
  const controller = new AbortController();
@@ -1149,6 +1208,157 @@ var GraphClient = class _GraphClient {
1149
1208
  return body;
1150
1209
  }
1151
1210
  };
1211
+
1212
+ // src/passport-client.ts
1213
+ var PassportClient = class {
1214
+ config;
1215
+ ws = null;
1216
+ _passport = null;
1217
+ _status = "disconnected";
1218
+ reconnectAttempt = 0;
1219
+ reconnectTimer = null;
1220
+ listeners = /* @__PURE__ */ new Map();
1221
+ closed = false;
1222
+ constructor(config) {
1223
+ this.config = {
1224
+ autoReconnect: true,
1225
+ maxReconnectDelay: 3e4,
1226
+ ...config
1227
+ };
1228
+ }
1229
+ /** Current passport object (null until first identity message) */
1230
+ get passport() {
1231
+ return this._passport;
1232
+ }
1233
+ /** Current connection status */
1234
+ get status() {
1235
+ return this._status;
1236
+ }
1237
+ /** Connect to the passport WebSocket */
1238
+ connect() {
1239
+ if (this.closed) return;
1240
+ this.setStatus("connecting");
1241
+ const url = new URL("/passport", this.config.bioIdUrl.replace(/^http/, "ws"));
1242
+ url.searchParams.set("token", this.config.accessToken);
1243
+ url.searchParams.set("version", "1");
1244
+ if (this.config.service) {
1245
+ url.searchParams.set("service", this.config.service);
1246
+ }
1247
+ this.ws = new WebSocket(url.toString());
1248
+ this.ws.onopen = () => {
1249
+ this.reconnectAttempt = 0;
1250
+ this.setStatus("connected");
1251
+ this.emit("connected", this._status);
1252
+ };
1253
+ this.ws.onmessage = (event) => {
1254
+ try {
1255
+ const data = JSON.parse(
1256
+ typeof event.data === "string" ? event.data : ""
1257
+ );
1258
+ if (data.type === "identity" || data.type === "passport_updated") {
1259
+ this._passport = data.passport ?? null;
1260
+ this.emit(data.type, this._passport);
1261
+ } else if (data.type === "revoked") {
1262
+ this._passport = null;
1263
+ this.emit("revoked");
1264
+ }
1265
+ } catch {
1266
+ }
1267
+ };
1268
+ this.ws.onclose = (event) => {
1269
+ this.setStatus("disconnected");
1270
+ this.emit("disconnected", this._status);
1271
+ if (event?.code === 4003 && this.config.refreshToken && this.config.bioAuth) {
1272
+ this.handleTokenRefresh();
1273
+ return;
1274
+ }
1275
+ this.scheduleReconnect();
1276
+ };
1277
+ this.ws.onerror = () => {
1278
+ const error = new Error("Passport WebSocket error");
1279
+ this.emit("error", error);
1280
+ };
1281
+ }
1282
+ /** Subscribe to an event */
1283
+ on(event, handler) {
1284
+ if (!this.listeners.has(event)) {
1285
+ this.listeners.set(event, /* @__PURE__ */ new Set());
1286
+ }
1287
+ this.listeners.get(event).add(handler);
1288
+ }
1289
+ /** Unsubscribe from an event */
1290
+ off(event, handler) {
1291
+ this.listeners.get(event)?.delete(handler);
1292
+ }
1293
+ /** Disconnect and stop reconnecting */
1294
+ close() {
1295
+ this.closed = true;
1296
+ if (this.reconnectTimer) {
1297
+ clearTimeout(this.reconnectTimer);
1298
+ this.reconnectTimer = null;
1299
+ }
1300
+ if (this.ws) {
1301
+ this.ws.onclose = null;
1302
+ this.ws.close();
1303
+ this.ws = null;
1304
+ }
1305
+ this.setStatus("disconnected");
1306
+ }
1307
+ /** Update access token (e.g. after refresh) and reconnect */
1308
+ updateToken(accessToken) {
1309
+ this.config.accessToken = accessToken;
1310
+ if (this.ws) {
1311
+ this.ws.onclose = null;
1312
+ this.ws.close();
1313
+ this.ws = null;
1314
+ }
1315
+ this.reconnectAttempt = 0;
1316
+ this.connect();
1317
+ }
1318
+ async handleTokenRefresh() {
1319
+ if (!this.config.refreshToken || !this.config.bioAuth) return;
1320
+ try {
1321
+ const tokens = await this.config.bioAuth.refreshToken(this.config.refreshToken);
1322
+ this.config.accessToken = tokens.access_token;
1323
+ if (tokens.refresh_token) {
1324
+ this.config.refreshToken = tokens.refresh_token;
1325
+ }
1326
+ if (this.config.onTokenRefresh) {
1327
+ this.config.onTokenRefresh(tokens);
1328
+ }
1329
+ this.reconnectAttempt = 0;
1330
+ this.connect();
1331
+ } catch {
1332
+ this.emit("error", new Error("Token refresh failed"));
1333
+ }
1334
+ }
1335
+ setStatus(status) {
1336
+ this._status = status;
1337
+ }
1338
+ emit(event, ...args) {
1339
+ const handlers = this.listeners.get(event);
1340
+ if (handlers) {
1341
+ for (const handler of handlers) {
1342
+ try {
1343
+ handler(...args);
1344
+ } catch {
1345
+ }
1346
+ }
1347
+ }
1348
+ }
1349
+ scheduleReconnect() {
1350
+ if (this.closed || !this.config.autoReconnect) return;
1351
+ const delay = Math.min(
1352
+ 1e3 * Math.pow(2, this.reconnectAttempt),
1353
+ this.config.maxReconnectDelay ?? 3e4
1354
+ );
1355
+ this.reconnectAttempt++;
1356
+ this.reconnectTimer = setTimeout(() => {
1357
+ this.reconnectTimer = null;
1358
+ this.connect();
1359
+ }, delay);
1360
+ }
1361
+ };
1152
1362
  // Annotate the CommonJS export names for ESM import in node:
1153
1363
  0 && (module.exports = {
1154
1364
  BioAdmin,
@@ -1156,6 +1366,7 @@ var GraphClient = class _GraphClient {
1156
1366
  BioError,
1157
1367
  EmbedClient,
1158
1368
  GraphClient,
1369
+ PassportClient,
1159
1370
  decodeToken,
1160
1371
  generatePKCE,
1161
1372
  isTokenExpired,
package/dist/index.mjs CHANGED
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  GraphClient
3
- } from "./chunk-PLN6QPED.mjs";
3
+ } from "./chunk-CKHMGUDP.mjs";
4
+ import {
5
+ PassportClient
6
+ } from "./chunk-UBURAGWI.mjs";
4
7
  import {
5
8
  BioError,
6
9
  parseJsonResponse,
@@ -100,6 +103,23 @@ var BioAuth = class _BioAuth {
100
103
  codeChallenge
101
104
  };
102
105
  }
106
+ /**
107
+ * Build an authorization URL with prompt=none for silent authentication.
108
+ *
109
+ * Useful for checking if the user has an existing session without showing
110
+ * a login screen. If the user is not authenticated, Bio-ID redirects back
111
+ * with an `error=login_required` query parameter instead of showing UI.
112
+ */
113
+ silentAuth(opts) {
114
+ const result = this.getAuthorizationUrl({
115
+ redirectUri: opts.redirectUri,
116
+ scopes: opts.scopes,
117
+ state: opts.state
118
+ });
119
+ const url = new URL(result.url);
120
+ url.searchParams.set("prompt", "none");
121
+ return { ...result, url: url.toString() };
122
+ }
103
123
  /**
104
124
  * Exchange an authorization code for tokens.
105
125
  *
@@ -924,6 +944,7 @@ export {
924
944
  BioError,
925
945
  EmbedClient,
926
946
  GraphClient,
947
+ PassportClient,
927
948
  decodeToken,
928
949
  generatePKCE,
929
950
  isTokenExpired,
@@ -0,0 +1,27 @@
1
+ import { P as Passport, a as PassportStatus } from './passport-types-bPgjNxv-.mjs';
2
+
3
+ interface UsePassportOptions {
4
+ /** Bio-ID base URL */
5
+ bioIdUrl: string;
6
+ /** Access token for authentication */
7
+ accessToken: string | null;
8
+ /** Service name for tracking */
9
+ service?: string;
10
+ /** Auto-reconnect (default: true) */
11
+ autoReconnect?: boolean;
12
+ }
13
+ interface UsePassportResult {
14
+ /** Current passport object (null until identity received) */
15
+ passport: Passport | null;
16
+ /** Connection status */
17
+ status: PassportStatus;
18
+ /** Last error (null if none) */
19
+ error: Error | null;
20
+ /** Manually disconnect */
21
+ disconnect: () => void;
22
+ /** Manually reconnect */
23
+ reconnect: () => void;
24
+ }
25
+ declare function usePassport(options: UsePassportOptions): UsePassportResult;
26
+
27
+ export { type UsePassportOptions, type UsePassportResult, usePassport };
@@ -0,0 +1,27 @@
1
+ import { P as Passport, a as PassportStatus } from './passport-types-bPgjNxv-.js';
2
+
3
+ interface UsePassportOptions {
4
+ /** Bio-ID base URL */
5
+ bioIdUrl: string;
6
+ /** Access token for authentication */
7
+ accessToken: string | null;
8
+ /** Service name for tracking */
9
+ service?: string;
10
+ /** Auto-reconnect (default: true) */
11
+ autoReconnect?: boolean;
12
+ }
13
+ interface UsePassportResult {
14
+ /** Current passport object (null until identity received) */
15
+ passport: Passport | null;
16
+ /** Connection status */
17
+ status: PassportStatus;
18
+ /** Last error (null if none) */
19
+ error: Error | null;
20
+ /** Manually disconnect */
21
+ disconnect: () => void;
22
+ /** Manually reconnect */
23
+ reconnect: () => void;
24
+ }
25
+ declare function usePassport(options: UsePassportOptions): UsePassportResult;
26
+
27
+ export { type UsePassportOptions, type UsePassportResult, usePassport };
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/passport-react.ts
21
+ var passport_react_exports = {};
22
+ __export(passport_react_exports, {
23
+ usePassport: () => usePassport
24
+ });
25
+ module.exports = __toCommonJS(passport_react_exports);
26
+ var import_react = require("react");
27
+ function usePassport(options) {
28
+ const { bioIdUrl, accessToken, service, autoReconnect = true } = options;
29
+ const [passport, setPassport] = (0, import_react.useState)(null);
30
+ const [status, setStatus] = (0, import_react.useState)("disconnected");
31
+ const [error, setError] = (0, import_react.useState)(null);
32
+ const wsRef = (0, import_react.useRef)(null);
33
+ const reconnectTimerRef = (0, import_react.useRef)(null);
34
+ const reconnectAttemptRef = (0, import_react.useRef)(0);
35
+ const closedRef = (0, import_react.useRef)(false);
36
+ const cleanup = (0, import_react.useCallback)(() => {
37
+ if (reconnectTimerRef.current) {
38
+ clearTimeout(reconnectTimerRef.current);
39
+ reconnectTimerRef.current = null;
40
+ }
41
+ if (wsRef.current) {
42
+ wsRef.current.onclose = null;
43
+ wsRef.current.onerror = null;
44
+ wsRef.current.onmessage = null;
45
+ wsRef.current.close();
46
+ wsRef.current = null;
47
+ }
48
+ }, []);
49
+ const connect = (0, import_react.useCallback)(() => {
50
+ if (!accessToken || !bioIdUrl || closedRef.current) return;
51
+ cleanup();
52
+ setStatus("connecting");
53
+ setError(null);
54
+ const url = new URL("/passport", bioIdUrl.replace(/^http/, "ws"));
55
+ url.searchParams.set("token", accessToken);
56
+ url.searchParams.set("version", "1");
57
+ if (service) url.searchParams.set("service", service);
58
+ const ws = new WebSocket(url.toString());
59
+ wsRef.current = ws;
60
+ ws.onopen = () => {
61
+ reconnectAttemptRef.current = 0;
62
+ setStatus("connected");
63
+ };
64
+ ws.onmessage = (event) => {
65
+ try {
66
+ const data = JSON.parse(event.data);
67
+ if (data.type === "identity" || data.type === "passport_updated") {
68
+ setPassport(data.passport ?? null);
69
+ } else if (data.type === "revoked") {
70
+ setPassport(null);
71
+ }
72
+ } catch {
73
+ }
74
+ };
75
+ ws.onclose = () => {
76
+ setStatus("disconnected");
77
+ if (!closedRef.current && autoReconnect) {
78
+ const delay = Math.min(1e3 * Math.pow(2, reconnectAttemptRef.current), 3e4);
79
+ reconnectAttemptRef.current++;
80
+ reconnectTimerRef.current = setTimeout(() => {
81
+ reconnectTimerRef.current = null;
82
+ connect();
83
+ }, delay);
84
+ }
85
+ };
86
+ ws.onerror = () => {
87
+ setError(new Error("Passport WebSocket error"));
88
+ setStatus("error");
89
+ };
90
+ }, [bioIdUrl, accessToken, service, autoReconnect, cleanup]);
91
+ (0, import_react.useEffect)(() => {
92
+ closedRef.current = false;
93
+ connect();
94
+ return () => {
95
+ closedRef.current = true;
96
+ cleanup();
97
+ setStatus("disconnected");
98
+ };
99
+ }, [connect, cleanup]);
100
+ const disconnect = (0, import_react.useCallback)(() => {
101
+ closedRef.current = true;
102
+ cleanup();
103
+ setStatus("disconnected");
104
+ }, [cleanup]);
105
+ const reconnect = (0, import_react.useCallback)(() => {
106
+ closedRef.current = false;
107
+ reconnectAttemptRef.current = 0;
108
+ connect();
109
+ }, [connect]);
110
+ return { passport, status, error, disconnect, reconnect };
111
+ }
112
+ // Annotate the CommonJS export names for ESM import in node:
113
+ 0 && (module.exports = {
114
+ usePassport
115
+ });
@@ -0,0 +1,90 @@
1
+ // src/passport-react.ts
2
+ import { useState, useEffect, useRef, useCallback } from "react";
3
+ function usePassport(options) {
4
+ const { bioIdUrl, accessToken, service, autoReconnect = true } = options;
5
+ const [passport, setPassport] = useState(null);
6
+ const [status, setStatus] = useState("disconnected");
7
+ const [error, setError] = useState(null);
8
+ const wsRef = useRef(null);
9
+ const reconnectTimerRef = useRef(null);
10
+ const reconnectAttemptRef = useRef(0);
11
+ const closedRef = useRef(false);
12
+ const cleanup = useCallback(() => {
13
+ if (reconnectTimerRef.current) {
14
+ clearTimeout(reconnectTimerRef.current);
15
+ reconnectTimerRef.current = null;
16
+ }
17
+ if (wsRef.current) {
18
+ wsRef.current.onclose = null;
19
+ wsRef.current.onerror = null;
20
+ wsRef.current.onmessage = null;
21
+ wsRef.current.close();
22
+ wsRef.current = null;
23
+ }
24
+ }, []);
25
+ const connect = useCallback(() => {
26
+ if (!accessToken || !bioIdUrl || closedRef.current) return;
27
+ cleanup();
28
+ setStatus("connecting");
29
+ setError(null);
30
+ const url = new URL("/passport", bioIdUrl.replace(/^http/, "ws"));
31
+ url.searchParams.set("token", accessToken);
32
+ url.searchParams.set("version", "1");
33
+ if (service) url.searchParams.set("service", service);
34
+ const ws = new WebSocket(url.toString());
35
+ wsRef.current = ws;
36
+ ws.onopen = () => {
37
+ reconnectAttemptRef.current = 0;
38
+ setStatus("connected");
39
+ };
40
+ ws.onmessage = (event) => {
41
+ try {
42
+ const data = JSON.parse(event.data);
43
+ if (data.type === "identity" || data.type === "passport_updated") {
44
+ setPassport(data.passport ?? null);
45
+ } else if (data.type === "revoked") {
46
+ setPassport(null);
47
+ }
48
+ } catch {
49
+ }
50
+ };
51
+ ws.onclose = () => {
52
+ setStatus("disconnected");
53
+ if (!closedRef.current && autoReconnect) {
54
+ const delay = Math.min(1e3 * Math.pow(2, reconnectAttemptRef.current), 3e4);
55
+ reconnectAttemptRef.current++;
56
+ reconnectTimerRef.current = setTimeout(() => {
57
+ reconnectTimerRef.current = null;
58
+ connect();
59
+ }, delay);
60
+ }
61
+ };
62
+ ws.onerror = () => {
63
+ setError(new Error("Passport WebSocket error"));
64
+ setStatus("error");
65
+ };
66
+ }, [bioIdUrl, accessToken, service, autoReconnect, cleanup]);
67
+ useEffect(() => {
68
+ closedRef.current = false;
69
+ connect();
70
+ return () => {
71
+ closedRef.current = true;
72
+ cleanup();
73
+ setStatus("disconnected");
74
+ };
75
+ }, [connect, cleanup]);
76
+ const disconnect = useCallback(() => {
77
+ closedRef.current = true;
78
+ cleanup();
79
+ setStatus("disconnected");
80
+ }, [cleanup]);
81
+ const reconnect = useCallback(() => {
82
+ closedRef.current = false;
83
+ reconnectAttemptRef.current = 0;
84
+ connect();
85
+ }, [connect]);
86
+ return { passport, status, error, disconnect, reconnect };
87
+ }
88
+ export {
89
+ usePassport
90
+ };
@@ -0,0 +1,79 @@
1
+ /** The full Passport identity object pushed via WebSocket */
2
+ interface Passport {
3
+ bioId: string;
4
+ email: string;
5
+ firstName: string;
6
+ lastName: string;
7
+ orgSlug: string;
8
+ orgId: string;
9
+ roles: string[];
10
+ villages: PassportVillage[];
11
+ serviceGrants: PassportServiceGrant[];
12
+ crossOrgPermissions: PassportCrossOrgPermission[];
13
+ session: PassportSession;
14
+ }
15
+ interface PassportVillage {
16
+ slug: string;
17
+ name: string;
18
+ role: 'member' | 'admin' | 'owner';
19
+ }
20
+ interface PassportServiceGrant {
21
+ service: string;
22
+ scopes: string[];
23
+ grantedAt: string;
24
+ }
25
+ interface PassportCrossOrgPermission {
26
+ targetOrgSlug: string;
27
+ modules: string[];
28
+ }
29
+ interface PassportSession {
30
+ issuedAt: string;
31
+ lastSeen: string;
32
+ connectedServices: string[];
33
+ }
34
+ /** Interface for token refresh — accepts any object with a refreshToken method */
35
+ interface PassportTokenRefresher {
36
+ refreshToken: (refreshToken: string) => Promise<{
37
+ access_token: string;
38
+ refresh_token?: string;
39
+ }>;
40
+ }
41
+ /** Configuration for PassportClient */
42
+ interface PassportClientConfig {
43
+ /** Bio-ID base URL (e.g. https://bio.insureco.io) */
44
+ bioIdUrl: string;
45
+ /** Access token for authentication */
46
+ accessToken: string;
47
+ /** Service name sent as ?service= query param */
48
+ service?: string;
49
+ /** Auto-reconnect on disconnect (default: true) */
50
+ autoReconnect?: boolean;
51
+ /** Max reconnect delay in ms (default: 30000) */
52
+ maxReconnectDelay?: number;
53
+ /** Optional refresh token for auto-refresh on 4003 close */
54
+ refreshToken?: string;
55
+ /** Callback when tokens are refreshed (so app can persist new tokens) */
56
+ onTokenRefresh?: (tokens: {
57
+ access_token: string;
58
+ refresh_token?: string;
59
+ }) => void;
60
+ /** Token refresher (e.g. BioAuth instance) — required if refreshToken is set */
61
+ bioAuth?: PassportTokenRefresher;
62
+ }
63
+ /** Events emitted by the passport socket */
64
+ type PassportEventType = 'identity' | 'passport_updated' | 'revoked';
65
+ /** Message received from the passport WebSocket */
66
+ interface PassportMessage {
67
+ type: PassportEventType;
68
+ passport?: Passport;
69
+ }
70
+ /** Status of the passport connection */
71
+ type PassportStatus = 'connecting' | 'connected' | 'disconnected' | 'error';
72
+ /** Branding config from passport (optional) */
73
+ interface PassportBranding {
74
+ logoUrl?: string;
75
+ primaryColor?: string;
76
+ appName?: string;
77
+ }
78
+
79
+ export type { Passport as P, PassportStatus as a, PassportBranding as b, PassportClientConfig as c, PassportCrossOrgPermission as d, PassportEventType as e, PassportMessage as f, PassportServiceGrant as g, PassportSession as h, PassportTokenRefresher as i, PassportVillage as j };