@rebasepro/server-core 0.7.0 → 0.8.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 (155) hide show
  1. package/build-errors.txt +52 -0
  2. package/dist/api/ast-schema-editor.d.ts +21 -0
  3. package/dist/api/collections_for_test/callbacks_test_collection.d.ts +2 -0
  4. package/dist/api/errors.d.ts +53 -0
  5. package/dist/api/graphql/graphql-schema-generator.d.ts +44 -0
  6. package/dist/api/graphql/index.d.ts +1 -0
  7. package/dist/api/index.d.ts +9 -0
  8. package/dist/api/logs-routes.d.ts +37 -0
  9. package/dist/api/openapi-generator.d.ts +16 -0
  10. package/dist/api/rest/api-generator.d.ts +76 -0
  11. package/dist/api/rest/index.d.ts +1 -0
  12. package/dist/api/rest/query-parser.d.ts +8 -0
  13. package/dist/api/schema-editor-routes.d.ts +3 -0
  14. package/dist/api/server.d.ts +40 -0
  15. package/dist/api/types.d.ts +104 -0
  16. package/dist/auth/adapter-middleware.d.ts +43 -0
  17. package/dist/auth/admin-roles-route.d.ts +18 -0
  18. package/dist/auth/admin-user-ops.d.ts +79 -0
  19. package/dist/auth/admin-users-route.d.ts +28 -0
  20. package/dist/auth/api-keys/api-key-middleware.d.ts +39 -0
  21. package/dist/auth/api-keys/api-key-permission-guard.d.ts +32 -0
  22. package/dist/auth/api-keys/api-key-routes.d.ts +20 -0
  23. package/dist/auth/api-keys/api-key-store.d.ts +35 -0
  24. package/dist/auth/api-keys/api-key-types.d.ts +96 -0
  25. package/dist/auth/api-keys/index.d.ts +17 -0
  26. package/dist/auth/apple-oauth.d.ts +30 -0
  27. package/dist/auth/auth-hooks.d.ts +242 -0
  28. package/dist/auth/bitbucket-oauth.d.ts +11 -0
  29. package/dist/auth/builtin-auth-adapter.d.ts +51 -0
  30. package/dist/auth/crypto-utils.d.ts +16 -0
  31. package/dist/auth/custom-auth-adapter.d.ts +39 -0
  32. package/dist/auth/discord-oauth.d.ts +14 -0
  33. package/dist/auth/facebook-oauth.d.ts +14 -0
  34. package/dist/auth/github-oauth.d.ts +15 -0
  35. package/dist/auth/gitlab-oauth.d.ts +13 -0
  36. package/dist/auth/google-oauth.d.ts +47 -0
  37. package/dist/auth/index.d.ts +37 -0
  38. package/dist/auth/interfaces.d.ts +431 -0
  39. package/dist/auth/jwt.d.ts +55 -0
  40. package/dist/auth/linkedin-oauth.d.ts +18 -0
  41. package/dist/auth/magic-link-routes.d.ts +30 -0
  42. package/dist/auth/mfa-crypto.d.ts +23 -0
  43. package/dist/auth/mfa-routes.d.ts +7 -0
  44. package/dist/auth/mfa.d.ts +49 -0
  45. package/dist/auth/microsoft-oauth.d.ts +16 -0
  46. package/dist/auth/middleware.d.ts +113 -0
  47. package/dist/auth/password.d.ts +22 -0
  48. package/dist/auth/rate-limiter.d.ts +50 -0
  49. package/dist/auth/reset-password-admin.d.ts +29 -0
  50. package/dist/auth/rls-scope.d.ts +31 -0
  51. package/dist/auth/routes.d.ts +35 -0
  52. package/dist/auth/session-routes.d.ts +27 -0
  53. package/dist/auth/slack-oauth.d.ts +12 -0
  54. package/dist/auth/spotify-oauth.d.ts +12 -0
  55. package/dist/auth/twitter-oauth.d.ts +18 -0
  56. package/dist/backend-CIxN4FVm.js +15 -0
  57. package/dist/backend-CIxN4FVm.js.map +1 -0
  58. package/dist/base64-js-C_frYBkI.js +1687 -0
  59. package/dist/base64-js-C_frYBkI.js.map +1 -0
  60. package/dist/chunk-Dze3rakg.js +42 -0
  61. package/dist/collections/BackendCollectionRegistry.d.ts +13 -0
  62. package/dist/collections/loader.d.ts +5 -0
  63. package/dist/cron/cron-loader.d.ts +17 -0
  64. package/dist/cron/cron-routes.d.ts +14 -0
  65. package/dist/cron/cron-scheduler.d.ts +106 -0
  66. package/dist/cron/cron-store.d.ts +32 -0
  67. package/dist/cron/index.d.ts +6 -0
  68. package/dist/db/interfaces.d.ts +18 -0
  69. package/dist/dist-DMO-zF6D.js +832 -0
  70. package/dist/dist-DMO-zF6D.js.map +1 -0
  71. package/dist/email/index.d.ts +6 -0
  72. package/dist/email/smtp-email-service.d.ts +25 -0
  73. package/dist/email/templates.d.ts +50 -0
  74. package/dist/email/types.d.ts +126 -0
  75. package/dist/env.d.ts +102 -0
  76. package/dist/from-VbwD7xRf.js +3849 -0
  77. package/dist/from-VbwD7xRf.js.map +1 -0
  78. package/dist/functions/define-function.d.ts +50 -0
  79. package/dist/functions/function-loader.d.ts +17 -0
  80. package/dist/functions/function-routes.d.ts +10 -0
  81. package/dist/functions/index.d.ts +5 -0
  82. package/dist/history/history-routes.d.ts +23 -0
  83. package/dist/history/index.d.ts +1 -0
  84. package/dist/index.d.ts +31 -0
  85. package/dist/index.es.js +61322 -0
  86. package/dist/index.es.js.map +1 -0
  87. package/dist/index.umd.js +103633 -0
  88. package/dist/index.umd.js.map +1 -0
  89. package/dist/init/docs.d.ts +4 -0
  90. package/dist/init/health.d.ts +2 -0
  91. package/dist/init/middlewares.d.ts +10 -0
  92. package/dist/init/shutdown.d.ts +11 -0
  93. package/dist/init/storage.d.ts +5 -0
  94. package/dist/init.d.ts +314 -0
  95. package/dist/jws-BqRRaK11.js +616 -0
  96. package/dist/jws-BqRRaK11.js.map +1 -0
  97. package/dist/jwt-BETC8a1J.js +3560 -0
  98. package/dist/jwt-BETC8a1J.js.map +1 -0
  99. package/dist/logger-BYU66ENZ.js +94 -0
  100. package/dist/logger-BYU66ENZ.js.map +1 -0
  101. package/dist/ms-BeBSuOXN.js +125 -0
  102. package/dist/ms-BeBSuOXN.js.map +1 -0
  103. package/dist/multipart-parser-CedBDOeC.js +299 -0
  104. package/dist/multipart-parser-CedBDOeC.js.map +1 -0
  105. package/dist/serve-spa.d.ts +30 -0
  106. package/dist/services/driver-registry.d.ts +78 -0
  107. package/dist/services/routed-realtime-service.d.ts +43 -0
  108. package/dist/services/webhook-service.d.ts +29 -0
  109. package/dist/singleton.d.ts +35 -0
  110. package/dist/src-CB2PIpBe.js +1182 -0
  111. package/dist/src-CB2PIpBe.js.map +1 -0
  112. package/dist/src-DjzOT1kG.js +29746 -0
  113. package/dist/src-DjzOT1kG.js.map +1 -0
  114. package/dist/storage/GCSStorageController.d.ts +43 -0
  115. package/dist/storage/LocalStorageController.d.ts +46 -0
  116. package/dist/storage/S3StorageController.d.ts +36 -0
  117. package/dist/storage/image-transform.d.ts +50 -0
  118. package/dist/storage/index.d.ts +31 -0
  119. package/dist/storage/routes.d.ts +70 -0
  120. package/dist/storage/storage-registry.d.ts +78 -0
  121. package/dist/storage/tus-handler.d.ts +53 -0
  122. package/dist/storage/types.d.ts +128 -0
  123. package/dist/types/index.d.ts +11 -0
  124. package/dist/utils/dev-port.d.ts +37 -0
  125. package/dist/utils/logger.d.ts +31 -0
  126. package/dist/utils/logging.d.ts +9 -0
  127. package/dist/utils/request-id.d.ts +4 -0
  128. package/dist/utils/request-logger.d.ts +19 -0
  129. package/dist/utils/sql.d.ts +27 -0
  130. package/package.json +22 -14
  131. package/src/api/graphql/graphql-schema-generator.ts +5 -5
  132. package/src/api/openapi-generator.ts +2 -2
  133. package/src/api/rest/api-generator.ts +44 -123
  134. package/src/api/rest/query-parser.ts +6 -23
  135. package/src/api/types.ts +2 -2
  136. package/src/auth/auth-hooks.ts +1 -1
  137. package/src/auth/builtin-auth-adapter.ts +1 -2
  138. package/src/auth/interfaces.ts +11 -2
  139. package/src/auth/middleware.ts +4 -4
  140. package/src/auth/routes.ts +1 -2
  141. package/src/functions/define-function.ts +59 -0
  142. package/src/functions/function-loader.ts +16 -0
  143. package/src/functions/index.ts +2 -0
  144. package/src/index.ts +70 -37
  145. package/src/init.ts +78 -21
  146. package/src/storage/GCSStorageController.ts +334 -0
  147. package/src/storage/index.ts +9 -3
  148. package/src/storage/routes.ts +191 -23
  149. package/src/storage/tus-handler.ts +16 -4
  150. package/src/storage/types.ts +25 -3
  151. package/test/api-generator.test.ts +1 -1
  152. package/test/auth-config-types.test.ts +40 -0
  153. package/test/define-function.test.ts +45 -0
  154. package/test/storage-routes.test.ts +160 -0
  155. package/test/backend-hooks-data.test.ts +0 -477
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Hono middleware for authenticating requests via Service API Keys.
3
+ *
4
+ * This middleware is integrated into `createAuthMiddleware()` and
5
+ * activates only when the bearer token starts with `rk_`. It:
6
+ *
7
+ * 1. Hashes the token with SHA-256
8
+ * 2. Looks up the hash in the `rebase.api_keys` table
9
+ * 3. Validates the key is not revoked and not expired
10
+ * 4. Sets `c.set("user", ...)` and `c.set("apiKey", ...)` for downstream use
11
+ * 5. Scopes the DataDriver via `withAuth()` using the API key's service identity
12
+ *
13
+ * @module
14
+ */
15
+ import type { Context } from "hono";
16
+ import type { DataDriver } from "@rebasepro/types";
17
+ import type { HonoEnv } from "../../api/types";
18
+ import type { ApiKeyStore } from "./api-key-store";
19
+ /**
20
+ * Check whether a token looks like a Rebase API key.
21
+ */
22
+ export declare function isApiKeyToken(token: string): boolean;
23
+ /**
24
+ * Options for the API key authentication handler.
25
+ */
26
+ export interface ApiKeyAuthOptions {
27
+ store: ApiKeyStore;
28
+ driver: DataDriver;
29
+ }
30
+ /**
31
+ * Validate an API key token and populate the Hono context.
32
+ *
33
+ * Returns `true` if the key is valid and context has been populated,
34
+ * or returns an error Response if the key is invalid.
35
+ *
36
+ * This is NOT a standalone middleware — it's called from within
37
+ * `createAuthMiddleware()` when a `rk_` prefixed token is detected.
38
+ */
39
+ export declare function validateApiKey(c: Context<HonoEnv>, token: string, options: ApiKeyAuthOptions): Promise<Response | true>;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Permission guard for Service API Keys.
3
+ *
4
+ * Checks whether an API key's permission set allows a specific operation
5
+ * on a specific collection. Used by the REST API generator middleware to
6
+ * enforce fine-grained access control.
7
+ *
8
+ * @module
9
+ */
10
+ import type { ApiKeyPermission } from "./api-key-types";
11
+ /** Operations that map to HTTP methods. */
12
+ export type ApiKeyOperation = "read" | "write" | "delete";
13
+ /**
14
+ * Map an HTTP method string to an `ApiKeyOperation`.
15
+ *
16
+ * - `GET`, `HEAD`, `OPTIONS` → `"read"`
17
+ * - `POST`, `PUT`, `PATCH` → `"write"`
18
+ * - `DELETE` → `"delete"`
19
+ */
20
+ export declare function httpMethodToOperation(method: string): ApiKeyOperation;
21
+ /**
22
+ * Check whether the given permissions array allows `operation` on `collection`.
23
+ *
24
+ * Supports the `"*"` wildcard for the collection field, which matches any
25
+ * collection. Returns `true` if at least one permission entry grants access.
26
+ *
27
+ * @param permissions - The API key's permission entries.
28
+ * @param collection - The target collection slug.
29
+ * @param operation - The requested operation.
30
+ * @returns `true` if the operation is permitted.
31
+ */
32
+ export declare function isOperationAllowed(permissions: ApiKeyPermission[], collection: string, operation: ApiKeyOperation): boolean;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Admin routes for managing Service API Keys.
3
+ *
4
+ * Mounted under `/api/admin/api-keys` with `requireAuth` + `requireAdmin`.
5
+ * All routes return masked keys (never the hash). The full plaintext key
6
+ * is returned exactly once in the POST response.
7
+ *
8
+ * @module
9
+ */
10
+ import { Hono } from "hono";
11
+ import type { HonoEnv } from "../../api/types";
12
+ import type { ApiKeyStore } from "./api-key-store";
13
+ export interface ApiKeyRouteOptions {
14
+ store: ApiKeyStore;
15
+ serviceKey?: string;
16
+ }
17
+ /**
18
+ * Create admin routes for API key management.
19
+ */
20
+ export declare function createApiKeyRoutes(options: ApiKeyRouteOptions): Hono<HonoEnv>;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Database operations for Service API Keys.
3
+ *
4
+ * Uses the DataDriver's `admin.executeSql` capability (same pattern as
5
+ * the cron-store and ensure-tables modules). All data lives in the
6
+ * `rebase.api_keys` table.
7
+ *
8
+ * @module
9
+ */
10
+ import type { DataDriver } from "@rebasepro/types";
11
+ import type { ApiKey, ApiKeyMasked, ApiKeyWithSecret, CreateApiKeyRequest, UpdateApiKeyRequest } from "./api-key-types";
12
+ export interface ApiKeyStore {
13
+ /** Ensure the `rebase.api_keys` table exists. Called once on startup. */
14
+ ensureTable(): Promise<void>;
15
+ /** Create a new API key. Returns the full plaintext key exactly once. */
16
+ createApiKey(request: CreateApiKeyRequest, createdBy: string): Promise<ApiKeyWithSecret>;
17
+ /** Look up an API key by its SHA-256 hash. Returns `null` if not found. */
18
+ findByKeyHash(hash: string): Promise<ApiKey | null>;
19
+ /** List all API keys (masked, never includes hash). */
20
+ listApiKeys(): Promise<ApiKeyMasked[]>;
21
+ /** Get a single API key by ID (masked). */
22
+ getApiKeyById(id: string): Promise<ApiKeyMasked | null>;
23
+ /** Update name, permissions, rate_limit, or expires_at. */
24
+ updateApiKey(id: string, updates: UpdateApiKeyRequest): Promise<ApiKeyMasked | null>;
25
+ /** Soft-delete: set `revoked_at` to now. */
26
+ revokeApiKey(id: string): Promise<boolean>;
27
+ /** Touch `last_used_at` to the current timestamp. */
28
+ updateLastUsed(id: string): Promise<void>;
29
+ }
30
+ /**
31
+ * Create an `ApiKeyStore` backed by the driver's SQL admin capability.
32
+ *
33
+ * Returns `undefined` if the driver does not support `executeSql`.
34
+ */
35
+ export declare function createApiKeyStore(driver: DataDriver): ApiKeyStore | undefined;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Type definitions for Service API Keys.
3
+ *
4
+ * API keys provide machine-to-machine authentication for scripts, cron jobs,
5
+ * and third-party integrations. Each key is scoped to specific collections
6
+ * and operations via the `ApiKeyPermission` model.
7
+ *
8
+ * @module
9
+ */
10
+ /**
11
+ * A single permission entry scoping an API key to a collection and set of operations.
12
+ *
13
+ * Use `"*"` as the collection value to grant access to all collections.
14
+ */
15
+ export interface ApiKeyPermission {
16
+ /** Collection slug, or `"*"` for all collections. */
17
+ collection: string;
18
+ /** Allowed operations on the collection. */
19
+ operations: ("read" | "write" | "delete")[];
20
+ }
21
+ /**
22
+ * Full database row for an API key.
23
+ * The `key_hash` is never exposed via the API — only stored for lookup.
24
+ */
25
+ export interface ApiKey {
26
+ id: string;
27
+ name: string;
28
+ /** First 12 characters of the plaintext key, for display only. */
29
+ key_prefix: string;
30
+ /** SHA-256 hash of the full plaintext key. */
31
+ key_hash: string;
32
+ permissions: ApiKeyPermission[];
33
+ /** When true, the key is granted the `admin` role (access to admin routes). */
34
+ admin: boolean;
35
+ /** Requests per 15-minute window. `null` means unlimited. */
36
+ rate_limit: number | null;
37
+ created_by: string;
38
+ created_at: string;
39
+ updated_at: string;
40
+ last_used_at: string | null;
41
+ expires_at: string | null;
42
+ revoked_at: string | null;
43
+ }
44
+ /**
45
+ * Masked version of an API key, safe for API responses.
46
+ * Omits `key_hash` and shows only the prefix.
47
+ */
48
+ export interface ApiKeyMasked {
49
+ id: string;
50
+ name: string;
51
+ key_prefix: string;
52
+ permissions: ApiKeyPermission[];
53
+ /** When true, the key is granted the `admin` role (access to admin routes). */
54
+ admin: boolean;
55
+ rate_limit: number | null;
56
+ created_by: string;
57
+ created_at: string;
58
+ updated_at: string;
59
+ last_used_at: string | null;
60
+ expires_at: string | null;
61
+ revoked_at: string | null;
62
+ }
63
+ /**
64
+ * Request body for creating a new API key.
65
+ */
66
+ export interface CreateApiKeyRequest {
67
+ name: string;
68
+ permissions: ApiKeyPermission[];
69
+ /** When true, grants the `admin` role — allows access to admin routes. */
70
+ admin?: boolean;
71
+ /** Requests per 15-minute window. Omit or `null` for unlimited. */
72
+ rate_limit?: number | null;
73
+ /** ISO-8601 expiration timestamp. Omit for no expiration. */
74
+ expires_at?: string | null;
75
+ }
76
+ /**
77
+ * Request body for updating an existing API key.
78
+ * All fields are optional — only provided fields are updated.
79
+ */
80
+ export interface UpdateApiKeyRequest {
81
+ name?: string;
82
+ permissions?: ApiKeyPermission[];
83
+ /** When true, grants the `admin` role — allows access to admin routes. */
84
+ admin?: boolean;
85
+ rate_limit?: number | null;
86
+ expires_at?: string | null;
87
+ }
88
+ /**
89
+ * Returned exactly once when a key is created.
90
+ * The `key` field contains the full plaintext key — it is never stored
91
+ * or returned again after creation.
92
+ */
93
+ export interface ApiKeyWithSecret extends ApiKeyMasked {
94
+ /** Full plaintext API key (e.g. `rk_live_abc123...`). */
95
+ key: string;
96
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Service API Keys module.
3
+ *
4
+ * Re-exports types, store, middleware, permission guard, and routes
5
+ * for the API key authentication system.
6
+ *
7
+ * @module
8
+ */
9
+ export type { ApiKey, ApiKeyMasked, ApiKeyPermission, ApiKeyWithSecret, CreateApiKeyRequest, UpdateApiKeyRequest } from "./api-key-types";
10
+ export { createApiKeyStore } from "./api-key-store";
11
+ export type { ApiKeyStore } from "./api-key-store";
12
+ export { isApiKeyToken, validateApiKey } from "./api-key-middleware";
13
+ export type { ApiKeyAuthOptions } from "./api-key-middleware";
14
+ export { httpMethodToOperation, isOperationAllowed } from "./api-key-permission-guard";
15
+ export type { ApiKeyOperation } from "./api-key-permission-guard";
16
+ export { createApiKeyRoutes } from "./api-key-routes";
17
+ export type { ApiKeyRouteOptions } from "./api-key-routes";
@@ -0,0 +1,30 @@
1
+ import type { OAuthProvider } from "./interfaces";
2
+ /**
3
+ * Creates an Apple Sign In OAuth Provider integration.
4
+ *
5
+ * Apple requires a client secret that is a signed JWT, regenerated on each
6
+ * token exchange (valid up to 6 months). This provider handles that automatically.
7
+ *
8
+ * Required Apple Developer configuration:
9
+ * - Services ID (clientId)
10
+ * - Key ID from the private key registered with Apple
11
+ * - Team ID from Apple Developer account
12
+ * - Private key (.p8 file contents) downloaded from Apple Developer portal
13
+ */
14
+ export declare function createAppleProvider(config: {
15
+ clientId: string;
16
+ teamId: string;
17
+ keyId: string;
18
+ /** The raw PEM contents of the .p8 private key file */
19
+ privateKey: string;
20
+ }): OAuthProvider<{
21
+ code: string;
22
+ redirectUri: string;
23
+ user?: {
24
+ name?: {
25
+ firstName?: string;
26
+ lastName?: string;
27
+ };
28
+ email?: string;
29
+ };
30
+ }>;
@@ -0,0 +1,242 @@
1
+ /**
2
+ * AuthHooks
3
+ *
4
+ * Customize specific behaviors of the built-in Rebase auth system.
5
+ *
6
+ * Each method replaces one piece of the default implementation.
7
+ * Unset methods fall through to the built-in defaults (scrypt passwords,
8
+ * standard validation rules, etc.).
9
+ *
10
+ * This interface is intentionally open for extension — new hooks
11
+ * can be added as optional methods without breaking existing configurations.
12
+ *
13
+ * @example bcrypt password support
14
+ * ```ts
15
+ * import bcrypt from "bcrypt";
16
+ *
17
+ * const hooks: AuthHooks = {
18
+ * hashPassword: (pw) => bcrypt.hash(pw, 12),
19
+ * verifyPassword: (pw, hash) => bcrypt.compare(pw, hash),
20
+ * validatePasswordStrength: (pw) => ({
21
+ * valid: pw.length >= 6,
22
+ * errors: pw.length < 6 ? ["Password must be at least 6 characters"] : []
23
+ * })
24
+ * };
25
+ * ```
26
+ *
27
+ * @example Override the entire login credential check
28
+ * ```ts
29
+ * const hooks: AuthHooks = {
30
+ * verifyCredentials: async (email, password, repo) => {
31
+ * const user = await repo.getUserByEmail(email);
32
+ * if (!user || !user.passwordHash) return null;
33
+ * const valid = await myCustomVerify(password, user.passwordHash);
34
+ * return valid ? user : null;
35
+ * }
36
+ * };
37
+ * ```
38
+ */
39
+ import type { PasswordValidationResult } from "./password";
40
+ import type { AuthRepository, UserData, CreateUserData } from "./interfaces";
41
+ import type { EmailService, EmailConfig } from "../email";
42
+ import type { AuthResponsePayload, TransformAuthResponseContext } from "@rebasepro/types";
43
+ /**
44
+ * Authentication method identifier for lifecycle hooks.
45
+ */
46
+ export type AuthMethod = "login" | "register" | "oauth" | "refresh" | "password-reset" | "anonymous" | "magic-link" | "mfa";
47
+ /**
48
+ * Hook specific parts of the built-in Rebase auth implementation.
49
+ *
50
+ * Every method is optional. The built-in defaults apply for any method
51
+ * that is not provided.
52
+ */
53
+ export interface AuthHooks {
54
+ /**
55
+ * Hash a cleartext password for storage.
56
+ *
57
+ * Default: scrypt (Node.js crypto, 64-byte key, random 32-byte salt).
58
+ *
59
+ * @param password - The cleartext password.
60
+ * @returns The hashed password string (format is implementation-defined).
61
+ */
62
+ hashPassword?(password: string): Promise<string>;
63
+ /**
64
+ * Verify a cleartext password against a stored hash.
65
+ *
66
+ * Default: scrypt verification with timing-safe comparison.
67
+ *
68
+ * @param password - The cleartext password to check.
69
+ * @param storedHash - The hash string retrieved from the database.
70
+ * @returns `true` if the password matches the hash.
71
+ */
72
+ verifyPassword?(password: string, storedHash: string): Promise<boolean>;
73
+ /**
74
+ * Validate password strength before hashing.
75
+ *
76
+ * Default: minimum 8 characters, at least one uppercase, one lowercase, one digit.
77
+ *
78
+ * @param password - The cleartext password to validate.
79
+ * @returns Validation result with `valid` flag and error messages.
80
+ */
81
+ validatePasswordStrength?(password: string): PasswordValidationResult;
82
+ /**
83
+ * Override the complete credential verification during email/password login.
84
+ *
85
+ * When set, this replaces the default flow:
86
+ * 1. Look up user by email
87
+ * 2. Verify password hash
88
+ *
89
+ * The auth repository is provided for database access. Return the user
90
+ * data if credentials are valid, or `null` to reject the login.
91
+ *
92
+ * Default: `getUserByEmail(email)` + `verifyPassword(password, user.passwordHash)`.
93
+ */
94
+ verifyCredentials?(email: string, password: string, repo: AuthRepository): Promise<UserData | null>;
95
+ /**
96
+ * Called after any successful authentication event (login, register,
97
+ * OAuth, token refresh, password reset).
98
+ *
99
+ * Use for audit logging, syncing external state, updating
100
+ * last-login timestamps, etc.
101
+ *
102
+ * This is fire-and-forget — errors are logged but do not fail the request.
103
+ */
104
+ onAuthenticated?(user: UserData, method: AuthMethod): Promise<void>;
105
+ /**
106
+ * Called before a new user is created (registration or admin creation).
107
+ *
108
+ * Return modified data to alter what gets stored, or throw an error
109
+ * to reject the creation entirely.
110
+ *
111
+ * Default: passthrough (returns data unchanged).
112
+ */
113
+ beforeUserCreate?(data: CreateUserData): Promise<CreateUserData>;
114
+ /**
115
+ * Called after a new user is created.
116
+ *
117
+ * Use for provisioning external resources, sending notifications
118
+ * to third-party systems, etc.
119
+ *
120
+ * This is fire-and-forget — errors are logged but do not fail the request.
121
+ */
122
+ afterUserCreate?(user: UserData): Promise<void>;
123
+ /**
124
+ * Pre-login validation. Called before credential verification.
125
+ *
126
+ * Throw an error to reject the login attempt (e.g. for account lockout,
127
+ * IP-based restrictions, etc.).
128
+ */
129
+ beforeLogin?(email: string, method: AuthMethod): Promise<void>;
130
+ /**
131
+ * Post-logout cleanup.
132
+ *
133
+ * Called after a user's session has been invalidated.
134
+ * Use for audit logging, cleanup of temporary resources, etc.
135
+ *
136
+ * This is fire-and-forget — errors are logged but do not fail the request.
137
+ */
138
+ afterLogout?(userId: string): Promise<void>;
139
+ /**
140
+ * Called after successful MFA verification.
141
+ *
142
+ * Use for audit logging, notifying external systems, etc.
143
+ *
144
+ * This is fire-and-forget — errors are logged but do not fail the request.
145
+ */
146
+ onMfaVerified?(userId: string, factorId: string): Promise<void>;
147
+ /**
148
+ * Customize JWT access token claims before signing.
149
+ *
150
+ * Return the modified claims object. The returned claims are merged
151
+ * into the JWT payload alongside standard claims (userId, roles).
152
+ *
153
+ * @param claims - The default claims that would be included.
154
+ * @param user - The authenticated user data.
155
+ * @returns Modified claims to include in the JWT.
156
+ */
157
+ customizeAccessToken?(claims: Record<string, unknown>, user: UserData): Promise<Record<string, unknown>>;
158
+ /**
159
+ * Transform the auth response before sending it to the client.
160
+ *
161
+ * Called after successful login, register, refresh, OAuth, anonymous,
162
+ * magic-link, and MFA flows. The hook receives the fully-formed
163
+ * response and returns a (potentially enriched) response.
164
+ *
165
+ * Use cases:
166
+ * - Inject tokens from external auth systems (custom provider tokens, etc.)
167
+ * - Add project-specific metadata to the response
168
+ * - Enrich the user object with data from external sources
169
+ *
170
+ * The hook runs in the request path — keep it fast.
171
+ * Heavy work should be offloaded to `onAuthenticated` (fire-and-forget).
172
+ */
173
+ transformAuthResponse?(response: AuthResponsePayload, context: TransformAuthResponseContext): Promise<AuthResponsePayload>;
174
+ /**
175
+ * Called after a successful password reset.
176
+ *
177
+ * Use for audit logging, sending confirmation notifications, etc.
178
+ *
179
+ * This is fire-and-forget — errors are logged but do not fail the request.
180
+ */
181
+ onPasswordReset?(userId: string): Promise<void>;
182
+ /**
183
+ * Called before a user is deleted.
184
+ *
185
+ * Throw an error to prevent deletion (e.g. for users with active
186
+ * subscriptions, pending transactions, etc.).
187
+ */
188
+ beforeUserDelete?(userId: string): Promise<void>;
189
+ /**
190
+ * Called after a user is deleted.
191
+ *
192
+ * Use for cleaning up external resources, audit logging, etc.
193
+ *
194
+ * This is fire-and-forget — errors are logged but do not fail the request.
195
+ */
196
+ afterUserDelete?(userId: string): Promise<void>;
197
+ /**
198
+ * Optional hook to customize or override the default user creation flow via the admin panel/REST API.
199
+ * When provided, this replaces the built-in password generation, hashing, and invitation email logic.
200
+ */
201
+ onAdminCreateUser?(values: Record<string, unknown>, ctx: {
202
+ authRepo: AuthRepository;
203
+ emailService?: EmailService;
204
+ emailConfig?: EmailConfig;
205
+ hashPassword: (password: string) => Promise<string>;
206
+ }): Promise<{
207
+ values: Record<string, unknown>;
208
+ temporaryPassword?: string;
209
+ invitationSent?: boolean;
210
+ }>;
211
+ /**
212
+ * Optional hook to customize or override the default password reset flow via the admin panel.
213
+ * When provided, this replaces the built-in password reset token generation, hashing, and email logic.
214
+ */
215
+ onAdminResetPassword?(userId: string, ctx: {
216
+ authRepo: AuthRepository;
217
+ emailService?: EmailService;
218
+ emailConfig?: EmailConfig;
219
+ }): Promise<{
220
+ temporaryPassword?: string;
221
+ invitationSent?: boolean;
222
+ }>;
223
+ }
224
+ /**
225
+ * Resolved auth hooks — password operations are guaranteed to exist,
226
+ * all other hooks are passed through as-is (optional).
227
+ *
228
+ * Created by `resolveAuthHooks()` which merges user hooks
229
+ * with built-in defaults.
230
+ *
231
+ * Consumers should use the resolved object exclusively —
232
+ * never access the raw `AuthHooks` directly.
233
+ */
234
+ export type ResolvedAuthHooks = Required<Pick<AuthHooks, "hashPassword" | "verifyPassword" | "validatePasswordStrength">> & Omit<AuthHooks, "hashPassword" | "verifyPassword" | "validatePasswordStrength">;
235
+ /**
236
+ * Merge user-provided hooks with the built-in defaults to produce
237
+ * a complete set of resolved hooks.
238
+ *
239
+ * This is the single point where defaults are applied — all consumers
240
+ * call this once and use the resolved hooks throughout.
241
+ */
242
+ export declare function resolveAuthHooks(hooks?: AuthHooks): ResolvedAuthHooks;
@@ -0,0 +1,11 @@
1
+ import type { OAuthProvider } from "./interfaces";
2
+ /**
3
+ * Creates a Bitbucket OAuth Provider integration (OAuth 2.0 consumer).
4
+ */
5
+ export declare function createBitbucketProvider(config: {
6
+ clientId: string;
7
+ clientSecret: string;
8
+ }): OAuthProvider<{
9
+ code: string;
10
+ redirectUri: string;
11
+ }>;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * RebaseBuiltinAuthAdapter
3
+ *
4
+ * Wraps Rebase's existing built-in JWT auth system (routes, middleware, user/role
5
+ * management) into the `AuthAdapter` interface. This is the default adapter used
6
+ * when the user passes a plain `RebaseAuthConfig` object.
7
+ *
8
+ * This is NOT a rewrite — it delegates to the existing `createAuthRoutes()`,
9
+ * `createResetPasswordRoute()`, and `verifyAccessToken()` functions. The goal is to
10
+ * present the same functionality through the pluggable `AuthAdapter` contract.
11
+ */
12
+ import type { AuthAdapter } from "@rebasepro/types";
13
+ import type { AuthRepository, OAuthProvider } from "./interfaces";
14
+ import type { AuthHooks } from "./auth-hooks";
15
+ import type { EmailService, EmailConfig } from "../email";
16
+ /**
17
+ * Configuration for the built-in Rebase auth adapter.
18
+ *
19
+ * This mirrors the existing `RebaseAuthConfig` — users pass this and
20
+ * server-core auto-wraps it in a `RebaseBuiltinAuthAdapter`.
21
+ */
22
+ export interface BuiltinAuthAdapterConfig {
23
+ /** The bootstrapper-provided auth repository (users, roles, tokens). */
24
+ authRepository: AuthRepository;
25
+ /** Email service for password resets, verification, etc. */
26
+ emailService?: EmailService;
27
+ /** Email configuration. */
28
+ emailConfig?: EmailConfig;
29
+ /** Whether to allow new user registration. */
30
+ allowRegistration?: boolean;
31
+ /** Default role to assign to new users. */
32
+ defaultRole?: string;
33
+ /** OAuth providers to register. */
34
+ oauthProviders?: OAuthProvider<unknown>[];
35
+ /** Static service key for server-to-server auth. */
36
+ serviceKey?: string;
37
+ /** Auth hooks for customizing password, credentials, lifecycle, etc. */
38
+ authHooks?: AuthHooks;
39
+ /** The parsed auth config from the collection (if `auth` is an object, not just `true`). */
40
+ collectionAuthConfig?: import("@rebasepro/types").AuthCollectionConfig;
41
+ /** Enable magic link (passwordless email) login. Requires email service. */
42
+ enableMagicLink?: boolean;
43
+ }
44
+ /**
45
+ * Create the built-in Rebase auth adapter.
46
+ *
47
+ * This wraps the existing auth infrastructure (JWT, OAuth, user/role management)
48
+ * into the `AuthAdapter` interface. It's used internally by `initializeRebaseBackend()`
49
+ * when the user passes a plain `RebaseAuthConfig` object.
50
+ */
51
+ export declare function createBuiltinAuthAdapter(config: BuiltinAuthAdapterConfig): AuthAdapter;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Cryptographic utility functions for auth.
3
+ *
4
+ * @module
5
+ */
6
+ /**
7
+ * Constant-time string comparison to prevent timing attacks.
8
+ *
9
+ * Used for comparing service keys, tokens, and other secrets where
10
+ * timing side-channels could leak information about the expected value.
11
+ *
12
+ * @param a - First string to compare.
13
+ * @param b - Second string to compare.
14
+ * @returns `true` if the strings are identical, `false` otherwise.
15
+ */
16
+ export declare function safeCompare(a: string, b: string): boolean;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Custom Auth Adapter Factory
3
+ *
4
+ * Provides a minimal-config way for users with existing auth systems
5
+ * to plug into Rebase. Only `verifyRequest` is required — everything
6
+ * else is optional.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { createCustomAuthAdapter } from "@rebasepro/server-core";
11
+ *
12
+ * const auth = createCustomAuthAdapter({
13
+ * verifyRequest: async (request) => {
14
+ * const token = request.headers.get("Authorization")?.replace("Bearer ", "");
15
+ * if (!token) return null;
16
+ * const decoded = jwt.verify(token, MY_SECRET);
17
+ * return {
18
+ * uid: decoded.sub,
19
+ * email: decoded.email,
20
+ * displayName: decoded.name,
21
+ * roles: decoded.roles || [],
22
+ * isAdmin: decoded.roles?.includes("admin") ?? false,
23
+ * };
24
+ * },
25
+ * });
26
+ * ```
27
+ */
28
+ import type { AuthAdapter, CustomAuthAdapterOptions } from "@rebasepro/types";
29
+ /**
30
+ * Create a custom auth adapter from minimal options.
31
+ *
32
+ * This is the recommended entry point for users who already have their own
33
+ * auth system and just need to tell Rebase how to extract the user from
34
+ * incoming requests.
35
+ *
36
+ * @param options - Configuration options. Only `verifyRequest` is required.
37
+ * @returns A fully-formed `AuthAdapter` ready for `initializeRebaseBackend()`.
38
+ */
39
+ export declare function createCustomAuthAdapter(options: CustomAuthAdapterOptions): AuthAdapter;
@@ -0,0 +1,14 @@
1
+ import type { OAuthProvider } from "./interfaces";
2
+ /**
3
+ * Creates a Discord OAuth2 Provider integration.
4
+ *
5
+ * Uses the authorization code flow. Requires the "identify" and "email"
6
+ * scopes to retrieve the user's email and profile information.
7
+ */
8
+ export declare function createDiscordProvider(config: {
9
+ clientId: string;
10
+ clientSecret: string;
11
+ }): OAuthProvider<{
12
+ code: string;
13
+ redirectUri: string;
14
+ }>;
@@ -0,0 +1,14 @@
1
+ import type { OAuthProvider } from "./interfaces";
2
+ /**
3
+ * Creates a Facebook / Meta OAuth Provider integration.
4
+ *
5
+ * Uses the authorization code flow to exchange a code for an access token,
6
+ * then fetches user profile from the Facebook Graph API.
7
+ */
8
+ export declare function createFacebookProvider(config: {
9
+ clientId: string;
10
+ clientSecret: string;
11
+ }): OAuthProvider<{
12
+ code: string;
13
+ redirectUri: string;
14
+ }>;