@orangecheck/auth-client 2.17.2 → 2.19.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.mjs CHANGED
@@ -27,6 +27,91 @@ function buildAddAccountUrl(cfg, returnTo) {
27
27
  u.searchParams.set("add", "1");
28
28
  return u.toString();
29
29
  }
30
+
31
+ // src/tab-session.ts
32
+ var TAB_SESSION_HEADER = "x-oc-tab-session";
33
+ var TAB_SESSION_STORAGE_KEY = "oc_tab_session";
34
+ var TAB_ADOPT_HASH = "#oc-adopt";
35
+ function readTabSession() {
36
+ if (typeof window === "undefined") return null;
37
+ try {
38
+ const raw = window.sessionStorage.getItem(TAB_SESSION_STORAGE_KEY);
39
+ if (!raw) return null;
40
+ const parsed = JSON.parse(raw);
41
+ if (typeof parsed.token !== "string" || parsed.token.length === 0) return null;
42
+ if (typeof parsed.didOc !== "string" || parsed.didOc.length === 0) return null;
43
+ return { token: parsed.token, didOc: parsed.didOc };
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+ function writeTabSession(session) {
49
+ if (typeof window === "undefined") return;
50
+ try {
51
+ window.sessionStorage.setItem(TAB_SESSION_STORAGE_KEY, JSON.stringify(session));
52
+ } catch {
53
+ }
54
+ }
55
+ function clearTabSession() {
56
+ if (typeof window === "undefined") return;
57
+ try {
58
+ window.sessionStorage.removeItem(TAB_SESSION_STORAGE_KEY);
59
+ } catch {
60
+ }
61
+ }
62
+ function tabSessionHeader() {
63
+ const pin = readTabSession();
64
+ return pin ? { [TAB_SESSION_HEADER]: pin.token } : {};
65
+ }
66
+ function isPinnableUrl(url, authOrigin) {
67
+ if (typeof window === "undefined") return false;
68
+ try {
69
+ const u = new URL(url, window.location.href);
70
+ return u.origin === window.location.origin || u.origin === authOrigin;
71
+ } catch {
72
+ return false;
73
+ }
74
+ }
75
+ function installTabFetchInterceptor(authOrigin) {
76
+ if (typeof window === "undefined") return () => {
77
+ };
78
+ const original = window.fetch;
79
+ const wrapped = (input, init) => {
80
+ try {
81
+ const pin = readTabSession();
82
+ if (pin) {
83
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
84
+ if (isPinnableUrl(url, authOrigin)) {
85
+ const headers = new Headers(
86
+ init?.headers ?? (input instanceof Request ? input.headers : void 0)
87
+ );
88
+ if (!headers.has("authorization") && !headers.has(TAB_SESSION_HEADER)) {
89
+ headers.set(TAB_SESSION_HEADER, pin.token);
90
+ init = { ...init, headers };
91
+ }
92
+ }
93
+ }
94
+ } catch {
95
+ }
96
+ return original.call(window, input, init);
97
+ };
98
+ window.fetch = wrapped;
99
+ return () => {
100
+ if (window.fetch === wrapped) window.fetch = original;
101
+ };
102
+ }
103
+ function consumeTabAdoptMarker() {
104
+ if (typeof window === "undefined") return false;
105
+ if (!window.location.hash.includes(TAB_ADOPT_HASH.slice(1))) return false;
106
+ clearTabSession();
107
+ try {
108
+ const url = new URL(window.location.href);
109
+ url.hash = "";
110
+ window.history.replaceState(window.history.state, "", url.toString());
111
+ } catch {
112
+ }
113
+ return true;
114
+ }
30
115
  var SessionContext = React3.createContext(null);
31
116
  function normalizeDisplayIdentity(raw, didOc) {
32
117
  const di = raw.display_identity ?? raw.displayIdentity;
@@ -53,7 +138,7 @@ async function fetchHostRoster(cfg) {
53
138
  const res = await fetch(`${cfg.authOrigin}${cfg.mePath}`, {
54
139
  method: "GET",
55
140
  credentials: "include",
56
- headers: { Accept: "application/json" }
141
+ headers: { Accept: "application/json", ...tabSessionHeader() }
57
142
  });
58
143
  if (!res.ok) return [];
59
144
  const body = await res.json();
@@ -90,14 +175,50 @@ function OcSessionProvider({
90
175
  const [roster, setRoster] = React3.useState([]);
91
176
  const [status, setStatus] = React3.useState("loading");
92
177
  const [error, setError] = React3.useState(null);
178
+ const [tabPinned, setTabPinned] = React3.useState(false);
179
+ const pinInFlightRef = React3.useRef(false);
180
+ const pinThisTab = React3.useCallback(
181
+ async (didOc) => {
182
+ if (pinInFlightRef.current || readTabSession()) return;
183
+ pinInFlightRef.current = true;
184
+ try {
185
+ const res = await fetch(`${cfg.authOrigin}/api/auth/tab`, {
186
+ method: "POST",
187
+ credentials: "include",
188
+ headers: { Accept: "application/json" }
189
+ });
190
+ if (!res.ok) return;
191
+ const body = await res.json();
192
+ if (body.ok && typeof body.token === "string" && body.account?.did_oc === didOc) {
193
+ writeTabSession({ token: body.token, didOc });
194
+ setTabPinned(true);
195
+ }
196
+ } catch {
197
+ } finally {
198
+ pinInFlightRef.current = false;
199
+ }
200
+ },
201
+ [cfg.authOrigin]
202
+ );
93
203
  const refresh = React3.useCallback(async () => {
94
204
  if (typeof window === "undefined") return;
95
205
  try {
96
- const res = await fetch(cfg.mePath, {
206
+ let pin = readTabSession();
207
+ let res = await fetch(cfg.mePath, {
97
208
  method: "GET",
98
209
  credentials: "include",
99
- headers: { Accept: "application/json" }
210
+ headers: { Accept: "application/json", ...tabSessionHeader() }
100
211
  });
212
+ if (res.status === 401 && pin) {
213
+ clearTabSession();
214
+ pin = null;
215
+ setTabPinned(false);
216
+ res = await fetch(cfg.mePath, {
217
+ method: "GET",
218
+ credentials: "include",
219
+ headers: { Accept: "application/json" }
220
+ });
221
+ }
101
222
  if (res.status === 401) {
102
223
  setAccount(null);
103
224
  setRoster([]);
@@ -112,11 +233,17 @@ function OcSessionProvider({
112
233
  }
113
234
  const body = await res.json();
114
235
  const acct = normalizeAccount(body.account);
236
+ if (acct && pin && acct.didOc !== pin.didOc) {
237
+ clearTabSession();
238
+ pin = null;
239
+ }
240
+ setTabPinned(pin !== null);
115
241
  const rosterEntries = Array.isArray(body.roster) ? body.roster.map(normalizeRosterEntry).filter((r) => r !== null) : [];
116
242
  setAccount(acct);
117
243
  setRoster(rosterEntries);
118
244
  setStatus(acct ? "authenticated" : "anonymous");
119
245
  setError(null);
246
+ if (acct && !pin) void pinThisTab(acct.didOc);
120
247
  const currentOrigin = typeof window !== "undefined" ? window.location.origin : null;
121
248
  if (acct && rosterEntries.length === 0 && currentOrigin !== null && !cfg.authOrigin.startsWith(currentOrigin)) {
122
249
  const peers = await fetchHostRoster(cfg);
@@ -126,10 +253,12 @@ function OcSessionProvider({
126
253
  setStatus("error");
127
254
  setError(err instanceof Error ? err : new Error(String(err)));
128
255
  }
129
- }, [cfg]);
256
+ }, [cfg, pinThisTab]);
130
257
  React3.useEffect(() => {
258
+ consumeTabAdoptMarker();
131
259
  void refresh();
132
260
  }, [refresh]);
261
+ React3.useEffect(() => installTabFetchInterceptor(cfg.authOrigin), [cfg.authOrigin]);
133
262
  const signOut = React3.useCallback(
134
263
  async (opts) => {
135
264
  const scope = opts?.scope ?? "all";
@@ -139,6 +268,10 @@ function OcSessionProvider({
139
268
  const res = await fetch(url.toString(), {
140
269
  method: "POST",
141
270
  credentials: "include",
271
+ // Per-tab · carry the pin so scope='current' signs out
272
+ // the account THIS tab is operating as, not whichever
273
+ // account the shared cookie happens to point at.
274
+ headers: { ...tabSessionHeader() },
142
275
  // `keepalive` lets the logout round-trip complete even if
143
276
  // the caller hard-navigates away in the same tick (e.g.
144
277
  // `<OcAccountMenu>` redirects home immediately on sign-out).
@@ -146,11 +279,15 @@ function OcSessionProvider({
146
279
  // and the `.ochk.io` cookie may never get cleared.
147
280
  keepalive: true
148
281
  });
282
+ clearTabSession();
283
+ setTabPinned(false);
149
284
  if (scope === "current" && res.ok) {
150
285
  await refresh();
151
286
  return;
152
287
  }
153
288
  } catch {
289
+ clearTabSession();
290
+ setTabPinned(false);
154
291
  }
155
292
  setAccount(null);
156
293
  setRoster([]);
@@ -164,7 +301,7 @@ function OcSessionProvider({
164
301
  const res = await fetch(`${cfg.authOrigin}/api/auth/switch`, {
165
302
  method: "POST",
166
303
  credentials: "include",
167
- headers: { "Content-Type": "application/json" },
304
+ headers: { "Content-Type": "application/json", ...tabSessionHeader() },
168
305
  body: JSON.stringify({ did_oc: didOc })
169
306
  });
170
307
  if (!res.ok) {
@@ -176,6 +313,14 @@ function OcSessionProvider({
176
313
  }
177
314
  throw new Error(`[@orangecheck/auth-client] switchAccount failed: ${reason}`);
178
315
  }
316
+ try {
317
+ const body = await res.json();
318
+ if (typeof body.token === "string" && body.account?.did_oc) {
319
+ writeTabSession({ token: body.token, didOc: body.account.did_oc });
320
+ setTabPinned(true);
321
+ }
322
+ } catch {
323
+ }
179
324
  await refresh();
180
325
  },
181
326
  [cfg.authOrigin, refresh]
@@ -193,7 +338,7 @@ function OcSessionProvider({
193
338
  const res = await fetch(`${cfg.authOrigin}/api/auth/account`, {
194
339
  method: "PATCH",
195
340
  credentials: "include",
196
- headers: { "Content-Type": "application/json" },
341
+ headers: { "Content-Type": "application/json", ...tabSessionHeader() },
197
342
  body: JSON.stringify({ display_identity: kind })
198
343
  });
199
344
  if (!res.ok) {
@@ -205,6 +350,14 @@ function OcSessionProvider({
205
350
  }
206
351
  throw new Error(`[@orangecheck/auth-client] setDisplayIdentity failed: ${reason}`);
207
352
  }
353
+ try {
354
+ const body = await res.json();
355
+ const pin = readTabSession();
356
+ if (pin && typeof body.token === "string" && body.account?.did_oc === pin.didOc) {
357
+ writeTabSession({ token: body.token, didOc: pin.didOc });
358
+ }
359
+ } catch {
360
+ }
208
361
  await refresh();
209
362
  },
210
363
  [cfg.authOrigin, refresh]
@@ -215,6 +368,7 @@ function OcSessionProvider({
215
368
  status,
216
369
  account,
217
370
  roster,
371
+ tabPinned,
218
372
  error,
219
373
  refresh,
220
374
  signOut,
@@ -227,6 +381,7 @@ function OcSessionProvider({
227
381
  status,
228
382
  account,
229
383
  roster,
384
+ tabPinned,
230
385
  error,
231
386
  refresh,
232
387
  signOut,
@@ -1752,6 +1907,18 @@ function safeReturnTo(input) {
1752
1907
  if (!candidate.startsWith("/") || candidate.startsWith("//")) return "/";
1753
1908
  return candidate;
1754
1909
  }
1910
+ function familyReturnTarget(input) {
1911
+ if (typeof input !== "string" || input.length === 0) return void 0;
1912
+ if (input.startsWith("/") && !input.startsWith("//")) return input;
1913
+ try {
1914
+ const u = new URL(input);
1915
+ if (u.protocol !== "https:") return void 0;
1916
+ const host = u.hostname.toLowerCase();
1917
+ if (host === "ochk.io" || host.endsWith(".ochk.io")) return u.toString();
1918
+ } catch {
1919
+ }
1920
+ return void 0;
1921
+ }
1755
1922
  function hardNavigate(target) {
1756
1923
  if (typeof window === "undefined") return;
1757
1924
  window.location.assign(target);
@@ -1764,13 +1931,27 @@ function OcSignIn({
1764
1931
  linkPrompt = true,
1765
1932
  add: addProp,
1766
1933
  authOrigin = "https://ochk.io",
1767
- initialPath = "wallet",
1934
+ initialPath,
1935
+ providersFirst = false,
1768
1936
  paths,
1769
1937
  className
1770
1938
  }) {
1771
1939
  const walletEnabled = paths?.wallet ?? true;
1772
1940
  const emailEnabled = paths?.email ?? true;
1773
- const safeReturn = safeReturnTo(returnTo);
1941
+ const [resolvedReturn, setResolvedReturn] = React3.useState(
1942
+ () => familyReturnTarget(returnTo) ?? safeReturnTo(returnTo)
1943
+ );
1944
+ React3.useEffect(() => {
1945
+ const fromProp = familyReturnTarget(returnTo);
1946
+ if (fromProp) {
1947
+ setResolvedReturn(fromProp);
1948
+ return;
1949
+ }
1950
+ if (typeof window === "undefined") return;
1951
+ const q = new URLSearchParams(window.location.search);
1952
+ const fromQuery = familyReturnTarget(q.get("return_to")) ?? familyReturnTarget(q.get("next"));
1953
+ setResolvedReturn(fromQuery ?? "/");
1954
+ }, [returnTo]);
1774
1955
  const [addMode, setAddMode] = React3.useState(Boolean(addProp));
1775
1956
  React3.useEffect(() => {
1776
1957
  if (typeof window === "undefined") return;
@@ -1780,7 +1961,9 @@ function OcSignIn({
1780
1961
  }
1781
1962
  setAddMode(new URLSearchParams(window.location.search).get("add") === "1");
1782
1963
  }, [addProp]);
1783
- const [path, setPath] = React3.useState(initialPath);
1964
+ const [path, setPath] = React3.useState(
1965
+ initialPath ?? (providersFirst ? "email" : "wallet")
1966
+ );
1784
1967
  const [signedIn, setSignedIn] = React3.useState(null);
1785
1968
  const [linkAlso, setLinkAlso] = React3.useState(false);
1786
1969
  const [oauthError, setOauthError] = React3.useState(false);
@@ -1794,18 +1977,20 @@ function OcSignIn({
1794
1977
  async (account) => {
1795
1978
  if (resolveReturnTo) {
1796
1979
  try {
1797
- hardNavigate(safeReturnTo(await resolveReturnTo(account)));
1980
+ const resolved = familyReturnTarget(await resolveReturnTo(account));
1981
+ hardNavigate(resolved ?? resolvedReturn);
1798
1982
  return;
1799
1983
  } catch {
1800
1984
  }
1801
1985
  }
1802
- hardNavigate(safeReturn);
1986
+ hardNavigate(resolvedReturn);
1803
1987
  },
1804
- [resolveReturnTo, safeReturn]
1988
+ [resolveReturnTo, resolvedReturn]
1805
1989
  );
1806
1990
  const handleSuccess = React3.useCallback(
1807
1991
  async (account, token, via) => {
1808
1992
  const proceed = () => {
1993
+ clearTabSession();
1809
1994
  if (onSuccess) onSuccess(account, token);
1810
1995
  else void navigate(account);
1811
1996
  };
@@ -1926,7 +2111,16 @@ function OcSignIn({
1926
2111
  ]
1927
2112
  }
1928
2113
  ),
1929
- bothEnabled && /* @__PURE__ */ jsxs(
2114
+ providersFirst && /* @__PURE__ */ jsx(
2115
+ ProviderSignIn,
2116
+ {
2117
+ authOrigin,
2118
+ returnTo: resolvedReturn,
2119
+ add: addMode,
2120
+ first: true
2121
+ }
2122
+ ),
2123
+ bothEnabled && /* @__PURE__ */ jsx(
1930
2124
  "div",
1931
2125
  {
1932
2126
  role: "tablist",
@@ -1938,7 +2132,24 @@ function OcSignIn({
1938
2132
  marginBottom: 16,
1939
2133
  borderBottom: "1px solid var(--border, #27272a)"
1940
2134
  },
1941
- children: [
2135
+ children: providersFirst ? /* @__PURE__ */ jsxs(Fragment, { children: [
2136
+ /* @__PURE__ */ jsx(
2137
+ SigninTab,
2138
+ {
2139
+ active: path === "email",
2140
+ onClick: () => setPath("email"),
2141
+ children: "email + otp"
2142
+ }
2143
+ ),
2144
+ /* @__PURE__ */ jsx(
2145
+ SigninTab,
2146
+ {
2147
+ active: path === "wallet",
2148
+ onClick: () => setPath("wallet"),
2149
+ children: "bitcoin \xB7 self-custody"
2150
+ }
2151
+ )
2152
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1942
2153
  /* @__PURE__ */ jsx(
1943
2154
  SigninTab,
1944
2155
  {
@@ -1947,8 +2158,15 @@ function OcSignIn({
1947
2158
  children: "bitcoin wallet"
1948
2159
  }
1949
2160
  ),
1950
- /* @__PURE__ */ jsx(SigninTab, { active: path === "email", onClick: () => setPath("email"), children: "email + otp" })
1951
- ]
2161
+ /* @__PURE__ */ jsx(
2162
+ SigninTab,
2163
+ {
2164
+ active: path === "email",
2165
+ onClick: () => setPath("email"),
2166
+ children: "email + otp"
2167
+ }
2168
+ )
2169
+ ] })
1952
2170
  }
1953
2171
  ),
1954
2172
  /* @__PURE__ */ jsxs("div", { "data-oc-signin-panel": "", role: "tabpanel", children: [
@@ -1970,7 +2188,7 @@ function OcSignIn({
1970
2188
  }
1971
2189
  )
1972
2190
  ] }),
1973
- /* @__PURE__ */ jsx(ProviderSignIn, { authOrigin, returnTo: safeReturn }),
2191
+ !providersFirst && /* @__PURE__ */ jsx(ProviderSignIn, { authOrigin, returnTo: resolvedReturn, add: addMode }),
1974
2192
  linkPrompt && /* @__PURE__ */ jsxs("label", { "data-oc-signin-linkalso": "", style: linkAlsoStyle, children: [
1975
2193
  /* @__PURE__ */ jsx(
1976
2194
  "input",
@@ -2040,7 +2258,9 @@ function ProviderIcon({ id }) {
2040
2258
  }
2041
2259
  function ProviderSignIn({
2042
2260
  authOrigin,
2043
- returnTo
2261
+ returnTo,
2262
+ add,
2263
+ first = false
2044
2264
  }) {
2045
2265
  const [providers, setProviders] = React3.useState([]);
2046
2266
  const [origin, setOrigin] = React3.useState("");
@@ -2056,62 +2276,67 @@ function ProviderSignIn({
2056
2276
  };
2057
2277
  }, [authOrigin]);
2058
2278
  if (providers.length === 0) return null;
2059
- const providerReturnTo = origin ? `${origin}${returnTo}` : returnTo;
2279
+ const providerReturnTo = returnTo.startsWith("/") ? origin ? `${origin}${returnTo}` : returnTo : returnTo;
2060
2280
  const line = { flex: 1, height: 1, background: "var(--border, #27272a)" };
2061
- return /* @__PURE__ */ jsxs("div", { "data-oc-signin-providers": "", style: { marginTop: 20 }, children: [
2062
- /* @__PURE__ */ jsxs(
2063
- "div",
2064
- {
2065
- style: {
2066
- display: "flex",
2067
- alignItems: "center",
2068
- gap: 10,
2069
- margin: "4px 0 12px",
2070
- color: "var(--muted-foreground, #a1a1aa)",
2071
- fontFamily: "ui-monospace, SFMono-Regular, monospace",
2072
- fontSize: 10,
2073
- letterSpacing: "0.16em",
2074
- textTransform: "uppercase"
2075
- },
2076
- children: [
2077
- /* @__PURE__ */ jsx("span", { style: line }),
2078
- "or",
2079
- /* @__PURE__ */ jsx("span", { style: line })
2080
- ]
2081
- }
2082
- ),
2083
- providers.map((p, i) => /* @__PURE__ */ jsxs(
2084
- "a",
2085
- {
2086
- href: `${authOrigin}/api/auth/${p.id}/start?return_to=${encodeURIComponent(
2087
- providerReturnTo
2088
- )}`,
2089
- "data-oc-signin-provider": p.id,
2090
- style: {
2091
- display: "flex",
2092
- alignItems: "center",
2093
- justifyContent: "center",
2094
- gap: 10,
2095
- boxSizing: "border-box",
2096
- width: "100%",
2097
- marginTop: i === 0 ? 0 : 8,
2098
- padding: "0.6rem 0.875rem",
2099
- border: "1px solid var(--border, #27272a)",
2100
- borderRadius: 6,
2101
- background: "transparent",
2102
- color: "var(--muted-foreground, #a1a1aa)",
2103
- fontFamily: "ui-monospace, SFMono-Regular, monospace",
2104
- fontSize: 12,
2105
- textDecoration: "none"
2106
- },
2107
- children: [
2108
- /* @__PURE__ */ jsx(ProviderIcon, { id: p.id }),
2109
- /* @__PURE__ */ jsx("span", { children: p.label })
2110
- ]
2281
+ const divider = /* @__PURE__ */ jsxs(
2282
+ "div",
2283
+ {
2284
+ style: {
2285
+ display: "flex",
2286
+ alignItems: "center",
2287
+ gap: 10,
2288
+ margin: first ? "14px 0 4px" : "4px 0 12px",
2289
+ color: "var(--muted-foreground, #a1a1aa)",
2290
+ fontFamily: "ui-monospace, SFMono-Regular, monospace",
2291
+ fontSize: 10,
2292
+ letterSpacing: "0.16em",
2293
+ textTransform: "uppercase"
2111
2294
  },
2112
- p.id
2113
- ))
2114
- ] });
2295
+ children: [
2296
+ /* @__PURE__ */ jsx("span", { style: line }),
2297
+ "or",
2298
+ /* @__PURE__ */ jsx("span", { style: line })
2299
+ ]
2300
+ }
2301
+ );
2302
+ const buttons = providers.map((p, i) => /* @__PURE__ */ jsxs(
2303
+ "a",
2304
+ {
2305
+ href: `${authOrigin}/api/auth/${p.id}/start?return_to=${encodeURIComponent(
2306
+ providerReturnTo
2307
+ )}${add ? "&add=1" : ""}`,
2308
+ "data-oc-signin-provider": p.id,
2309
+ style: {
2310
+ display: "flex",
2311
+ alignItems: "center",
2312
+ justifyContent: "center",
2313
+ gap: 10,
2314
+ boxSizing: "border-box",
2315
+ width: "100%",
2316
+ marginTop: i === 0 ? 0 : 8,
2317
+ padding: "0.6rem 0.875rem",
2318
+ border: "1px solid var(--border, #27272a)",
2319
+ borderRadius: 6,
2320
+ background: "transparent",
2321
+ color: "var(--muted-foreground, #a1a1aa)",
2322
+ fontFamily: "ui-monospace, SFMono-Regular, monospace",
2323
+ fontSize: 12,
2324
+ textDecoration: "none"
2325
+ },
2326
+ children: [
2327
+ /* @__PURE__ */ jsx(ProviderIcon, { id: p.id }),
2328
+ /* @__PURE__ */ jsx("span", { children: p.label })
2329
+ ]
2330
+ },
2331
+ p.id
2332
+ ));
2333
+ return /* @__PURE__ */ jsx("div", { "data-oc-signin-providers": "", style: first ? { marginBottom: 4 } : { marginTop: 20 }, children: first ? /* @__PURE__ */ jsxs(Fragment, { children: [
2334
+ buttons,
2335
+ divider
2336
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2337
+ divider,
2338
+ buttons
2339
+ ] }) });
2115
2340
  }
2116
2341
  function WalletFlow({ authOrigin, audience, add, onSuccess }) {
2117
2342
  const [address, setAddress] = React3.useState("");
@@ -2766,6 +2991,6 @@ function handleSudoRequired(body, args = {}) {
2766
2991
  return false;
2767
2992
  }
2768
2993
 
2769
- export { DEFAULT_CONFIG, DISPLAY_IDENTITY_KINDS, OcAccountChip, OcAccountPill, OcAddressInput, OcLinkedIdentities, OcSessionProvider, OcSignIn, OcSignInButton, buildAddAccountUrl, buildSignInUrl, fetchOcLinkedIdentities, handleSudoRequired, redirectToSudo, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister };
2994
+ export { DEFAULT_CONFIG, DISPLAY_IDENTITY_KINDS, OcAccountChip, OcAccountPill, OcAddressInput, OcLinkedIdentities, OcSessionProvider, OcSignIn, OcSignInButton, TAB_ADOPT_HASH, TAB_SESSION_HEADER, TAB_SESSION_STORAGE_KEY, buildAddAccountUrl, buildSignInUrl, clearTabSession, consumeTabAdoptMarker, fetchOcLinkedIdentities, handleSudoRequired, installTabFetchInterceptor, readTabSession, redirectToSudo, tabSessionHeader, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister, writeTabSession };
2770
2995
  //# sourceMappingURL=index.mjs.map
2771
2996
  //# sourceMappingURL=index.mjs.map