@better-auth/infra 0.3.7 → 0.4.1

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.
@@ -0,0 +1,672 @@
1
+ import { BetterAuthPlugin, GenericEndpointContext } from "better-auth";
2
+ import { createFetch } from "@better-fetch/fetch";
3
+ import { APIError as APIError$1, Endpoint, EndpointOptions } from "better-call";
4
+ //#region src/identification.d.ts
5
+ interface IPLocation {
6
+ lat: number;
7
+ lng: number;
8
+ city: string | null;
9
+ region: string | null;
10
+ postalCode: string | null;
11
+ country: {
12
+ code: string;
13
+ name: string;
14
+ } | null;
15
+ timezone: string | null;
16
+ }
17
+ interface Identification {
18
+ visitorId: string;
19
+ requestId: string;
20
+ timestamp: number;
21
+ url: string;
22
+ ip: string | null;
23
+ location: IPLocation | null;
24
+ browser: {
25
+ name: string | null;
26
+ version: string | null;
27
+ os: string | null;
28
+ osVersion: string | null;
29
+ device: string | null;
30
+ userAgent: string | null;
31
+ };
32
+ confidence: number;
33
+ incognito: boolean;
34
+ bot: "notDetected" | "detected" | "unknown";
35
+ }
36
+ //#endregion
37
+ //#region src/sentinel/security.d.ts
38
+ type SecurityAction = "log" | "block" | "challenge";
39
+ interface ThresholdConfig {
40
+ challenge?: number;
41
+ block?: number;
42
+ }
43
+ interface SecurityOptions {
44
+ unknownDeviceNotification?: boolean;
45
+ credentialStuffing?: {
46
+ enabled: boolean;
47
+ action?: SecurityAction;
48
+ thresholds?: ThresholdConfig;
49
+ windowSeconds?: number;
50
+ cooldownSeconds?: number;
51
+ };
52
+ impossibleTravel?: {
53
+ enabled: boolean;
54
+ maxSpeedKmh?: number;
55
+ action?: SecurityAction;
56
+ };
57
+ geoBlocking?: {
58
+ allowList?: string[];
59
+ denyList?: string[];
60
+ action?: "block" | "challenge";
61
+ };
62
+ botBlocking?: boolean | {
63
+ action: SecurityAction;
64
+ };
65
+ suspiciousIpBlocking?: boolean | {
66
+ action: SecurityAction;
67
+ };
68
+ velocity?: {
69
+ enabled: boolean;
70
+ thresholds?: ThresholdConfig;
71
+ maxSignupsPerVisitor?: number;
72
+ maxPasswordResetsPerIp?: number;
73
+ maxSignInsPerIp?: number;
74
+ windowSeconds?: number;
75
+ action?: SecurityAction;
76
+ };
77
+ freeTrialAbuse?: {
78
+ enabled: boolean;
79
+ thresholds?: ThresholdConfig;
80
+ maxAccountsPerVisitor?: number;
81
+ action?: SecurityAction;
82
+ };
83
+ compromisedPassword?: {
84
+ enabled: boolean;
85
+ action?: SecurityAction;
86
+ minBreachCount?: number;
87
+ };
88
+ emailValidation?: {
89
+ enabled?: boolean;
90
+ strictness?: "low" | "medium" | "high";
91
+ action?: SecurityAction;
92
+ domainAllowlist?: string[];
93
+ };
94
+ emailNormalization?: {
95
+ enabled?: boolean;
96
+ };
97
+ staleUsers?: {
98
+ enabled: boolean;
99
+ staleDays?: number;
100
+ action?: SecurityAction;
101
+ notifyUser?: boolean;
102
+ notifyAdmin?: boolean;
103
+ adminEmail?: string;
104
+ };
105
+ challengeDifficulty?: number;
106
+ }
107
+ interface SecurityVerdict {
108
+ action: "allow" | "challenge" | "block";
109
+ challenge?: string;
110
+ reason?: string;
111
+ details?: Record<string, unknown>;
112
+ /** Set when the request included a valid, consumed PoW solution. */
113
+ powVerified?: boolean;
114
+ }
115
+ interface CredentialStuffingResult {
116
+ blocked: boolean;
117
+ challenged?: boolean;
118
+ challenge?: string;
119
+ reason?: string;
120
+ details?: Record<string, unknown>;
121
+ }
122
+ interface ImpossibleTravelResult {
123
+ isImpossible: boolean;
124
+ action?: "allow" | "challenge" | "block";
125
+ challenged?: boolean;
126
+ challenge?: string;
127
+ powVerified?: boolean;
128
+ distance?: number;
129
+ timeElapsedHours?: number;
130
+ speedRequired?: number;
131
+ from?: {
132
+ city: string | null;
133
+ country: string | null;
134
+ } | null;
135
+ to?: {
136
+ city: string | null;
137
+ country: string | null;
138
+ } | null;
139
+ }
140
+ interface CompromisedPasswordResult {
141
+ compromised: boolean;
142
+ breachCount?: number;
143
+ action?: SecurityAction;
144
+ }
145
+ interface StaleUserResult {
146
+ isStale: boolean;
147
+ daysSinceLastActive?: number;
148
+ staleDays?: number;
149
+ lastActiveAt?: string | null;
150
+ action?: SecurityAction;
151
+ notifyUser?: boolean;
152
+ notifyAdmin?: boolean;
153
+ }
154
+ interface SecurityEvent {
155
+ type: SecurityEventType;
156
+ timestamp: number;
157
+ userId: string | null;
158
+ visitorId: string | null;
159
+ ip: string | null;
160
+ country: string | null;
161
+ details: Record<string, unknown>;
162
+ action: "logged" | "blocked" | "challenged";
163
+ }
164
+ 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";
165
+ //#endregion
166
+ //#region src/sentinel/sentinel.d.ts
167
+ declare const sentinel: (options?: SentinelOptions) => {
168
+ id: "sentinel";
169
+ init(ctx: import("better-auth").AuthContext): {
170
+ options: {
171
+ emailValidation: {
172
+ enabled?: boolean;
173
+ strictness?: "low" | "medium" | "high";
174
+ action?: SecurityAction;
175
+ domainAllowlist?: string[];
176
+ } | undefined;
177
+ emailNormalization: {
178
+ enabled?: boolean;
179
+ } | undefined;
180
+ databaseHooks: {
181
+ user: {
182
+ create: {
183
+ before(user: {
184
+ id: string;
185
+ createdAt: Date;
186
+ updatedAt: Date;
187
+ email: string;
188
+ emailVerified: boolean;
189
+ name: string;
190
+ image?: string | null | undefined;
191
+ } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<{
192
+ data: {
193
+ email: string;
194
+ id: string;
195
+ createdAt: Date;
196
+ updatedAt: Date;
197
+ emailVerified: boolean;
198
+ name: string;
199
+ image?: string | null | undefined;
200
+ };
201
+ } | undefined>;
202
+ after(user: {
203
+ id: string;
204
+ createdAt: Date;
205
+ updatedAt: Date;
206
+ email: string;
207
+ emailVerified: boolean;
208
+ name: string;
209
+ image?: string | null | undefined;
210
+ } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
211
+ };
212
+ update: {
213
+ before(user: Partial<{
214
+ id: string;
215
+ createdAt: Date;
216
+ updatedAt: Date;
217
+ email: string;
218
+ emailVerified: boolean;
219
+ name: string;
220
+ image?: string | null | undefined;
221
+ }> & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<{
222
+ data: {
223
+ email: string;
224
+ id?: string | undefined;
225
+ createdAt?: Date | undefined;
226
+ updatedAt?: Date | undefined;
227
+ emailVerified?: boolean | undefined;
228
+ name?: string | undefined;
229
+ image?: string | null | undefined;
230
+ };
231
+ } | undefined>;
232
+ };
233
+ };
234
+ session: {
235
+ create: {
236
+ before(session: {
237
+ id: string;
238
+ createdAt: Date;
239
+ updatedAt: Date;
240
+ userId: string;
241
+ expiresAt: Date;
242
+ token: string;
243
+ ipAddress?: string | null | undefined;
244
+ userAgent?: string | null | undefined;
245
+ } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
246
+ after(session: {
247
+ id: string;
248
+ createdAt: Date;
249
+ updatedAt: Date;
250
+ userId: string;
251
+ expiresAt: Date;
252
+ token: string;
253
+ ipAddress?: string | null | undefined;
254
+ userAgent?: string | null | undefined;
255
+ } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
256
+ };
257
+ };
258
+ };
259
+ };
260
+ };
261
+ hooks: {
262
+ before: ({
263
+ matcher: (context: Pick<import("better-auth").HookEndpointContext, "path">) => boolean;
264
+ handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
265
+ context: {
266
+ method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
267
+ path: string;
268
+ body: any;
269
+ query: Record<string, any> | undefined;
270
+ params: Record<string, any> & string;
271
+ request: Request | undefined;
272
+ headers: Headers | undefined;
273
+ setHeader: ((key: string, value: string) => void) & ((key: string, value: string) => void);
274
+ setStatus: (status: import("better-call").Status) => void;
275
+ getHeader: ((key: string) => string | null) & ((key: string) => string | null);
276
+ getCookie: (key: string, prefix?: import("better-call").CookiePrefixOptions) => string | null;
277
+ getSignedCookie: (key: string, secret: string, prefix?: import("better-call").CookiePrefixOptions) => Promise<string | null | false>;
278
+ setCookie: (key: string, value: string, options?: import("better-call").CookieOptions) => string;
279
+ setSignedCookie: (key: string, value: string, secret: string, options?: import("better-call").CookieOptions) => Promise<string>;
280
+ responseHeaders: Headers;
281
+ json: (<R extends Record<string, any> | null>(json: R, routerResponse?: {
282
+ status?: number;
283
+ headers?: Record<string, string>;
284
+ response?: Response;
285
+ body?: Record<string, string>;
286
+ } | Response) => Promise<R>) & (<R extends Record<string, any> | null>(json: R, routerResponse?: {
287
+ status?: number;
288
+ headers?: Record<string, string>;
289
+ response?: Response;
290
+ } | Response) => Promise<R>);
291
+ context: {
292
+ [x: string]: any;
293
+ } & {
294
+ returned?: unknown | undefined;
295
+ responseHeaders?: Headers | undefined;
296
+ 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 {
297
+ creator: infer C;
298
+ } ? C extends ((...args: any[]) => infer R) ? R : never : never : BetterAuthPlugin) | null;
299
+ hasPlugin: <ID extends import("better-auth").BetterAuthPluginRegistryIdentifier | import("better-auth").LiteralString>(pluginId: ID) => ID extends never ? true : boolean;
300
+ appName: string;
301
+ baseURL: string;
302
+ version: string;
303
+ options: import("better-auth").BetterAuthOptions;
304
+ trustedOrigins: string[];
305
+ trustedProviders: string[];
306
+ isTrustedOrigin: (url: string, settings?: {
307
+ allowRelativePaths: boolean;
308
+ }) => boolean;
309
+ oauthConfig: {
310
+ skipStateCookieCheck?: boolean | undefined;
311
+ storeStateStrategy: "database" | "cookie";
312
+ };
313
+ newSession: {
314
+ session: {
315
+ id: string;
316
+ createdAt: Date;
317
+ updatedAt: Date;
318
+ userId: string;
319
+ expiresAt: Date;
320
+ token: string;
321
+ ipAddress?: string | null | undefined;
322
+ userAgent?: string | null | undefined;
323
+ } & Record<string, any>;
324
+ user: {
325
+ id: string;
326
+ createdAt: Date;
327
+ updatedAt: Date;
328
+ email: string;
329
+ emailVerified: boolean;
330
+ name: string;
331
+ image?: string | null | undefined;
332
+ } & Record<string, any>;
333
+ } | null;
334
+ session: {
335
+ session: {
336
+ id: string;
337
+ createdAt: Date;
338
+ updatedAt: Date;
339
+ userId: string;
340
+ expiresAt: Date;
341
+ token: string;
342
+ ipAddress?: string | null | undefined;
343
+ userAgent?: string | null | undefined;
344
+ } & Record<string, any>;
345
+ user: {
346
+ id: string;
347
+ createdAt: Date;
348
+ updatedAt: Date;
349
+ email: string;
350
+ emailVerified: boolean;
351
+ name: string;
352
+ image?: string | null | undefined;
353
+ } & Record<string, any>;
354
+ } | null;
355
+ setNewSession: (session: {
356
+ session: {
357
+ id: string;
358
+ createdAt: Date;
359
+ updatedAt: Date;
360
+ userId: string;
361
+ expiresAt: Date;
362
+ token: string;
363
+ ipAddress?: string | null | undefined;
364
+ userAgent?: string | null | undefined;
365
+ } & Record<string, any>;
366
+ user: {
367
+ id: string;
368
+ createdAt: Date;
369
+ updatedAt: Date;
370
+ email: string;
371
+ emailVerified: boolean;
372
+ name: string;
373
+ image?: string | null | undefined;
374
+ } & Record<string, any>;
375
+ } | null) => void;
376
+ socialProviders: import("better-auth").OAuthProvider[];
377
+ authCookies: import("better-auth").BetterAuthCookies;
378
+ logger: ReturnType<(options?: import("better-auth").Logger | undefined) => import("better-auth").InternalLogger>;
379
+ rateLimit: {
380
+ enabled: boolean;
381
+ window: number;
382
+ max: number;
383
+ storage: "memory" | "database" | "secondary-storage";
384
+ } & Omit<import("better-auth").BetterAuthRateLimitOptions, "enabled" | "window" | "max" | "storage">;
385
+ adapter: import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>;
386
+ internalAdapter: import("better-auth").InternalAdapter<import("better-auth").BetterAuthOptions>;
387
+ createAuthCookie: (cookieName: string, overrideAttributes?: Partial<import("better-call").CookieOptions> | undefined) => import("better-auth").BetterAuthCookie;
388
+ secret: string;
389
+ secretConfig: string | import("better-auth").SecretConfig;
390
+ sessionConfig: {
391
+ updateAge: number;
392
+ expiresIn: number;
393
+ freshAge: number;
394
+ cookieRefreshCache: false | {
395
+ enabled: true;
396
+ updateAge: number;
397
+ };
398
+ };
399
+ generateId: (options: {
400
+ model: import("better-auth").ModelNames;
401
+ size?: number | undefined;
402
+ }) => string | false;
403
+ secondaryStorage: import("better-auth").SecondaryStorage | undefined;
404
+ password: {
405
+ hash: (password: string) => Promise<string>;
406
+ verify: (data: {
407
+ password: string;
408
+ hash: string;
409
+ }) => Promise<boolean>;
410
+ config: {
411
+ minPasswordLength: number;
412
+ maxPasswordLength: number;
413
+ };
414
+ checkPassword: (userId: string, ctx: import("better-auth").GenericEndpointContext<import("better-auth").BetterAuthOptions>) => Promise<boolean>;
415
+ };
416
+ tables: import("better-auth").BetterAuthDBSchema;
417
+ runMigrations: () => Promise<void>;
418
+ publishTelemetry: (event: {
419
+ type: string;
420
+ anonymousId?: string | undefined;
421
+ payload: Record<string, any>;
422
+ }) => Promise<void>;
423
+ skipOriginCheck: boolean | string[];
424
+ skipCSRFCheck: boolean;
425
+ runInBackground: (promise: Promise<unknown>) => void;
426
+ runInBackgroundOrAwait: (promise: Promise<unknown> | void) => import("better-auth").Awaitable<unknown>;
427
+ };
428
+ redirect: (url: string) => import("better-call").APIError;
429
+ 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?: {
430
+ message?: string;
431
+ code?: string;
432
+ } & Record<string, any>, headers?: HeadersInit) => import("better-call").APIError;
433
+ };
434
+ } | undefined>;
435
+ } | {
436
+ matcher: (ctx: import("better-auth").HookEndpointContext) => boolean;
437
+ handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
438
+ })[];
439
+ after: {
440
+ matcher: (ctx: import("better-auth").HookEndpointContext) => boolean;
441
+ handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
442
+ }[];
443
+ };
444
+ };
445
+ //#endregion
446
+ //#region src/types.d.ts
447
+ /**
448
+ * Retry/backoff for identify HTTP calls.
449
+ */
450
+ interface KvRetryOptions {
451
+ /**
452
+ * Max retry index after a thrown failure. `0` = single attempt.
453
+ * @default 2
454
+ */
455
+ attempts?: number;
456
+ /**
457
+ * Base delay (ms) before the first retry.
458
+ * @default 400
459
+ */
460
+ baseDelay?: number;
461
+ /**
462
+ * Cap for exponential retry delay (ms).
463
+ * @default 600
464
+ */
465
+ maxDelay?: number;
466
+ }
467
+ /**
468
+ * Resolved {@link KvRetryOptions} with defaults applied.
469
+ */
470
+ type KvRetryOptionsResolved = Required<KvRetryOptions>;
471
+ /**
472
+ * Dash API HTTP client options.
473
+ */
474
+ interface ApiOptions {
475
+ /**
476
+ * Timeout for Dash API HTTP requests (milliseconds).
477
+ * @default 3000
478
+ */
479
+ timeout?: number;
480
+ }
481
+ /**
482
+ * Resolved {@link ApiOptions} with defaults applied.
483
+ */
484
+ type ApiOptionsResolved = Required<ApiOptions>;
485
+ /**
486
+ * KV HTTP client options.
487
+ */
488
+ interface KvOptions {
489
+ /**
490
+ * Timeout for KV HTTP requests (milliseconds).
491
+ * @default 1000
492
+ */
493
+ timeout?: number;
494
+ /**
495
+ * Retry/backoff for KV identify lookups.
496
+ * @default { attempts: 2, baseDelay: 400, maxDelay: 600 }
497
+ */
498
+ retry?: KvRetryOptions;
499
+ }
500
+ /**
501
+ * Resolved {@link KvOptions} with defaults applied.
502
+ */
503
+ interface KvOptionsResolved {
504
+ timeout: number;
505
+ retry: KvRetryOptionsResolved;
506
+ }
507
+ /**
508
+ * Shared connection options used by infra plugins.
509
+ */
510
+ interface InfraPluginConnectionOptions {
511
+ /**
512
+ * The URL of the Better Auth Dash API
513
+ * @default "https://dash.better-auth.com"
514
+ */
515
+ apiUrl?: string;
516
+ /**
517
+ * The URL of the KV storage service
518
+ * @default "https://kv.better-auth.com"
519
+ */
520
+ kvUrl?: string;
521
+ /**
522
+ * Your Better Auth Dash API key
523
+ * @default process.env.BETTER_AUTH_API_KEY
524
+ */
525
+ apiKey?: string;
526
+ /**
527
+ * Dash API HTTP client options.
528
+ */
529
+ apiOptions?: ApiOptions;
530
+ /**
531
+ * KV HTTP client options.
532
+ */
533
+ kvOptions?: KvOptions;
534
+ /**
535
+ * Timeout for Dash API HTTP requests (milliseconds).
536
+ * @default 3000
537
+ * @deprecated Use `apiOptions.timeout` instead.
538
+ */
539
+ apiTimeout?: number;
540
+ /**
541
+ * Timeout for KV HTTP requests (milliseconds).
542
+ * @default 1000
543
+ * @deprecated Use `kvOptions.timeout` instead.
544
+ */
545
+ kvTimeout?: number;
546
+ }
547
+ /**
548
+ * Configuration options for the dash plugin.
549
+ */
550
+ interface DashOptions extends InfraPluginConnectionOptions {
551
+ /**
552
+ * User activity tracking configuration
553
+ */
554
+ activityTracking?: {
555
+ /**
556
+ * Whether to enable user activity tracking
557
+ *
558
+ * This requires a database schema change to the user table.
559
+ * @default false
560
+ */
561
+ enabled?: boolean;
562
+ /**
563
+ * Interval in milliseconds to update lastActiveAt for active users
564
+ * Set to 0 to disable interval-based tracking
565
+ * @default 300000 (5 minutes)
566
+ */
567
+ updateInterval?: number;
568
+ };
569
+ /**
570
+ * Opt into the 1.7+ managed directory-sync control plane.
571
+ *
572
+ * Enable together with `scim({ managedConnections })` when the dashboard
573
+ * should reserve and manage SCIM connections. This does not replace or
574
+ * disable legacy pre-1.7 SCIM provider APIs.
575
+ */
576
+ managedDirectorySync?: {
577
+ /**
578
+ * Whether to enable managed directory-sync reservation tables/APIs.
579
+ *
580
+ * Adds `directorySyncConnection` and
581
+ * `directorySyncMembershipProvenance` via plugin schema.
582
+ * @default false
583
+ */
584
+ enabled?: boolean;
585
+ /**
586
+ * Install SSO `resolveUser` / `guardProviderMutation` for directory
587
+ * pairing. Required only when creating paired directories. Needs
588
+ * `sso({})` (or richer options) so callbacks can be installed.
589
+ * @default true
590
+ */
591
+ ssoPairing?: boolean;
592
+ /**
593
+ * SCIM → organization membership projection.
594
+ *
595
+ * When enabled, dash installs SCIM `projection.reconcileUser` so
596
+ * provisioned users are projected into organization memberships.
597
+ */
598
+ membershipProjection?: {
599
+ /**
600
+ * Whether to install membership projection.
601
+ * @default true
602
+ */
603
+ enabled?: boolean;
604
+ /**
605
+ * Role assigned when projection creates organization memberships.
606
+ * @default "member"
607
+ */
608
+ role?: string;
609
+ };
610
+ };
611
+ }
612
+ /**
613
+ * Configuration options for the sentinel plugin.
614
+ */
615
+ interface SentinelOptions extends InfraPluginConnectionOptions {
616
+ /**
617
+ * Security features configuration
618
+ */
619
+ security?: SecurityOptions;
620
+ }
621
+ /**
622
+ * Internal connection options with required fields resolved.
623
+ */
624
+ interface InfraPluginConnectionOptionsInternal extends Omit<InfraPluginConnectionOptions, "apiOptions" | "kvOptions" | "apiTimeout" | "kvTimeout"> {
625
+ apiUrl: string;
626
+ kvUrl: string;
627
+ apiKey: string;
628
+ apiOptions: ApiOptionsResolved;
629
+ kvOptions: KvOptionsResolved;
630
+ }
631
+ /**
632
+ * Internal options with required fields resolved
633
+ */
634
+ interface DashOptionsInternal extends Omit<DashOptions, keyof InfraPluginConnectionOptions>, InfraPluginConnectionOptionsInternal {
635
+ /**
636
+ * Shared Dash HTTP client from {@link createAPI}; injected by {@link dash} when wiring endpoints.
637
+ *
638
+ * @internal
639
+ */
640
+ $api: ReturnType<typeof import("@better-fetch/fetch").createFetch>;
641
+ }
642
+ /**
643
+ * Resolved dash options from {@link resolveDashOptions} / plugin-stored config; excludes injected `$api`.
644
+ */
645
+ type DashOptionsResolved = Omit<DashOptionsInternal, "$api">;
646
+ /**
647
+ * Internal sentinel options with required fields resolved.
648
+ */
649
+ interface SentinelOptionsInternal extends Omit<SentinelOptions, keyof InfraPluginConnectionOptions>, InfraPluginConnectionOptionsInternal {}
650
+ /**
651
+ * Location/geo data used across events, audit logs, and request context.
652
+ */
653
+ interface LocationData {
654
+ ipAddress?: string | null;
655
+ city?: string | null;
656
+ country?: string | null;
657
+ countryCode?: string | null;
658
+ }
659
+ /** @deprecated Use LocationData instead */
660
+ type LocationDataContext = LocationData;
661
+ type InfraEndpointContext = (GenericEndpointContext & {
662
+ context: {
663
+ identification?: Identification | null | undefined;
664
+ visitorId: string | null;
665
+ requestId: string | null;
666
+ ip: string | null;
667
+ untrustedVisitorId: string | null;
668
+ location: LocationData | undefined;
669
+ };
670
+ }) | undefined;
671
+ //#endregion
672
+ export { ImpossibleTravelResult as C, SecurityVerdict as D, SecurityOptions as E, StaleUserResult as O, CredentialStuffingResult as S, SecurityEventType as T, LocationDataContext as _, DashOptionsInternal as a, sentinel as b, EndpointOptions as c, InfraPluginConnectionOptionsInternal as d, KvOptions as f, LocationData as g, KvRetryOptionsResolved as h, DashOptions as i, ThresholdConfig as k, InfraEndpointContext as l, KvRetryOptions as m, ApiOptions as n, DashOptionsResolved as o, KvOptionsResolved as p, ApiOptionsResolved as r, Endpoint as s, APIError$1 as t, InfraPluginConnectionOptions as u, SentinelOptions as v, SecurityEvent as w, CompromisedPasswordResult as x, SentinelOptionsInternal as y };