@better-auth/infra 0.3.6 → 0.4.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.d.mts CHANGED
@@ -1,567 +1,11 @@
1
+ import { C as ImpossibleTravelResult, D as SecurityVerdict, E as SecurityOptions, O as StaleUserResult, S as CredentialStuffingResult, T as SecurityEventType, _ as LocationDataContext, a as DashOptionsInternal, b as sentinel, c as EndpointOptions, d as InfraPluginConnectionOptionsInternal, f as KvOptions, g as LocationData, h as KvRetryOptionsResolved, i as DashOptions, k as ThresholdConfig, l as InfraEndpointContext, m as KvRetryOptions, n as ApiOptions, o as DashOptionsResolved, p as KvOptionsResolved, r as ApiOptionsResolved, s as Endpoint, t as APIError, u as InfraPluginConnectionOptions, v as SentinelOptions, w as SecurityEvent, x as CompromisedPasswordResult, y as SentinelOptionsInternal } from "./types-B673lCib.mjs";
1
2
  import { EMAIL_TEMPLATES, EmailConfig, EmailTemplateId, EmailTemplateVariables, SendBulkEmailsOptions, SendBulkEmailsResult, SendEmailOptions, SendEmailResult, createEmailSender, sendBulkEmails, sendEmail } from "./email.mjs";
2
- import { Account, AuthContext, BetterAuthPlugin, GenericEndpointContext, Session, User } from "better-auth";
3
- import { createFetch } from "@better-fetch/fetch";
3
+ import { Account, AuthContext, GenericEndpointContext, Session, User } from "better-auth";
4
4
  import z$1 from "zod";
5
- import { APIError, Endpoint, EndpointOptions } from "better-call";
6
5
  import { DBFieldAttribute } from "better-auth/db";
7
6
  import { Invitation, Member, Organization, Team, TeamMember } from "better-auth/plugins";
8
7
  export type * from "better-call";
9
8
 
10
- //#region src/identification.d.ts
11
- interface IPLocation {
12
- lat: number;
13
- lng: number;
14
- city: string | null;
15
- region: string | null;
16
- postalCode: string | null;
17
- country: {
18
- code: string;
19
- name: string;
20
- } | null;
21
- timezone: string | null;
22
- }
23
- interface Identification {
24
- visitorId: string;
25
- requestId: string;
26
- timestamp: number;
27
- url: string;
28
- ip: string | null;
29
- location: IPLocation | null;
30
- browser: {
31
- name: string | null;
32
- version: string | null;
33
- os: string | null;
34
- osVersion: string | null;
35
- device: string | null;
36
- userAgent: string | null;
37
- };
38
- confidence: number;
39
- incognito: boolean;
40
- bot: "notDetected" | "detected" | "unknown";
41
- }
42
- //#endregion
43
- //#region src/sentinel/security.d.ts
44
- type SecurityAction = "log" | "block" | "challenge";
45
- interface ThresholdConfig {
46
- challenge?: number;
47
- block?: number;
48
- }
49
- interface SecurityOptions {
50
- unknownDeviceNotification?: boolean;
51
- credentialStuffing?: {
52
- enabled: boolean;
53
- thresholds?: ThresholdConfig;
54
- windowSeconds?: number;
55
- cooldownSeconds?: number;
56
- };
57
- impossibleTravel?: {
58
- enabled: boolean;
59
- maxSpeedKmh?: number;
60
- action?: SecurityAction;
61
- };
62
- geoBlocking?: {
63
- allowList?: string[];
64
- denyList?: string[];
65
- action?: "block" | "challenge";
66
- };
67
- botBlocking?: boolean | {
68
- action: SecurityAction;
69
- };
70
- suspiciousIpBlocking?: boolean | {
71
- action: SecurityAction;
72
- };
73
- velocity?: {
74
- enabled: boolean;
75
- thresholds?: ThresholdConfig;
76
- maxSignupsPerVisitor?: number;
77
- maxPasswordResetsPerIp?: number;
78
- maxSignInsPerIp?: number;
79
- windowSeconds?: number;
80
- action?: SecurityAction;
81
- };
82
- freeTrialAbuse?: {
83
- enabled: boolean;
84
- thresholds?: ThresholdConfig;
85
- maxAccountsPerVisitor?: number;
86
- action?: SecurityAction;
87
- };
88
- compromisedPassword?: {
89
- enabled: boolean;
90
- action?: SecurityAction;
91
- minBreachCount?: number;
92
- };
93
- emailValidation?: {
94
- enabled?: boolean;
95
- strictness?: "low" | "medium" | "high";
96
- action?: SecurityAction;
97
- domainAllowlist?: string[];
98
- };
99
- emailNormalization?: {
100
- enabled?: boolean;
101
- };
102
- staleUsers?: {
103
- enabled: boolean;
104
- staleDays?: number;
105
- action?: SecurityAction;
106
- notifyUser?: boolean;
107
- notifyAdmin?: boolean;
108
- adminEmail?: string;
109
- };
110
- challengeDifficulty?: number;
111
- }
112
- interface SecurityVerdict {
113
- action: "allow" | "challenge" | "block";
114
- challenge?: string;
115
- reason?: string;
116
- details?: Record<string, unknown>;
117
- /** Set when the request included a valid, consumed PoW solution. */
118
- powVerified?: boolean;
119
- }
120
- interface CredentialStuffingResult {
121
- blocked: boolean;
122
- challenged?: boolean;
123
- challenge?: string;
124
- reason?: string;
125
- details?: Record<string, unknown>;
126
- }
127
- interface ImpossibleTravelResult {
128
- isImpossible: boolean;
129
- action?: "allow" | "challenge" | "block";
130
- challenged?: boolean;
131
- challenge?: string;
132
- powVerified?: boolean;
133
- distance?: number;
134
- timeElapsedHours?: number;
135
- speedRequired?: number;
136
- from?: {
137
- city: string | null;
138
- country: string | null;
139
- } | null;
140
- to?: {
141
- city: string | null;
142
- country: string | null;
143
- } | null;
144
- }
145
- interface CompromisedPasswordResult {
146
- compromised: boolean;
147
- breachCount?: number;
148
- action?: SecurityAction;
149
- }
150
- interface StaleUserResult {
151
- isStale: boolean;
152
- daysSinceLastActive?: number;
153
- staleDays?: number;
154
- lastActiveAt?: string | null;
155
- action?: SecurityAction;
156
- notifyUser?: boolean;
157
- notifyAdmin?: boolean;
158
- }
159
- interface SecurityEvent {
160
- type: SecurityEventType;
161
- timestamp: number;
162
- userId: string | null;
163
- visitorId: string | null;
164
- ip: string | null;
165
- country: string | null;
166
- details: Record<string, unknown>;
167
- action: "logged" | "blocked" | "challenged";
168
- }
169
- type SecurityEventType = "unknown_device" | "credential_stuffing" | "impossible_travel" | "geo_blocked" | "bot_blocked" | "suspicious_ip_detected" | "velocity_exceeded" | "free_trial_abuse" | "compromised_password" | "stale_account_reactivation";
170
- //#endregion
171
- //#region src/sentinel/sentinel.d.ts
172
- declare const sentinel: (options?: SentinelOptions) => {
173
- id: "sentinel";
174
- init(ctx: import("better-auth").AuthContext): {
175
- options: {
176
- emailValidation: {
177
- enabled?: boolean;
178
- strictness?: "low" | "medium" | "high";
179
- action?: SecurityAction;
180
- domainAllowlist?: string[];
181
- } | undefined;
182
- emailNormalization: {
183
- enabled?: boolean;
184
- } | undefined;
185
- databaseHooks: {
186
- user: {
187
- create: {
188
- before(user: {
189
- id: string;
190
- createdAt: Date;
191
- updatedAt: Date;
192
- email: string;
193
- emailVerified: boolean;
194
- name: string;
195
- image?: string | null | undefined;
196
- } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<{
197
- data: {
198
- email: string;
199
- id: string;
200
- createdAt: Date;
201
- updatedAt: Date;
202
- emailVerified: boolean;
203
- name: string;
204
- image?: string | null | undefined;
205
- };
206
- } | undefined>;
207
- after(user: {
208
- id: string;
209
- createdAt: Date;
210
- updatedAt: Date;
211
- email: string;
212
- emailVerified: boolean;
213
- name: string;
214
- image?: string | null | undefined;
215
- } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
216
- };
217
- update: {
218
- before(user: Partial<{
219
- id: string;
220
- createdAt: Date;
221
- updatedAt: Date;
222
- email: string;
223
- emailVerified: boolean;
224
- name: string;
225
- image?: string | null | undefined;
226
- }> & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<{
227
- data: {
228
- email: string;
229
- id?: string | undefined;
230
- createdAt?: Date | undefined;
231
- updatedAt?: Date | undefined;
232
- emailVerified?: boolean | undefined;
233
- name?: string | undefined;
234
- image?: string | null | undefined;
235
- };
236
- } | undefined>;
237
- };
238
- };
239
- session: {
240
- create: {
241
- before(session: {
242
- id: string;
243
- createdAt: Date;
244
- updatedAt: Date;
245
- userId: string;
246
- expiresAt: Date;
247
- token: string;
248
- ipAddress?: string | null | undefined;
249
- userAgent?: string | null | undefined;
250
- } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
251
- after(session: {
252
- id: string;
253
- createdAt: Date;
254
- updatedAt: Date;
255
- userId: string;
256
- expiresAt: Date;
257
- token: string;
258
- ipAddress?: string | null | undefined;
259
- userAgent?: string | null | undefined;
260
- } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
261
- };
262
- };
263
- };
264
- };
265
- };
266
- hooks: {
267
- before: ({
268
- matcher: (context: Pick<import("better-auth").HookEndpointContext, "path">) => boolean;
269
- handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
270
- context: {
271
- method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
272
- path: string;
273
- body: any;
274
- query: Record<string, any> | undefined;
275
- params: Record<string, any> & string;
276
- request: Request | undefined;
277
- headers: Headers | undefined;
278
- setHeader: ((key: string, value: string) => void) & ((key: string, value: string) => void);
279
- setStatus: (status: import("better-call").Status) => void;
280
- getHeader: ((key: string) => string | null) & ((key: string) => string | null);
281
- getCookie: (key: string, prefix?: import("better-call").CookiePrefixOptions) => string | null;
282
- getSignedCookie: (key: string, secret: string, prefix?: import("better-call").CookiePrefixOptions) => Promise<string | null | false>;
283
- setCookie: (key: string, value: string, options?: import("better-call").CookieOptions) => string;
284
- setSignedCookie: (key: string, value: string, secret: string, options?: import("better-call").CookieOptions) => Promise<string>;
285
- responseHeaders: Headers;
286
- json: (<R extends Record<string, any> | null>(json: R, routerResponse?: {
287
- status?: number;
288
- headers?: Record<string, string>;
289
- response?: Response;
290
- body?: Record<string, string>;
291
- } | Response) => Promise<R>) & (<R extends Record<string, any> | null>(json: R, routerResponse?: {
292
- status?: number;
293
- headers?: Record<string, string>;
294
- response?: Response;
295
- } | Response) => Promise<R>);
296
- context: {
297
- [x: string]: any;
298
- } & {
299
- returned?: unknown | undefined;
300
- responseHeaders?: Headers | undefined;
301
- getPlugin: <ID extends import("better-auth").BetterAuthPluginRegistryIdentifier | import("better-auth").LiteralString, PluginOptions extends never>(pluginId: ID) => (ID extends keyof import("better-auth").BetterAuthPluginRegistry<unknown, unknown> ? import("better-auth").BetterAuthPluginRegistry<import("better-auth").BetterAuthOptions, PluginOptions>[ID] extends {
302
- creator: infer C;
303
- } ? C extends ((...args: any[]) => infer R) ? R : never : never : BetterAuthPlugin) | null;
304
- hasPlugin: <ID extends import("better-auth").BetterAuthPluginRegistryIdentifier | import("better-auth").LiteralString>(pluginId: ID) => ID extends never ? true : boolean;
305
- appName: string;
306
- baseURL: string;
307
- version: string;
308
- options: import("better-auth").BetterAuthOptions;
309
- trustedOrigins: string[];
310
- trustedProviders: string[];
311
- isTrustedOrigin: (url: string, settings?: {
312
- allowRelativePaths: boolean;
313
- }) => boolean;
314
- oauthConfig: {
315
- skipStateCookieCheck?: boolean | undefined;
316
- storeStateStrategy: "database" | "cookie";
317
- };
318
- newSession: {
319
- session: {
320
- id: string;
321
- createdAt: Date;
322
- updatedAt: Date;
323
- userId: string;
324
- expiresAt: Date;
325
- token: string;
326
- ipAddress?: string | null | undefined;
327
- userAgent?: string | null | undefined;
328
- } & Record<string, any>;
329
- user: {
330
- id: string;
331
- createdAt: Date;
332
- updatedAt: Date;
333
- email: string;
334
- emailVerified: boolean;
335
- name: string;
336
- image?: string | null | undefined;
337
- } & Record<string, any>;
338
- } | null;
339
- session: {
340
- session: {
341
- id: string;
342
- createdAt: Date;
343
- updatedAt: Date;
344
- userId: string;
345
- expiresAt: Date;
346
- token: string;
347
- ipAddress?: string | null | undefined;
348
- userAgent?: string | null | undefined;
349
- } & Record<string, any>;
350
- user: {
351
- id: string;
352
- createdAt: Date;
353
- updatedAt: Date;
354
- email: string;
355
- emailVerified: boolean;
356
- name: string;
357
- image?: string | null | undefined;
358
- } & Record<string, any>;
359
- } | null;
360
- setNewSession: (session: {
361
- session: {
362
- id: string;
363
- createdAt: Date;
364
- updatedAt: Date;
365
- userId: string;
366
- expiresAt: Date;
367
- token: string;
368
- ipAddress?: string | null | undefined;
369
- userAgent?: string | null | undefined;
370
- } & Record<string, any>;
371
- user: {
372
- id: string;
373
- createdAt: Date;
374
- updatedAt: Date;
375
- email: string;
376
- emailVerified: boolean;
377
- name: string;
378
- image?: string | null | undefined;
379
- } & Record<string, any>;
380
- } | null) => void;
381
- socialProviders: import("better-auth").OAuthProvider[];
382
- authCookies: import("better-auth").BetterAuthCookies;
383
- logger: ReturnType<(options?: import("better-auth").Logger | undefined) => import("better-auth").InternalLogger>;
384
- rateLimit: {
385
- enabled: boolean;
386
- window: number;
387
- max: number;
388
- storage: "memory" | "database" | "secondary-storage";
389
- } & Omit<import("better-auth").BetterAuthRateLimitOptions, "enabled" | "window" | "max" | "storage">;
390
- adapter: import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>;
391
- internalAdapter: import("better-auth").InternalAdapter<import("better-auth").BetterAuthOptions>;
392
- createAuthCookie: (cookieName: string, overrideAttributes?: Partial<import("better-call").CookieOptions> | undefined) => import("better-auth").BetterAuthCookie;
393
- secret: string;
394
- secretConfig: string | import("better-auth").SecretConfig;
395
- sessionConfig: {
396
- updateAge: number;
397
- expiresIn: number;
398
- freshAge: number;
399
- cookieRefreshCache: false | {
400
- enabled: true;
401
- updateAge: number;
402
- };
403
- };
404
- generateId: (options: {
405
- model: import("better-auth").ModelNames;
406
- size?: number | undefined;
407
- }) => string | false;
408
- secondaryStorage: import("better-auth").SecondaryStorage | undefined;
409
- password: {
410
- hash: (password: string) => Promise<string>;
411
- verify: (data: {
412
- password: string;
413
- hash: string;
414
- }) => Promise<boolean>;
415
- config: {
416
- minPasswordLength: number;
417
- maxPasswordLength: number;
418
- };
419
- checkPassword: (userId: string, ctx: import("better-auth").GenericEndpointContext<import("better-auth").BetterAuthOptions>) => Promise<boolean>;
420
- };
421
- tables: import("better-auth").BetterAuthDBSchema;
422
- runMigrations: () => Promise<void>;
423
- publishTelemetry: (event: {
424
- type: string;
425
- anonymousId?: string | undefined;
426
- payload: Record<string, any>;
427
- }) => Promise<void>;
428
- skipOriginCheck: boolean | string[];
429
- skipCSRFCheck: boolean;
430
- runInBackground: (promise: Promise<unknown>) => void;
431
- runInBackgroundOrAwait: (promise: Promise<unknown> | void) => import("better-auth").Awaitable<unknown>;
432
- };
433
- redirect: (url: string) => import("better-call").APIError;
434
- error: (status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | import("better-call").Status, body?: {
435
- message?: string;
436
- code?: string;
437
- } & Record<string, any>, headers?: HeadersInit) => import("better-call").APIError;
438
- };
439
- } | undefined>;
440
- } | {
441
- matcher: (ctx: import("better-auth").HookEndpointContext) => boolean;
442
- handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
443
- })[];
444
- after: {
445
- matcher: (ctx: import("better-auth").HookEndpointContext) => boolean;
446
- handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
447
- }[];
448
- };
449
- };
450
- //#endregion
451
- //#region src/types.d.ts
452
- /**
453
- * Shared connection options used by infra plugins.
454
- */
455
- interface InfraPluginConnectionOptions {
456
- /**
457
- * The URL of the Better Auth Dash API
458
- * @default "https://dash.better-auth.com"
459
- */
460
- apiUrl?: string;
461
- /**
462
- * The URL of the KV storage service
463
- * @default "https://kv.better-auth.com"
464
- */
465
- kvUrl?: string;
466
- /**
467
- * Your Better Auth Dash API key
468
- * @default process.env.BETTER_AUTH_API_KEY
469
- */
470
- apiKey?: string;
471
- /**
472
- * Timeout for Dash API HTTP requests (milliseconds).
473
- * @default 3000
474
- */
475
- apiTimeout?: number;
476
- /**
477
- * Timeout for KV HTTP requests (milliseconds).
478
- * @default 1000
479
- */
480
- kvTimeout?: number;
481
- }
482
- /**
483
- * Configuration options for the dash plugin.
484
- */
485
- interface DashOptions extends InfraPluginConnectionOptions {
486
- /**
487
- * User activity tracking configuration
488
- */
489
- activityTracking?: {
490
- /**
491
- * Whether to enable user activity tracking
492
- *
493
- * This requires a database schema change to the user table.
494
- * @default false
495
- */
496
- enabled?: boolean;
497
- /**
498
- * Interval in milliseconds to update lastActiveAt for active users
499
- * Set to 0 to disable interval-based tracking
500
- * @default 300000 (5 minutes)
501
- */
502
- updateInterval?: number;
503
- };
504
- }
505
- /**
506
- * Configuration options for the sentinel plugin.
507
- */
508
- interface SentinelOptions extends InfraPluginConnectionOptions {
509
- /**
510
- * Security features configuration
511
- */
512
- security?: SecurityOptions;
513
- }
514
- /**
515
- * Internal connection options with required fields resolved.
516
- */
517
- interface InfraPluginConnectionOptionsInternal extends InfraPluginConnectionOptions {
518
- apiUrl: string;
519
- kvUrl: string;
520
- apiKey: string;
521
- apiTimeout: number;
522
- kvTimeout: number;
523
- }
524
- /**
525
- * Internal options with required fields resolved
526
- */
527
- interface DashOptionsInternal extends Omit<DashOptions, keyof InfraPluginConnectionOptions>, InfraPluginConnectionOptionsInternal {
528
- /**
529
- * Shared Dash HTTP client from {@link createAPI}; injected by {@link dash} when wiring endpoints.
530
- *
531
- * @internal
532
- */
533
- $api: ReturnType<typeof import("@better-fetch/fetch").createFetch>;
534
- }
535
- /**
536
- * Resolved dash options from {@link resolveDashOptions} / plugin-stored config; excludes injected `$api`.
537
- */
538
- type DashOptionsResolved = Omit<DashOptionsInternal, "$api">;
539
- /**
540
- * Internal sentinel options with required fields resolved.
541
- */
542
- interface SentinelOptionsInternal extends Omit<SentinelOptions, keyof InfraPluginConnectionOptions>, InfraPluginConnectionOptionsInternal {}
543
- /**
544
- * Location/geo data used across events, audit logs, and request context.
545
- */
546
- interface LocationData {
547
- ipAddress?: string | null;
548
- city?: string | null;
549
- country?: string | null;
550
- countryCode?: string | null;
551
- }
552
- /** @deprecated Use LocationData instead */
553
- type LocationDataContext = LocationData;
554
- type InfraEndpointContext = (GenericEndpointContext & {
555
- context: {
556
- identification?: Identification | null | undefined;
557
- visitorId: string | null;
558
- requestId: string | null;
559
- ip: string | null;
560
- untrustedVisitorId: string | null;
561
- location: LocationData | undefined;
562
- };
563
- }) | undefined;
564
- //#endregion
565
9
  //#region src/pow.d.ts
566
10
  /**
567
11
  * Proof of Work Challenge System - Client Side
@@ -650,9 +94,20 @@ interface SendSMSResult {
650
94
  interface SMSConfig {
651
95
  apiKey?: string;
652
96
  apiUrl?: string;
97
+ /**
98
+ * Dash API HTTP client options.
99
+ */
100
+ apiOptions?: {
101
+ /**
102
+ * Timeout for Dash SMS API HTTP requests (milliseconds).
103
+ * @default 3000
104
+ */
105
+ timeout?: number;
106
+ };
653
107
  /**
654
108
  * Timeout for Dash SMS API HTTP requests (milliseconds).
655
109
  * @default 3000
110
+ * @deprecated Use `apiOptions.timeout` instead.
656
111
  */
657
112
  apiTimeout?: number;
658
113
  }
@@ -778,23 +233,112 @@ interface DashIdRow {
778
233
  }
779
234
  //#endregion
780
235
  //#region src/routes/directory-sync/types.d.ts
236
+ /**
237
+ * SCIM authorization scope supported by the managed directory workflow.
238
+ *
239
+ * Redeclared rather than imported from `@better-auth/scim`: this type is part
240
+ * of the root package's public surface, and `@better-auth/scim` is an
241
+ * optional peer the root entry must never reference (see
242
+ * smoke/directory-sync-root-types).
243
+ */
244
+ type DashSCIMScope = "scim.users.read" | "scim.users.write" | "scim.groups.read" | "scim.groups.write";
245
+ /** Public lifecycle state of a managed SCIM credential. */
246
+ type DashSCIMManagedCredentialStatus = "active" | "revoked" | "expired" | "decommissioned";
247
+ /** Public managed-catalog event emitted by the SCIM plugin. */
248
+ type DashSCIMManagedConnectionEventType = "connection.created" | "credential.issued" | "credential.rotated" | "credential.revoked" | "connection.decommissioning" | "connection.decommissioned";
249
+ /** Lifecycle state for one Infrastructure-owned directory-sync alias. */
250
+ type DirectorySyncConnectionStatus = "active" | "decommissioning" | "decommissioned";
251
+ type DirectorySyncMode = "legacy" | "managed" | "unavailable";
781
252
  type SCIMPlugin = ReturnType<typeof import("@better-auth/scim").scim>;
253
+ /** Public credential metadata. Raw bearer tokens are never included here. */
254
+ interface DashDirectoryCredential {
255
+ credentialId: string;
256
+ status: DashSCIMManagedCredentialStatus;
257
+ scopes: readonly DashSCIMScope[];
258
+ expiresAt: string;
259
+ createdAt: string;
260
+ createdBy: string;
261
+ lastUsedAt: string | null;
262
+ revokedAt: string | null;
263
+ revokedBy: string | null;
264
+ }
265
+ /** One bounded framework-managed SCIM audit event. */
266
+ interface DashDirectoryEvent {
267
+ sequence: number;
268
+ type: DashSCIMManagedConnectionEventType;
269
+ actorId: string;
270
+ credentialId: string | null;
271
+ createdAt: string;
272
+ }
273
+ /** Atomic SSO provider and verified identity source paired to a directory. */
274
+ type DashDirectorySyncSSOPairing = {
275
+ ssoProviderId: string;
276
+ protocol: "oidc";
277
+ externalIdSource: {
278
+ kind: "subject";
279
+ } | {
280
+ kind: "verifiedIdTokenClaim";
281
+ name: string;
282
+ };
283
+ } | {
284
+ ssoProviderId: string;
285
+ protocol: "saml";
286
+ externalIdSource: {
287
+ kind: "nameId";
288
+ } | {
289
+ kind: "attribute";
290
+ name: string;
291
+ };
292
+ };
293
+ /** Infra alias plus the corresponding framework-managed SCIM state. */
782
294
  interface DirectorySyncConnection {
295
+ connectionId: string | null;
783
296
  organizationId: string;
784
297
  providerId: string;
298
+ provisioningDomainId: string;
299
+ status: DirectorySyncConnectionStatus;
300
+ scimEndpoint: string;
301
+ credentials: DashDirectoryCredential[];
302
+ createdAt: string;
303
+ updatedAt: string;
304
+ pairing: DashDirectorySyncSSOPairing | null;
305
+ pairingEnforced: boolean;
306
+ unpairedAt: string | null;
307
+ unpairedBy: string | null;
308
+ decommissionedAt: string | null;
309
+ }
310
+ type DashDirectoryItem = DirectorySyncConnection;
311
+ /** Create returns a raw bearer token exactly once. */
312
+ interface DashDirectoryCreateResponse extends DirectorySyncConnection {
313
+ connectionId: string;
314
+ credential: DashDirectoryCredential;
315
+ scimToken: string;
316
+ }
317
+ /** Rotation returns only the newly issued raw bearer token. */
318
+ interface DashDirectoryRotateCredentialResponse {
319
+ connectionId: string;
320
+ credential: DashDirectoryCredential;
321
+ scimToken: string;
785
322
  scimEndpoint: string;
786
323
  }
787
- interface DashDirectoryCreateResponse {
324
+ interface DashDirectoryEventsResponse {
325
+ events: DashDirectoryEvent[];
326
+ total: number;
327
+ limit: number;
328
+ offset: number;
329
+ }
330
+ /** Legacy (pre-1.7) directory sync connection listed for an organization. */
331
+ interface LegacyDashDirectoryItem {
788
332
  organizationId: string;
789
333
  providerId: string;
790
334
  scimEndpoint: string;
791
- scimToken: string;
792
335
  }
793
- interface DashDirectoryItem {
794
- id?: string;
795
- providerId: string;
336
+ /** Legacy create returns a one-time SCIM token. */
337
+ interface LegacyDashDirectoryCreateResponse {
796
338
  organizationId: string;
339
+ providerId: string;
797
340
  scimEndpoint: string;
341
+ scimToken: string;
798
342
  }
799
343
  interface DashDirectoryDeleteResponse {
800
344
  success: boolean;
@@ -1848,7 +1392,7 @@ declare const dash: <O extends DashOptions>(options?: O) => {
1848
1392
  }>)[];
1849
1393
  body: import("zod").ZodObject<{
1850
1394
  providerId: import("zod").ZodString;
1851
- accountId: import("zod").ZodOptional<import("zod").ZodString>;
1395
+ accountId: import("zod").ZodString;
1852
1396
  }, import("zod/v4/core").$strip>;
1853
1397
  }, DashSuccessResponse>;
1854
1398
  dashRevokeSession: import("better-call").StrictEndpoint<"/dash/sessions/revoke", {
@@ -2462,7 +2006,7 @@ declare const dash: <O extends DashOptions>(options?: O) => {
2462
2006
  use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
2463
2007
  payload: Record<string, unknown>;
2464
2008
  }>)[];
2465
- }, DashDirectoryItem[]>;
2009
+ }, DirectorySyncConnection[] | LegacyDashDirectoryItem[]>;
2466
2010
  createDashOrganizationDirectory: import("better-call").StrictEndpoint<"/dash/organization/directory/create", {
2467
2011
  method: "POST";
2468
2012
  use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
@@ -2474,7 +2018,7 @@ declare const dash: <O extends DashOptions>(options?: O) => {
2474
2018
  providerId: import("zod").ZodString;
2475
2019
  ownerUserId: import("zod").ZodString;
2476
2020
  }, import("zod/v4/core").$strip>;
2477
- }, DashDirectoryCreateResponse>;
2021
+ }, LegacyDashDirectoryCreateResponse>;
2478
2022
  deleteDashOrganizationDirectory: import("better-call").StrictEndpoint<"/dash/organization/directory/delete", {
2479
2023
  method: "POST";
2480
2024
  use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
@@ -2497,6 +2041,138 @@ declare const dash: <O extends DashOptions>(options?: O) => {
2497
2041
  providerId: import("zod").ZodString;
2498
2042
  }, import("zod/v4/core").$strip>;
2499
2043
  }, DashDirectoryRegenerateTokenResponse>;
2044
+ getDashManagedOrganizationDirectory: import("better-call").StrictEndpoint<"/dash/organization/:id/directories/:providerId", {
2045
+ method: "GET";
2046
+ use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
2047
+ payload: {
2048
+ purpose: "directory-sync-management";
2049
+ organizationId: string;
2050
+ actorId: string;
2051
+ setupOperationId?: string | undefined;
2052
+ };
2053
+ }>)[];
2054
+ }, DirectorySyncConnection>;
2055
+ createDashManagedOrganizationDirectory: import("better-call").StrictEndpoint<"/dash/organization/:id/directories", {
2056
+ method: "POST";
2057
+ use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
2058
+ payload: {
2059
+ purpose: "directory-sync-management";
2060
+ organizationId: string;
2061
+ actorId: string;
2062
+ setupOperationId?: string | undefined;
2063
+ };
2064
+ }>)[];
2065
+ body: import("zod").ZodObject<{
2066
+ scopes: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodEnum<{
2067
+ "scim.users.read": "scim.users.read";
2068
+ "scim.users.write": "scim.users.write";
2069
+ "scim.groups.read": "scim.groups.read";
2070
+ "scim.groups.write": "scim.groups.write";
2071
+ }>>>;
2072
+ expiresAt: import("zod").ZodOptional<import("zod").ZodCoercedDate<unknown>>;
2073
+ providerId: import("zod").ZodString;
2074
+ pairing: import("zod").ZodOptional<import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
2075
+ ssoProviderId: import("zod").ZodString;
2076
+ protocol: import("zod").ZodLiteral<"oidc">;
2077
+ externalIdSource: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
2078
+ kind: import("zod").ZodLiteral<"subject">;
2079
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
2080
+ kind: import("zod").ZodLiteral<"verifiedIdTokenClaim">;
2081
+ name: import("zod").ZodString;
2082
+ }, import("zod/v4/core").$strip>], "kind">;
2083
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
2084
+ ssoProviderId: import("zod").ZodString;
2085
+ protocol: import("zod").ZodLiteral<"saml">;
2086
+ externalIdSource: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
2087
+ kind: import("zod").ZodLiteral<"nameId">;
2088
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
2089
+ kind: import("zod").ZodLiteral<"attribute">;
2090
+ name: import("zod").ZodString;
2091
+ }, import("zod/v4/core").$strip>], "kind">;
2092
+ }, import("zod/v4/core").$strip>], "protocol">>;
2093
+ }, import("zod/v4/core").$strip>;
2094
+ metadata: {
2095
+ noStore: boolean;
2096
+ };
2097
+ }, DashDirectoryCreateResponse>;
2098
+ rotateDashManagedDirectoryCredential: import("better-call").StrictEndpoint<"/dash/organization/:id/directories/:providerId/credentials/rotate", {
2099
+ method: "POST";
2100
+ use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
2101
+ payload: {
2102
+ purpose: "directory-sync-management";
2103
+ organizationId: string;
2104
+ actorId: string;
2105
+ setupOperationId?: string | undefined;
2106
+ };
2107
+ }>)[];
2108
+ body: import("zod").ZodObject<{
2109
+ scopes: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodEnum<{
2110
+ "scim.users.read": "scim.users.read";
2111
+ "scim.users.write": "scim.users.write";
2112
+ "scim.groups.read": "scim.groups.read";
2113
+ "scim.groups.write": "scim.groups.write";
2114
+ }>>>;
2115
+ expiresAt: import("zod").ZodOptional<import("zod").ZodCoercedDate<unknown>>;
2116
+ }, import("zod/v4/core").$strip>;
2117
+ metadata: {
2118
+ noStore: boolean;
2119
+ };
2120
+ }, DashDirectoryRotateCredentialResponse>;
2121
+ revokeDashManagedDirectoryCredential: import("better-call").StrictEndpoint<"/dash/organization/:id/directories/:providerId/credentials/:credentialId/revoke", {
2122
+ method: "POST";
2123
+ use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
2124
+ payload: {
2125
+ purpose: "directory-sync-management";
2126
+ organizationId: string;
2127
+ actorId: string;
2128
+ setupOperationId?: string | undefined;
2129
+ };
2130
+ }>)[];
2131
+ body: import("zod").ZodObject<{}, import("zod/v4/core").$strip>;
2132
+ }, DirectorySyncConnection>;
2133
+ listDashManagedDirectoryEvents: import("better-call").StrictEndpoint<"/dash/organization/:id/directories/:providerId/events", {
2134
+ method: "GET";
2135
+ use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
2136
+ payload: {
2137
+ purpose: "directory-sync-management";
2138
+ organizationId: string;
2139
+ actorId: string;
2140
+ setupOperationId?: string | undefined;
2141
+ };
2142
+ }>)[];
2143
+ query: import("zod").ZodOptional<import("zod").ZodObject<{
2144
+ limit: import("zod").ZodOptional<import("zod").ZodUnion<[import("zod").ZodNumber, import("zod").ZodPipe<import("zod").ZodString, import("zod").ZodTransform<number, string>>]>>;
2145
+ offset: import("zod").ZodOptional<import("zod").ZodUnion<[import("zod").ZodNumber, import("zod").ZodPipe<import("zod").ZodString, import("zod").ZodTransform<number, string>>]>>;
2146
+ sortDirection: import("zod").ZodOptional<import("zod").ZodEnum<{
2147
+ asc: "asc";
2148
+ desc: "desc";
2149
+ }>>;
2150
+ }, import("zod/v4/core").$strip>>;
2151
+ }, DashDirectoryEventsResponse>;
2152
+ decommissionDashManagedOrganizationDirectory: import("better-call").StrictEndpoint<"/dash/organization/:id/directories/:providerId/decommission", {
2153
+ method: "POST";
2154
+ use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
2155
+ payload: {
2156
+ purpose: "directory-sync-management";
2157
+ organizationId: string;
2158
+ actorId: string;
2159
+ setupOperationId?: string | undefined;
2160
+ };
2161
+ }>)[];
2162
+ body: import("zod").ZodObject<{}, import("zod/v4/core").$strip>;
2163
+ }, DirectorySyncConnection>;
2164
+ unpairDashManagedOrganizationDirectory: import("better-call").StrictEndpoint<"/dash/organization/:id/directories/:providerId/unpair", {
2165
+ method: "POST";
2166
+ use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
2167
+ payload: {
2168
+ purpose: "directory-sync-management";
2169
+ organizationId: string;
2170
+ actorId: string;
2171
+ setupOperationId?: string | undefined;
2172
+ };
2173
+ }>)[];
2174
+ body: import("zod").ZodObject<{}, import("zod/v4/core").$strip>;
2175
+ }, DirectorySyncConnection>;
2500
2176
  dashExecuteAdapter: import("better-call").StrictEndpoint<"/dash/execute-adapter", {
2501
2177
  method: "POST";
2502
2178
  use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
@@ -2614,7 +2290,7 @@ declare const dash: <O extends DashOptions>(options?: O) => {
2614
2290
  }, import("zod/v4/core").$strip>], "action">;
2615
2291
  }, DashExecuteAdapterResponse>;
2616
2292
  };
2617
- schema: O extends {
2293
+ schema: (O extends {
2618
2294
  activityTracking: {
2619
2295
  enabled: true;
2620
2296
  };
@@ -2627,7 +2303,18 @@ declare const dash: <O extends DashOptions>(options?: O) => {
2627
2303
  };
2628
2304
  };
2629
2305
  };
2630
- } : {};
2306
+ } : {}) & (O extends {
2307
+ managedDirectorySync: {
2308
+ enabled: true;
2309
+ };
2310
+ } ? {
2311
+ directorySyncConnection: {
2312
+ fields: Record<string, DBFieldAttribute>;
2313
+ };
2314
+ directorySyncMembershipProvenance: {
2315
+ fields: Record<string, DBFieldAttribute>;
2316
+ };
2317
+ } : {});
2631
2318
  };
2632
2319
  //#endregion
2633
- export { type APIError, CHALLENGE_TTL, type CompromisedPasswordResult, type CredentialStuffingResult, type DBField, DEFAULT_DIFFICULTY, type DashAddTeamMemberResponse, type DashBanManyResponse, type DashCheckUserByEmailResponse, type DashCheckUserExistsResponse, type DashCompleteInvitationResponse, type DashConfigResponse, type DashCreateOrganizationBody, type DashCreateOrganizationResponse, type DashCreateTeamResponse, type DashCreateUserResponse, type DashDeleteManyUsersResponse, type DashDirectoryCreateResponse, type DashDirectoryDeleteResponse, type DashDirectoryItem, type DashDirectoryRegenerateTokenResponse, type DashExecuteAdapterCountResponse, type DashExecuteAdapterFindManyResponse, type DashExecuteAdapterFindOneResponse, type DashExecuteAdapterMutationResponse, type DashExecuteAdapterResponse, type DashExportOrganizationsResponse, type DashIdRow, type DashInviteMemberResponse, type DashMaybeSuccessResponse, type DashOptions, type DashOptionsInternal, type DashOptionsResolved, type DashOrganizationAddMemberResponse, type DashOrganizationDeleteManyResponse, type DashOrganizationDetailResponse, type DashOrganizationInvitationItem, type DashOrganizationInvitationListResponse, type DashOrganizationInvitationStatusItem, type DashOrganizationListResponse, type DashOrganizationMember, type DashOrganizationMemberListItem, type DashOrganizationMemberListResponse, type DashOrganizationMemberUser, type DashOrganizationOptionsResponse, type DashOrganizationTeamItem, type DashOrganizationTeamListResponse, type DashOrganizationUpdateMemberRoleResponse, type DashOrganizationUpdateResponse, type DashSendManyVerificationEmailsResponse, type DashSessionRevokeManyResponse, type DashSsoCreateProviderResponse, type DashSsoDeleteResponse, type DashSsoMarkDomainVerifiedResponse, type DashSsoProviderItem, type DashSsoProviderSummary, type DashSsoUpdateProviderResponse, type DashSsoVerificationTokenResponse, type DashSsoVerifyDomainResponse, type DashSuccessResponse, type DashTeam, type DashTeamMember, type DashTeamMemberListResponse, type DashTwoFactorBackupCodesResponse, type DashTwoFactorEnableResponse, type DashTwoFactorStatus, type DashTwoFactorTotpViewResponse, type DashUpdateTeamResponse, type DashUpdateUserResponse, type DashUserDetailsResponse, type DashUserGraphDataResponse, type DashUserListResponse, type DashUserOrganizationsResponse, type DashUserRetentionDataResponse, type DashUserStatsActivePeriod, type DashUserStatsResponse, type DashUserStatsSignUpPeriod, type DashValidateResponse, type DirectorySyncConnection, EMAIL_TEMPLATES, type EmailConfig, type EmailTemplateId, type EmailTemplateVariables, type Endpoint, type EndpointOptions, type EventLocation, type EventTypesResponse, type ImpossibleTravelResult, type InfraEndpointContext, type InfraPluginConnectionOptions, type InfraPluginConnectionOptionsInternal, type LocationData, type LocationDataContext, type ORGANIZATION_USER_PREVIEW_SELECT, type OrganizationUserPreview, type PoWChallenge, type PoWSolution, type SCIMPlugin, type SMSConfig, type SMSTemplateId, type SMSTemplateVariables, SMS_TEMPLATES, type SecurityEvent, type SecurityEventType, type SecurityOptions, type SecurityVerdict, type SendBulkEmailsOptions, type SendBulkEmailsResult, type SendEmailOptions, type SendEmailResult, type SendSMSOptions, type SendSMSResult, type SentinelOptions, type SentinelOptionsInternal, type StaleUserResult, type ThresholdConfig, USER_EVENT_TYPES, type UserEvent, type UserEventType, type UserEventsResponse, createEmailSender, createSMSSender, dash, decodePoWChallenge, encodePoWSolution, normalizeEmail, sendBulkEmails, sendEmail, sendSMS, sentinel, solvePoWChallenge, verifyPoWSolution };
2320
+ export { type APIError, type ApiOptions, type ApiOptionsResolved, CHALLENGE_TTL, type CompromisedPasswordResult, type CredentialStuffingResult, type DBField, DEFAULT_DIFFICULTY, type DashAddTeamMemberResponse, type DashBanManyResponse, type DashCheckUserByEmailResponse, type DashCheckUserExistsResponse, type DashCompleteInvitationResponse, type DashConfigResponse, type DashCreateOrganizationBody, type DashCreateOrganizationResponse, type DashCreateTeamResponse, type DashCreateUserResponse, type DashDeleteManyUsersResponse, type DashDirectoryCreateResponse, type DashDirectoryCredential, type DashDirectoryDeleteResponse, type DashDirectoryEvent, type DashDirectoryEventsResponse, type DashDirectoryItem, type DashDirectoryRegenerateTokenResponse, type DashDirectoryRotateCredentialResponse, type DashDirectorySyncSSOPairing, type DashExecuteAdapterCountResponse, type DashExecuteAdapterFindManyResponse, type DashExecuteAdapterFindOneResponse, type DashExecuteAdapterMutationResponse, type DashExecuteAdapterResponse, type DashExportOrganizationsResponse, type DashIdRow, type DashInviteMemberResponse, type DashMaybeSuccessResponse, type DashOptions, type DashOptionsInternal, type DashOptionsResolved, type DashOrganizationAddMemberResponse, type DashOrganizationDeleteManyResponse, type DashOrganizationDetailResponse, type DashOrganizationInvitationItem, type DashOrganizationInvitationListResponse, type DashOrganizationInvitationStatusItem, type DashOrganizationListResponse, type DashOrganizationMember, type DashOrganizationMemberListItem, type DashOrganizationMemberListResponse, type DashOrganizationMemberUser, type DashOrganizationOptionsResponse, type DashOrganizationTeamItem, type DashOrganizationTeamListResponse, type DashOrganizationUpdateMemberRoleResponse, type DashOrganizationUpdateResponse, type DashSCIMManagedConnectionEventType, type DashSCIMManagedCredentialStatus, type DashSCIMScope, type DashSendManyVerificationEmailsResponse, type DashSessionRevokeManyResponse, type DashSsoCreateProviderResponse, type DashSsoDeleteResponse, type DashSsoMarkDomainVerifiedResponse, type DashSsoProviderItem, type DashSsoProviderSummary, type DashSsoUpdateProviderResponse, type DashSsoVerificationTokenResponse, type DashSsoVerifyDomainResponse, type DashSuccessResponse, type DashTeam, type DashTeamMember, type DashTeamMemberListResponse, type DashTwoFactorBackupCodesResponse, type DashTwoFactorEnableResponse, type DashTwoFactorStatus, type DashTwoFactorTotpViewResponse, type DashUpdateTeamResponse, type DashUpdateUserResponse, type DashUserDetailsResponse, type DashUserGraphDataResponse, type DashUserListResponse, type DashUserOrganizationsResponse, type DashUserRetentionDataResponse, type DashUserStatsActivePeriod, type DashUserStatsResponse, type DashUserStatsSignUpPeriod, type DashValidateResponse, type DirectorySyncConnection, type DirectorySyncConnectionStatus, type DirectorySyncMode, EMAIL_TEMPLATES, type EmailConfig, type EmailTemplateId, type EmailTemplateVariables, type Endpoint, type EndpointOptions, type EventLocation, type EventTypesResponse, type ImpossibleTravelResult, type InfraEndpointContext, type InfraPluginConnectionOptions, type InfraPluginConnectionOptionsInternal, type KvOptions, type KvOptionsResolved, type KvRetryOptions, type KvRetryOptionsResolved, type LegacyDashDirectoryCreateResponse, type LegacyDashDirectoryItem, type LocationData, type LocationDataContext, type ORGANIZATION_USER_PREVIEW_SELECT, type OrganizationUserPreview, type PoWChallenge, type PoWSolution, type SCIMPlugin, type SMSConfig, type SMSTemplateId, type SMSTemplateVariables, SMS_TEMPLATES, type SecurityEvent, type SecurityEventType, type SecurityOptions, type SecurityVerdict, type SendBulkEmailsOptions, type SendBulkEmailsResult, type SendEmailOptions, type SendEmailResult, type SendSMSOptions, type SendSMSResult, type SentinelOptions, type SentinelOptionsInternal, type StaleUserResult, type ThresholdConfig, USER_EVENT_TYPES, type UserEvent, type UserEventType, type UserEventsResponse, createEmailSender, createSMSSender, dash, decodePoWChallenge, encodePoWSolution, normalizeEmail, sendBulkEmails, sendEmail, sendSMS, sentinel, solvePoWChallenge, verifyPoWSolution };