hazo_auth 10.1.0 โ†’ 10.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  A reusable authentication UI component package powered by Next.js, TailwindCSS, and shadcn. It integrates `hazo_config` for configuration management and `hazo_connect` for data access, enabling future components to stay aligned with platform conventions.
4
4
 
5
+ ### What's New in v10.2.0 ๐Ÿงช
6
+
7
+ **Test-friendly hazo_connect injection + autotest/middleware fixes.**
8
+
9
+ - **`set_hazo_connect_instance(adapter)` / `reset_hazo_connect_instance()`** from `hazo_auth/server-lib` โ€” inject a pre-built adapter into both the hazo_auth singleton cache and the underlying hazo_connect singleton (companion to hazo_connect 3.6.0 FR-001). Call `set_*` in `beforeAll` and `reset_*` in `afterAll` to swap in a test SQLite adapter without touching the production config:
10
+
11
+ ```typescript
12
+ import { set_hazo_connect_instance, reset_hazo_connect_instance } from "hazo_auth/server-lib";
13
+
14
+ beforeAll(() => set_hazo_connect_instance(testAdapter));
15
+ afterAll(() => reset_hazo_connect_instance());
16
+ ```
17
+
18
+ - **Middleware no longer redirects `/api/` requests to the login page** โ€” protected API routes return JSON `401`/`403` and the login redirect is now built from the request's own origin (fixes `Failed to fetch` on any non-default dev/prod port).
19
+ - **`/api/hazo_auth/me`** now exposes `legal_acceptance` at the top level; **`/api/hazo_auth/health`** now returns a top-level `ok` boolean.
20
+ - Browser autotest scenarios corrected for browser `fetch` semantics (opaque redirects, `*_default.jpg` images, admin-gated `401`/`403`, current `relationships` body shape).
21
+
22
+ Requires `hazo_connect ^3.6.0`.
23
+
5
24
  ### What's New in v10.1.0 ๐Ÿš€
6
25
 
7
26
  **Incremental Google OAuth Scopes & Server-Side Token Access** โ€” Grant additional Google API scopes (Analytics, Sheets, Drive, etc.) without creating a separate OAuth app. Store encrypted tokens server-side and access them programmatically.
@@ -35,6 +54,16 @@ HAZO_AUTH_OAUTH_KEY_V1=$(openssl rand -base64 32)
35
54
  npm install hazo_secure
36
55
  ```
37
56
 
57
+ ```js
58
+ // 4. Add hazo_secure to serverExternalPackages in next.config.mjs / next.config.js
59
+ // so the bundler leaves the literal import("hazo_secure/crypto") as a native
60
+ // external import. Without this, Google sign-in fails with
61
+ // GoogleTokenStorageUnconfigured even when hazo_secure is installed.
62
+ const nextConfig = {
63
+ serverExternalPackages: ["hazo_secure", /* ...existing entries */],
64
+ };
65
+ ```
66
+
38
67
  **Client Usage:**
39
68
  ```tsx
40
69
  import { requestGoogleScopes } from "hazo_auth/client";
@@ -1321,6 +1350,10 @@ Google OAuth adds one new dependency:
1321
1350
  HAZO_AUTH_OAUTH_KEY_V1=$(openssl rand -base64 32)
1322
1351
  ```
1323
1352
  3. Install the optional peer: `npm install hazo_secure`
1353
+ 4. Add `hazo_secure` to `serverExternalPackages` in `next.config.mjs` / `next.config.js`. The
1354
+ service loads encryption via a literal `import("hazo_secure/crypto")`; if the bundler inlines
1355
+ `hazo_secure` instead of treating it as an external import, Google sign-in fails with
1356
+ `GoogleTokenStorageUnconfigured` even when the peer is installed and keys are set.
1324
1357
 
1325
1358
  **Usage:**
1326
1359
 
@@ -13,6 +13,7 @@ const nextConfig = {
13
13
  serverExternalPackages: [
14
14
  "hazo_notify", "argon2",
15
15
  "hazo_core", "hazo_config", // required for Next 16 + Turbopack
16
+ "hazo_secure", // required if using Google API token storage (getGoogleToken)
16
17
  ],
17
18
  };
18
19
  ```
@@ -1138,13 +1139,17 @@ ls app/api/hazo_auth/set_password/route.ts
1138
1139
  Only needed if you use `requestGoogleScopes` / `getGoogleToken` for Google API access beyond sign-in:
1139
1140
 
1140
1141
  1. Install optional peer: `npm install hazo_secure`
1141
- 2. Run migration: `npm run migrate -- migrations/021_hazo_google_oauth_tokens.sql`
1142
- 3. Set env vars:
1142
+ 2. Add `hazo_secure` to `serverExternalPackages` in `next.config.mjs` / `next.config.js`. The
1143
+ service loads encryption via a literal `import("hazo_secure/crypto")`; if the bundler inlines
1144
+ `hazo_secure` rather than leaving it as a native external import, Google sign-in fails with
1145
+ `GoogleTokenStorageUnconfigured` even when the peer is installed and keys are configured.
1146
+ 3. Run migration: `npm run migrate -- migrations/021_hazo_google_oauth_tokens.sql`
1147
+ 4. Set env vars:
1143
1148
  ```env
1144
1149
  HAZO_AUTH_OAUTH_KEY_CURRENT=v1
1145
1150
  HAZO_AUTH_OAUTH_KEY_V1=<base64-32-bytes from: openssl rand -base64 32>
1146
1151
  ```
1147
- 4. Wire the new routes in your Next.js app (same pattern as other hazo_auth routes):
1152
+ 5. Wire the new routes in your Next.js app (same pattern as other hazo_auth routes):
1148
1153
  ```ts
1149
1154
  // app/api/hazo_auth/google/token/route.ts
1150
1155
  export { GET as googleTokenGET, DELETE as googleTokenDELETE } from "hazo_auth/server/routes";
@@ -8,6 +8,7 @@ import "server-only";
8
8
  // section: imports
9
9
  import type { HazoConnectAdapter } from "hazo_connect";
10
10
  import { getHazoConnectSingleton } from "hazo_connect/nextjs/setup";
11
+ import { setHazoConnectSingleton, resetHazoConnectSingleton } from "hazo_connect/testing";
11
12
  import { create_sqlite_hazo_connect_server, get_hazo_connect_config_options } from "./hazo_connect_setup.server.js";
12
13
  import { initializeAdminService, getSqliteAdminService } from "hazo_connect/server";
13
14
  import { create_app_logger } from "./app_logger.js";
@@ -32,6 +33,8 @@ let isInitialized = false;
32
33
  * @returns The singleton HazoConnectAdapter instance
33
34
  */
34
35
  export function get_hazo_connect_instance(): HazoConnectAdapter {
36
+ // Honor test injection or cached fallback first
37
+ if (hazoConnectInstance) return hazoConnectInstance;
35
38
  // Use the new singleton API from hazo_connect
36
39
  // This automatically handles:
37
40
  // - Instance reuse
@@ -102,3 +105,16 @@ export function get_hazo_connect_instance(): HazoConnectAdapter {
102
105
  }
103
106
  }
104
107
 
108
+ /** Inject a connect adapter for tests (mirrors set_hazo_connect_instance pattern). */
109
+ export function set_hazo_connect_instance(adapter: HazoConnectAdapter): void {
110
+ hazoConnectInstance = adapter;
111
+ setHazoConnectSingleton(adapter);
112
+ }
113
+
114
+ /** Reset the injected adapter (call in afterAll). */
115
+ export function reset_hazo_connect_instance(): void {
116
+ hazoConnectInstance = null;
117
+ isInitialized = false;
118
+ resetHazoConnectSingleton();
119
+ }
120
+
@@ -3,7 +3,6 @@
3
3
  import { createCrudService } from "hazo_connect/server";
4
4
  import { get_hazo_connect_instance } from "../hazo_connect_instance.server.js";
5
5
  import { create_app_logger } from "../app_logger.js";
6
- import { optional_import } from "hazo_core";
7
6
  import { randomUUID } from "crypto";
8
7
 
9
8
  // section: errors
@@ -70,10 +69,32 @@ function makeKeyProvider(
70
69
  });
71
70
  }
72
71
 
72
+ /**
73
+ * Indirection around the hazo_secure/crypto dynamic import.
74
+ *
75
+ * The import specifier MUST be a string literal. hazo_secure is an optional
76
+ * peer dep, so this used to go through hazo_core's `optional_import(pkg)` โ€” but
77
+ * that performs a dynamic `import(variable)`, which Turbopack/webpack cannot
78
+ * statically resolve when consumers bundle their server. The import then fails
79
+ * unconditionally and sign-in dies on GoogleTokenStorageUnconfigured even when
80
+ * hazo_secure is installed. A literal `import("hazo_secure/crypto")` is left as
81
+ * a native external import and resolves at runtime (consumers must list
82
+ * hazo_secure in serverExternalPackages so it isn't bundled).
83
+ *
84
+ * Wrapped in an object so tests can stub `_cryptoLoader.load` without touching
85
+ * the literal specifier. Not part of the public API (underscore-prefixed).
86
+ */
87
+ export const _cryptoLoader = {
88
+ load: (): Promise<typeof import("hazo_secure/crypto")> => import("hazo_secure/crypto"),
89
+ };
90
+
73
91
  async function load_crypto_module() {
74
- const cryptoModule = await optional_import<typeof import("hazo_secure/crypto")>(
75
- "hazo_secure/crypto"
76
- );
92
+ let cryptoModule: typeof import("hazo_secure/crypto") | null;
93
+ try {
94
+ cryptoModule = await _cryptoLoader.load();
95
+ } catch {
96
+ cryptoModule = null;
97
+ }
77
98
  if (!cryptoModule) throw new GoogleTokenStorageUnconfigured();
78
99
  return cryptoModule;
79
100
  }
@@ -11,5 +11,5 @@ import { ProfilePicMenu } from "./profile_pic_menu.js";
11
11
  // section: component
12
12
  export function SidebarLayoutWrapper({ children }) {
13
13
  const authStatus = use_auth_status();
14
- return (_jsx(SidebarProvider, { children: _jsxs("div", { className: "cls_sidebar_layout_wrapper flex min-h-screen w-full", children: [_jsxs(Sidebar, { children: [_jsx(SidebarHeader, { className: "cls_sidebar_layout_header", children: _jsx("div", { className: "cls_sidebar_layout_title flex items-center gap-2 px-2 py-4", children: _jsx("h1", { className: "cls_sidebar_layout_title_text text-lg font-semibold text-sidebar-foreground", children: "hazo auth" }) }) }), _jsxs(SidebarContent, { className: "cls_sidebar_layout_content", children: [_jsxs(SidebarGroup, { className: "cls_sidebar_layout_test_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Test components" }), _jsxs(SidebarMenu, { className: "cls_sidebar_layout_test_menu", children: [_jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_login_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/login", className: "cls_sidebar_layout_test_login_link flex items-center gap-2", "aria-label": "Test login layout component", children: [_jsx(LogIn, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test login" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_register_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/register", className: "cls_sidebar_layout_test_register_link flex items-center gap-2", "aria-label": "Test register layout component", children: [_jsx(UserPlus, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test register" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_forgot_password_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/forgot_password", className: "cls_sidebar_layout_test_forgot_password_link flex items-center gap-2", "aria-label": "Test forgot password layout component", children: [_jsx(KeyRound, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test forgot password" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_reset_password_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/reset_password", className: "cls_sidebar_layout_test_reset_password_link flex items-center gap-2", "aria-label": "Test reset password layout component", children: [_jsx(Key, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test reset password" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_email_verification_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/verify_email", className: "cls_sidebar_layout_test_email_verification_link flex items-center gap-2", "aria-label": "Test email verification layout component", children: [_jsx(MailCheck, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test email verification" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_sqlite_admin_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_connect/sqlite_admin", className: "cls_sidebar_layout_sqlite_admin_link flex items-center gap-2", "aria-label": "Open SQLite admin UI to browse and edit database", children: [_jsx(Database, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "SQLite Admin" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_user_management_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/user_management", className: "cls_sidebar_layout_user_management_link flex items-center gap-2", "aria-label": "Open User Management to manage users, roles, and permissions", children: [_jsx(User, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "User Management" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_rbac_test_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/rbac_test", className: "cls_sidebar_layout_rbac_test_link flex items-center gap-2", "aria-label": "Test RBAC and HRBAC access control", children: [_jsx(ShieldCheck, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "RBAC/HRBAC Test" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_profile_stamp_test_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/profile_stamp_test", className: "cls_sidebar_layout_profile_stamp_test_link flex items-center gap-2", "aria-label": "Test ProfileStamp component", children: [_jsx(CircleUserRound, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "ProfileStamp Test" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_app_user_data_test_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/app_user_data_test", className: "cls_sidebar_layout_app_user_data_test_link flex items-center gap-2", "aria-label": "Test app_user_data JSON storage", children: [_jsx(FileJson, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "App User Data Test" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_google_token_test_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/google_token_test", className: "cls_sidebar_layout_google_token_test_link flex items-center gap-2", "aria-label": "Test Google OAuth token storage and revocation", children: [_jsx(Globe, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Google Token Test" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_create_firm_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/create_firm", className: "cls_sidebar_layout_create_firm_link flex items-center gap-2", "aria-label": "Test create firm flow", children: [_jsx(Building2, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Create Firm" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_edit_firm_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/edit_firm", className: "cls_sidebar_layout_edit_firm_link flex items-center gap-2", "aria-label": "Test branding editor for firm", children: [_jsx(Palette, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Edit Firm" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_relationships_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/relationships", className: "cls_sidebar_layout_relationships_link flex items-center gap-2", "aria-label": "Test relationship accounts", children: [_jsx(User, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Relationships" })] }) }) })] })] }), _jsxs(SidebarGroup, { className: "cls_sidebar_layout_testing_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Testing" }), _jsx(SidebarMenu, { className: "cls_sidebar_layout_testing_menu", children: _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_scenarios_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/test_scenarios", className: "cls_sidebar_layout_test_scenarios_link flex items-center gap-2", "aria-label": "Test scenarios", children: [_jsx(Settings2, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test Scenarios" })] }) }) }) })] }), _jsxs(SidebarGroup, { className: "cls_sidebar_layout_auto_test_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Auto Tests" }), _jsx(SidebarMenu, { className: "cls_sidebar_layout_auto_test_menu", children: _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_auto_test_runner_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/auto_test", className: "cls_sidebar_layout_auto_test_runner_link flex items-center gap-2", "aria-label": "Run automated tests", children: [_jsx(Play, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Auto Test Runner" })] }) }) }) })] }), _jsx(ProfilePicMenu, { variant: "sidebar", avatar_size: "sm", className: "cls_sidebar_layout_profile_menu", sidebar_group_label: "Account" }), _jsxs(SidebarGroup, { className: "cls_sidebar_layout_resources_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Resources" }), _jsxs(SidebarMenu, { className: "cls_sidebar_layout_resources_menu", children: [_jsx(SidebarMenuItem, { className: "cls_sidebar_layout_storybook_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs("a", { href: "http://localhost:6006", target: "_blank", rel: "noopener noreferrer", className: "cls_sidebar_layout_storybook_link flex items-center gap-2", "aria-label": "Open Storybook preview for reusable components", children: [_jsx(BookOpen, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Storybook" }), _jsx(ExternalLink, { className: "ml-auto h-3 w-3", "aria-hidden": "true" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_docs_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs("a", { href: "https://ui.shadcn.com/docs", target: "_blank", rel: "noopener noreferrer", className: "cls_sidebar_layout_docs_link flex items-center gap-2", "aria-label": "Review shadcn documentation for styling guidance", children: [_jsx(BookOpen, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Shadcn docs" }), _jsx(ExternalLink, { className: "ml-auto h-3 w-3", "aria-hidden": "true" })] }) }) })] })] })] })] }), _jsxs(SidebarInset, { className: "cls_sidebar_layout_inset", children: [_jsxs("header", { className: "cls_sidebar_layout_main_header flex h-16 shrink-0 items-center gap-2 border-b px-4", children: [_jsx(SidebarTrigger, { className: "cls_sidebar_layout_trigger" }), _jsx("div", { className: "cls_sidebar_layout_main_header_content flex flex-1 items-center gap-2", children: _jsx("h2", { className: "cls_sidebar_layout_main_title text-lg font-semibold text-foreground", children: "hazo reusable ui library workspace" }) }), _jsx(ProfilePicMenu, { className: "cls_sidebar_layout_auth_status", avatar_size: "sm" })] }), _jsx("main", { className: "cls_sidebar_layout_main_content flex flex-1 items-center justify-center p-6", children: children })] })] }) }));
14
+ return (_jsx(SidebarProvider, { children: _jsxs("div", { className: "cls_sidebar_layout_wrapper flex min-h-screen w-full", children: [_jsxs(Sidebar, { children: [_jsx(SidebarHeader, { className: "cls_sidebar_layout_header", children: _jsx("div", { className: "cls_sidebar_layout_title flex items-center gap-2 px-2 py-4", children: _jsx("h1", { className: "cls_sidebar_layout_title_text text-lg font-semibold text-sidebar-foreground", children: "hazo auth" }) }) }), _jsxs(SidebarContent, { className: "cls_sidebar_layout_content", children: [_jsxs(SidebarGroup, { className: "cls_sidebar_layout_test_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Test components" }), _jsxs(SidebarMenu, { className: "cls_sidebar_layout_test_menu", children: [_jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_login_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/login", className: "cls_sidebar_layout_test_login_link flex items-center gap-2", "aria-label": "Test login layout component", children: [_jsx(LogIn, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test login" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_register_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/register", className: "cls_sidebar_layout_test_register_link flex items-center gap-2", "aria-label": "Test register layout component", children: [_jsx(UserPlus, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test register" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_forgot_password_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/forgot_password", className: "cls_sidebar_layout_test_forgot_password_link flex items-center gap-2", "aria-label": "Test forgot password layout component", children: [_jsx(KeyRound, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test forgot password" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_reset_password_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/reset_password", className: "cls_sidebar_layout_test_reset_password_link flex items-center gap-2", "aria-label": "Test reset password layout component", children: [_jsx(Key, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test reset password" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_email_verification_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/verify_email", className: "cls_sidebar_layout_test_email_verification_link flex items-center gap-2", "aria-label": "Test email verification layout component", children: [_jsx(MailCheck, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test email verification" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_sqlite_admin_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_connect/sqlite_admin", className: "cls_sidebar_layout_sqlite_admin_link flex items-center gap-2", "aria-label": "Open SQLite admin UI to browse and edit database", children: [_jsx(Database, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "SQLite Admin" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_user_management_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/user_management", className: "cls_sidebar_layout_user_management_link flex items-center gap-2", "aria-label": "Open User Management to manage users, roles, and permissions", children: [_jsx(User, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "User Management" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_rbac_test_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/rbac_test", className: "cls_sidebar_layout_rbac_test_link flex items-center gap-2", "aria-label": "Test RBAC and HRBAC access control", children: [_jsx(ShieldCheck, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "RBAC/HRBAC Test" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_profile_stamp_test_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/profile_stamp_test", className: "cls_sidebar_layout_profile_stamp_test_link flex items-center gap-2", "aria-label": "Test ProfileStamp component", children: [_jsx(CircleUserRound, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "ProfileStamp Test" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_app_user_data_test_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/app_user_data_test", className: "cls_sidebar_layout_app_user_data_test_link flex items-center gap-2", "aria-label": "Test app_user_data JSON storage", children: [_jsx(FileJson, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "App User Data Test" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_google_token_test_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/google_token_test", className: "cls_sidebar_layout_google_token_test_link flex items-center gap-2", "aria-label": "Test Google OAuth token storage and revocation", children: [_jsx(Globe, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Google Token Test" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_create_firm_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/create_firm", className: "cls_sidebar_layout_create_firm_link flex items-center gap-2", "aria-label": "Test create firm flow", children: [_jsx(Building2, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Create Firm" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_edit_firm_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/edit_firm", className: "cls_sidebar_layout_edit_firm_link flex items-center gap-2", "aria-label": "Test branding editor for firm", children: [_jsx(Palette, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Edit Firm" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_relationships_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/relationships", className: "cls_sidebar_layout_relationships_link flex items-center gap-2", "aria-label": "Test relationship accounts", children: [_jsx(User, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Relationships" })] }) }) })] })] }), _jsxs(SidebarGroup, { className: "cls_sidebar_layout_testing_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Testing" }), _jsx(SidebarMenu, { className: "cls_sidebar_layout_testing_menu", children: _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_test_scenarios_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/test_scenarios", className: "cls_sidebar_layout_test_scenarios_link flex items-center gap-2", "aria-label": "Test scenarios", children: [_jsx(Settings2, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Test Scenarios" })] }) }) }) })] }), _jsxs(SidebarGroup, { className: "cls_sidebar_layout_auto_test_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Auto Tests" }), _jsx(SidebarMenu, { className: "cls_sidebar_layout_auto_test_menu", children: _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_auto_test_runner_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs(Link, { href: "/hazo_auth/autotest", className: "cls_sidebar_layout_auto_test_runner_link flex items-center gap-2", "aria-label": "Run browser autotests", children: [_jsx(Play, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Browser Autotest" })] }) }) }) })] }), _jsx(ProfilePicMenu, { variant: "sidebar", avatar_size: "sm", className: "cls_sidebar_layout_profile_menu", sidebar_group_label: "Account" }), _jsxs(SidebarGroup, { className: "cls_sidebar_layout_resources_group", children: [_jsx(SidebarGroupLabel, { className: "cls_sidebar_layout_group_label", children: "Resources" }), _jsxs(SidebarMenu, { className: "cls_sidebar_layout_resources_menu", children: [_jsx(SidebarMenuItem, { className: "cls_sidebar_layout_storybook_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs("a", { href: "http://localhost:6006", target: "_blank", rel: "noopener noreferrer", className: "cls_sidebar_layout_storybook_link flex items-center gap-2", "aria-label": "Open Storybook preview for reusable components", children: [_jsx(BookOpen, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Storybook" }), _jsx(ExternalLink, { className: "ml-auto h-3 w-3", "aria-hidden": "true" })] }) }) }), _jsx(SidebarMenuItem, { className: "cls_sidebar_layout_docs_item", children: _jsx(SidebarMenuButton, { asChild: true, children: _jsxs("a", { href: "https://ui.shadcn.com/docs", target: "_blank", rel: "noopener noreferrer", className: "cls_sidebar_layout_docs_link flex items-center gap-2", "aria-label": "Review shadcn documentation for styling guidance", children: [_jsx(BookOpen, { className: "h-4 w-4", "aria-hidden": "true" }), _jsx("span", { children: "Shadcn docs" }), _jsx(ExternalLink, { className: "ml-auto h-3 w-3", "aria-hidden": "true" })] }) }) })] })] })] })] }), _jsxs(SidebarInset, { className: "cls_sidebar_layout_inset", children: [_jsxs("header", { className: "cls_sidebar_layout_main_header flex h-16 shrink-0 items-center gap-2 border-b px-4", children: [_jsx(SidebarTrigger, { className: "cls_sidebar_layout_trigger" }), _jsx("div", { className: "cls_sidebar_layout_main_header_content flex flex-1 items-center gap-2", children: _jsx("h2", { className: "cls_sidebar_layout_main_title text-lg font-semibold text-foreground", children: "hazo reusable ui library workspace" }) }), _jsx(ProfilePicMenu, { className: "cls_sidebar_layout_auth_status", avatar_size: "sm" })] }), _jsx("main", { className: "cls_sidebar_layout_main_content flex flex-1 items-center justify-center p-6", children: children })] })] }) }));
15
15
  }
@@ -15,4 +15,8 @@ import type { HazoConnectAdapter } from "hazo_connect";
15
15
  * @returns The singleton HazoConnectAdapter instance
16
16
  */
17
17
  export declare function get_hazo_connect_instance(): HazoConnectAdapter;
18
+ /** Inject a connect adapter for tests (mirrors set_hazo_connect_instance pattern). */
19
+ export declare function set_hazo_connect_instance(adapter: HazoConnectAdapter): void;
20
+ /** Reset the injected adapter (call in afterAll). */
21
+ export declare function reset_hazo_connect_instance(): void;
18
22
  //# sourceMappingURL=hazo_connect_instance.server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hazo_connect_instance.server.d.ts","sourceRoot":"","sources":["../../src/lib/hazo_connect_instance.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAMrB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAWvD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,IAAI,kBAAkB,CAqE9D"}
1
+ {"version":3,"file":"hazo_connect_instance.server.d.ts","sourceRoot":"","sources":["../../src/lib/hazo_connect_instance.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAMrB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAYvD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,IAAI,kBAAkB,CAuE9D;AAED,sFAAsF;AACtF,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAG3E;AAED,qDAAqD;AACrD,wBAAgB,2BAA2B,IAAI,IAAI,CAIlD"}
@@ -2,6 +2,7 @@
2
2
  // section: server-only-guard
3
3
  import "server-only";
4
4
  import { getHazoConnectSingleton } from "hazo_connect/nextjs/setup";
5
+ import { setHazoConnectSingleton, resetHazoConnectSingleton } from "hazo_connect/testing";
5
6
  import { create_sqlite_hazo_connect_server, get_hazo_connect_config_options } from "./hazo_connect_setup.server.js";
6
7
  import { initializeAdminService, getSqliteAdminService } from "hazo_connect/server";
7
8
  import { create_app_logger } from "./app_logger.js";
@@ -24,6 +25,9 @@ let isInitialized = false;
24
25
  * @returns The singleton HazoConnectAdapter instance
25
26
  */
26
27
  export function get_hazo_connect_instance() {
28
+ // Honor test injection or cached fallback first
29
+ if (hazoConnectInstance)
30
+ return hazoConnectInstance;
27
31
  // Use the new singleton API from hazo_connect
28
32
  // This automatically handles:
29
33
  // - Instance reuse
@@ -89,3 +93,14 @@ export function get_hazo_connect_instance() {
89
93
  return hazoConnectInstance;
90
94
  }
91
95
  }
96
+ /** Inject a connect adapter for tests (mirrors set_hazo_connect_instance pattern). */
97
+ export function set_hazo_connect_instance(adapter) {
98
+ hazoConnectInstance = adapter;
99
+ setHazoConnectSingleton(adapter);
100
+ }
101
+ /** Reset the injected adapter (call in afterAll). */
102
+ export function reset_hazo_connect_instance() {
103
+ hazoConnectInstance = null;
104
+ isInitialized = false;
105
+ resetHazoConnectSingleton();
106
+ }
@@ -21,6 +21,24 @@ export type GoogleTokenStatus = {
21
21
  scopes: string;
22
22
  expires_at: string | null;
23
23
  };
24
+ /**
25
+ * Indirection around the hazo_secure/crypto dynamic import.
26
+ *
27
+ * The import specifier MUST be a string literal. hazo_secure is an optional
28
+ * peer dep, so this used to go through hazo_core's `optional_import(pkg)` โ€” but
29
+ * that performs a dynamic `import(variable)`, which Turbopack/webpack cannot
30
+ * statically resolve when consumers bundle their server. The import then fails
31
+ * unconditionally and sign-in dies on GoogleTokenStorageUnconfigured even when
32
+ * hazo_secure is installed. A literal `import("hazo_secure/crypto")` is left as
33
+ * a native external import and resolves at runtime (consumers must list
34
+ * hazo_secure in serverExternalPackages so it isn't bundled).
35
+ *
36
+ * Wrapped in an object so tests can stub `_cryptoLoader.load` without touching
37
+ * the literal specifier. Not part of the public API (underscore-prefixed).
38
+ */
39
+ export declare const _cryptoLoader: {
40
+ load: () => Promise<typeof import("hazo_secure/crypto")>;
41
+ };
24
42
  /**
25
43
  * Stores (inserts or updates) Google OAuth tokens for a user, encrypting sensitive fields.
26
44
  * Throws GoogleTokenStorageUnconfigured if hazo_secure/crypto is unavailable or keys are missing.
@@ -1 +1 @@
1
- {"version":3,"file":"google_token_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/google_token_service.ts"],"names":[],"mappings":"AAUA,qBAAa,8BAA+B,SAAQ,KAAK;;CAOxD;AAID,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,eAAe,GAAG,oBAAoB,GAAG,gBAAgB,GAAG,cAAc,CAAA;CAAE,CAAC;AAErG,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AA6CF;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC,IAAI,CAAC,CA0Ef;AAID;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CA6I5B;AAID;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6D1C;AAID;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAexF"}
1
+ {"version":3,"file":"google_token_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/google_token_service.ts"],"names":[],"mappings":"AASA,qBAAa,8BAA+B,SAAQ,KAAK;;CAOxD;AAID,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,eAAe,GAAG,oBAAoB,GAAG,gBAAgB,GAAG,cAAc,CAAA;CAAE,CAAC;AAErG,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAmCF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa;gBACd,OAAO,CAAC,cAAc,oBAAoB,CAAC,CAAC;CACvD,CAAC;AAeF;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC,IAAI,CAAC,CA0Ef;AAID;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CA6I5B;AAID;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6D1C;AAID;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAexF"}
@@ -3,7 +3,6 @@
3
3
  import { createCrudService } from "hazo_connect/server";
4
4
  import { get_hazo_connect_instance } from "../hazo_connect_instance.server.js";
5
5
  import { create_app_logger } from "../app_logger.js";
6
- import { optional_import } from "hazo_core";
7
6
  import { randomUUID } from "crypto";
8
7
  // section: errors
9
8
  export class GoogleTokenStorageUnconfigured extends Error {
@@ -26,8 +25,32 @@ function makeKeyProvider(LookupKeyProvider) {
26
25
  return undefined;
27
26
  });
28
27
  }
28
+ /**
29
+ * Indirection around the hazo_secure/crypto dynamic import.
30
+ *
31
+ * The import specifier MUST be a string literal. hazo_secure is an optional
32
+ * peer dep, so this used to go through hazo_core's `optional_import(pkg)` โ€” but
33
+ * that performs a dynamic `import(variable)`, which Turbopack/webpack cannot
34
+ * statically resolve when consumers bundle their server. The import then fails
35
+ * unconditionally and sign-in dies on GoogleTokenStorageUnconfigured even when
36
+ * hazo_secure is installed. A literal `import("hazo_secure/crypto")` is left as
37
+ * a native external import and resolves at runtime (consumers must list
38
+ * hazo_secure in serverExternalPackages so it isn't bundled).
39
+ *
40
+ * Wrapped in an object so tests can stub `_cryptoLoader.load` without touching
41
+ * the literal specifier. Not part of the public API (underscore-prefixed).
42
+ */
43
+ export const _cryptoLoader = {
44
+ load: () => import("hazo_secure/crypto"),
45
+ };
29
46
  async function load_crypto_module() {
30
- const cryptoModule = await optional_import("hazo_secure/crypto");
47
+ let cryptoModule;
48
+ try {
49
+ cryptoModule = await _cryptoLoader.load();
50
+ }
51
+ catch (_a) {
52
+ cryptoModule = null;
53
+ }
31
54
  if (!cryptoModule)
32
55
  throw new GoogleTokenStorageUnconfigured();
33
56
  return cryptoModule;
@@ -1 +1 @@
1
- {"version":3,"file":"me.d.ts","sourceRoot":"","sources":["../../../src/server/routes/me.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAoBxD;;;;;GAKG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;IA+G7C"}
1
+ {"version":3,"file":"me.d.ts","sourceRoot":"","sources":["../../../src/server/routes/me.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAoBxD;;;;;GAKG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;IAiH7C"}
@@ -24,6 +24,7 @@ function strip_sentinel_email(email) {
24
24
  * Always returns the same format to prevent downstream variations.
25
25
  */
26
26
  export async function GET(request) {
27
+ var _a;
27
28
  const logger = create_app_logger();
28
29
  try {
29
30
  // Use hazo_get_auth to get user with permissions
@@ -94,6 +95,8 @@ export async function GET(request) {
94
95
  user_type_info,
95
96
  // App-specific user data (JSON object, always included)
96
97
  app_user_data: auth_result.user.app_user_data,
98
+ // Legal documents the user has accepted (map of key -> { hash, accepted_at })
99
+ legal_acceptance: (_a = auth_result.user.legal_acceptance) !== null && _a !== void 0 ? _a : null,
97
100
  // Permissions and user object (always included)
98
101
  user: auth_result.user,
99
102
  permissions: auth_result.permissions,
@@ -25,7 +25,7 @@ export type { OAuthConfig } from "./lib/oauth_config.server";
25
25
  export { get_branding_config, is_branding_enabled, is_allowed_logo_format, get_max_logo_size_bytes, } from "./lib/branding_config.server.js";
26
26
  export type { FirmBrandingConfig } from "./lib/branding_config.server";
27
27
  export { create_sqlite_hazo_connect } from "./lib/hazo_connect_setup.js";
28
- export { get_hazo_connect_instance } from "./lib/hazo_connect_instance.server.js";
28
+ export { get_hazo_connect_instance, set_hazo_connect_instance, reset_hazo_connect_instance, } from "./lib/hazo_connect_instance.server.js";
29
29
  export { create_app_logger } from "./lib/app_logger.js";
30
30
  export { sanitize_error_for_user } from "./lib/utils/error_sanitizer.js";
31
31
  export type { ErrorSanitizationOptions } from "./lib/utils/error_sanitizer";
@@ -1 +1 @@
1
- {"version":3,"file":"server-lib.d.ts","sourceRoot":"","sources":["../src/server-lib.ts"],"names":[],"mappings":"AAYA,OAAO,aAAa,CAAC;AAGrB,cAAc,kBAAkB,CAAC;AAGjC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAGrF,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AACvF,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,2BAA2B,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,gCAAgC,EAAE,MAAM,2CAA2C,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAG/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,YAAY,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,cAAc,+BAA+B,CAAC"}
1
+ {"version":3,"file":"server-lib.d.ts","sourceRoot":"","sources":["../src/server-lib.ts"],"names":[],"mappings":"AAYA,OAAO,aAAa,CAAC;AAGrB,cAAc,kBAAkB,CAAC;AAGjC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAGrF,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AACvF,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,2BAA2B,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,gCAAgC,EAAE,MAAM,2CAA2C,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,YAAY,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,cAAc,+BAA+B,CAAC"}
@@ -39,7 +39,7 @@ export { get_oauth_config, is_google_oauth_enabled, is_email_password_enabled, }
39
39
  export { get_branding_config, is_branding_enabled, is_allowed_logo_format, get_max_logo_size_bytes, } from "./lib/branding_config.server.js";
40
40
  // section: hazo_connect_exports
41
41
  export { create_sqlite_hazo_connect } from "./lib/hazo_connect_setup.js";
42
- export { get_hazo_connect_instance } from "./lib/hazo_connect_instance.server.js";
42
+ export { get_hazo_connect_instance, set_hazo_connect_instance, reset_hazo_connect_instance, } from "./lib/hazo_connect_instance.server.js";
43
43
  // section: logger_exports
44
44
  export { create_app_logger } from "./lib/app_logger.js";
45
45
  // section: util_exports
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_auth",
3
- "version": "10.1.0",
3
+ "version": "10.2.1",
4
4
  "description": "Zero-config authentication UI components for Next.js with RBAC, OAuth, scope-based multi-tenancy, and invitations",
5
5
  "keywords": [
6
6
  "authentication",
@@ -252,14 +252,14 @@
252
252
  "@radix-ui/react-switch": "^1.2.0",
253
253
  "@radix-ui/react-tabs": "^1.1.0",
254
254
  "@radix-ui/react-tooltip": "^1.2.0",
255
- "hazo_api": "^2.3.1",
256
- "hazo_config": "^2.1.10",
257
- "hazo_connect": "^3.5.1",
258
- "hazo_core": "^1.1.0",
255
+ "hazo_api": "^2.4.0",
256
+ "hazo_config": "^2.1.11",
257
+ "hazo_connect": "^3.7.0",
258
+ "hazo_core": "^1.2.0",
259
259
  "hazo_logs": "^2.0.3",
260
260
  "hazo_notify": "^6.1.3",
261
261
  "hazo_secure": "^1.1.0",
262
- "hazo_ui": "^3.4.1",
262
+ "hazo_ui": "^4.0.0",
263
263
  "input-otp": "^1.4.0",
264
264
  "lucide-react": "^0.553.0",
265
265
  "next": "^14.0.0",
@@ -392,13 +392,13 @@
392
392
  "eslint": "^9.39.1",
393
393
  "eslint-config-next": "^16.0.4",
394
394
  "eslint-plugin-storybook": "^10.0.6",
395
- "hazo_api": "^2.3.1",
396
- "hazo_config": "^2.1.10",
397
- "hazo_connect": "^3.5.1",
398
- "hazo_core": "^1.1.0",
395
+ "hazo_api": "^2.4.0",
396
+ "hazo_config": "^2.1.11",
397
+ "hazo_connect": "^3.7.0",
398
+ "hazo_core": "^1.2.0",
399
399
  "hazo_logs": "^2.0.3",
400
400
  "hazo_notify": "^6.1.3",
401
- "hazo_ui": "^3.4.1",
401
+ "hazo_ui": "^4.0.0",
402
402
  "input-otp": "^1.4.0",
403
403
  "jest": "^30.2.0",
404
404
  "jest-environment-jsdom": "^30.0.0",