@banata-auth/convex 0.1.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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +104 -0
  3. package/dist/auth-config.d.ts +22 -0
  4. package/dist/auth-config.d.ts.map +1 -0
  5. package/dist/auth-config.js +3 -0
  6. package/dist/auth-config.js.map +1 -0
  7. package/dist/auth.d.ts +462 -0
  8. package/dist/auth.d.ts.map +1 -0
  9. package/dist/component/adapter.d.ts +21 -0
  10. package/dist/component/adapter.d.ts.map +1 -0
  11. package/dist/component/adapter.js +3 -0
  12. package/dist/component/adapter.js.map +1 -0
  13. package/dist/component/schema.d.ts +1026 -0
  14. package/dist/component/schema.d.ts.map +1 -0
  15. package/dist/hooks.d.ts +25 -0
  16. package/dist/hooks.d.ts.map +1 -0
  17. package/dist/http.d.ts +41 -0
  18. package/dist/http.d.ts.map +1 -0
  19. package/dist/http.js +62 -0
  20. package/dist/http.js.map +1 -0
  21. package/dist/index.d.ts +9 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +9516 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/node.d.ts +389 -0
  26. package/dist/node.d.ts.map +1 -0
  27. package/dist/node.js +9559 -0
  28. package/dist/node.js.map +1 -0
  29. package/dist/plugins/audit.d.ts +106 -0
  30. package/dist/plugins/audit.d.ts.map +1 -0
  31. package/dist/plugins/config.d.ts +83 -0
  32. package/dist/plugins/config.d.ts.map +1 -0
  33. package/dist/plugins/domains.d.ts +3 -0
  34. package/dist/plugins/domains.d.ts.map +1 -0
  35. package/dist/plugins/email-sender.d.ts +75 -0
  36. package/dist/plugins/email-sender.d.ts.map +1 -0
  37. package/dist/plugins/email-templates.d.ts +108 -0
  38. package/dist/plugins/email-templates.d.ts.map +1 -0
  39. package/dist/plugins/email.d.ts +82 -0
  40. package/dist/plugins/email.d.ts.map +1 -0
  41. package/dist/plugins/enterprise.d.ts +3 -0
  42. package/dist/plugins/enterprise.d.ts.map +1 -0
  43. package/dist/plugins/events.d.ts +40 -0
  44. package/dist/plugins/events.d.ts.map +1 -0
  45. package/dist/plugins/index.d.ts +18 -0
  46. package/dist/plugins/index.d.ts.map +1 -0
  47. package/dist/plugins/index.js +9192 -0
  48. package/dist/plugins/index.js.map +1 -0
  49. package/dist/plugins/organization-rbac.d.ts +3 -0
  50. package/dist/plugins/organization-rbac.d.ts.map +1 -0
  51. package/dist/plugins/portal.d.ts +34 -0
  52. package/dist/plugins/portal.d.ts.map +1 -0
  53. package/dist/plugins/projects.d.ts +16 -0
  54. package/dist/plugins/projects.d.ts.map +1 -0
  55. package/dist/plugins/protection.d.ts +127 -0
  56. package/dist/plugins/protection.d.ts.map +1 -0
  57. package/dist/plugins/types.d.ts +508 -0
  58. package/dist/plugins/types.d.ts.map +1 -0
  59. package/dist/plugins/user-management.d.ts +8 -0
  60. package/dist/plugins/user-management.d.ts.map +1 -0
  61. package/dist/plugins/vault.d.ts +68 -0
  62. package/dist/plugins/vault.d.ts.map +1 -0
  63. package/dist/plugins/webhook.d.ts +65 -0
  64. package/dist/plugins/webhook.d.ts.map +1 -0
  65. package/dist/triggers.d.ts +158 -0
  66. package/dist/triggers.d.ts.map +1 -0
  67. package/dist/triggers.js +36 -0
  68. package/dist/triggers.js.map +1 -0
  69. package/package.json +102 -0
  70. package/src/component/adapter.ts +21 -0
  71. package/src/component/convex.config.ts +15 -0
  72. package/src/component/schema.ts +916 -0
@@ -0,0 +1,3 @@
1
+ import type { BetterAuthPlugin } from "better-auth";
2
+ export declare function organizationRbacPlugin(): BetterAuthPlugin;
3
+ //# sourceMappingURL=organization-rbac.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization-rbac.d.ts","sourceRoot":"","sources":["../../src/plugins/organization-rbac.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA2YpD,wBAAgB,sBAAsB,IAAI,gBAAgB,CA05BzD"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Portal plugin for Banata Auth.
3
+ *
4
+ * Provides an Admin Portal link generation API that creates short-lived,
5
+ * scoped portal sessions for organization IT admins. Each portal link
6
+ * grants access to a specific intent (SSO, Directory Sync, Audit Logs, etc.)
7
+ * within an organization context.
8
+ *
9
+ * This mirrors WorkOS's Admin Portal feature, allowing you to generate
10
+ * a URL that redirects an org admin to a self-serve configuration page.
11
+ *
12
+ * @see {@link ../../../shared/src/types.ts} for the PortalSession SDK type
13
+ */
14
+ import type { BetterAuthPlugin } from "better-auth";
15
+ /**
16
+ * Portal plugin for Banata Auth.
17
+ *
18
+ * Registers API endpoints under `/api/auth/banata/portal/*` that allow
19
+ * programmatic generation of short-lived admin portal links.
20
+ *
21
+ * @returns A Better Auth plugin descriptor
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * import { portalPlugin } from "./plugins/portal";
26
+ *
27
+ * const plugins = [
28
+ * portalPlugin(),
29
+ * // ... other plugins
30
+ * ];
31
+ * ```
32
+ */
33
+ export declare function portalPlugin(): BetterAuthPlugin;
34
+ //# sourceMappingURL=portal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../src/plugins/portal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAwEpD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,IAAI,gBAAgB,CA+K/C"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Banata Auth Projects Plugin
3
+ *
4
+ * Provides multi-project support.
5
+ * Each project is a fully isolated auth tenant with its own users, sessions,
6
+ * organizations, branding, email templates, API keys, webhooks, etc.
7
+ */
8
+ import type { BetterAuthPlugin } from "better-auth";
9
+ export interface ProjectsPluginOptions {
10
+ /** Whether to auto-create a default project if none exist. Default: true */
11
+ autoCreateDefault?: boolean;
12
+ /** Default project name when auto-creating. Default: "Default Project" */
13
+ defaultProjectName?: string;
14
+ }
15
+ export declare function projectsPlugin(options?: ProjectsPluginOptions): BetterAuthPlugin;
16
+ //# sourceMappingURL=projects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/plugins/projects.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAkTpD,MAAM,WAAW,qBAAqB;IACrC,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAID,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,gBAAgB,CA6PpF"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Bot protection plugin for Banata Auth.
3
+ *
4
+ * Provides request-level bot detection and abuse prevention using
5
+ * Better Auth's `onRequest` hook. This plugin intercepts incoming
6
+ * requests BEFORE any auth processing occurs and can short-circuit
7
+ * with a 403 if a bot is detected.
8
+ *
9
+ * The plugin is provider-agnostic — it accepts a `verifyRequest`
10
+ * callback that consumers implement with their preferred bot detection
11
+ * service (Vercel BotID, Cloudflare Turnstile, hCaptcha, reCAPTCHA, etc.).
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { banataProtection } from "@banata-auth/convex/plugins";
16
+ *
17
+ * // The plugin is automatically included when you configure protection
18
+ * // in your BanataAuthConfig:
19
+ * const config: BanataAuthConfig = {
20
+ * protection: {
21
+ * enabled: true,
22
+ * protectedPaths: ["/sign-in", "/sign-up", "/forget-password", "/reset-password"],
23
+ * verifyRequest: async (request) => {
24
+ * // Implement your bot verification logic here
25
+ * return { isBot: false };
26
+ * },
27
+ * },
28
+ * };
29
+ * ```
30
+ */
31
+ import type { BetterAuthPlugin } from "better-auth";
32
+ /**
33
+ * Result of a bot verification check.
34
+ */
35
+ export interface BotVerificationResult {
36
+ /** Whether the request was identified as coming from a bot. */
37
+ isBot: boolean;
38
+ /** Optional reason for the bot detection (for logging). */
39
+ reason?: string;
40
+ }
41
+ /**
42
+ * Function that verifies whether a request is from a bot.
43
+ * Implement this with your bot detection provider of choice.
44
+ *
45
+ * @param request - The incoming HTTP request
46
+ * @returns Verification result indicating whether the request is from a bot
47
+ */
48
+ export type BotVerifyFn = (request: Request) => Promise<BotVerificationResult>;
49
+ /**
50
+ * Configuration for the bot protection plugin.
51
+ */
52
+ export interface BanataProtectionOptions {
53
+ /**
54
+ * Whether bot protection is enabled.
55
+ * When false, all requests pass through without verification.
56
+ * @default true
57
+ */
58
+ enabled?: boolean;
59
+ /**
60
+ * Path prefixes to protect from bots.
61
+ * Only requests whose pathname starts with one of these prefixes
62
+ * will be verified. All other requests pass through.
63
+ *
64
+ * @default ["/sign-in", "/sign-up", "/forget-password", "/reset-password"]
65
+ */
66
+ protectedPaths?: string[];
67
+ /**
68
+ * The bot verification function.
69
+ * Called for every request that matches a protected path.
70
+ * If not provided, requests pass through (useful for development).
71
+ */
72
+ verifyRequest?: BotVerifyFn;
73
+ /**
74
+ * HTTP methods to check. By default only POST requests are verified
75
+ * since GET requests to auth endpoints are typically metadata/redirect
76
+ * flows, not credential submissions.
77
+ *
78
+ * @default ["POST"]
79
+ */
80
+ protectedMethods?: string[];
81
+ /**
82
+ * Custom error message returned when a bot is detected.
83
+ * @default "Bot detected. Access denied."
84
+ */
85
+ blockedMessage?: string;
86
+ /**
87
+ * Called when a bot is detected (for logging/analytics).
88
+ */
89
+ onBotDetected?: (request: Request, result: BotVerificationResult) => void | Promise<void>;
90
+ /**
91
+ * Whether to fail open (allow request) when the verification
92
+ * function throws an error. This prevents legitimate users from
93
+ * being locked out if the bot detection service is unavailable.
94
+ *
95
+ * @default true
96
+ */
97
+ failOpen?: boolean;
98
+ }
99
+ /**
100
+ * Bot protection plugin for Banata Auth.
101
+ *
102
+ * Uses Better Auth's `onRequest` hook to intercept requests before
103
+ * any auth processing. Protected paths are checked against the
104
+ * configured `verifyRequest` function.
105
+ *
106
+ * @param options - Protection configuration
107
+ * @returns A Better Auth plugin
108
+ *
109
+ * @example
110
+ * ```ts
111
+ * import { banataProtection } from "@banata-auth/convex/plugins";
112
+ * import { checkBotId } from "botid/server";
113
+ *
114
+ * banataProtection({
115
+ * verifyRequest: async (request) => {
116
+ * try {
117
+ * const result = await checkBotId();
118
+ * return { isBot: result.isBot };
119
+ * } catch {
120
+ * return { isBot: false }; // fail open
121
+ * }
122
+ * },
123
+ * });
124
+ * ```
125
+ */
126
+ export declare function banataProtection(options?: BanataProtectionOptions): BetterAuthPlugin;
127
+ //# sourceMappingURL=protection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protection.d.ts","sourceRoot":"","sources":["../../src/plugins/protection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,+DAA+D;IAC/D,KAAK,EAAE,OAAO,CAAC;IACf,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAC;AAE/E;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACvC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,WAAW,CAAC;IAE5B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE5B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1F;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAUD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,gBAAgB,CA4FxF"}
@@ -0,0 +1,508 @@
1
+ /**
2
+ * Shared type definitions for Banata Auth plugins.
3
+ *
4
+ * These types provide type-safe interfaces for the Better Auth plugin system,
5
+ * replacing raw `any` usage throughout the plugin codebase.
6
+ *
7
+ * Better Auth's plugin system uses `better-call` endpoints under the hood.
8
+ * The handler context (`EndpointContext`) includes the full `AuthContext` which
9
+ * contains the database adapter, session info, and more.
10
+ *
11
+ * @see https://www.better-auth.com/docs/plugins/custom-plugin
12
+ */
13
+ import type { BetterAuthOptions } from "better-auth";
14
+ import { z } from "zod";
15
+ /**
16
+ * Where clause for database queries.
17
+ * Matches Better Auth's Where type from @better-auth/core/dist/db/adapter.
18
+ */
19
+ export interface WhereClause {
20
+ field: string;
21
+ value: string | number | boolean | string[] | number[] | Date | null;
22
+ operator?: "eq" | "ne" | "lt" | "lte" | "gt" | "gte" | "in" | "not_in" | "contains" | "starts_with" | "ends_with";
23
+ connector?: "AND" | "OR";
24
+ }
25
+ /**
26
+ * Sort specification for database queries.
27
+ */
28
+ export interface SortBy {
29
+ field: string;
30
+ direction: "asc" | "desc";
31
+ }
32
+ /**
33
+ * Typed subset of Better Auth's DBAdapter.
34
+ *
35
+ * This represents the adapter available on `ctx.context.adapter`.
36
+ * We use generic `Record<string, unknown>` for data instead of `any`.
37
+ */
38
+ export interface PluginDBAdapter {
39
+ create: <T extends Record<string, unknown> = Record<string, unknown>>(data: {
40
+ model: string;
41
+ data: Record<string, unknown>;
42
+ select?: string[];
43
+ forceAllowId?: boolean;
44
+ }) => Promise<T>;
45
+ findOne: <T = Record<string, unknown>>(data: {
46
+ model: string;
47
+ where: WhereClause[];
48
+ select?: string[];
49
+ }) => Promise<T | null>;
50
+ findMany: <T = Record<string, unknown>>(data: {
51
+ model: string;
52
+ where?: WhereClause[];
53
+ limit?: number;
54
+ select?: string[];
55
+ sortBy?: SortBy;
56
+ offset?: number;
57
+ }) => Promise<T[]>;
58
+ update: <T = Record<string, unknown>>(data: {
59
+ model: string;
60
+ where: WhereClause[];
61
+ update: Record<string, unknown>;
62
+ }) => Promise<T | null>;
63
+ delete: (data: {
64
+ model: string;
65
+ where: WhereClause[];
66
+ }) => Promise<void>;
67
+ deleteMany: (data: {
68
+ model: string;
69
+ where: WhereClause[];
70
+ }) => Promise<number>;
71
+ count: (data: {
72
+ model: string;
73
+ where?: WhereClause[];
74
+ }) => Promise<number>;
75
+ }
76
+ /**
77
+ * Shape of a user record from the session context.
78
+ */
79
+ export interface SessionUser {
80
+ id: string;
81
+ email: string;
82
+ name: string;
83
+ emailVerified: boolean;
84
+ image?: string | null;
85
+ role?: string;
86
+ banned?: boolean;
87
+ [key: string]: unknown;
88
+ }
89
+ /**
90
+ * Shape of a session record from the session context.
91
+ */
92
+ export interface SessionRecord {
93
+ id: string;
94
+ userId: string;
95
+ token: string;
96
+ expiresAt: number | Date;
97
+ ipAddress?: string | null;
98
+ userAgent?: string | null;
99
+ activeOrganizationId?: string | null;
100
+ impersonatedBy?: string | null;
101
+ createdAt: number | Date;
102
+ updatedAt: number | Date;
103
+ [key: string]: unknown;
104
+ }
105
+ /**
106
+ * The AuthContext subset available on `ctx.context` in endpoint handlers.
107
+ *
108
+ * This is a narrowed version of Better Auth's full AuthContext, including
109
+ * only the fields typically used by custom plugins.
110
+ */
111
+ export interface PluginAuthContext {
112
+ adapter: PluginDBAdapter;
113
+ session: {
114
+ session: SessionRecord;
115
+ user: SessionUser;
116
+ } | null;
117
+ options: BetterAuthOptions;
118
+ secret: string;
119
+ baseURL: string;
120
+ appName: string;
121
+ generateId: (options: {
122
+ model: string;
123
+ size?: number;
124
+ }) => string | false;
125
+ }
126
+ /**
127
+ * The full endpoint handler context for plugin endpoints.
128
+ *
129
+ * This is the `ctx` parameter received by endpoint handlers registered
130
+ * in a BetterAuthPlugin's `endpoints` object.
131
+ */
132
+ export interface PluginEndpointContext<TBody = Record<string, unknown>> {
133
+ /** Parsed and validated request body */
134
+ body: TBody;
135
+ /** Request query parameters */
136
+ query: Record<string, string | undefined>;
137
+ /** Request headers */
138
+ headers: Headers | undefined;
139
+ /** The auth context containing adapter, session, etc. */
140
+ context: PluginAuthContext;
141
+ /** Return a JSON response */
142
+ json: <R extends Record<string, unknown> | null>(data: R, options?: {
143
+ status?: number;
144
+ headers?: Record<string, string>;
145
+ } | Response) => Promise<R>;
146
+ /** Return an error response */
147
+ error: (status: number | string, body?: {
148
+ message?: string;
149
+ code?: string;
150
+ } & Record<string, unknown>, headers?: Record<string, string>) => Error;
151
+ /** The request path */
152
+ path: string;
153
+ /** The request object */
154
+ request: Request | undefined;
155
+ /** Get a request header */
156
+ getHeader: (key: string) => string | null;
157
+ }
158
+ /**
159
+ * Context passed to plugin hook matchers and handlers.
160
+ */
161
+ export interface PluginHookContext {
162
+ path?: string;
163
+ context: PluginAuthContext & {
164
+ returned?: unknown;
165
+ responseHeaders?: Headers;
166
+ };
167
+ headers?: Headers;
168
+ body?: Record<string, unknown>;
169
+ query?: Record<string, string | undefined>;
170
+ }
171
+ /**
172
+ * Row shape for the `auditEvent` table.
173
+ *
174
+ * Index signature allows these types to satisfy Record<string, unknown>
175
+ * which is required by Better Auth's DBAdapter generic constraints.
176
+ */
177
+ export interface AuditEventRow extends Record<string, unknown> {
178
+ id: string;
179
+ action: string;
180
+ version: number | null;
181
+ actorType: string;
182
+ actorId: string;
183
+ actorName: string | null;
184
+ actorEmail: string | null;
185
+ /** JSON-serialized Record<string, string> */
186
+ actorMetadata: string | null;
187
+ targets: string | null;
188
+ organizationId: string | null;
189
+ ipAddress: string | null;
190
+ userAgent: string | null;
191
+ requestId: string | null;
192
+ changes: string | null;
193
+ idempotencyKey: string | null;
194
+ /** JSON-serialized Record<string, string> */
195
+ metadata: string | null;
196
+ occurredAt: number;
197
+ createdAt: number;
198
+ }
199
+ /**
200
+ * Row shape for the `webhookEndpoint` table.
201
+ */
202
+ export interface WebhookEndpointRow extends Record<string, unknown> {
203
+ id: string;
204
+ url: string;
205
+ secret: string;
206
+ eventTypes: string | null;
207
+ enabled: boolean;
208
+ successCount: number | null;
209
+ failureCount: number | null;
210
+ consecutiveFailures: number | null;
211
+ lastDeliveryAt: number | null;
212
+ lastDeliveryStatus: string | null;
213
+ createdAt: number;
214
+ updatedAt: number;
215
+ }
216
+ /**
217
+ * Row shape for the `webhookDelivery` table.
218
+ */
219
+ export interface WebhookDeliveryRow extends Record<string, unknown> {
220
+ id: string;
221
+ endpointId: string;
222
+ eventType: string;
223
+ payload: string;
224
+ attempt: number;
225
+ maxAttempts: number;
226
+ status: "pending" | "success" | "failed" | "retrying";
227
+ httpStatus: number | null;
228
+ responseBody: string | null;
229
+ errorMessage: string | null;
230
+ nextRetryAt: number | null;
231
+ deliveredAt: number | null;
232
+ createdAt: number;
233
+ }
234
+ /**
235
+ * Row shape for the `roleDefinition` table.
236
+ */
237
+ export interface RoleDefinitionRow extends Record<string, unknown> {
238
+ id: string;
239
+ name: string;
240
+ slug: string;
241
+ description: string | null;
242
+ permissions: string | null;
243
+ isDefault: boolean | null;
244
+ createdAt: number;
245
+ updatedAt: number;
246
+ }
247
+ /**
248
+ * Row shape for the `permissionDefinition` table.
249
+ */
250
+ export interface PermissionDefinitionRow extends Record<string, unknown> {
251
+ id: string;
252
+ name: string;
253
+ slug: string;
254
+ description: string | null;
255
+ createdAt: number;
256
+ updatedAt: number;
257
+ }
258
+ /**
259
+ * Row shape for the `brandingConfig` table.
260
+ */
261
+ export interface BrandingConfigRow extends Record<string, unknown> {
262
+ id: string;
263
+ primaryColor: string | null;
264
+ bgColor: string | null;
265
+ borderRadius: number | null;
266
+ darkMode: boolean | null;
267
+ customCss: string | null;
268
+ font: string | null;
269
+ logoUrl: string | null;
270
+ createdAt: number;
271
+ updatedAt: number;
272
+ }
273
+ /**
274
+ * Row shape for the `emailTemplate` table.
275
+ */
276
+ export interface EmailTemplateRow extends Record<string, unknown> {
277
+ id: string;
278
+ name: string;
279
+ slug: string;
280
+ subject: string;
281
+ previewText: string | null;
282
+ category: string;
283
+ description: string | null;
284
+ /** JSON-serialized EmailBlock[] array. */
285
+ blocksJson: string;
286
+ /** JSON-serialized EmailTemplateVariable[] array. */
287
+ variablesJson: string | null;
288
+ builtIn: boolean | null;
289
+ builtInType: string | null;
290
+ createdAt: number;
291
+ updatedAt: number;
292
+ }
293
+ /**
294
+ * Row shape for the `emailConfig` table.
295
+ */
296
+ export interface EmailConfigRow extends Record<string, unknown> {
297
+ id: string;
298
+ emailType: string;
299
+ name: string;
300
+ description: string | null;
301
+ enabled: boolean;
302
+ category: string;
303
+ createdAt: number;
304
+ updatedAt: number;
305
+ }
306
+ /**
307
+ * Row shape for the `dashboardConfig` table.
308
+ * Singleton row pattern: at most one row exists.
309
+ * Stores JSON-serialized partial dashboard config overrides.
310
+ */
311
+ export interface DashboardConfigRow extends Record<string, unknown> {
312
+ id: string;
313
+ /** JSON-serialized partial dashboard config overrides */
314
+ configJson: string;
315
+ createdAt: number;
316
+ updatedAt: number;
317
+ }
318
+ /**
319
+ * Row shape for the `domainConfig` table.
320
+ */
321
+ export interface DomainConfigRow extends Record<string, unknown> {
322
+ id: string;
323
+ domainKey: string;
324
+ title: string;
325
+ description: string | null;
326
+ value: string;
327
+ isDefault: boolean | null;
328
+ createdAt: number;
329
+ updatedAt: number;
330
+ }
331
+ /**
332
+ * Row shape for the `redirectConfig` table.
333
+ * Singleton row with JSON-serialized redirect settings.
334
+ */
335
+ export interface RedirectConfigRow extends Record<string, unknown> {
336
+ id: string;
337
+ configJson: string;
338
+ createdAt: number;
339
+ updatedAt: number;
340
+ }
341
+ /**
342
+ * Row shape for the `actionConfig` table.
343
+ */
344
+ export interface ActionConfigRow extends Record<string, unknown> {
345
+ id: string;
346
+ name: string;
347
+ description: string | null;
348
+ triggerEvent: string;
349
+ webhookUrl: string;
350
+ createdAt: number;
351
+ updatedAt: number;
352
+ }
353
+ /**
354
+ * Row shape for the `radarConfig` table.
355
+ * Singleton row with JSON-serialized radar/bot protection settings.
356
+ */
357
+ export interface RadarConfigRow extends Record<string, unknown> {
358
+ id: string;
359
+ configJson: string;
360
+ createdAt: number;
361
+ updatedAt: number;
362
+ }
363
+ /**
364
+ * Row shape for the `emailProviderConfig` table.
365
+ * Singleton row with JSON-serialized email provider settings.
366
+ */
367
+ export interface EmailProviderConfigRow extends Record<string, unknown> {
368
+ id: string;
369
+ configJson: string;
370
+ createdAt: number;
371
+ updatedAt: number;
372
+ }
373
+ /**
374
+ * Row shape for the `resourceType` table.
375
+ */
376
+ export interface ResourceTypeRow extends Record<string, unknown> {
377
+ id: string;
378
+ name: string;
379
+ slug: string;
380
+ description: string | null;
381
+ createdAt: number;
382
+ updatedAt: number;
383
+ }
384
+ /**
385
+ * Row shape for the `addonConfig` table.
386
+ * Singleton row with JSON-serialized addon states.
387
+ */
388
+ export interface AddonConfigRow extends Record<string, unknown> {
389
+ id: string;
390
+ configJson: string;
391
+ createdAt: number;
392
+ updatedAt: number;
393
+ }
394
+ /**
395
+ * Row shape for the `projectConfig` table.
396
+ * One row per project with JSON-serialized project settings.
397
+ */
398
+ export interface ProjectConfigRow extends Record<string, unknown> {
399
+ id: string;
400
+ configJson: string;
401
+ projectId?: string;
402
+ createdAt: number;
403
+ updatedAt: number;
404
+ }
405
+ /**
406
+ * Row shape for the `project` table.
407
+ * Each project is a fully isolated auth tenant.
408
+ */
409
+ export interface ProjectRow extends Record<string, unknown> {
410
+ id: string;
411
+ name: string;
412
+ slug: string;
413
+ description?: string;
414
+ logoUrl?: string;
415
+ ownerId: string;
416
+ createdAt: number;
417
+ updatedAt: number;
418
+ }
419
+ export declare function parseRoleSlugs(value: string | string[] | null | undefined): string[];
420
+ export declare function isGlobalAdminRole(role: string | null | undefined): boolean;
421
+ export declare function isGlobalAdminUser(user: Pick<SessionUser, "role"> | null | undefined): boolean;
422
+ /**
423
+ * Verify that the current request has an authenticated session.
424
+ *
425
+ * This MUST be called at the top of every custom plugin endpoint
426
+ * that performs administrative operations (webhook CRUD, audit log
427
+ * management, roles/permissions CRUD, branding, email config, etc.).
428
+ *
429
+ * The function uses a loose type signature to remain compatible with
430
+ * Better Auth's `EndpointContext` which uses a narrower union type
431
+ * for error status codes (e.g. `"UNAUTHORIZED" | "FORBIDDEN" | ...`)
432
+ * rather than `string | number`.
433
+ *
434
+ * @param ctx - The endpoint handler context from Better Auth
435
+ * @throws Error with status "UNAUTHORIZED" if not authenticated
436
+ */
437
+ export declare function requireAuthenticated(ctx: any): {
438
+ session: SessionRecord;
439
+ user: SessionUser;
440
+ };
441
+ /**
442
+ * @deprecated Use `requireAuthenticated` or `requireGlobalAdmin` instead.
443
+ */
444
+ export declare function requireAdmin(ctx: any): {
445
+ session: SessionRecord;
446
+ user: SessionUser;
447
+ };
448
+ export declare function requireGlobalAdmin(ctx: any): {
449
+ session: SessionRecord;
450
+ user: SessionUser;
451
+ };
452
+ export declare function getRolePermissions(db: PluginDBAdapter, params: {
453
+ projectId?: string;
454
+ roleSlugs: string[];
455
+ }): Promise<Set<string>>;
456
+ /**
457
+ * Resolve the effective permission slugs for a user in a project.
458
+ *
459
+ * Permission sources:
460
+ * 1) Global Better Auth admin role (`user.role`)
461
+ * 2) Project ownership (`project.ownerId`)
462
+ * 3) Organization membership roles in the project (`member.role`)
463
+ */
464
+ export declare function getEffectiveProjectPermissions(db: PluginDBAdapter, params: {
465
+ userId: string;
466
+ projectId?: string;
467
+ }): Promise<Set<string>>;
468
+ /**
469
+ * Throws FORBIDDEN unless the current user has the given permission in project scope.
470
+ */
471
+ export declare function requireProjectPermission(ctx: any, params: {
472
+ db: PluginDBAdapter;
473
+ permission: string;
474
+ projectId?: string;
475
+ }): Promise<void>;
476
+ /**
477
+ * Zod schema partial for project-scoped endpoints.
478
+ * Add `.merge(projectScopeSchema)` to any endpoint body schema that
479
+ * should accept an optional projectId.
480
+ */
481
+ export declare const projectScopeSchema: z.ZodObject<{
482
+ projectId: z.ZodOptional<z.ZodString>;
483
+ }, "strip", z.ZodTypeAny, {
484
+ projectId?: string | undefined;
485
+ }, {
486
+ projectId?: string | undefined;
487
+ }>;
488
+ /**
489
+ * Extract projectId from a parsed body and return scope helpers.
490
+ *
491
+ * **Strict by default**: throws if `projectId` is missing.
492
+ * All project-scoped data MUST be isolated — returning empty filters
493
+ * would silently leak data across projects.
494
+ *
495
+ * Pass `{ optional: true }` only for endpoints that genuinely operate
496
+ * across all projects (e.g. project list, ensure-default).
497
+ */
498
+ export declare function getProjectScope(body: Record<string, unknown>, opts?: {
499
+ optional?: boolean;
500
+ }): {
501
+ /** Where clause filter for findMany/findOne/update/delete. */
502
+ where: WhereClause[];
503
+ /** Data fields to include in create. */
504
+ data: Record<string, string>;
505
+ /** The resolved projectId (always present when strict). */
506
+ projectId: string | undefined;
507
+ };
508
+ //# sourceMappingURL=types.d.ts.map