@proveanything/smartlinks-auth-ui 0.5.22 → 0.6.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.
@@ -0,0 +1,411 @@
1
+ # UI Customization Guide
2
+
3
+ The Smartlinks Auth UI module supports flexible customization through a hybrid API-based and props-based approach. This allows you to maintain consistent branding across multiple applications while still allowing per-instance overrides.
4
+
5
+ ## ⚠️ Important: CSS Import Required
6
+
7
+ Before using any components, you **must** import the CSS file in your application:
8
+
9
+ ```tsx
10
+ import '@smartlinks/auth-ui/dist/index.css';
11
+ ```
12
+
13
+ Add this import to your app's entry point (e.g., `main.tsx`, `index.tsx`, or `App.tsx`).
14
+
15
+ **Without this CSS import, the authentication UI will appear unstyled.**
16
+
17
+ ### CSS Override and Customization
18
+
19
+ The module's CSS uses scoped class names (`.auth-*`) and CSS custom properties (CSS variables) to allow easy customization without style conflicts. You can:
20
+
21
+ 1. **Override CSS variables** for quick theming (see below)
22
+ 2. **Override specific classes** in your own stylesheet after importing the module CSS
23
+ 3. **Use the `customization` prop** to configure colors, fonts, and branding via the component API
24
+
25
+ ## Quick Start
26
+
27
+ ### Option 1: Props-Based Customization (Simplest)
28
+
29
+ Pass customization directly as props:
30
+
31
+ ```tsx
32
+ import { FirebaseAuthUI } from '@your-org/smartlinks-auth-ui';
33
+
34
+ function App() {
35
+ return (
36
+ <FirebaseAuthUI
37
+ apiEndpoint="https://api.smartlinks.com/api/v1/authkit"
38
+ customization={{
39
+ logoUrl: "https://cdn.acme.com/logo.png",
40
+ title: "Welcome to Acme",
41
+ subtitle: "Sign in to continue",
42
+ primaryColor: "#6366f1",
43
+ secondaryColor: "#4f46e5",
44
+ backgroundColor: "#f0f9ff",
45
+ buttonStyle: "rounded",
46
+ termsUrl: "https://acme.com/terms",
47
+ privacyUrl: "https://acme.com/privacy"
48
+ }}
49
+ skipConfigFetch={true}
50
+ onAuthSuccess={(token, user) => {
51
+ console.log('Auth success:', user);
52
+ }}
53
+ />
54
+ );
55
+ }
56
+ ```
57
+
58
+ ### Option 2: API-Based Customization (Multi-Tenant)
59
+
60
+ For multi-tenant applications, store configuration in Firestore and fetch by `clientId`:
61
+
62
+ ```tsx
63
+ <FirebaseAuthUI
64
+ apiEndpoint="https://api.smartlinks.com/api/v1/authkit"
65
+ clientId="acme-corp"
66
+ onAuthSuccess={(token, user) => {
67
+ console.log('Auth success:', user);
68
+ }}
69
+ />
70
+ ```
71
+
72
+ ### Option 3: Hybrid (API + Props Override)
73
+
74
+ Fetch base config from API but allow per-instance overrides:
75
+
76
+ ```tsx
77
+ <FirebaseAuthUI
78
+ apiEndpoint="https://api.smartlinks.com/api/v1/authkit"
79
+ clientId="acme-corp"
80
+ customization={{
81
+ title: "Welcome Back!", // Override just the title
82
+ }}
83
+ onAuthSuccess={(token, user) => {
84
+ console.log('Auth success:', user);
85
+ }}
86
+ />
87
+ ```
88
+
89
+ ## Configuration Options
90
+
91
+ ### Available Configuration Properties
92
+
93
+ ```typescript
94
+ interface AuthUIConfig {
95
+ branding?: {
96
+ logoUrl?: string; // URL to logo image (40x40px recommended)
97
+ title?: string; // Main heading text
98
+ subtitle?: string; // Subheading text below title
99
+ primaryColor?: string; // Primary brand color (hex)
100
+ secondaryColor?: string; // Secondary brand color (hex)
101
+ backgroundColor?: string; // Background gradient start color (hex)
102
+ buttonStyle?: 'rounded' | 'square'; // Button and card style
103
+ fontFamily?: string; // Custom font family
104
+ inheritHostStyles?: boolean; // Use host app's CSS variables
105
+ };
106
+ signupProminence?: 'minimal' | 'balanced' | 'emphasized'; // New user journey prominence
107
+ customCss?: string; // Advanced: inject custom CSS
108
+ termsUrl?: string; // Link to Terms of Service
109
+ privacyUrl?: string; // Link to Privacy Policy
110
+ supportEmail?: string; // Support email (future use)
111
+ }
112
+ ```
113
+
114
+ ### Signup Prominence
115
+
116
+ The `signupProminence` option controls how prominently signup is featured relative to login. This is configured via the admin interface or programmatically:
117
+
118
+ | Mode | Description | Best For |
119
+ |------|-------------|----------|
120
+ | `minimal` | Login is default, small "Sign up" link at bottom | Returning users, locked content |
121
+ | `balanced` | Equal-weight toggle for Sign In / Create Account | General purpose portals |
122
+ | `emphasized` | Signup is default, small "Sign in" link at bottom | Product claiming, onboarding flows |
123
+
124
+ ```tsx
125
+ // Programmatic configuration
126
+ <SmartlinksAuthUI
127
+ clientId="your-client-123"
128
+ signupProminence="emphasized" // For claiming flows
129
+ onAuthSuccess={handleAuth}
130
+ />
131
+
132
+ // Or via customization prop
133
+ <SmartlinksAuthUI
134
+ clientId="your-client-123"
135
+ customization={{
136
+ signupProminence: 'balanced'
137
+ }}
138
+ onAuthSuccess={handleAuth}
139
+ />
140
+ ```
141
+
142
+ ## Backend Setup (API-Based Customization)
143
+
144
+ ### 1. Create Firestore Collection
145
+
146
+ Create a collection named `auth_ui_config` in your Firebase project:
147
+
148
+ ```javascript
149
+ // Document structure
150
+ {
151
+ clientId: "acme-corp",
152
+ branding: {
153
+ logoUrl: "https://cdn.acme.com/logo.png",
154
+ title: "Welcome to Acme",
155
+ subtitle: "Sign in to your account",
156
+ primaryColor: "#6366f1",
157
+ secondaryColor: "#4f46e5",
158
+ backgroundColor: "#f0f9ff",
159
+ buttonStyle: "rounded",
160
+ fontFamily: "Inter, sans-serif"
161
+ },
162
+ customCss: null,
163
+ termsUrl: "https://acme.com/terms",
164
+ privacyUrl: "https://acme.com/privacy",
165
+ supportEmail: "support@acme.com",
166
+ updatedAt: serverTimestamp()
167
+ }
168
+ ```
169
+
170
+ ### 2. Add Backend Endpoint
171
+
172
+ Add the config helper and endpoint to your backend:
173
+
174
+ ```javascript
175
+ // In your main Express app
176
+ const authUIConfigRoutes = require('./backend-reference/authui-routes-custom');
177
+
178
+ app.use('/api/v1/authkit', authUIConfigRoutes);
179
+ ```
180
+
181
+ The endpoint `GET /api/v1/authkit/config/:clientId` will now serve configurations.
182
+
183
+ ### 3. Manage Configurations
184
+
185
+ Use the helper functions to manage configs:
186
+
187
+ ```javascript
188
+ const configHelper = require('./authui-config-helper');
189
+
190
+ // Save a new config
191
+ await configHelper.saveUIConfig('acme-corp', {
192
+ logoUrl: "https://cdn.acme.com/logo.png",
193
+ title: "Welcome to Acme",
194
+ primaryColor: "#6366f1",
195
+ // ... other options
196
+ });
197
+
198
+ // Get a config
199
+ const config = await configHelper.getUIConfig('acme-corp');
200
+
201
+ // Delete a config
202
+ await configHelper.deleteUIConfig('acme-corp');
203
+ ```
204
+
205
+ ## Caching Strategy
206
+
207
+ The module implements intelligent caching to optimize performance:
208
+
209
+ 1. **Props Override**: Always applied first (no API call)
210
+ 2. **localStorage Cache**: Checked for recently fetched configs (1 hour TTL)
211
+ 3. **Background Fetch**: Updates cache while showing cached version
212
+ 4. **API Fetch**: Only if no cache exists or cache is stale
213
+
214
+ ### Cache Key Format
215
+
216
+ ```
217
+ auth_ui_config_{clientId}
218
+ ```
219
+
220
+ ### Cache Structure
221
+
222
+ ```json
223
+ {
224
+ "config": { /* AuthUIConfig */ },
225
+ "timestamp": 1234567890
226
+ }
227
+ ```
228
+
229
+ ### Clear Cache
230
+
231
+ ```javascript
232
+ // Clear specific client cache
233
+ localStorage.removeItem('auth_ui_config_acme-corp');
234
+
235
+ // Clear all auth UI caches
236
+ Object.keys(localStorage).forEach(key => {
237
+ if (key.startsWith('auth_ui_config_')) {
238
+ localStorage.removeItem(key);
239
+ }
240
+ });
241
+ ```
242
+
243
+ ## Advanced Customization
244
+
245
+ ### Custom CSS Injection
246
+
247
+ For advanced styling needs, you can inject custom CSS:
248
+
249
+ ```typescript
250
+ customization={{
251
+ customCss: `
252
+ .auth-card {
253
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15) !important;
254
+ }
255
+
256
+ .auth-title {
257
+ font-weight: 900 !important;
258
+ letter-spacing: -0.02em !important;
259
+ }
260
+
261
+ button[type="submit"] {
262
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
263
+ }
264
+ `
265
+ }}
266
+ ```
267
+
268
+ ⚠️ **Warning**: Custom CSS can break future updates. Use sparingly and test thoroughly.
269
+
270
+ ### Custom Fonts
271
+
272
+ To use custom fonts:
273
+
274
+ 1. **Add font link** to your HTML:
275
+
276
+ ```html
277
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
278
+ ```
279
+
280
+ 2. **Set in config**:
281
+
282
+ ```typescript
283
+ customization={{
284
+ fontFamily: "'Poppins', sans-serif"
285
+ }}
286
+ ```
287
+
288
+ ## Props Reference
289
+
290
+ ### FirebaseAuthUIProps
291
+
292
+ | Prop | Type | Required | Default | Description |
293
+ |------|------|----------|---------|-------------|
294
+ | `apiEndpoint` | string | Yes | - | Your API base URL |
295
+ | `clientId` | string | No | - | Client identifier for multi-tenant |
296
+ | `clientName` | string | No | - | Client name for branded emails |
297
+ | `customization` | `Partial<AuthUIConfig>` | No | `{}` | UI customization overrides |
298
+ | `skipConfigFetch` | boolean | No | `false` | Skip API config fetch |
299
+ | `theme` | `'light' \| 'dark'` | No | `'light'` | UI theme |
300
+ | `enabledProviders` | `AuthProvider[]` | No | `['email', 'google', 'phone']` | Auth methods |
301
+ | `redirectUrl` | string | No | - | Post-auth redirect URL |
302
+ | `accountData` | `Record<string, any>` | No | - | Additional account data |
303
+ | `onAuthSuccess` | function | Yes | - | Success callback |
304
+ | `onAuthError` | function | No | - | Error callback |
305
+ | `className` | string | No | `''` | Additional CSS class |
306
+
307
+ ## Priority Order
308
+
309
+ When multiple sources provide configuration, the priority is:
310
+
311
+ 1. **Props (`customization`)** - Highest priority
312
+ 2. **localStorage Cache** - If fresh (< 1 hour old)
313
+ 3. **API Fetch** - Fresh data from backend
314
+ 4. **Default Values** - Built-in fallbacks
315
+
316
+ ## Best Practices
317
+
318
+ ### For Single-Tenant Apps
319
+
320
+ Use props-based customization with `skipConfigFetch={true}`:
321
+
322
+ ```tsx
323
+ <FirebaseAuthUI
324
+ customization={{ /* your config */ }}
325
+ skipConfigFetch={true}
326
+ // ... other props
327
+ />
328
+ ```
329
+
330
+ ### For Multi-Tenant SaaS
331
+
332
+ Use API-based with `clientId`:
333
+
334
+ ```tsx
335
+ <FirebaseAuthUI
336
+ clientId={currentTenant.id}
337
+ // Config fetched automatically
338
+ // ... other props
339
+ />
340
+ ```
341
+
342
+ ### For White-Label Products
343
+
344
+ Use API-based with props override for per-deployment customization:
345
+
346
+ ```tsx
347
+ <FirebaseAuthUI
348
+ clientId={currentTenant.id}
349
+ customization={{
350
+ logoUrl: deploymentConfig.logoUrl // Override per deployment
351
+ }}
352
+ // ... other props
353
+ />
354
+ ```
355
+
356
+ ## Troubleshooting
357
+
358
+ ### Config Not Loading
359
+
360
+ 1. Check browser console for fetch errors
361
+ 2. Verify `clientId` is correct
362
+ 3. Check backend endpoint is accessible: `GET /api/v1/authkit/config/{clientId}`
363
+ 4. Verify Firestore collection `auth_ui_config` exists
364
+
365
+ ### Colors Not Applying
366
+
367
+ 1. Ensure color values are hex format: `#3B82F6` (not `rgb()` or color names)
368
+ 2. Check browser dev tools for CSS variable values
369
+ 3. Clear localStorage cache and refresh
370
+
371
+ ### Logo Not Showing
372
+
373
+ 1. Verify `logoUrl` is publicly accessible
374
+ 2. Check image size (40x40px recommended)
375
+ 3. Check browser console for CORS errors
376
+ 4. Ensure URL is HTTPS in production
377
+
378
+ ### Cache Issues
379
+
380
+ Clear the cache manually:
381
+
382
+ ```javascript
383
+ localStorage.removeItem(`auth_ui_config_${clientId}`);
384
+ ```
385
+
386
+ ## Security Considerations
387
+
388
+ 1. **Validate redirect URLs** on backend (already implemented)
389
+ 2. **Sanitize custom CSS** to prevent XSS (consider Content Security Policy)
390
+ 3. **Use HTTPS** for logo and asset URLs
391
+ 4. **Rate limit** config endpoint to prevent abuse
392
+ 5. **Authenticate** config management endpoints (future enhancement)
393
+
394
+ ## Future Enhancements
395
+
396
+ Planned features:
397
+
398
+ - [ ] Admin UI for managing configs
399
+ - [ ] Theme presets (Material, iOS, etc.)
400
+ - [ ] A/B testing support
401
+ - [ ] Analytics integration
402
+ - [ ] Real-time config updates
403
+ - [ ] Config versioning and rollback
404
+ - [ ] Visual editor with live preview
405
+
406
+ ## Support
407
+
408
+ For issues or questions:
409
+ - Check the [main README](./README.md)
410
+ - Review [Integration Guide](../backend-reference/INTEGRATION_GUIDE.md)
411
+ - Contact: support@smartlinks.com
package/README.md CHANGED
@@ -289,24 +289,42 @@ The AuthProvider component manages authentication state across your application.
289
289
 
290
290
  | Prop | Type | Required | Description |
291
291
  |------|------|----------|-------------|
292
- | `clientId` | string | **Yes** | Client identifier for your application |
293
- | `clientName` | string | No | Client name for branded communications |
294
- | `accountCacheTTL` | number | No | Account cache TTL in ms (default: 300000 / 5 min) |
295
- | `preloadAccountInfo` | boolean | No | Fetch account info on login (default: false) |
292
+ | `clientId` | string | No¹ | AuthKit client identifier. **Auto-resolved** from `collection.defaultAuthKitId` when `collectionId` is provided. |
293
+ | `collectionId` | string | No¹ | SmartLinks collection id. Enables contact sync, interaction tracking, and `clientId` auto-resolution. |
294
+ | `proxyMode` | boolean | No | Delegate session to the parent window (iframe embeds). Default `false`. |
295
+ | `accountCacheTTL` | number | No | Account-info cache TTL in ms (default `300_000` = 5 min). |
296
+ | `preloadAccountInfo` | boolean | No | Fetch account info eagerly on login (default `false`). |
297
+ | `enableAutoRefresh` | boolean | No | Background token refresh timer (default `true`). |
298
+ | `refreshThresholdPercent` | number | No | Refresh when this % of the access-token lifetime has elapsed (default `75`). |
299
+ | `refreshCheckInterval` | number | No | Background check interval in ms (default `60_000`). |
300
+ | `refreshOnResume` | boolean | No | Refresh the session when the app returns to the foreground. **Default `true` on native shells** (Capacitor / `window.AuthKit.isNative`), `false` on web. Listens to `App.addListener('appStateChange')` via a dynamic `@capacitor/app` import (no web runtime dep) and to `document.visibilitychange` as a universal fallback. |
301
+ | `enableContactSync` | boolean | No | Default `true` when `collectionId` is set. |
302
+ | `enableInteractionTracking` | boolean | No | Default `true` when `collectionId` is set. |
303
+ | `interactionAppId` | string | No | App id used for interaction events. |
304
+ | `interactionConfig` | object | No | Custom interaction ids — see [`AUTH_STATE_MANAGEMENT.md`](./AUTH_STATE_MANAGEMENT.md). |
305
+
306
+ ¹ Either `clientId` **or** `collectionId` is required. Most apps only need `collectionId` — the kit looks up the collection's `defaultAuthKitId` and uses it for refresh-token rotation and server-side logout. See [`architecture/default-authkit-collection-property`](../.lovable/memory/architecture/default-authkit-collection-property.md).
296
307
 
297
308
  #### Example
298
309
 
299
310
  ```tsx
300
- <AuthProvider
311
+ // Minimal — clientId auto-resolved from the collection's defaultAuthKitId
312
+ <AuthProvider collectionId="col_abc123">
313
+ <App />
314
+ </AuthProvider>
315
+
316
+ // Explicit clientId + long-lived native sessions
317
+ <AuthProvider
301
318
  clientId="your-client-123"
302
- clientName="Acme Corp"
303
- accountCacheTTL={600000} // 10 minutes
304
- preloadAccountInfo={true}
319
+ collectionId="col_abc123"
320
+ refreshOnResume // explicit on (auto-on under Capacitor)
321
+ accountCacheTTL={600_000}
305
322
  >
306
323
  <App />
307
324
  </AuthProvider>
308
325
  ```
309
326
 
327
+
310
328
  ### useAuth Hook
311
329
 
312
330
  Access authentication state and methods anywhere in your app:
@@ -544,6 +562,27 @@ The component automatically handles URL-based authentication flows:
544
562
 
545
563
  Authentication state automatically syncs across browser tabs using BroadcastChannel API and IndexedDB. When a user logs in or out in one tab, all other tabs update immediately.
546
564
 
565
+ ### Native / Mobile (Capacitor)
566
+
567
+ The kit ships first-class support for native shells — Capacitor, Capgo, and Ionic WebView. When a native host is detected (`window.Capacitor.isNativePlatform()` or `window.AuthKit.isNative`):
568
+
569
+ - **Long-lived sessions** via refresh-token rotation. Login responses carry a `refreshToken` + `refreshTokenExpiresAt`; the kit persists them next to the access JWT and calls `smartlinks.authKit.refreshToken(clientId, ...)` automatically. Reuse / invalid / expired refresh tokens force re-login.
570
+ - **Refresh on resume.** `refreshOnResume` defaults to `true` on native, hooking `App.addListener('appStateChange')` (dynamic import — no web runtime dep) and `document.visibilitychange`. Stale sessions self-heal the moment the user reopens the app.
571
+ - **Secure storage adapter.** Replace IndexedDB with Keychain / Keystore via `setStorageAdapter(adapter)`. See [`CAPACITOR_INTEGRATION.md`](./CAPACITOR_INTEGRATION.md) §5.
572
+ - **Native Google / Apple Sign-In** via the unified `window.AuthKit` bridge. See [`ANDROID_NATIVE_BRIDGE.md`](./ANDROID_NATIVE_BRIDGE.md).
573
+
574
+ Tell the SmartLinks SDK it's running native so refresh tokens are issued:
575
+
576
+ ```ts
577
+ smartlinks.initializeApi({
578
+ baseURL: '…',
579
+ platform: 'native', // adds X-Client-Platform: native to every request
580
+ persistToken: false, // AuthKit owns persistence
581
+ });
582
+ ```
583
+
584
+ Full step-by-step (Keychain adapter, biometric gating, deep-link routing): **[`CAPACITOR_INTEGRATION.md`](./CAPACITOR_INTEGRATION.md)**. Backend contract for the refresh endpoint: **[`../backend-reference/REFRESH_TOKEN_BACKEND_SPEC.md`](../backend-reference/REFRESH_TOKEN_BACKEND_SPEC.md)**.
585
+
547
586
  ## TypeScript Support
548
587
 
549
588
  Full TypeScript definitions included:
@@ -558,16 +597,37 @@ import type {
558
597
  SmartlinksAuthUIProps,
559
598
  AccountManagementProps,
560
599
  ClaimField,
561
- ClaimResult
600
+ ClaimResult,
601
+ PersistentStorage,
602
+ StorageBackend,
562
603
  } from '@smartlinks/auth-ui';
563
604
  ```
564
605
 
565
606
  ## Documentation
566
607
 
567
- - **[AUTH_STATE_MANAGEMENT.md](./AUTH_STATE_MANAGEMENT.md)** - Complete guide to authentication state, callbacks, and cross-tab sync
568
- - **[ACCOUNT_CACHING.md](./ACCOUNT_CACHING.md)** - Account information caching strategies and configuration
569
- - **[CUSTOMIZATION_GUIDE.md](./CUSTOMIZATION_GUIDE.md)** - Detailed customization and theming guide
570
- - **[SMARTLINKS_INTEGRATION.md](./SMARTLINKS_INTEGRATION.md)** - Smartlinks SDK integration details
608
+ All guides ship inside the published package so consumers can read them locally (`node_modules/@proveanything/smartlinks-auth-ui/*.md`).
609
+
610
+ ### Core
611
+ - **[AUTH_STATE_MANAGEMENT.md](./AUTH_STATE_MANAGEMENT.md)** auth state lifecycle, `onAuthStateChange` callbacks, cross-tab sync.
612
+ - **[ACCOUNT_CACHING.md](./ACCOUNT_CACHING.md)** — account-info caching strategy, TTLs, manual invalidation.
613
+ - **[CUSTOMIZATION_GUIDE.md](./CUSTOMIZATION_GUIDE.md)** — theming, branding, dark mode, provider ordering, email template config.
614
+ - **[SMARTLINKS_INTEGRATION.md](./SMARTLINKS_INTEGRATION.md)** — how the kit wires into `@proveanything/smartlinks` (token, refresh, profile, account, logout).
615
+
616
+ ### Native / Mobile
617
+ - **[CAPACITOR_INTEGRATION.md](./CAPACITOR_INTEGRATION.md)** — Capacitor / Capgo setup: native platform flag, secure storage adapter, refresh-on-resume, deep-link routing, native sign-out, biometric gating.
618
+ - **[ANDROID_NATIVE_BRIDGE.md](./ANDROID_NATIVE_BRIDGE.md)** — `window.AuthKit` bridge contract for native Google sign-in, scanner, and other host capabilities.
619
+
620
+ ### Specialized features
621
+ - **[SMARTLINKS_FRAME.md](./SMARTLINKS_FRAME.md)** — `SmartlinksFrame` embed component (optional auth, iframe messaging).
622
+ - **[WHATSAPP_OTP_PLAN.md](./WHATSAPP_OTP_PLAN.md)** — WhatsApp OTP flow and backend contract.
623
+ - **[SDK_DEBUGGING_GUIDE.md](./SDK_DEBUGGING_GUIDE.md)** — troubleshooting SDK init, proxy mode, token storage, iframe ack flow.
624
+
625
+ ### Backend contracts (in `backend-reference/`)
626
+ - **[REFRESH_TOKEN_BACKEND_SPEC.md](../backend-reference/REFRESH_TOKEN_BACKEND_SPEC.md)** — refresh-token endpoint, rotation, reuse detection, family revocation.
627
+ - **[APPLE_SIGNIN_BACKEND_SPEC.md](../backend-reference/APPLE_SIGNIN_BACKEND_SPEC.md)** — Apple Sign-In identity-token verification contract.
628
+ - **[ACCOUNT_MANAGEMENT_API.md](../backend-reference/ACCOUNT_MANAGEMENT_API.md)** — profile / email / password / delete endpoints used by `<AccountManagement>`.
629
+ - **[API_DOCUMENTATION.md](../backend-reference/API_DOCUMENTATION.md)** — full AuthKit REST surface.
630
+
571
631
 
572
632
  ## Troubleshooting
573
633