@authowl/core 0.22.0 → 0.23.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.
@@ -1,282 +1,265 @@
1
- import { R as ResolvedAuthConfig, H as HasParams, O as OrganizationMembership } from './organization-membership-BIify9hZ.js';
2
-
3
- /**
4
- * The organization invitation an emailed link is asking this browser to accept.
5
- *
6
- * The link lands on the TENANT'S OWN page carrying `?authowl_invitation=<id>`,
7
- * and the only route that can redeem it needs a session the visitor usually does
8
- * not have yet. So the id has to survive an entire sign-up or sign-in - which
9
- * means surviving that flow's redirects: the OAuth round trip, the email
10
- * verification round trip (which can land on a different page entirely), the MFA
11
- * hold, and whatever navigation the operator's own `redirectTo` performs. A query
12
- * parameter survives none of those, so it is read once, moved into storage, and
13
- * taken out of the URL.
14
- *
15
- * Best-effort storage, deliberately: a browser that refuses `localStorage`
16
- * degrades to "this invitation is claimable until you navigate", which is worse
17
- * than the ideal and much better than a sign-in that throws.
18
- */
19
- declare const INVITATION_QUERY_PARAM = "authowl_invitation";
20
- /**
21
- * The only hint value that exists. There is deliberately no `existing_user`:
22
- * absence has to stay ambiguous across an existing account, an older AuthOwl,
23
- * and an account created between the invite and the click - so it can never be
24
- * read as proof that an address IS registered.
25
- */
26
- type InvitationRecipientHint = 'new_user';
27
- type InvitationClaim = {
28
- id: string;
29
- /** Epoch milliseconds, for age display and for expiring a forgotten claim. */
30
- capturedAt: number;
1
+ type DecodedPublishableKey = {
2
+ prefix: 'pk_live' | 'pk_test';
3
+ env: 'live' | 'test';
4
+ projectId: string;
31
5
  };
32
- /** Claims older than this are dropped unread: a month-old link is not a pending intent. */
33
- declare const INVITATION_CLAIM_MAX_AGE_MS: number;
34
- /**
35
- * Read `?authowl_invitation` once, stash it, and strip it from the URL.
36
- *
37
- * Namespaced and only ours - a bare `invitation` belongs to the tenant's app as
38
- * much as to us, and rewriting their parameters is not ours to do. Returns the
39
- * captured claim, or the one already stashed when there is no parameter, so a
40
- * caller can render from a single call.
41
- */
42
- declare function captureInvitationClaim(now?: number): InvitationClaim | null;
43
- /** The stashed claim, or null when there is none, it is unreadable, or it is stale. */
44
- declare function readInvitationClaim(now?: number): InvitationClaim | null;
45
- declare function clearInvitationClaim(): void;
6
+ declare function decodePublishableKey(key: string): DecodedPublishableKey;
46
7
 
47
- type EnvironmentType = 'development' | 'production';
48
- /**
49
- * The public, publishable-key-safe project config the SDK renders its sign-in
50
- * UI from (server contract CONTRACTS §2, `GET /api/projects/:id/public-config`).
51
- * Nothing here is secret. Method slugs are canonical snake_case.
52
- */
8
+ /** How a session BEGINS, as the minting door knows it. */
9
+ type SessionStart = {
10
+ /**
11
+ * Whether the session is meant to outlive the tab.
12
+ *
13
+ * `dont_remember` is a SECOND cookie, and on the browsers this transport
14
+ * exists for it is dropped exactly like the session cookie is - so the engine
15
+ * never sees it and treats every bearer session as persistent. The token is
16
+ * the only copy of that session the SDK controls, so "don't remember me" has
17
+ * to be honoured by WHERE it is kept: `sessionStorage`, which dies with the
18
+ * tab, rather than `localStorage`, which does not.
19
+ *
20
+ * NOTE the behaviour change that buys: `sessionStorage` is per TAB, where
21
+ * `dont_remember` was per browser session. A "don't remember me" bearer
22
+ * session is therefore not shared with other tabs. That is deliberate and it
23
+ * is the safe direction (a session that ends too soon rather than one that
24
+ * outlives the machine's owner), but it is a real difference from the cookie
25
+ * transport and callers should not discover it by accident.
26
+ */
27
+ remember: boolean;
28
+ };
29
+ /** Secret-free events for framework adapters that project the current session. */
30
+ type SessionLifecycleEvent = Readonly<{
31
+ type: 'beginSession';
32
+ remember: boolean;
33
+ }> | Readonly<{
34
+ type: 'endSession';
35
+ }>;
53
36
  /**
54
- * A project's configured bot challenge.
37
+ * One session read, from the moment it is dispatched to the moment it answers.
55
38
  *
56
- * `provider` is deliberately a plain string rather than a union of the ones this
57
- * SDK can render. A project may be switched to a provider that predates the
58
- * copy of the SDK an application is running, and the difference between
59
- * "no challenge configured" and "a challenge this build cannot render" is the
60
- * difference between signing in and a silent 403 the user cannot act on. Keeping
61
- * the slug lets the renderer say which provider it does not know.
39
+ * Cut by the store, so the rule about which answers may be acted on lives with
40
+ * the state it protects rather than being restated by every caller. The token
41
+ * the read is about is captured INSIDE it: `hasToken` explains why nothing hands
42
+ * the credential out, and a receipt that leaked it would be the same hole with a
43
+ * shorter lifetime.
62
44
  */
63
- interface CaptchaConfig {
64
- provider: string;
65
- siteKey: string;
66
- }
67
- type PublicConfig = {
68
- /** Stable workspace product container shared by its environments. */
69
- applicationId: string;
70
- /** Stable tenant id for the exact environment selected by the publishable key. */
71
- environmentId: string;
72
- /** Environment class that determines key prefixes and billing treatment. */
73
- environmentType: EnvironmentType;
45
+ type SessionRead = {
74
46
  /**
75
- * Authentication endpoint used by this SDK instance. Hosted portals and
76
- * custom domains keep this same-origin even when the stable JWT issuer uses
77
- * the platform's canonical origin.
47
+ * Whether the read this receipt was cut for actually presented a token.
48
+ *
49
+ * The cookie measurement turns on it: a read that carried NO token and still
50
+ * found a session IS the proof that our cross-site cookie survives here.
78
51
  */
79
- authBaseUrl: string;
52
+ readonly carriedToken: boolean;
80
53
  /**
81
- * Public acquisition mode. Optional only for rolling compatibility with
82
- * servers released before waitlist support.
54
+ * The read came back with no session. End the session it was reading - unless
55
+ * the token it presented is no longer the session in play.
56
+ *
57
+ * This is the path-independent catch for every ending that is not sign-out:
58
+ * expiry, a revoke from another device, `account.revokeSession` called with
59
+ * your own id, `account.delete`, an admin ban. None of those are visible in
60
+ * the response to the call that caused them, and a token we PRESENTED and got
61
+ * nothing back for is dead by definition.
83
62
  */
84
- signUp?: {
85
- mode: 'open' | 'restricted' | 'allowlist' | 'waitlist';
86
- };
63
+ endIfDead(): void;
87
64
  /**
88
- * Identity and credential lifecycle policy. Optional only for rolling
89
- * compatibility with AuthOwl servers released before plan 35.
65
+ * Record what this read proved about the browser's cookies. `true` means the
66
+ * cookie came back and no token is needed here.
67
+ *
68
+ * On the receipt rather than on the store, because a detached read answers
69
+ * "there is no cookie session" for two completely different reasons, and only
70
+ * one of them is about the browser. A probe dispatched for one session and
71
+ * answered after that session ENDED - a sign-out, or a sign-out and a fresh
72
+ * sign-in, both of which fit inside one probe's round trip - reports the
73
+ * signed-out gap as a broken cookie. Acting on it would record `bearer` on a
74
+ * browser whose cookies are fine and then persist the NEXT session's token to
75
+ * disk under it, which is the exact defect this gate exists to remove, and it
76
+ * would stick until the sign-in after next.
77
+ *
78
+ * Two facts here, with different authorities, and reading them as one is what
79
+ * this comment used to license. RECORDING the verdict needs no token-value
80
+ * comparison of the kind `endIfDead` does: it is a statement about the
81
+ * BROWSER, every tab on this origin is the same browser, and a verdict
82
+ * wrongly skipped only costs another measurement. The WRITE it unlocks is the
83
+ * opposite - the token this receipt closed over is at least a probe round trip
84
+ * old, and across tabs arbitrarily old, so flushing it unguarded puts a
85
+ * superseded credential into the slot every tab shares. See `flushHeldToken`,
86
+ * which is where that write goes and why.
90
87
  */
91
- authentication?: {
92
- email: {
93
- signUp: boolean;
94
- signIn: Array<'password' | 'magic_link' | 'email_otp'>;
95
- };
96
- phone: {
97
- signUp: boolean;
98
- signIn: boolean;
99
- };
100
- password: {
101
- signUp: boolean;
102
- add: boolean;
103
- /** Server-owned password length policy. Optional for rolling compatibility. */
104
- minLength?: number;
105
- maxLength?: number;
106
- };
107
- passkey: {
108
- signIn: boolean;
109
- add: boolean;
110
- /**
111
- * The domain this environment binds passkeys to. Absent or null means the
112
- * server derives it from the auth host, which is what every server before
113
- * this field did - so treating both the same keeps a new SDK correct
114
- * against an older server.
115
- */
116
- relyingPartyId?: string | null;
117
- };
118
- username: {
119
- collectOnSignUp: boolean;
120
- signIn: boolean;
121
- };
122
- };
123
- /** Email ownership ceremony selected by the project. */
124
- emailVerification?: {
125
- required: boolean;
126
- method: 'link' | 'code';
127
- };
128
- /** End-user profile fields and self-service permissions. */
129
- userModel?: {
130
- requireEmail: boolean;
131
- firstLastName: boolean;
132
- emailChange: boolean;
133
- accountDeletion: boolean;
134
- };
88
+ recordCookieVerdict(cookiesWork: boolean): void;
89
+ };
90
+ type SessionTokenStore = {
91
+ /** Observe lifecycle changes without receiving the token or proof key. */
92
+ subscribeLifecycle(listener: (event: SessionLifecycleEvent) => void): () => void;
135
93
  /**
136
- * MFA presentation contract. Backup codes follow TOTP and are not an
137
- * independently configurable authentication method.
94
+ * Whether a token is held. Deliberately not a getter for the token itself:
95
+ * `declareOn` is the only thing that puts it on the wire, so nothing else
96
+ * needs the credential in hand.
138
97
  */
139
- mfa?: {
140
- totp: boolean;
141
- required: boolean;
142
- backupCodes: boolean;
143
- };
144
- branding: {
145
- appName?: string;
146
- logoUrl?: string;
147
- /** Whether the application name is visible beside the logo. */
148
- showAppName?: boolean;
149
- /** Alignment of the brand identity within managed component headers. */
150
- alignment?: 'left' | 'center' | 'right';
151
- primaryColor?: string;
152
- theme?: 'light' | 'dark' | 'system';
153
- };
154
- /** Canonical method slugs, e.g. "password", "magic_link", "passkey". */
155
- enabledMethods: string[];
156
- /** Configured social provider ids, e.g. "google". */
157
- socialProviders: string[];
98
+ hasToken(): boolean;
99
+ /** Thumbprint paired with the current token, or null for a legacy unbound session. */
100
+ bindingThumbprint(): string | null;
158
101
  /**
159
- * Public OAuth client ids keyed by provider. Optional for rolling compatibility
160
- * with servers released before Google One Tap support.
102
+ * Put this request on the transport - EVERY header, or none of them.
103
+ *
104
+ * The declaration, the bearer when one is held, and the challenge when one is
105
+ * held. Returns whether it declared, which is also the only condition under
106
+ * which the response can carry either cargo back.
107
+ *
108
+ * The challenge rides here rather than at whichever call site knows it is
109
+ * doing 2FA, and that is the point of the shape: `dont_remember` outlives the
110
+ * challenge it arrived with - `get-session` reads it for the life of the
111
+ * session to decide expiry refresh - so a store presented only when answering
112
+ * a code leaves a "don't remember me" session quietly resuming refresh. A
113
+ * request that is on this transport at all is on it for both cargoes.
161
114
  */
162
- socialProviderClientIds?: Record<string, string>;
115
+ declareOn(headers: Headers): boolean;
163
116
  /**
164
- * When true, an email/password sign-up does not create a session - the user
165
- * must confirm their address first. <SignUp/> shows a "check your email" state
166
- * instead of redirecting. Always false unless password sign-up is enabled.
117
+ * Whether this transport is still in play at all - for EITHER cargo, since one
118
+ * declaration governs both.
119
+ *
120
+ * False only once cookies are PROVEN to work here, after which `declareOn`
121
+ * changes nothing and no response can carry a token or a challenge back - so a
122
+ * caller may skip the decoration entirely rather than copy headers it will not
123
+ * touch. A browser that keeps our cookies keeps the ticket in its jar, where it
124
+ * is HttpOnly and strictly safer than anything a header can carry.
167
125
  */
168
- requireEmailVerification: boolean;
126
+ wantsToken(): boolean;
127
+ /** Whether this browser's cookie behaviour is still unmeasured. */
128
+ needsProbe(): boolean;
169
129
  /**
170
- * Legal consent gate. When `required`, <SignUp/> shows an acceptance checkbox
171
- * linking `termsUrl`/`privacyUrl` and blocks sign-up until it's checked, echoing
172
- * `version` back so the server records and enforces it. `required` is true only
173
- * when the project both requires consent and has a document URL to link.
130
+ * Capture a token the server handed back, and put it where it belongs.
131
+ *
132
+ * "Where it belongs" is MEMORY until the cookie has demonstrably failed. The
133
+ * verdict is not knowable at the moment of capture and the token is not needed
134
+ * on most browsers, so the safe order is to hold it, ask, and write only if
135
+ * the answer says this browser has no other way to keep a session. Capturing
136
+ * one is also what ASKS the question - see `measureWith` - because a gate on a
137
+ * measurement nobody runs is just a session that dies at the next reload.
174
138
  */
175
- legal: {
176
- termsUrl?: string;
177
- privacyUrl?: string;
178
- version: number;
179
- required: boolean;
180
- };
181
- /** Published, bilingual privacy notices and optional consent purposes. */
182
- privacy?: {
183
- notices: Array<{
184
- noticeId: string;
185
- noticeVersionId: string;
186
- code: string;
187
- version: number;
188
- title: {
189
- en: string;
190
- ar: string;
191
- };
192
- body: {
193
- en: string;
194
- ar: string;
195
- };
196
- digest: {
197
- en: string;
198
- ar: string;
199
- };
200
- activityCodes: string[];
201
- purposeCodes: string[];
202
- effectiveFrom: string;
203
- }>;
204
- consentPurposes: Array<{
205
- purposeId: string;
206
- purposeVersionId: string;
207
- code: string;
208
- version: number;
209
- title: {
210
- en: string;
211
- ar: string;
212
- };
213
- description: {
214
- en: string;
215
- ar: string;
216
- };
217
- digest: {
218
- en: string;
219
- ar: string;
220
- };
221
- activityCodes: string[];
222
- dataCategories: string[];
223
- }>;
224
- };
139
+ observe(headers: Headers): void;
225
140
  /**
226
- * Whether the project lets signed-in users enrol a second factor (TOTP). A
227
- * capability flag, not a sign-in method (so it's absent from `enabledMethods`):
228
- * gate an "enable two-factor" affordance / <MFAEnrollment/> on it. The sign-in
229
- * 2FA challenge is handled by <SignIn/> regardless of this flag.
141
+ * The server rejected the challenge this store presented: the ticket is spent,
142
+ * expired, or was never there, and the user has to start at the first factor
143
+ * again.
144
+ *
145
+ * Separate from `endSession` because no session ended - the challenge one was
146
+ * pending on did. Keeping the store instead would present a dead ticket on
147
+ * every later request, and keep a `dont_remember` that no longer describes
148
+ * anything, for as long as the tab lives.
230
149
  */
231
- twoFactor: boolean;
232
- /** Whether enrolled MFA is mandatory rather than optional for this project. */
233
- mfaRequired: boolean;
234
- /** Whether signed-in users may delete their own account. */
235
- accountDeletion: boolean;
236
- /** Whether organization routes and components are available for this project. */
237
- organizations: boolean;
150
+ dropChallenge(): void;
238
151
  /**
239
- * Whether inbound enterprise SSO is enabled for this project. SSO IS a sign-in
240
- * method, so when true the server also pushes `'sso'` into `enabledMethods`;
241
- * this flag mirrors the server capability (matching the `twoFactor`
242
- * convention). <SignIn/> gates the SSO affordance on `enabledMethods`, not on
243
- * this flag, so the two never drift.
152
+ * Register the one thing that can actually settle the verdict: a session read
153
+ * with the token deliberately detached. The store holds the question and every
154
+ * fact bearing on it, and none of the network.
155
+ *
156
+ * Called the moment a token is captured with the verdict still unmeasured, and
157
+ * at registration if that already happened. Registration is what makes this
158
+ * work at all: a controller registers when a CLIENT is built, so the
159
+ * measurement no longer waits on a host app subscribing to the session store -
160
+ * which is a thing plenty of integrations never do, and every one of them used
161
+ * to keep a durable token for it.
162
+ *
163
+ * At most one measurer. A second registration replaces the first rather than
164
+ * joining it, because StrictMode double-invokes the memo that builds a client
165
+ * and two probes answer one question.
244
166
  */
245
- sso: boolean;
167
+ measureWith(measure: () => void): void;
246
168
  /**
247
- * JWT issuer (server contract CONTRACTS §8). Non-null only when the project's
248
- * issuer toggle is on: exactly what a third-party verifier needs (Convex
249
- * `auth.config.ts` = `{ type: "customJwt", issuer, jwks: jwksUrl,
250
- * applicationID: aud, algorithm: "ES256" }`). The issuer remains stable when
251
- * `authBaseUrl` follows a hosted or custom account-portal origin.
169
+ * Cut a receipt for a session read that is about to go out.
170
+ *
171
+ * A session read is answered asynchronously, and the session can be replaced
172
+ * while one is in flight - by a sign-in in THIS tab (`observe` runs inside the
173
+ * fetch decorator, while the store's post-mutation refresh only fires once the
174
+ * action resolves), or by one in ANOTHER tab, which lands in shared storage
175
+ * that this store holds no copy of. A read that started before either and
176
+ * comes back "no session" then describes a session that no longer exists, and
177
+ * acting on it wipes the token that just replaced it: a silent sign-out
178
+ * immediately after a successful sign-in, in whichever tab reloads first.
179
+ *
180
+ * The caller states no rule of its own. It cuts the receipt before dispatch
181
+ * and hands the answer back; deciding whether that answer still describes the
182
+ * session in play needs both the token and the lifecycle, and this is the only
183
+ * thing that has them.
252
184
  */
253
- jwtIssuer: {
254
- issuer: string;
255
- jwksUrl: string;
256
- aud: string;
257
- } | null;
185
+ beginRead(): SessionRead;
258
186
  /**
259
- * The bot challenge a project has configured, provider-agnostic.
187
+ * A session BEGINS here, before the request that mints it goes out.
260
188
  *
261
- * Prefer this over the two Turnstile fields below, which predate provider
262
- * choice and remain populated whenever the provider IS Turnstile.
189
+ * Called pre-dispatch at every minting door, because both facts it sets have
190
+ * to be true by the time the RESPONSE arrives: the verdict decides whether the
191
+ * request declares the transport at all (and an un-re-armed "cookies work"
192
+ * means it does not, so no token is ever minted), and `remember` decides where
193
+ * the token that comes back is written.
194
+ *
195
+ * It deliberately does NOT drop the token already held. Several minting doors
196
+ * run ON an existing session - the 2FA verifies upgrade a pending one, phone
197
+ * and email OTP verification can run signed in - so dropping the credential
198
+ * before dispatch would send the very request that needs it out anonymous. A
199
+ * failed attempt (a mistyped password at a re-auth prompt, a wrong OTP) would
200
+ * likewise sign the user out locally on exactly the browsers this exists for.
201
+ * The old token is replaced when the new one ARRIVES, which is the only moment
202
+ * the old session is actually over.
263
203
  */
264
- captcha: CaptchaConfig | null;
265
- /** Public Cloudflare Turnstile site key for the phone OTP challenge. */
266
- turnstileSiteKey: string | null;
267
- /** Public Cloudflare Turnstile site key for protected sign-up/sign-in actions. */
268
- authTurnstileSiteKey: string | null;
269
- locale: string;
270
- badge: boolean;
271
- configVersion: number;
204
+ beginSession(start: SessionStart): void;
205
+ /** Select the safer cookie-only path before a new session is minted. */
206
+ useCookieTransport(): void;
207
+ /** Drop a previous bearer only after its replacement cookie was delivered. */
208
+ completeCookieTransport(): void;
209
+ /** Select bearer delivery and remember which browser key the new token binds to. */
210
+ useBoundBearerTransport(thumbprint: string, keyIsPersistent: boolean): void;
211
+ /**
212
+ * A session ENDS here, unconditionally: this is sign-out, the one ending a
213
+ * response states plainly, and it means "end whatever is in play".
214
+ *
215
+ * Every other ending - expiry, a revoke from another device, the account
216
+ * deleted - is invisible in the response to the call that caused it and is
217
+ * caught instead by `SessionRead.endIfDead`, which has to establish that the
218
+ * ending is even about the session it is holding.
219
+ */
220
+ endSession(): void;
272
221
  };
222
+
223
+ type TransportErrorKind = 'aborted' | 'timeout' | 'network' | 'response_too_large' | 'invalid_response';
224
+ /**
225
+ * Stable, secret-safe failure from the shared HTTP boundary.
226
+ *
227
+ * Deliberately does not retain the request URL, headers, body, or underlying
228
+ * error. Server clients may carry secret authorization headers and hostile
229
+ * fetch implementations may echo those values in their error messages.
230
+ */
231
+ declare class TransportError extends Error {
232
+ readonly kind: TransportErrorKind;
233
+ readonly requestId?: string;
234
+ constructor(kind: TransportErrorKind, requestId?: string);
235
+ }
236
+ declare const TRANSPORT_FETCH: unique symbol;
273
237
  /**
274
- * Fetch a project's public config. Publishable-key gated server-side; sent
275
- * without cookies (the payload is public, so no session is needed). Throws on a
276
- * non-2xx response so the caller can distinguish "config unavailable" from a
277
- * project that simply has a method disabled.
238
+ * A `fetch` that has been through the SDK's transport wiring - the ONLY thing
239
+ * this boundary will execute.
240
+ *
241
+ * The brand is a phantom: it exists purely so that `fetchImpl: fetch` and
242
+ * `fetchImpl: config.fetch ?? fetch` stop compiling. That is not pedantry, it is
243
+ * the bug this file has already shipped. The session transport lives in a
244
+ * decorator around `fetch` (see `session-transport.ts`), and the SDK had TWO
245
+ * sibling lines - `http.ts` and `http-client.ts` - each independently writing
246
+ * `config.fetch ?? fetch`. One got the decorator and the other did not, so the
247
+ * JWT issuer and the consent gate stayed broken on exactly the browsers the
248
+ * work existed to fix, with nothing failing anywhere to say so.
249
+ *
250
+ * A brand cannot stop a deliberate cast, and is not meant to. What it stops is
251
+ * the ACCIDENT: reaching this boundary now forces the author to name where the
252
+ * fetch came from, and there are only two answers - `config.fetch`, which
253
+ * carries the session, or `withoutSessionTransport(...)`, which says in one
254
+ * greppable word that this request has no session to carry.
255
+ *
256
+ * The brand is why `requestBoundedJson` can stay what it says it is - network
257
+ * mechanics, stateless, no idea what a session is - while still being the place
258
+ * a missing transport is caught.
278
259
  */
279
- declare function getPublicConfig(config: ResolvedAuthConfig): Promise<PublicConfig>;
260
+ type TransportFetch = typeof fetch & {
261
+ readonly [TRANSPORT_FETCH]: true;
262
+ };
280
263
 
281
264
  /** Legal-consent status for the signed-in user (server contract: `GET /consent`). */
282
265
  type ConsentStatus = {
@@ -468,6 +451,136 @@ interface AccountClient {
468
451
  delete(params?: DeleteAccountOptions, fetchOptions?: ActionFetchOptions): Promise<AuthActionResult<DeleteAccountData>>;
469
452
  }
470
453
 
454
+ /**
455
+ * The organization invitation an emailed link is asking this browser to accept.
456
+ *
457
+ * The link lands on the TENANT'S OWN page carrying `?authowl_invitation=<id>`,
458
+ * and the only route that can redeem it needs a session the visitor usually does
459
+ * not have yet. So the id has to survive an entire sign-up or sign-in - which
460
+ * means surviving that flow's redirects: the OAuth round trip, the email
461
+ * verification round trip (which can land on a different page entirely), the MFA
462
+ * hold, and whatever navigation the operator's own `redirectTo` performs. A query
463
+ * parameter survives none of those, so it is read once, moved into storage, and
464
+ * taken out of the URL.
465
+ *
466
+ * Best-effort storage, deliberately: a browser that refuses `localStorage`
467
+ * degrades to "this invitation is claimable until you navigate", which is worse
468
+ * than the ideal and much better than a sign-in that throws.
469
+ */
470
+ declare const INVITATION_QUERY_PARAM = "authowl_invitation";
471
+ /**
472
+ * The only hint value that exists. There is deliberately no `existing_user`:
473
+ * absence has to stay ambiguous across an existing account, an older AuthOwl,
474
+ * and an account created between the invite and the click - so it can never be
475
+ * read as proof that an address IS registered.
476
+ */
477
+ type InvitationRecipientHint = 'new_user';
478
+ type InvitationClaim = {
479
+ id: string;
480
+ /** Epoch milliseconds, for age display and for expiring a forgotten claim. */
481
+ capturedAt: number;
482
+ };
483
+ /** Claims older than this are dropped unread: a month-old link is not a pending intent. */
484
+ declare const INVITATION_CLAIM_MAX_AGE_MS: number;
485
+ /**
486
+ * Read `?authowl_invitation` once, stash it, and strip it from the URL.
487
+ *
488
+ * Namespaced and only ours - a bare `invitation` belongs to the tenant's app as
489
+ * much as to us, and rewriting their parameters is not ours to do. Returns the
490
+ * captured claim, or the one already stashed when there is no parameter, so a
491
+ * caller can render from a single call.
492
+ */
493
+ declare function captureInvitationClaim(now?: number): InvitationClaim | null;
494
+ /** The stashed claim, or null when there is none, it is unreadable, or it is stale. */
495
+ declare function readInvitationClaim(now?: number): InvitationClaim | null;
496
+ declare function clearInvitationClaim(): void;
497
+
498
+ /**
499
+ * Pure, dependency-free evaluators for an organization membership's advisory
500
+ * permission claim. Shared by the CLIENT `has()` (organization-client.ts, over
501
+ * the browser session) and the SERVER `has()` (server.ts, over a verified JWT),
502
+ * so the two paths can never disagree on what a membership grants.
503
+ *
504
+ * The membership carries the SAME `permissions` array AuthOwl emits into the
505
+ * session and the JWT claim (plan §4/§5): the relabelled `org:sys_*` system ids
506
+ * (plus their legacy bare forms during the dual-emit window) AND the operator's
507
+ * custom `org:<feature>:<action>` ids. Evaluation is a pure array/string check
508
+ * over that local claim - it NEVER calls a statement-only `/organization/has-
509
+ * permission` route, which only knows the 14 static statements and would wrongly
510
+ * report `false` for any custom permission.
511
+ */
512
+ /** The active-membership shape carried on the session / decoded from a token. */
513
+ interface OrganizationMembership {
514
+ /**
515
+ * The member's PRIMARY role key (built-in `owner`/`admin`/`member` or a
516
+ * project role). One value, for display - use {@link membershipHas} to gate,
517
+ * because a member can hold more than one.
518
+ */
519
+ role: string;
520
+ /**
521
+ * EVERY role the member holds, sorted. `member.role` is a comma-separated set
522
+ * server-side, so `admin,editor` is an ordinary membership - and gating on
523
+ * `role` alone made the others invisible.
524
+ *
525
+ * Optional because a token or session minted by an older AuthOwl carries only
526
+ * `role`; readers fall back to it rather than reporting a member holds nothing.
527
+ */
528
+ roles?: string[];
529
+ /**
530
+ * The member's effective permission ids: `org:sys_*` system claims (with
531
+ * their legacy bare forms during dual-emit) plus custom `org:<feature>:<action>`
532
+ * ids. Advisory only - the real boundary is server-side over the verified token.
533
+ */
534
+ permissions: string[];
535
+ /**
536
+ * Team ids the member holds inside the ACTIVE organization, as emitted by
537
+ * AuthOwl into both the session and the JWT claim. Teams are pure grouping:
538
+ * belonging to one grants nothing on its own, so this is for the application's
539
+ * own gating, never an authority check.
540
+ *
541
+ * Optional because a token minted before teams shipped carries no `teams` claim.
542
+ * `has({ teamId })` then returns false rather than guessing - it can only ever
543
+ * confirm a team the claim actually proves.
544
+ */
545
+ teams?: string[];
546
+ }
547
+ /** Clerk-style `has()` query: match the role, the permission, the team, or a combination (AND). */
548
+ interface HasParams {
549
+ role?: string;
550
+ permission?: string;
551
+ /** Require membership of this team within the active organization. */
552
+ teamId?: string;
553
+ }
554
+ /** True when the membership's permission claim includes `permission`. Pure. */
555
+ declare function membershipHasPermission(membership: OrganizationMembership | null | undefined, permission: string): boolean;
556
+ /**
557
+ * True when the membership's team claim includes `teamId`. Pure.
558
+ *
559
+ * False when the claim carries no `teams` at all, which is what a token minted
560
+ * before teams shipped looks like - an absent claim is never read as "any team".
561
+ */
562
+ declare function membershipHasTeam(membership: OrganizationMembership | null | undefined, teamId: string): boolean;
563
+ /**
564
+ * Clerk-style `has()`: true when the membership satisfies EVERY provided
565
+ * criterion - the role matches AND the permission is included AND the team is
566
+ * held. Returns false when there is no membership, or when no criterion at all is
567
+ * given. Pure: no I/O, evaluated entirely against the local claim.
568
+ */
569
+ /**
570
+ * True when the member holds `role` - as one of their roles, not merely as the
571
+ * primary one. Falls back to the primary when `roles` is absent, which is what a
572
+ * session or token from an older server carries.
573
+ */
574
+ declare function membershipHasRole(membership: OrganizationMembership | null | undefined, role: string): boolean;
575
+ declare function membershipHas(membership: OrganizationMembership | null | undefined, params: HasParams): boolean;
576
+ /** Bind the pure evaluators to one membership (drives the client / hook `has`). */
577
+ declare function createMembershipHas(membership: OrganizationMembership | null | undefined): {
578
+ has: (params: HasParams) => boolean;
579
+ hasPermission: (params: {
580
+ permission: string;
581
+ }) => boolean;
582
+ };
583
+
471
584
  interface Organization {
472
585
  id: string;
473
586
  name: string;
@@ -961,7 +1074,7 @@ type AuthErrorContext = Readonly<AuthRequestContext & {
961
1074
  failure: 'api' | 'aborted' | 'timeout' | 'network' | 'response_too_large' | 'invalid_response';
962
1075
  }>;
963
1076
  /** Stable AuthOwl policy codes that callers can handle without matching messages. */
964
- type AuthOwlErrorCode = 'MAU_BUDGET_REACHED' | 'BOT_CHALLENGE_FAILED' | 'VERSION_CONFLICT' | 'SESSION_NOT_FRESH' | 'ORGANIZATION_LAST_OWNER' | 'ORGANIZATION_NOT_FOUND' | 'MEMBER_NOT_FOUND' | 'INVITATION_NOT_FOUND' | 'EMAIL_VERIFICATION_REQUIRED_FOR_INVITATION' | 'EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION' | 'YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION';
1077
+ type AuthOwlErrorCode = 'MAU_BUDGET_REACHED' | 'BOT_CHALLENGE_FAILED' | 'VERSION_CONFLICT' | 'SESSION_NOT_FRESH' | 'EMAIL_OTP_RECOVERY_DISABLED' | 'ORGANIZATION_LAST_OWNER' | 'ORGANIZATION_NOT_FOUND' | 'MEMBER_NOT_FOUND' | 'INVITATION_NOT_FOUND' | 'EMAIL_VERIFICATION_REQUIRED_FOR_INVITATION' | 'EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION' | 'YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION';
965
1078
  /** Framework-neutral reactive session snapshot. */
966
1079
  interface SessionState {
967
1080
  data: {
@@ -1587,4 +1700,137 @@ interface AuthOwlClient {
1587
1700
  */
1588
1701
  declare function createAuthOwlClient(config: ResolvedAuthConfig): AuthOwlClient;
1589
1702
 
1590
- export { type EmailAuthData as $, type ActionFetchOptions as A, type AccountClient as B, type CreatePrivacyRightsRequestOptions as C, type AccountSession as D, type AccountStatusData as E, type AddOrganizationTeamMemberOptions as F, type AuthErrorContext as G, type AuthOwlErrorCode as H, type AuthRequestContext as I, type AuthResponseContext as J, type ChangeEmailOptions as K, type ChangePasswordData as L, type ChangePasswordOptions as M, type ConsentAcceptResult as N, type Organization as O, type PublicConfig as P, type ConsentStatus as Q, type RecordPrivacyConsentOptions as R, type SocialIdTokenOptions as S, type CreateOrganizationOptions as T, type CreateOrganizationTeamOptions as U, type DeleteAccountData as V, type DeleteAccountOptions as W, type DeleteOrganizationOptions as X, type DeletePasskeyData as Y, type DeletePasskeyOptions as Z, type DisableTwoFactorOptions as _, type AuthActionResult as a, type SendTwoFactorOtpOptions as a$, type EmailOtpAuthData as a0, type EmailOtpSignInOptions as a1, type EmailOtpType as a2, type EmailSignInOptions as a3, type EmailSignUpData as a4, type EmailSignUpOptions as a5, type EnableTwoFactorOptions as a6, type EnvironmentType as a7, type GenerateBackupCodesOptions as a8, type GetOrganizationInvitationOptions as a9, type OrganizationMember as aA, type OrganizationMemberUser as aB, type OrganizationMemberWithUser as aC, type OrganizationMembersData as aD, type OrganizationRoleSummary as aE, type OrganizationSelector as aF, type OrganizationTeam as aG, type OrganizationTeamMember as aH, type OrganizationUserInvitation as aI, type PasswordResetData as aJ, type PhoneAuthUser as aK, type PhoneOtpStartData as aL, type PhoneOtpStartOptions as aM, type PhoneOtpVerifyData as aN, type PhoneOtpVerifyOptions as aO, type RejectOrganizationInvitationData as aP, type RemoveOrganizationMemberData as aQ, type RemoveOrganizationMemberOptions as aR, type RemoveOrganizationTeamData as aS, type RemoveOrganizationTeamMemberData as aT, type RemoveOrganizationTeamMemberOptions as aU, type RemoveOrganizationTeamOptions as aV, type RequestPasswordResetOptions as aW, type ResetPasswordOptions as aX, type RevokeSessionOptions as aY, type SendOtpData as aZ, type SendTwoFactorOtpData as a_, type GetOrganizationOptions as aa, type GetToken as ab, type GetTokenOptions as ac, INVITATION_CLAIM_MAX_AGE_MS as ad, INVITATION_QUERY_PARAM as ae, type InvitationClaim as af, type InvitationRecipientHint as ag, type InviteOrganizationMemberOptions as ah, type JsonObject as ai, type JsonPrimitive as aj, type JsonValue as ak, type LeaveOrganizationOptions as al, type LinkSocialData as am, type LinkSocialOptions as an, type ListOrganizationInvitationsOptions as ao, type ListOrganizationMembersOptions as ap, type ListOrganizationRolesOptions as aq, type ListOrganizationTeamMembersOptions as ar, type ListOrganizationTeamsOptions as as, type MagicLinkData as at, type MagicLinkSignInOptions as au, type OrganizationFilterOperator as av, type OrganizationInvitation as aw, type OrganizationInvitationActionOptions as ax, type OrganizationInvitationDetails as ay, type OrganizationInvitationStatus as az, type AuthOwlClient as b, type SendVerificationOtpOptions as b0, type SetActiveTeamOptions as b1, type SignOutData as b2, type SocialAccount as b3, type SocialSignInOptions as b4, type TokenClient as b5, type TwoFactorBackupCodesData as b6, type TwoFactorEnableData as b7, type TwoFactorRedirectData as b8, type TwoFactorStatusData as b9, type TwoFactorVerifyData as ba, type UnlinkSocialOptions as bb, type UpdateOrganizationMemberRoleOptions as bc, type UpdateOrganizationOptions as bd, type UpdateOrganizationTeamOptions as be, type UpdatePasskeyData as bf, type UpdatePasskeyOptions as bg, type UpdateProfileOptions as bh, type UpdateUnsafeMetadataOptions as bi, type UserMetadata as bj, type UsernameSignInOptions as bk, type VerifyBackupCodeOptions as bl, type VerifyEmailOtpData as bm, type VerifyEmailOtpOptions as bn, type VerifyTotpOptions as bo, type VerifyTwoFactorOtpOptions as bp, type WaitlistJoinData as bq, type WaitlistJoinOptions as br, acceptConsent as bs, captureInvitationClaim as bt, clearInvitationClaim as bu, createAuthOwlClient as bv, createTokenClient as bw, getConsentStatus as bx, readInvitationClaim as by, type PasskeySignInOptions as c, type PasskeyAuthData as d, type AddPasskeyOptions as e, type AuthPasskey as f, type AuthClientError as g, type AuthSession as h, type AuthUser as i, type OrganizationClient as j, type OrganizationDetails as k, type PrivacyClient as l, type PrivacyConsentPreference as m, type PrivacyConsentState as n, type PrivacyLocale as o, type PrivacyRightState as p, type PrivacyRightType as q, type PrivacyRightsRequest as r, type SessionState as s, type SessionStore as t, type SetActiveOrganizationOptions as u, type SocialAuthData as v, getPublicConfig as w, type PhoneOtpChallengeData as x, type AkedlyShieldStartProof as y, type AcceptOrganizationInvitationData as z };
1703
+ /**
1704
+ * A framework adapter's supported view of the browser session transport.
1705
+ *
1706
+ * `authenticatedFetch` is the exact fetch owned by the resolved core client,
1707
+ * so out-of-band requests inherit the current cookie/bearer verdict and sender
1708
+ * proof. The lifecycle contains no credential or response data.
1709
+ */
1710
+ type SessionTransportConnection = Readonly<{
1711
+ authenticatedFetch: TransportFetch;
1712
+ sessionStore: SessionStore;
1713
+ subscribeLifecycle(listener: (event: SessionLifecycleEvent) => void): () => void;
1714
+ }>;
1715
+ type SessionTransportIntegration = Readonly<{
1716
+ connect(connection: SessionTransportConnection): void;
1717
+ /** Project a newly established AuthOwl session before its action resolves. */
1718
+ sessionEstablished(): Promise<void>;
1719
+ /** Remove the framework-owned projection before sign-out resolves. */
1720
+ sessionEnded(): Promise<void>;
1721
+ }>;
1722
+ /** Attach a framework integration to the fetch it asks the core client to use. */
1723
+ declare function withSessionTransportIntegration(fetchImpl: typeof fetch, integration: SessionTransportIntegration): typeof fetch;
1724
+
1725
+ /**
1726
+ * The session, attached to a request and harvested off a response, in ONE place.
1727
+ *
1728
+ * BOTH CARGOES, NO SECOND WIRE. The sign-in challenge - the `two_factor` ticket
1729
+ * and the `dont_remember` flag - travels on this same transport, and it needed
1730
+ * not one line here: `declareOn` and `observe` below each carry both, so a
1731
+ * request that gets the session gets the challenge by construction. That is
1732
+ * deliberate rather than incidental. Wiring the challenge at the call sites that
1733
+ * know about 2FA is precisely the bug class this file exists to make
1734
+ * unrepresentable - a door that gets one cargo and not the other - and the
1735
+ * server's own ingress is built the same way for the same reason
1736
+ * (`bearerTransportHeaders` does both translations in one function, and the
1737
+ * headers it returns are obtainable nowhere else, so no door can opt into the
1738
+ * session half and forget the challenge half). See `session-challenge.ts`.
1739
+ *
1740
+ * WHY THIS IS A `fetch` DECORATOR AND NOT A STEP IN A CLIENT
1741
+ *
1742
+ * Because this SDK used to reach the network through two independent doors and
1743
+ * the first version of this transport wired one and missed the other. See
1744
+ * `TransportFetch` in `transport.ts`, which owns that incident and the guard it
1745
+ * produced.
1746
+ *
1747
+ * The doors have since been collapsed into one (`requestPublishableJson`), but
1748
+ * the session does not ride THAT, because a door is a thing somebody can add.
1749
+ * It rides the `fetch`, which no door can make a request without, and the brand
1750
+ * on `TransportFetch` makes an undecorated one refuse to typecheck at the one
1751
+ * boundary every request passes through. A deliberate opt-out still compiles and
1752
+ * is meant to; what the brand removes is the SILENT version, where a client
1753
+ * somebody added simply never carries the session and nothing anywhere says so.
1754
+ *
1755
+ * `resolveConfig` is the single producer: `config.fetch` is ALWAYS the decorated
1756
+ * fetch, wrapped around the host's if one was supplied. There is no undecorated
1757
+ * fetch left on a resolved config to reach for by mistake.
1758
+ */
1759
+
1760
+ /**
1761
+ * Everything about this project's session that is NOT the ordinary fetch.
1762
+ *
1763
+ * Handed to the session controller directly rather than looked up from a project
1764
+ * id. The controller used to take that id and use it as BOTH the token store's
1765
+ * key and a BroadcastChannel name, which is only correct while the two strings
1766
+ * are the same string: pass a channel name and the controller silently measures
1767
+ * a private, permanently empty store. Two facts, two parameters.
1768
+ */
1769
+ type SessionBinding = {
1770
+ /**
1771
+ * The same transport with the session deliberately DETACHED - no token, no
1772
+ * challenge, no declaration, cookies only.
1773
+ *
1774
+ * Exactly one caller: the probe that measures whether this browser keeps our
1775
+ * cross-site cookie. Every other request attaches the token when we hold one,
1776
+ * which would make a session read succeed whether or not the cookie survived,
1777
+ * and the SDK would never learn the difference.
1778
+ */
1779
+ readonly probe: TransportFetch;
1780
+ /** The store the fetch above attaches from, and the lifecycle the doors drive. */
1781
+ readonly tokens: SessionTokenStore;
1782
+ /** Framework adapter registered on the caller-supplied fetch, when present. */
1783
+ readonly integration?: SessionTransportIntegration | null;
1784
+ /** Decide cookie-only or sender-bound bearer transport before a session mint. */
1785
+ prepareSession(start: SessionStart): Promise<void>;
1786
+ };
1787
+
1788
+ type AuthConfig = {
1789
+ publishableKey: string;
1790
+ apiUrl: string;
1791
+ /** Optional fetch override (e.g. for testing). */
1792
+ fetch?: typeof fetch;
1793
+ };
1794
+ type ResolvedAuthConfig = Omit<AuthConfig, 'fetch'> & {
1795
+ decoded: DecodedPublishableKey;
1796
+ /** Fully-resolved base URL pointing at the per-project auth endpoint. */
1797
+ projectBaseURL: string;
1798
+ /**
1799
+ * THE fetch for this project - the caller's, wrapped in the session transport.
1800
+ *
1801
+ * Required rather than optional, and branded, so that `config.fetch ?? fetch`
1802
+ * cannot be written at all. See `TransportFetch` in `transport.ts` for what
1803
+ * the brand buys and which bug it closes.
1804
+ */
1805
+ fetch: TransportFetch;
1806
+ /**
1807
+ * The session itself, resolved here because this function is the only producer
1808
+ * of the fetch that carries it. Nothing else has to find the store by id, and
1809
+ * no request boundary has to grow a "but not this one" flag to reach the
1810
+ * detached fetch.
1811
+ *
1812
+ * A BROWSER SIGN-IN FLOW MUST GO THROUGH A CONSTRUCTED CLIENT, not through
1813
+ * `config.fetch` directly. Resolving a config builds the token store, but the
1814
+ * thing that SETTLES its cookie verdict is registered by the session
1815
+ * controller a client builds - so a hand-rolled integration that drives sign-in
1816
+ * off this fetch captures a token nothing will ever measure. The token is then
1817
+ * held in memory and never written, and the session dies at the next reload on
1818
+ * exactly the browsers this transport exists for. Every shipped surface
1819
+ * (`createAuthOwlClient`, the native client, the React provider) builds one;
1820
+ * this note is for anyone reaching below them. Moving the measurement onto
1821
+ * this binding is the queued fix that removes the hazard rather than
1822
+ * documenting it.
1823
+ */
1824
+ session: SessionBinding;
1825
+ };
1826
+ type ResolvedAuthTarget = Readonly<{
1827
+ publishableKey: string;
1828
+ apiUrl: string;
1829
+ decoded: DecodedPublishableKey;
1830
+ projectBaseURL: string;
1831
+ }>;
1832
+ /** Resolve the shared, side-effect-free project endpoint contract. */
1833
+ declare function resolveAuthTarget(input: Pick<AuthConfig, 'publishableKey' | 'apiUrl'>): ResolvedAuthTarget;
1834
+ declare function resolveConfig(input: AuthConfig): ResolvedAuthConfig;
1835
+
1836
+ export { type DeleteAccountData as $, type ActionFetchOptions as A, resolveConfig as B, type CreatePrivacyRightsRequestOptions as C, type DecodedPublishableKey as D, type PhoneOtpChallengeData as E, type AkedlyShieldStartProof as F, type AcceptOrganizationInvitationData as G, type HasParams as H, type AccountClient as I, type AccountSession as J, type AccountStatusData as K, type AddOrganizationTeamMemberOptions as L, type AuthErrorContext as M, type AuthOwlErrorCode as N, type Organization as O, type PasskeySignInOptions as P, type AuthRequestContext as Q, type ResolvedAuthConfig as R, type SocialIdTokenOptions as S, type AuthResponseContext as T, type ChangeEmailOptions as U, type ChangePasswordData as V, type ChangePasswordOptions as W, type ConsentAcceptResult as X, type ConsentStatus as Y, type CreateOrganizationOptions as Z, type CreateOrganizationTeamOptions as _, type AuthActionResult as a, type RequestPasswordResetOptions as a$, type DeleteAccountOptions as a0, type DeleteOrganizationOptions as a1, type DeletePasskeyData as a2, type DeletePasskeyOptions as a3, type DisableTwoFactorOptions as a4, type EmailAuthData as a5, type EmailOtpAuthData as a6, type EmailOtpSignInOptions as a7, type EmailOtpType as a8, type EmailSignInOptions as a9, type OrganizationFilterOperator as aA, type OrganizationInvitation as aB, type OrganizationInvitationActionOptions as aC, type OrganizationInvitationDetails as aD, type OrganizationInvitationStatus as aE, type OrganizationMember as aF, type OrganizationMemberUser as aG, type OrganizationMemberWithUser as aH, type OrganizationMembersData as aI, type OrganizationRoleSummary as aJ, type OrganizationSelector as aK, type OrganizationTeam as aL, type OrganizationTeamMember as aM, type OrganizationUserInvitation as aN, type PasswordResetData as aO, type PhoneAuthUser as aP, type PhoneOtpStartData as aQ, type PhoneOtpStartOptions as aR, type PhoneOtpVerifyData as aS, type PhoneOtpVerifyOptions as aT, type RejectOrganizationInvitationData as aU, type RemoveOrganizationMemberData as aV, type RemoveOrganizationMemberOptions as aW, type RemoveOrganizationTeamData as aX, type RemoveOrganizationTeamMemberData as aY, type RemoveOrganizationTeamMemberOptions as aZ, type RemoveOrganizationTeamOptions as a_, type EmailSignUpData as aa, type EmailSignUpOptions as ab, type EnableTwoFactorOptions as ac, type GenerateBackupCodesOptions as ad, type GetOrganizationInvitationOptions as ae, type GetOrganizationOptions as af, type GetToken as ag, type GetTokenOptions as ah, INVITATION_CLAIM_MAX_AGE_MS as ai, INVITATION_QUERY_PARAM as aj, type InvitationClaim as ak, type InvitationRecipientHint as al, type InviteOrganizationMemberOptions as am, type JsonObject as an, type JsonPrimitive as ao, type JsonValue as ap, type LeaveOrganizationOptions as aq, type LinkSocialData as ar, type LinkSocialOptions as as, type ListOrganizationInvitationsOptions as at, type ListOrganizationMembersOptions as au, type ListOrganizationRolesOptions as av, type ListOrganizationTeamMembersOptions as aw, type ListOrganizationTeamsOptions as ax, type MagicLinkData as ay, type MagicLinkSignInOptions as az, type AuthOwlClient as b, type ResetPasswordOptions as b0, type ResolvedAuthTarget as b1, type RevokeSessionOptions as b2, type SendOtpData as b3, type SendTwoFactorOtpData as b4, type SendTwoFactorOtpOptions as b5, type SendVerificationOtpOptions as b6, type SessionLifecycleEvent as b7, type SessionTransportConnection as b8, type SessionTransportIntegration as b9, type VerifyTwoFactorOtpOptions as bA, type WaitlistJoinData as bB, type WaitlistJoinOptions as bC, acceptConsent as bD, captureInvitationClaim as bE, clearInvitationClaim as bF, createAuthOwlClient as bG, createTokenClient as bH, getConsentStatus as bI, membershipHas as bJ, membershipHasPermission as bK, membershipHasRole as bL, membershipHasTeam as bM, readInvitationClaim as bN, resolveAuthTarget as bO, withSessionTransportIntegration as bP, type SetActiveTeamOptions as ba, type SignOutData as bb, type SocialAccount as bc, type SocialSignInOptions as bd, type TokenClient as be, TransportError as bf, type TransportErrorKind as bg, type TwoFactorBackupCodesData as bh, type TwoFactorEnableData as bi, type TwoFactorRedirectData as bj, type TwoFactorStatusData as bk, type TwoFactorVerifyData as bl, type UnlinkSocialOptions as bm, type UpdateOrganizationMemberRoleOptions as bn, type UpdateOrganizationOptions as bo, type UpdateOrganizationTeamOptions as bp, type UpdatePasskeyData as bq, type UpdatePasskeyOptions as br, type UpdateProfileOptions as bs, type UpdateUnsafeMetadataOptions as bt, type UserMetadata as bu, type UsernameSignInOptions as bv, type VerifyBackupCodeOptions as bw, type VerifyEmailOtpData as bx, type VerifyEmailOtpOptions as by, type VerifyTotpOptions as bz, type PasskeyAuthData as c, type AddPasskeyOptions as d, type AuthPasskey as e, type AuthConfig as f, type AuthClientError as g, type AuthSession as h, type AuthUser as i, type OrganizationClient as j, type OrganizationDetails as k, type OrganizationMembership as l, type PrivacyClient as m, type PrivacyConsentPreference as n, type PrivacyConsentState as o, type PrivacyLocale as p, type PrivacyRightState as q, type PrivacyRightType as r, type PrivacyRightsRequest as s, type RecordPrivacyConsentOptions as t, type SessionState as u, type SessionStore as v, type SetActiveOrganizationOptions as w, type SocialAuthData as x, createMembershipHas as y, decodePublishableKey as z };