hazo_auth 7.0.1 → 7.0.2

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 (210) hide show
  1. package/README.md +73 -330
  2. package/SETUP_CHECKLIST.md +28 -248
  3. package/cli-src/cli/generate.ts +1 -10
  4. package/cli-src/cli/validate.ts +0 -4
  5. package/cli-src/lib/auth/auth_types.ts +12 -21
  6. package/cli-src/lib/auth/hazo_get_tenant_auth.server.ts +24 -25
  7. package/cli-src/lib/auth/index.ts +2 -2
  8. package/cli-src/lib/auth/nextauth_config.ts +27 -67
  9. package/cli-src/lib/auth/with_auth.server.ts +15 -15
  10. package/cli-src/lib/config/default_config.ts +8 -0
  11. package/cli-src/lib/cookies_config.server.ts +1 -1
  12. package/cli-src/lib/email_verification_config.server.ts +34 -0
  13. package/cli-src/lib/forgot_password_config.server.ts +34 -0
  14. package/cli-src/lib/login_config.server.ts +29 -14
  15. package/cli-src/lib/my_settings_config.server.ts +3 -0
  16. package/cli-src/lib/oauth_config.server.ts +31 -57
  17. package/cli-src/lib/register_config.server.ts +35 -11
  18. package/cli-src/lib/reset_password_config.server.ts +31 -0
  19. package/cli-src/lib/services/email_template_manifest.ts +0 -17
  20. package/cli-src/lib/services/index.ts +2 -8
  21. package/cli-src/lib/services/oauth_service.ts +74 -128
  22. package/cli-src/lib/services/otp_service.ts +7 -2
  23. package/cli-src/lib/services/session_token_service.ts +0 -2
  24. package/config/hazo_auth_config.example.ini +41 -76
  25. package/dist/cli/generate.d.ts.map +1 -1
  26. package/dist/cli/generate.js +1 -10
  27. package/dist/cli/validate.d.ts.map +1 -1
  28. package/dist/cli/validate.js +0 -4
  29. package/dist/client.d.ts +0 -2
  30. package/dist/client.d.ts.map +1 -1
  31. package/dist/client.js +0 -1
  32. package/dist/components/layouts/create_firm/index.d.ts +8 -4
  33. package/dist/components/layouts/create_firm/index.d.ts.map +1 -1
  34. package/dist/components/layouts/create_firm/index.js +3 -3
  35. package/dist/components/layouts/email_verification/index.d.ts +5 -4
  36. package/dist/components/layouts/email_verification/index.d.ts.map +1 -1
  37. package/dist/components/layouts/email_verification/index.js +4 -4
  38. package/dist/components/layouts/forgot_password/index.d.ts +5 -4
  39. package/dist/components/layouts/forgot_password/index.d.ts.map +1 -1
  40. package/dist/components/layouts/forgot_password/index.js +2 -2
  41. package/dist/components/layouts/login/index.d.ts +13 -19
  42. package/dist/components/layouts/login/index.d.ts.map +1 -1
  43. package/dist/components/layouts/login/index.js +8 -11
  44. package/dist/components/layouts/otp/index.d.ts +5 -1
  45. package/dist/components/layouts/otp/index.d.ts.map +1 -1
  46. package/dist/components/layouts/otp/index.js +2 -2
  47. package/dist/components/layouts/register/index.d.ts +11 -11
  48. package/dist/components/layouts/register/index.d.ts.map +1 -1
  49. package/dist/components/layouts/register/index.js +6 -7
  50. package/dist/components/layouts/reset_password/index.d.ts +5 -4
  51. package/dist/components/layouts/reset_password/index.d.ts.map +1 -1
  52. package/dist/components/layouts/reset_password/index.js +5 -5
  53. package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts +5 -3
  54. package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts.map +1 -1
  55. package/dist/components/layouts/shared/components/already_logged_in_guard.js +2 -2
  56. package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts +2 -6
  57. package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts.map +1 -1
  58. package/dist/components/layouts/shared/components/facebook_sign_in_button.js +11 -13
  59. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -1
  60. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +3 -8
  61. package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts +6 -3
  62. package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts.map +1 -1
  63. package/dist/components/layouts/shared/components/two_column_auth_layout.js +5 -8
  64. package/dist/components/layouts/shared/index.d.ts +2 -0
  65. package/dist/components/layouts/shared/index.d.ts.map +1 -1
  66. package/dist/components/layouts/shared/index.js +1 -0
  67. package/dist/components/layouts/user_management/index.d.ts.map +1 -1
  68. package/dist/components/layouts/user_management/index.js +39 -2
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/lib/auth/auth_types.d.ts +12 -13
  72. package/dist/lib/auth/auth_types.d.ts.map +1 -1
  73. package/dist/lib/auth/auth_types.js +0 -8
  74. package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts +7 -8
  75. package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts.map +1 -1
  76. package/dist/lib/auth/hazo_get_tenant_auth.server.js +22 -23
  77. package/dist/lib/auth/index.d.ts +2 -2
  78. package/dist/lib/auth/index.d.ts.map +1 -1
  79. package/dist/lib/auth/nextauth_config.d.ts +0 -10
  80. package/dist/lib/auth/nextauth_config.d.ts.map +1 -1
  81. package/dist/lib/auth/nextauth_config.js +23 -52
  82. package/dist/lib/auth/with_auth.server.d.ts +13 -13
  83. package/dist/lib/auth/with_auth.server.d.ts.map +1 -1
  84. package/dist/lib/auth/with_auth.server.js +2 -2
  85. package/dist/lib/config/default_config.d.ts +16 -0
  86. package/dist/lib/config/default_config.d.ts.map +1 -1
  87. package/dist/lib/config/default_config.js +8 -0
  88. package/dist/lib/cookies_config.server.d.ts +1 -1
  89. package/dist/lib/cookies_config.server.js +1 -1
  90. package/dist/lib/email_verification_config.server.d.ts +3 -0
  91. package/dist/lib/email_verification_config.server.d.ts.map +1 -1
  92. package/dist/lib/email_verification_config.server.js +15 -0
  93. package/dist/lib/forgot_password_config.server.d.ts +3 -0
  94. package/dist/lib/forgot_password_config.server.d.ts.map +1 -1
  95. package/dist/lib/forgot_password_config.server.js +15 -0
  96. package/dist/lib/login_config.server.d.ts +3 -6
  97. package/dist/lib/login_config.server.d.ts.map +1 -1
  98. package/dist/lib/login_config.server.js +11 -7
  99. package/dist/lib/my_settings_config.server.d.ts +1 -0
  100. package/dist/lib/my_settings_config.server.d.ts.map +1 -1
  101. package/dist/lib/my_settings_config.server.js +2 -0
  102. package/dist/lib/oauth_config.server.d.ts +8 -17
  103. package/dist/lib/oauth_config.server.d.ts.map +1 -1
  104. package/dist/lib/oauth_config.server.js +10 -25
  105. package/dist/lib/register_config.server.d.ts +5 -2
  106. package/dist/lib/register_config.server.d.ts.map +1 -1
  107. package/dist/lib/register_config.server.js +15 -4
  108. package/dist/lib/reset_password_config.server.d.ts +3 -0
  109. package/dist/lib/reset_password_config.server.d.ts.map +1 -1
  110. package/dist/lib/reset_password_config.server.js +13 -0
  111. package/dist/lib/services/email_template_manifest.d.ts.map +1 -1
  112. package/dist/lib/services/email_template_manifest.js +0 -17
  113. package/dist/lib/services/index.d.ts +0 -2
  114. package/dist/lib/services/index.d.ts.map +1 -1
  115. package/dist/lib/services/index.js +0 -1
  116. package/dist/lib/services/oauth_service.d.ts +11 -22
  117. package/dist/lib/services/oauth_service.d.ts.map +1 -1
  118. package/dist/lib/services/oauth_service.js +63 -96
  119. package/dist/lib/services/otp_service.d.ts +1 -1
  120. package/dist/lib/services/otp_service.d.ts.map +1 -1
  121. package/dist/lib/services/otp_service.js +6 -1
  122. package/dist/lib/services/session_token_service.d.ts +0 -2
  123. package/dist/lib/services/session_token_service.d.ts.map +1 -1
  124. package/dist/lib/services/session_token_service.js +0 -2
  125. package/dist/page_components/create_firm.d.ts +1 -13
  126. package/dist/page_components/create_firm.d.ts.map +1 -1
  127. package/dist/page_components/create_firm.js +6 -10
  128. package/dist/page_components/forgot_password.d.ts +4 -1
  129. package/dist/page_components/forgot_password.d.ts.map +1 -1
  130. package/dist/page_components/forgot_password.js +6 -2
  131. package/dist/page_components/login.d.ts +4 -1
  132. package/dist/page_components/login.d.ts.map +1 -1
  133. package/dist/page_components/login.js +6 -2
  134. package/dist/page_components/register.d.ts +4 -1
  135. package/dist/page_components/register.d.ts.map +1 -1
  136. package/dist/page_components/register.js +6 -2
  137. package/dist/page_components/reset_password.d.ts +4 -1
  138. package/dist/page_components/reset_password.d.ts.map +1 -1
  139. package/dist/page_components/reset_password.js +6 -2
  140. package/dist/page_components/verify_email.d.ts +4 -1
  141. package/dist/page_components/verify_email.d.ts.map +1 -1
  142. package/dist/page_components/verify_email.js +6 -2
  143. package/dist/server/routes/assets.d.ts +8 -0
  144. package/dist/server/routes/assets.d.ts.map +1 -0
  145. package/dist/server/routes/assets.js +38 -0
  146. package/dist/server/routes/consent_me.d.ts +4 -0
  147. package/dist/server/routes/consent_me.d.ts.map +1 -0
  148. package/dist/server/routes/consent_me.js +15 -0
  149. package/dist/server/routes/index.d.ts +6 -4
  150. package/dist/server/routes/index.d.ts.map +1 -1
  151. package/dist/server/routes/index.js +9 -5
  152. package/dist/server/routes/me.d.ts.map +1 -1
  153. package/dist/server/routes/me.js +1 -43
  154. package/dist/server/routes/oauth_facebook_callback.d.ts +1 -1
  155. package/dist/server/routes/oauth_facebook_callback.d.ts.map +1 -1
  156. package/dist/server/routes/oauth_facebook_callback.js +8 -1
  157. package/dist/server/routes/oauth_google_callback.js +1 -1
  158. package/dist/server/routes/otp/verify.js +2 -2
  159. package/dist/server/routes/strings_defaults.d.ts +4 -0
  160. package/dist/server/routes/strings_defaults.d.ts.map +1 -0
  161. package/dist/server/routes/strings_defaults.js +7 -0
  162. package/dist/server/routes/user_management_users.d.ts +11 -0
  163. package/dist/server/routes/user_management_users.d.ts.map +1 -1
  164. package/dist/server/routes/user_management_users.js +50 -0
  165. package/dist/server-lib.d.ts +0 -3
  166. package/dist/server-lib.d.ts.map +1 -1
  167. package/dist/server-lib.js +0 -2
  168. package/dist/server_pages/forgot_password.d.ts +18 -14
  169. package/dist/server_pages/forgot_password.d.ts.map +1 -1
  170. package/dist/server_pages/forgot_password.js +14 -12
  171. package/dist/server_pages/forgot_password_client_wrapper.d.ts +8 -7
  172. package/dist/server_pages/forgot_password_client_wrapper.d.ts.map +1 -1
  173. package/dist/server_pages/forgot_password_client_wrapper.js +2 -2
  174. package/dist/server_pages/index.d.ts +2 -0
  175. package/dist/server_pages/index.d.ts.map +1 -1
  176. package/dist/server_pages/index.js +1 -0
  177. package/dist/server_pages/login.d.ts +22 -23
  178. package/dist/server_pages/login.d.ts.map +1 -1
  179. package/dist/server_pages/login.js +27 -14
  180. package/dist/server_pages/login_client_wrapper.d.ts +9 -10
  181. package/dist/server_pages/login_client_wrapper.d.ts.map +1 -1
  182. package/dist/server_pages/login_client_wrapper.js +2 -2
  183. package/dist/server_pages/my_settings.d.ts +1 -3
  184. package/dist/server_pages/my_settings.d.ts.map +1 -1
  185. package/dist/server_pages/my_settings.js +2 -9
  186. package/dist/server_pages/register.d.ts +17 -20
  187. package/dist/server_pages/register.d.ts.map +1 -1
  188. package/dist/server_pages/register.js +20 -15
  189. package/dist/server_pages/register_client_wrapper.d.ts +8 -10
  190. package/dist/server_pages/register_client_wrapper.d.ts.map +1 -1
  191. package/dist/server_pages/register_client_wrapper.js +2 -2
  192. package/dist/server_pages/reset_password.d.ts +16 -11
  193. package/dist/server_pages/reset_password.d.ts.map +1 -1
  194. package/dist/server_pages/reset_password.js +14 -10
  195. package/dist/server_pages/reset_password_client_wrapper.d.ts +8 -7
  196. package/dist/server_pages/reset_password_client_wrapper.d.ts.map +1 -1
  197. package/dist/server_pages/reset_password_client_wrapper.js +2 -2
  198. package/dist/server_pages/verify_email.d.ts +18 -12
  199. package/dist/server_pages/verify_email.d.ts.map +1 -1
  200. package/dist/server_pages/verify_email.js +13 -11
  201. package/dist/server_pages/verify_email_client_wrapper.d.ts +8 -7
  202. package/dist/server_pages/verify_email_client_wrapper.d.ts.map +1 -1
  203. package/dist/server_pages/verify_email_client_wrapper.js +2 -2
  204. package/dist/themes/index.d.ts +0 -1
  205. package/dist/themes/index.d.ts.map +1 -1
  206. package/dist/themes/index.js +1 -1
  207. package/package.json +26 -40
  208. package/dist/themes/preset_indigo_sunset.d.ts +0 -3
  209. package/dist/themes/preset_indigo_sunset.d.ts.map +0 -1
  210. package/dist/themes/preset_indigo_sunset.js +0 -20
@@ -958,7 +958,27 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_hazo_users_google_id_unique ON hazo_users(
958
958
  CREATE INDEX IF NOT EXISTS idx_hazo_users_google_id ON hazo_users(google_id);
959
959
  ```
960
960
 
961
- ### Step 3.2.4: Configure OAuth in hazo_auth_config.ini
961
+ ### Step 3.2.4 (Optional): Run Email OTP Migration
962
+
963
+ Required only if you plan to enable `enable_email_otp = true` in `[hazo_auth__otp]`.
964
+
965
+ ```bash
966
+ npx hazo_auth migrate migrations/015_email_otp.sql
967
+ ```
968
+
969
+ Creates `hazo_email_otps` table for OTP codes and rate limiting.
970
+
971
+ ### Step 3.2.4b (Optional): Run Facebook OAuth Migration
972
+
973
+ Required only if `enable_facebook_oauth = true` in `[hazo_auth__oauth]`.
974
+
975
+ ```bash
976
+ npx hazo_auth migrate migrations/016_add_facebook_id_to_hazo_users.sql
977
+ ```
978
+
979
+ Adds `facebook_id` column to `hazo_users`.
980
+
981
+ ### Step 3.2.5: Configure OAuth in hazo_auth_config.ini
962
982
 
963
983
  Add (or modify) the OAuth section:
964
984
 
@@ -1443,246 +1463,6 @@ export { POST } from "hazo_auth/server/routes/pin_login";
1443
1463
 
1444
1464
  ---
1445
1465
 
1446
- ## Phase 5.3: Email-OTP Sign-in Setup (Optional)
1447
-
1448
- Email-OTP sign-in lets users authenticate with a 6-digit code sent to their email — no password or Google OAuth required. Skip this phase if your app uses only password or OAuth authentication.
1449
-
1450
- ### Step 5.3.1: Apply the OTP migration
1451
-
1452
- ```bash
1453
- npm run migrate migrations/015_email_otp.sql
1454
- ```
1455
-
1456
- This creates the `hazo_email_otps` table (stores hashed codes with expiry).
1457
-
1458
- **Verify the table exists:**
1459
- ```bash
1460
- sqlite3 data/hazo_auth.sqlite ".tables" | tr ' ' '\n' | grep hazo_email_otps
1461
- # Expected: hazo_email_otps
1462
- ```
1463
-
1464
- ### Step 5.3.2: Add OTP config section
1465
-
1466
- Add to `config/hazo_auth_config.ini`:
1467
-
1468
- ```ini
1469
- [hazo_auth__otp]
1470
- # Whether OTP sign-in is enabled
1471
- enabled = true
1472
-
1473
- # Auto-register unknown emails on first successful verify (default: false)
1474
- otp_auto_register = false
1475
-
1476
- # Code expiry in minutes (default: 10)
1477
- code_expiry_minutes = 10
1478
- ```
1479
-
1480
- ### Step 5.3.3: Create OTP API routes
1481
-
1482
- ```bash
1483
- npx hazo_auth generate-routes
1484
- ```
1485
-
1486
- Or manually:
1487
-
1488
- `app/api/hazo_auth/otp/request/route.ts`:
1489
- ```typescript
1490
- export { otpRequestPOST as POST } from "hazo_auth/server/routes";
1491
- ```
1492
-
1493
- `app/api/hazo_auth/otp/verify/route.ts`:
1494
- ```typescript
1495
- export { otpVerifyPOST as POST } from "hazo_auth/server/routes";
1496
- ```
1497
-
1498
- ### Step 5.3.4: Create the OTP sign-in page
1499
-
1500
- `app/hazo_auth/otp/page.tsx`:
1501
- ```typescript
1502
- export { default } from "hazo_auth/pages/otp";
1503
- ```
1504
-
1505
- ### Step 5.3.5: Add OTP routes to middleware/proxy public_routes (REQUIRED)
1506
-
1507
- **This step is critical.** Unauthenticated users arrive at the OTP sign-in page before they have auth cookies. If the OTP routes are not in `public_routes`, your middleware will redirect them to `/login` in a loop.
1508
-
1509
- Edit your `middleware.ts` or `proxy.ts`:
1510
-
1511
- ```typescript
1512
- const public_routes = [
1513
- // ... existing entries ...
1514
- "/hazo_auth/otp", // OTP sign-in page (public — users arrive unauthenticated)
1515
- "/api/hazo_auth/otp", // OTP request + verify API routes
1516
- ];
1517
- ```
1518
-
1519
- ### Step 5.3.6: Install optional peer dep (if using OTPVerifyForm)
1520
-
1521
- If you render `<OTPVerifyForm/>` directly (rather than using the zero-config page), install:
1522
-
1523
- ```bash
1524
- npm install input-otp
1525
- ```
1526
-
1527
- **OTP Setup Checklist:**
1528
- - [ ] `hazo_email_otps` table created (`npm run migrate migrations/015_email_otp.sql`)
1529
- - [ ] `[hazo_auth__otp]` section added to `hazo_auth_config.ini`
1530
- - [ ] OTP API routes created (`/api/hazo_auth/otp/request` and `/api/hazo_auth/otp/verify`)
1531
- - [ ] OTP page created (`/hazo_auth/otp`)
1532
- - [ ] `/hazo_auth/otp` and `/api/hazo_auth/otp` added to middleware `public_routes`
1533
- - [ ] `input-otp` installed (only if using `<OTPVerifyForm/>` directly)
1534
- - [ ] Email delivery configured (`hazo_notify` + valid `ZEPTOMAIL_API_KEY`)
1535
-
1536
- ---
1537
-
1538
- ## Phase 5.4: Theme Setup (v7.0.0+)
1539
-
1540
- ### Step 5.4.1: Mount HazoAuthThemeProvider (Required for themed auth pages)
1541
-
1542
- Mount `<HazoAuthThemeProvider>` in `app/layout.tsx`. Use `preset_neutral` for the default look, or configure a custom theme.
1543
-
1544
- **Option A: Default look (no config needed)**
1545
- ```tsx
1546
- import { HazoAuthThemeProvider } from "hazo_auth/theme";
1547
- import { preset_neutral } from "hazo_auth/themes";
1548
-
1549
- export default function RootLayout({ children }) {
1550
- return (
1551
- <html>
1552
- <body>
1553
- <HazoAuthThemeProvider theme={preset_neutral}>
1554
- {children}
1555
- </HazoAuthThemeProvider>
1556
- </body>
1557
- </html>
1558
- );
1559
- }
1560
- ```
1561
-
1562
- **Option B: Custom theme**
1563
- ```tsx
1564
- import { createTheme, HazoAuthThemeProvider } from "hazo_auth/theme";
1565
-
1566
- const theme = createTheme({
1567
- colors: { primary: "#2563EB" },
1568
- layout: "split",
1569
- brandPanel: { logoSrc: "/logo.svg", tagline: "Welcome." },
1570
- });
1571
-
1572
- <HazoAuthThemeProvider theme={theme}>{children}</HazoAuthThemeProvider>
1573
- ```
1574
-
1575
- **If using `preset_indigo_sunset` (custom fonts required):**
1576
-
1577
- Wire `next/font` in `app/layout.tsx` to expose `--font-display` and `--font-body` CSS variables. See [MIGRATION.md §3](./MIGRATION.md).
1578
-
1579
- ```tsx
1580
- import { Crimson_Pro, DM_Sans } from "next/font/google";
1581
- const display = Crimson_Pro({ subsets: ["latin"], variable: "--font-display" });
1582
- const body = DM_Sans({ subsets: ["latin"], variable: "--font-body" });
1583
-
1584
- export default function Layout({ children }) {
1585
- return <html className={`${display.variable} ${body.variable}`}>{children}</html>;
1586
- }
1587
- ```
1588
-
1589
- **Checklist:**
1590
- - [ ] `<HazoAuthThemeProvider>` mounted in `app/layout.tsx`
1591
- - [ ] Preset or custom theme configured
1592
- - [ ] If using `preset_indigo_sunset`: `next/font` wired for `--font-display` and `--font-body`
1593
-
1594
- ---
1595
-
1596
- ## Phase 5.5: Facebook OAuth Setup (Optional, v7.0.0+)
1597
-
1598
- ### Step 5.5.1: Get Facebook App credentials
1599
-
1600
- 1. Go to [Meta Developers](https://developers.facebook.com/)
1601
- 2. Create or select an app
1602
- 3. Add the **Facebook Login** product
1603
- 4. Set authorized redirect URIs: `http://localhost:3000/api/auth/callback/facebook` (dev) and your production URL
1604
- 5. Copy **App ID** and **App Secret**
1605
-
1606
- ### Step 5.5.2: Add Facebook OAuth environment variables
1607
-
1608
- Add to your `.env.local`:
1609
- ```env
1610
- HAZO_AUTH_FACEBOOK_APP_ID=your_app_id
1611
- HAZO_AUTH_FACEBOOK_APP_SECRET=your_app_secret
1612
- ```
1613
-
1614
- The Facebook sign-in button is hidden when these vars are not set.
1615
-
1616
- ### Step 5.5.3: Enable Facebook in config
1617
-
1618
- Add to `config/hazo_auth_config.ini`:
1619
- ```ini
1620
- [hazo_auth__oauth]
1621
- enable_facebook = true
1622
-
1623
- ; Facebook: default false — stricter security posture
1624
- ; Set true only if you want to auto-link to unverified email accounts
1625
- auto_link_unverified_accounts_facebook = false
1626
- ```
1627
-
1628
- ### Step 5.5.4: Apply Facebook migration
1629
-
1630
- ```bash
1631
- npm run migrate migrations/016_facebook_oauth.sql
1632
- ```
1633
-
1634
- ### Step 5.5.5: Create Facebook OAuth callback route
1635
-
1636
- ```typescript
1637
- // app/api/hazo_auth/oauth/facebook/callback/route.ts
1638
- export { GET } from "hazo_auth/server/routes/oauth_facebook_callback";
1639
- ```
1640
-
1641
- **Facebook OAuth Checklist:**
1642
- - [ ] Facebook App credentials obtained
1643
- - [ ] `HAZO_AUTH_FACEBOOK_APP_ID` and `HAZO_AUTH_FACEBOOK_APP_SECRET` set in `.env.local`
1644
- - [ ] `enable_facebook = true` in `[hazo_auth__oauth]`
1645
- - [ ] Migration `016_facebook_oauth.sql` applied
1646
- - [ ] Facebook callback route created
1647
-
1648
- ---
1649
-
1650
- ## Phase 5.6: Cookie Consent Setup (Optional, v7.0.0+)
1651
-
1652
- ### Step 5.6.1: Mount CookieConsentBanner
1653
-
1654
- Mount `<CookieConsentBanner>` in your root layout:
1655
-
1656
- ```tsx
1657
- import { CookieConsentBanner } from "hazo_auth/consent";
1658
-
1659
- export default function RootLayout({ children }) {
1660
- return (
1661
- <html>
1662
- <body>
1663
- <HazoAuthThemeProvider theme={preset_neutral}>
1664
- {children}
1665
- <CookieConsentBanner />
1666
- </HazoAuthThemeProvider>
1667
- </body>
1668
- </html>
1669
- );
1670
- }
1671
- ```
1672
-
1673
- **With GTM (optional):**
1674
- ```tsx
1675
- <CookieConsentBanner enableGTM gtmContainerId="GTM-XXXX" />
1676
- ```
1677
-
1678
- See the README [Cookie Consent](#cookie-consent-v700) section for server-side `read_consent` usage.
1679
-
1680
- **Checklist:**
1681
- - [ ] `<CookieConsentBanner>` mounted in root layout
1682
- - [ ] GTM container ID configured (if using GTM)
1683
-
1684
- ---
1685
-
1686
1466
  ## Phase 6: Verification Tests
1687
1467
 
1688
1468
  Run these tests to verify your setup is working correctly.
@@ -2164,10 +1944,10 @@ import { hazo_get_tenant_auth } from "hazo_auth/server-lib";
2164
1944
  export async function GET(request: NextRequest) {
2165
1945
  const auth = await hazo_get_tenant_auth(request);
2166
1946
 
2167
- if (auth.authenticated && auth.selected_scope) {
2168
- // auth.selected_scope contains the currently selected tenant/scope
1947
+ if (auth.authenticated && auth.organization) {
1948
+ // auth.organization contains tenant details
2169
1949
  // auth.user_scopes contains all scopes user can access (for UI switcher)
2170
- const data = await getTenantData(auth.selected_scope.id);
1950
+ const data = await getTenantData(auth.organization.id);
2171
1951
  }
2172
1952
  }
2173
1953
  ```
@@ -2179,8 +1959,8 @@ import { require_tenant_auth, HazoAuthError } from "hazo_auth/server-lib";
2179
1959
  export async function GET(request: NextRequest) {
2180
1960
  try {
2181
1961
  const auth = await require_tenant_auth(request);
2182
- // auth.selected_scope is guaranteed non-null
2183
- return NextResponse.json(await getData(auth.selected_scope.id));
1962
+ // auth.organization is guaranteed non-null
1963
+ return NextResponse.json(await getData(auth.organization.id));
2184
1964
  } catch (error) {
2185
1965
  if (error instanceof HazoAuthError) {
2186
1966
  return NextResponse.json(
@@ -2200,7 +1980,7 @@ import { withAuth } from "hazo_auth/server-lib";
2200
1980
  // Auth + params + error handling all automatic
2201
1981
  export const GET = withAuth<{ id: string }>(
2202
1982
  async (request, auth, { id }) => {
2203
- const data = await getData(auth.selected_scope.id, id);
1983
+ const data = await getData(auth.organization.id, id);
2204
1984
  return NextResponse.json(data);
2205
1985
  },
2206
1986
  { require_tenant: true }
@@ -2249,7 +2029,7 @@ const auth = await hazo_get_tenant_auth(request);
2249
2029
 
2250
2030
  // Return available scopes to frontend
2251
2031
  return NextResponse.json({
2252
- current_scope: auth.selected_scope,
2032
+ current_scope: auth.organization,
2253
2033
  available_scopes: auth.user_scopes.map(s => ({
2254
2034
  id: s.id,
2255
2035
  name: s.name,
@@ -127,20 +127,11 @@ ${exports}
127
127
  }
128
128
 
129
129
  function generate_page_content(page: PageDefinition): string {
130
- // Next 16 requires page default exports to satisfy `PageProps` (i.e. accept
131
- // `{ params?, searchParams? }` and nothing else). Re-exporting the named
132
- // component directly fails that check because the component carries custom
133
- // props (image_src, layout, …). The wrapper below is a parameter-less
134
- // function that returns the component — Next sees a `() => JSX` signature
135
- // which trivially satisfies PageProps. Direct JSX consumers still use the
136
- // named export from `hazo_auth/pages` and get the full custom-prop API.
137
130
  return `// Generated by hazo_auth - do not edit manually
138
131
  // Page: /${page.path}
139
132
  import { ${page.component_name} } from "hazo_auth/pages";
140
133
 
141
- export default function Page() {
142
- return <${page.component_name} />;
143
- }
134
+ export default ${page.component_name};
144
135
  `;
145
136
  }
146
137
 
@@ -64,9 +64,6 @@ const REQUIRED_API_ROUTES = [
64
64
  { path: "api/hazo_auth/user_management/users/roles", method: "GET" },
65
65
  { path: "api/hazo_auth/user_management/users/roles", method: "POST" },
66
66
  { path: "api/hazo_auth/user_management/users/roles", method: "PUT" },
67
- // OTP routes
68
- { path: "api/hazo_auth/otp/request", method: "POST" },
69
- { path: "api/hazo_auth/otp/verify", method: "POST" },
70
67
  ];
71
68
 
72
69
  // section: helpers
@@ -537,7 +534,6 @@ const REQUIRED_TABLES = [
537
534
  "hazo_role_permissions",
538
535
  "hazo_invitations",
539
536
  "hazo_refresh_tokens",
540
- "hazo_email_otps",
541
537
  ];
542
538
 
543
539
  const TEXT_ID_TABLES = [
@@ -1,12 +1,4 @@
1
1
  // file_description: Type definitions and error classes for hazo_get_auth utility
2
- //
3
- // Naming note (v6.0.0): the field previously called `organization` (and
4
- // `organization_id`) on `TenantAuthResult` was renamed to `selected_scope`
5
- // (and `selected_scope_id`), and the type `TenantOrganization` was renamed
6
- // to `SelectedScope`. The multi-tenancy model is scopes throughout; the
7
- // old name was a legacy synonym for "the currently selected scope" derived
8
- // from the scope-selection cookie/header. No deprecation shim is provided.
9
- //
10
2
  // section: types
11
3
 
12
4
  /**
@@ -131,11 +123,10 @@ export type ScopeDetails = {
131
123
  };
132
124
 
133
125
  /**
134
- * Currently selected scope information returned in tenant auth results.
135
- * Simplified view of the scope chosen via the scope-selection cookie or
136
- * `X-Hazo-Scope-Id` header.
126
+ * Tenant/organization information returned in tenant auth results
127
+ * Simplified view of scope for API responses
137
128
  */
138
- export type SelectedScope = {
129
+ export type TenantOrganization = {
139
130
  id: string;
140
131
  name: string;
141
132
  slug: string | null;
@@ -176,9 +167,9 @@ export type TenantAuthResult =
176
167
  permissions: string[];
177
168
  permission_ok: boolean;
178
169
  missing_permissions?: string[];
179
- selected_scope: SelectedScope | null;
180
- /** Shorthand for selected_scope?.id - commonly used for DB query filters. */
181
- selected_scope_id: string | null;
170
+ organization: TenantOrganization | null;
171
+ /** Shorthand for organization?.id - commonly used for DB query filters */
172
+ organization_id: string | null;
182
173
  user_scopes: ScopeDetails[];
183
174
  scope_ok?: boolean;
184
175
  scope_access_via?: ScopeAccessInfo;
@@ -188,20 +179,20 @@ export type TenantAuthResult =
188
179
  user: null;
189
180
  permissions: [];
190
181
  permission_ok: false;
191
- selected_scope: null;
192
- /** Shorthand for selected_scope?.id - commonly used for DB query filters. */
193
- selected_scope_id: null;
182
+ organization: null;
183
+ /** Shorthand for organization?.id - commonly used for DB query filters */
184
+ organization_id: null;
194
185
  user_scopes: [];
195
186
  scope_ok?: false;
196
187
  };
197
188
 
198
189
  /**
199
- * Guaranteed authenticated result with non-null selected_scope.
200
- * Returned by require_tenant_auth when validation passes.
190
+ * Guaranteed authenticated result with non-null organization
191
+ * Returned by require_tenant_auth when validation passes
201
192
  */
202
193
  export type RequiredTenantAuthResult = TenantAuthResult & {
203
194
  authenticated: true;
204
- selected_scope: SelectedScope;
195
+ organization: TenantOrganization;
205
196
  };
206
197
 
207
198
  // section: tenant_error_classes
@@ -14,7 +14,7 @@ import type {
14
14
  TenantAuthOptions,
15
15
  TenantAuthResult,
16
16
  RequiredTenantAuthResult,
17
- SelectedScope,
17
+ TenantOrganization,
18
18
  ScopeDetails,
19
19
  } from "./auth_types";
20
20
  import {
@@ -62,15 +62,15 @@ export function extract_scope_id_from_request(
62
62
  }
63
63
 
64
64
  /**
65
- * Builds SelectedScope from scope details and access info.
65
+ * Builds TenantOrganization from scope details and access info
66
66
  * @param scope_details - Full scope details from cache
67
67
  * @param is_super_admin - Whether user is accessing as super admin
68
- * @returns SelectedScope object
68
+ * @returns TenantOrganization object
69
69
  */
70
- function build_selected_scope(
70
+ function build_tenant_organization(
71
71
  scope_details: ScopeDetails,
72
72
  is_super_admin: boolean,
73
- ): SelectedScope {
73
+ ): TenantOrganization {
74
74
  return {
75
75
  id: scope_details.id,
76
76
  name: scope_details.name,
@@ -96,21 +96,20 @@ function build_selected_scope(
96
96
  * Tenant-aware authentication function
97
97
  *
98
98
  * Extracts tenant/scope context from request headers or cookies,
99
- * validates access, and returns enriched result including the currently
100
- * selected scope.
99
+ * validates access, and returns enriched result with organization info.
101
100
  *
102
101
  * Header priority: X-Hazo-Scope-Id > Cookie
103
102
  *
104
103
  * @param request - NextRequest object
105
104
  * @param options - TenantAuthOptions for customization
106
- * @returns TenantAuthResult with user, permissions, selected_scope, and user_scopes
105
+ * @returns TenantAuthResult with user, permissions, organization, and user_scopes
107
106
  *
108
107
  * @example
109
108
  * ```typescript
110
109
  * const auth = await hazo_get_tenant_auth(request);
111
- * if (auth.authenticated && auth.selected_scope) {
110
+ * if (auth.authenticated && auth.organization) {
112
111
  * // Access tenant-specific data
113
- * const data = await getData(auth.selected_scope.id);
112
+ * const data = await getData(auth.organization.id);
114
113
  * }
115
114
  * ```
116
115
  */
@@ -137,8 +136,8 @@ export async function hazo_get_tenant_auth(
137
136
  user: null,
138
137
  permissions: [],
139
138
  permission_ok: false,
140
- selected_scope: null,
141
- selected_scope_id: null,
139
+ organization: null,
140
+ organization_id: null,
142
141
  user_scopes: [],
143
142
  scope_ok: false,
144
143
  };
@@ -156,8 +155,8 @@ export async function hazo_get_tenant_auth(
156
155
  // User scopes from cache or empty array
157
156
  const user_scopes: ScopeDetails[] = cached?.scopes || [];
158
157
 
159
- // Build selected_scope info if scope access was successful
160
- let selected_scope: SelectedScope | null = null;
158
+ // Build organization info if scope access was successful
159
+ let organization: TenantOrganization | null = null;
161
160
 
162
161
  if (scope_id && auth_result.scope_ok && auth_result.scope_access_via) {
163
162
  // Find the scope in user's scopes that matches the access_via scope
@@ -166,7 +165,7 @@ export async function hazo_get_tenant_auth(
166
165
  );
167
166
 
168
167
  if (access_scope) {
169
- selected_scope = build_selected_scope(
168
+ organization = build_tenant_organization(
170
169
  access_scope,
171
170
  auth_result.scope_access_via.is_super_admin || false,
172
171
  );
@@ -175,7 +174,7 @@ export async function hazo_get_tenant_auth(
175
174
  const hazoConnect = get_hazo_connect_instance();
176
175
  const scope_result = await get_scope_by_id(hazoConnect, scope_id);
177
176
  if (scope_result.success && scope_result.scope) {
178
- selected_scope = {
177
+ organization = {
179
178
  id: scope_result.scope.id,
180
179
  name: scope_result.scope.name,
181
180
  slug: null, // Could fetch from scope if slug column exists
@@ -201,8 +200,8 @@ export async function hazo_get_tenant_auth(
201
200
  permissions: auth_result.permissions,
202
201
  permission_ok: auth_result.permission_ok,
203
202
  missing_permissions: auth_result.missing_permissions,
204
- selected_scope,
205
- selected_scope_id: selected_scope?.id || null,
203
+ organization,
204
+ organization_id: organization?.id || null,
206
205
  user_scopes,
207
206
  scope_ok: auth_result.scope_ok,
208
207
  scope_access_via: auth_result.scope_access_via,
@@ -219,15 +218,15 @@ export async function hazo_get_tenant_auth(
219
218
  *
220
219
  * @param request - NextRequest object
221
220
  * @param options - TenantAuthOptions for customization
222
- * @returns RequiredTenantAuthResult with guaranteed non-null selected_scope
221
+ * @returns RequiredTenantAuthResult with guaranteed non-null organization
223
222
  * @throws AuthenticationRequiredError, TenantRequiredError, TenantAccessDeniedError
224
223
  *
225
224
  * @example
226
225
  * ```typescript
227
226
  * try {
228
227
  * const auth = await require_tenant_auth(request);
229
- * // auth.selected_scope is guaranteed non-null here
230
- * const data = await getData(auth.selected_scope.id);
228
+ * // auth.organization is guaranteed non-null here
229
+ * const data = await getData(auth.organization.id);
231
230
  * } catch (error) {
232
231
  * if (error instanceof HazoAuthError) {
233
232
  * return NextResponse.json(
@@ -258,14 +257,14 @@ export async function require_tenant_auth(
258
257
  throw new TenantAccessDeniedError(scope_id, result.user_scopes);
259
258
  }
260
259
 
261
- // Check if scope context is required but missing
262
- if (!result.selected_scope) {
260
+ // Check if organization context is required but missing
261
+ if (!result.organization) {
263
262
  throw new TenantRequiredError(
264
- "No tenant scope context provided. Include X-Hazo-Scope-Id header or scope cookie.",
263
+ "No organization context provided. Include X-Hazo-Scope-Id header or scope cookie.",
265
264
  result.user_scopes,
266
265
  );
267
266
  }
268
267
 
269
- // Type assertion: at this point we know selected_scope is non-null
268
+ // Type assertion: at this point we know organization is non-null
270
269
  return result as RequiredTenantAuthResult;
271
270
  }
@@ -22,7 +22,7 @@ export {
22
22
  } from "./hazo_get_tenant_auth.server.js";
23
23
  export type {
24
24
  ScopeDetails,
25
- SelectedScope,
25
+ TenantOrganization,
26
26
  TenantAuthOptions,
27
27
  TenantAuthResult,
28
28
  RequiredTenantAuthResult,
@@ -50,7 +50,7 @@ export {
50
50
  } from "./with_auth.server.js";
51
51
  export type {
52
52
  AuthenticatedTenantAuth,
53
- AuthenticatedTenantAuthWithSelectedScope,
53
+ AuthenticatedTenantAuthWithOrg,
54
54
  WithAuthOptions,
55
55
  } from "./with_auth.server";
56
56