hazo_auth 10.2.3 → 10.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/cli-src/lib/auth/deny_permission.server.ts +101 -0
  2. package/cli-src/lib/auth/index.ts +8 -0
  3. package/cli-src/lib/auth/with_permission_issue_capture.server.ts +222 -0
  4. package/cli-src/lib/services/find_roles_with_permission.ts +47 -0
  5. package/dist/admin-issues/permission_denied_provider.client.d.ts +14 -0
  6. package/dist/admin-issues/permission_denied_provider.client.d.ts.map +1 -0
  7. package/dist/admin-issues/permission_denied_provider.client.js +80 -0
  8. package/dist/admin-issues/plugin.client.d.ts +34 -0
  9. package/dist/admin-issues/plugin.client.d.ts.map +1 -0
  10. package/dist/admin-issues/plugin.client.js +64 -0
  11. package/dist/admin-issues/plugin.server.d.ts +59 -0
  12. package/dist/admin-issues/plugin.server.d.ts.map +1 -0
  13. package/dist/admin-issues/plugin.server.js +168 -0
  14. package/dist/admin-issues/wire.server.d.ts +23 -0
  15. package/dist/admin-issues/wire.server.d.ts.map +1 -0
  16. package/dist/admin-issues/wire.server.js +30 -0
  17. package/dist/client.d.ts +5 -0
  18. package/dist/client.d.ts.map +1 -1
  19. package/dist/client.js +6 -0
  20. package/dist/components/layouts/create_firm/index.d.ts +2 -1
  21. package/dist/components/layouts/create_firm/index.d.ts.map +1 -1
  22. package/dist/components/layouts/dev_lock/index.d.ts +1 -1
  23. package/dist/components/layouts/dev_lock/index.d.ts.map +1 -1
  24. package/dist/components/layouts/email_verification/index.d.ts +1 -1
  25. package/dist/components/layouts/email_verification/index.d.ts.map +1 -1
  26. package/dist/components/layouts/forgot_password/index.d.ts +1 -1
  27. package/dist/components/layouts/forgot_password/index.d.ts.map +1 -1
  28. package/dist/components/layouts/google_token_test/index.d.ts +1 -1
  29. package/dist/components/layouts/google_token_test/index.d.ts.map +1 -1
  30. package/dist/components/layouts/legal/legal_acceptance_gate.d.ts +1 -1
  31. package/dist/components/layouts/legal/legal_acceptance_gate.d.ts.map +1 -1
  32. package/dist/components/layouts/legal/legal_doc_checkbox_list.d.ts +1 -1
  33. package/dist/components/layouts/legal/legal_doc_checkbox_list.d.ts.map +1 -1
  34. package/dist/components/layouts/legal/legal_doc_combined_view.d.ts +1 -1
  35. package/dist/components/layouts/legal/legal_doc_combined_view.d.ts.map +1 -1
  36. package/dist/components/layouts/legal/legal_doc_drawer.d.ts +1 -1
  37. package/dist/components/layouts/legal/legal_doc_drawer.d.ts.map +1 -1
  38. package/dist/components/layouts/login/index.d.ts +1 -1
  39. package/dist/components/layouts/login/index.d.ts.map +1 -1
  40. package/dist/components/layouts/my_settings/components/connected_accounts_section.d.ts +1 -1
  41. package/dist/components/layouts/my_settings/components/connected_accounts_section.d.ts.map +1 -1
  42. package/dist/components/layouts/my_settings/components/editable_field.d.ts +1 -1
  43. package/dist/components/layouts/my_settings/components/editable_field.d.ts.map +1 -1
  44. package/dist/components/layouts/my_settings/components/password_change_dialog.d.ts +1 -1
  45. package/dist/components/layouts/my_settings/components/password_change_dialog.d.ts.map +1 -1
  46. package/dist/components/layouts/my_settings/components/profile_picture_dialog.d.ts +1 -1
  47. package/dist/components/layouts/my_settings/components/profile_picture_dialog.d.ts.map +1 -1
  48. package/dist/components/layouts/my_settings/components/profile_picture_display.d.ts +1 -1
  49. package/dist/components/layouts/my_settings/components/profile_picture_display.d.ts.map +1 -1
  50. package/dist/components/layouts/my_settings/components/profile_picture_gravatar_tab.d.ts +1 -1
  51. package/dist/components/layouts/my_settings/components/profile_picture_gravatar_tab.d.ts.map +1 -1
  52. package/dist/components/layouts/my_settings/components/profile_picture_library_tab.d.ts +1 -1
  53. package/dist/components/layouts/my_settings/components/profile_picture_library_tab.d.ts.map +1 -1
  54. package/dist/components/layouts/my_settings/components/profile_picture_upload_tab.d.ts +1 -1
  55. package/dist/components/layouts/my_settings/components/profile_picture_upload_tab.d.ts.map +1 -1
  56. package/dist/components/layouts/my_settings/components/set_password_section.d.ts +1 -1
  57. package/dist/components/layouts/my_settings/components/set_password_section.d.ts.map +1 -1
  58. package/dist/components/layouts/my_settings/index.d.ts +1 -1
  59. package/dist/components/layouts/my_settings/index.d.ts.map +1 -1
  60. package/dist/components/layouts/register/index.d.ts +1 -1
  61. package/dist/components/layouts/register/index.d.ts.map +1 -1
  62. package/dist/components/layouts/reset_password/index.d.ts +1 -1
  63. package/dist/components/layouts/reset_password/index.d.ts.map +1 -1
  64. package/dist/components/layouts/scope_management/components/branding_editor.d.ts +1 -1
  65. package/dist/components/layouts/scope_management/components/branding_editor.d.ts.map +1 -1
  66. package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts +1 -1
  67. package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts.map +1 -1
  68. package/dist/components/layouts/shared/components/auth_navbar.d.ts +1 -1
  69. package/dist/components/layouts/shared/components/auth_navbar.d.ts.map +1 -1
  70. package/dist/components/layouts/shared/components/auth_page_shell.d.ts +1 -1
  71. package/dist/components/layouts/shared/components/auth_page_shell.d.ts.map +1 -1
  72. package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts +1 -1
  73. package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts.map +1 -1
  74. package/dist/components/layouts/shared/components/field_error_message.d.ts +1 -1
  75. package/dist/components/layouts/shared/components/field_error_message.d.ts.map +1 -1
  76. package/dist/components/layouts/shared/components/floating_home_link.d.ts +1 -1
  77. package/dist/components/layouts/shared/components/floating_home_link.d.ts.map +1 -1
  78. package/dist/components/layouts/shared/components/form_action_buttons.d.ts +1 -1
  79. package/dist/components/layouts/shared/components/form_action_buttons.d.ts.map +1 -1
  80. package/dist/components/layouts/shared/components/form_field_wrapper.d.ts +1 -1
  81. package/dist/components/layouts/shared/components/form_field_wrapper.d.ts.map +1 -1
  82. package/dist/components/layouts/shared/components/form_header.d.ts +1 -1
  83. package/dist/components/layouts/shared/components/form_header.d.ts.map +1 -1
  84. package/dist/components/layouts/shared/components/google_icon.d.ts +1 -1
  85. package/dist/components/layouts/shared/components/google_icon.d.ts.map +1 -1
  86. package/dist/components/layouts/shared/components/google_sign_in_button.d.ts +1 -1
  87. package/dist/components/layouts/shared/components/google_sign_in_button.d.ts.map +1 -1
  88. package/dist/components/layouts/shared/components/logout_button.d.ts +1 -1
  89. package/dist/components/layouts/shared/components/logout_button.d.ts.map +1 -1
  90. package/dist/components/layouts/shared/components/oauth_divider.d.ts +1 -1
  91. package/dist/components/layouts/shared/components/oauth_divider.d.ts.map +1 -1
  92. package/dist/components/layouts/shared/components/password_field.d.ts +1 -1
  93. package/dist/components/layouts/shared/components/password_field.d.ts.map +1 -1
  94. package/dist/components/layouts/shared/components/profile_pic_menu.d.ts +1 -1
  95. package/dist/components/layouts/shared/components/profile_pic_menu.d.ts.map +1 -1
  96. package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.d.ts +1 -1
  97. package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.d.ts.map +1 -1
  98. package/dist/components/layouts/shared/components/profile_stamp.d.ts +1 -1
  99. package/dist/components/layouts/shared/components/profile_stamp.d.ts.map +1 -1
  100. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts +1 -1
  101. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -1
  102. package/dist/components/layouts/shared/components/standalone_layout_wrapper.d.ts +1 -1
  103. package/dist/components/layouts/shared/components/standalone_layout_wrapper.d.ts.map +1 -1
  104. package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts +1 -1
  105. package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts.map +1 -1
  106. package/dist/components/layouts/shared/components/unauthorized_guard.d.ts +1 -1
  107. package/dist/components/layouts/shared/components/unauthorized_guard.d.ts.map +1 -1
  108. package/dist/components/layouts/shared/components/visual_panel.d.ts +1 -1
  109. package/dist/components/layouts/shared/components/visual_panel.d.ts.map +1 -1
  110. package/dist/components/layouts/user_management/components/app_user_data_editor.d.ts +1 -1
  111. package/dist/components/layouts/user_management/components/app_user_data_editor.d.ts.map +1 -1
  112. package/dist/components/layouts/user_management/components/roles_matrix.d.ts +1 -1
  113. package/dist/components/layouts/user_management/components/roles_matrix.d.ts.map +1 -1
  114. package/dist/components/layouts/user_management/components/scope_hierarchy_tab.d.ts +1 -1
  115. package/dist/components/layouts/user_management/components/scope_hierarchy_tab.d.ts.map +1 -1
  116. package/dist/components/layouts/user_management/components/user_scopes_tab.d.ts +1 -1
  117. package/dist/components/layouts/user_management/components/user_scopes_tab.d.ts.map +1 -1
  118. package/dist/components/layouts/user_management/index.d.ts +1 -1
  119. package/dist/components/layouts/user_management/index.d.ts.map +1 -1
  120. package/dist/components/permission_denied_dialog.client.d.ts +19 -0
  121. package/dist/components/permission_denied_dialog.client.d.ts.map +1 -0
  122. package/dist/components/permission_denied_dialog.client.js +112 -0
  123. package/dist/components/ui/alert-dialog.d.ts +2 -2
  124. package/dist/components/ui/dialog.d.ts +2 -2
  125. package/dist/components/ui/dropdown-menu.d.ts +1 -1
  126. package/dist/components/ui/hazo_ui_tooltip.d.ts +1 -1
  127. package/dist/components/ui/hazo_ui_tooltip.d.ts.map +1 -1
  128. package/dist/components/ui/sheet.d.ts +2 -2
  129. package/dist/components/ui/skeleton.d.ts +1 -1
  130. package/dist/components/ui/skeleton.d.ts.map +1 -1
  131. package/dist/components/ui/sonner.d.ts +1 -1
  132. package/dist/components/ui/sonner.d.ts.map +1 -1
  133. package/dist/components/ui/tree-view.d.ts +1 -1
  134. package/dist/components/ui/tree-view.d.ts.map +1 -1
  135. package/dist/components/ui/user-type-badge.d.ts +1 -1
  136. package/dist/components/ui/user-type-badge.d.ts.map +1 -1
  137. package/dist/consent/cookie_consent_banner.d.ts +1 -1
  138. package/dist/consent/cookie_consent_banner.d.ts.map +1 -1
  139. package/dist/consent/manage_modal.d.ts +1 -1
  140. package/dist/consent/manage_modal.d.ts.map +1 -1
  141. package/dist/contexts/hazo_auth_provider.d.ts +2 -2
  142. package/dist/contexts/hazo_auth_provider.d.ts.map +1 -1
  143. package/dist/lib/auth/deny_permission.server.d.ts +18 -0
  144. package/dist/lib/auth/deny_permission.server.d.ts.map +1 -0
  145. package/dist/lib/auth/deny_permission.server.js +66 -0
  146. package/dist/lib/auth/index.d.ts +2 -0
  147. package/dist/lib/auth/index.d.ts.map +1 -1
  148. package/dist/lib/auth/index.js +2 -0
  149. package/dist/lib/auth/with_permission_issue_capture.server.d.ts +49 -0
  150. package/dist/lib/auth/with_permission_issue_capture.server.d.ts.map +1 -0
  151. package/dist/lib/auth/with_permission_issue_capture.server.js +152 -0
  152. package/dist/lib/services/find_roles_with_permission.d.ts +12 -0
  153. package/dist/lib/services/find_roles_with_permission.d.ts.map +1 -0
  154. package/dist/lib/services/find_roles_with_permission.js +38 -0
  155. package/dist/page_components/create_firm.d.ts +1 -1
  156. package/dist/page_components/create_firm.d.ts.map +1 -1
  157. package/dist/page_components/dev_lock.d.ts +1 -1
  158. package/dist/page_components/dev_lock.d.ts.map +1 -1
  159. package/dist/page_components/my_settings.d.ts +1 -1
  160. package/dist/page_components/my_settings.d.ts.map +1 -1
  161. package/dist/server-lib.d.ts +7 -0
  162. package/dist/server-lib.d.ts.map +1 -1
  163. package/dist/server-lib.js +7 -0
  164. package/dist/server_pages/forgot_password.d.ts +1 -1
  165. package/dist/server_pages/forgot_password.d.ts.map +1 -1
  166. package/dist/server_pages/forgot_password_client_wrapper.d.ts +1 -1
  167. package/dist/server_pages/forgot_password_client_wrapper.d.ts.map +1 -1
  168. package/dist/server_pages/login.d.ts +1 -1
  169. package/dist/server_pages/login.d.ts.map +1 -1
  170. package/dist/server_pages/login_client_wrapper.d.ts +1 -1
  171. package/dist/server_pages/login_client_wrapper.d.ts.map +1 -1
  172. package/dist/server_pages/my_settings.d.ts +1 -1
  173. package/dist/server_pages/my_settings.d.ts.map +1 -1
  174. package/dist/server_pages/register.d.ts +1 -1
  175. package/dist/server_pages/register.d.ts.map +1 -1
  176. package/dist/server_pages/register_client_wrapper.d.ts +1 -1
  177. package/dist/server_pages/register_client_wrapper.d.ts.map +1 -1
  178. package/dist/server_pages/reset_password.d.ts +1 -1
  179. package/dist/server_pages/reset_password.d.ts.map +1 -1
  180. package/dist/server_pages/reset_password_client_wrapper.d.ts +1 -1
  181. package/dist/server_pages/reset_password_client_wrapper.d.ts.map +1 -1
  182. package/dist/server_pages/verify_email.d.ts +1 -1
  183. package/dist/server_pages/verify_email.d.ts.map +1 -1
  184. package/dist/server_pages/verify_email_client_wrapper.d.ts +1 -1
  185. package/dist/server_pages/verify_email_client_wrapper.d.ts.map +1 -1
  186. package/dist/strings/strings_provider.d.ts +1 -1
  187. package/dist/strings/strings_provider.d.ts.map +1 -1
  188. package/dist/theme/theme_provider.d.ts +1 -1
  189. package/dist/theme/theme_provider.d.ts.map +1 -1
  190. package/package.json +19 -11
@@ -0,0 +1,112 @@
1
+ // file_description: dialog component shown when a fetch response returns error.code === 'PERMISSION_DENIED'
2
+ // Probes hazo_ui at mount time (it's a peer dep) and falls back to plain HTML if unavailable.
3
+ 'use client';
4
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
+ // section: imports
6
+ import React, { useEffect, useState } from 'react';
7
+ // section: ui_probe
8
+ // Lazy-loaded hazo_ui Dialog + Accordion primitives.
9
+ // We use dynamic import so the build never hard-requires hazo_ui to be resolvable.
10
+ let _Dialog = null;
11
+ let _DialogContent = null;
12
+ let _DialogHeader = null;
13
+ let _DialogTitle = null;
14
+ let _DialogDescription = null;
15
+ let _Accordion = null;
16
+ let _AccordionItem = null;
17
+ let _AccordionTrigger = null;
18
+ let _AccordionContent = null;
19
+ let _uiReady = false;
20
+ function probeUi() {
21
+ if (_uiReady)
22
+ return Promise.resolve(true);
23
+ return import('hazo_ui')
24
+ .then((m) => {
25
+ _Dialog = m.HazoUiDialogRoot;
26
+ _DialogContent = m.HazoUiDialogContent;
27
+ _DialogHeader = m.HazoUiDialogHeader;
28
+ _DialogTitle = m.HazoUiDialogTitle;
29
+ _DialogDescription = m.HazoUiDialogDescription;
30
+ _Accordion = m.Accordion;
31
+ _AccordionItem = m.AccordionItem;
32
+ _AccordionTrigger = m.AccordionTrigger;
33
+ _AccordionContent = m.AccordionContent;
34
+ _uiReady = true;
35
+ return true;
36
+ })
37
+ .catch(() => false);
38
+ }
39
+ // section: helpers
40
+ /** Only allow http/https/relative URLs in hrefs to prevent javascript:/data: XSS. */
41
+ function sanitizeHref(url) {
42
+ try {
43
+ // Relative paths (starting with /) are always safe
44
+ if (url.startsWith('/'))
45
+ return url;
46
+ const u = new URL(url);
47
+ return (u.protocol === 'http:' || u.protocol === 'https:') ? url : null;
48
+ }
49
+ catch (_a) {
50
+ return null;
51
+ }
52
+ }
53
+ // section: component
54
+ /**
55
+ * Dialog shown when a user attempts an action they don't have permission for.
56
+ * Uses hazo_ui primitives when available, falls back to plain HTML overlay if not.
57
+ */
58
+ export function PermissionDeniedDialog({ open, onOpenChange, friendlyMessage = "You don't have permission to perform this action. A request has been sent to your administrator.", technicalDetails, }) {
59
+ var _a, _b, _c;
60
+ const [uiReady, setUiReady] = useState(false);
61
+ useEffect(() => {
62
+ probeUi().then(setUiReady);
63
+ }, []);
64
+ const hasTechnical = technicalDetails &&
65
+ (((_b = (_a = technicalDetails.missing_permissions) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 ||
66
+ technicalDetails.action_label ||
67
+ technicalDetails.origin_url);
68
+ if (!open)
69
+ return null;
70
+ // Fallback: plain HTML overlay when hazo_ui is not installed
71
+ if (!uiReady) {
72
+ return (_jsx("div", { style: {
73
+ position: 'fixed',
74
+ inset: 0,
75
+ background: 'rgba(0,0,0,0.5)',
76
+ zIndex: 9999,
77
+ display: 'flex',
78
+ alignItems: 'center',
79
+ justifyContent: 'center',
80
+ }, children: _jsxs("div", { style: {
81
+ background: '#fff',
82
+ borderRadius: 8,
83
+ padding: 24,
84
+ maxWidth: 480,
85
+ width: '100%',
86
+ }, children: [_jsx("h2", { style: { margin: '0 0 8px', fontSize: 18, fontWeight: 600 }, children: "Access Required" }), _jsx("p", { style: { margin: '0 0 16px', color: '#555' }, children: friendlyMessage }), _jsx("button", { onClick: () => onOpenChange(false), style: {
87
+ padding: '8px 16px',
88
+ background: '#000',
89
+ color: '#fff',
90
+ border: 'none',
91
+ borderRadius: 4,
92
+ cursor: 'pointer',
93
+ }, children: "Close" })] }) }));
94
+ }
95
+ // Full hazo_ui dialog with optional technical-details accordion
96
+ return React.createElement(_Dialog, { open, onOpenChange }, React.createElement(_DialogContent, { className: 'sm:max-w-[480px]' }, React.createElement(_DialogHeader, null, React.createElement(_DialogTitle, null, 'Access Required'), React.createElement(_DialogDescription, null, friendlyMessage)), hasTechnical &&
97
+ React.createElement(_Accordion, { type: 'single', collapsible: true, className: 'mt-4' }, React.createElement(_AccordionItem, { value: 'details' }, React.createElement(_AccordionTrigger, { className: 'text-sm text-gray-500' }, 'Technical details'), React.createElement(_AccordionContent, null, React.createElement('div', { className: 'text-xs text-gray-600 space-y-2 pt-2' }, ((_c = technicalDetails === null || technicalDetails === void 0 ? void 0 : technicalDetails.missing_permissions) === null || _c === void 0 ? void 0 : _c.length)
98
+ ? React.createElement('div', null, React.createElement('span', { className: 'font-medium' }, 'Missing permissions: '), technicalDetails.missing_permissions.join(', '))
99
+ : null, (technicalDetails === null || technicalDetails === void 0 ? void 0 : technicalDetails.action_label)
100
+ ? React.createElement('div', null, React.createElement('span', { className: 'font-medium' }, 'Action: '), technicalDetails.action_label)
101
+ : null, (technicalDetails === null || technicalDetails === void 0 ? void 0 : technicalDetails.origin_url)
102
+ ? React.createElement('div', null, React.createElement('span', { className: 'font-medium' }, 'Return to: '), (() => {
103
+ const safe = sanitizeHref(technicalDetails.origin_url);
104
+ return safe
105
+ ? React.createElement('a', { href: safe, className: 'underline text-blue-600' }, technicalDetails.origin_url)
106
+ : React.createElement('span', { className: 'text-gray-500' }, technicalDetails.origin_url);
107
+ })())
108
+ : null)))), React.createElement('div', { className: 'mt-6 flex justify-end' }, React.createElement('button', {
109
+ onClick: () => onOpenChange(false),
110
+ className: 'px-4 py-2 text-sm font-medium bg-gray-900 text-white rounded-md hover:bg-gray-800',
111
+ }, 'Close'))));
112
+ }
@@ -6,11 +6,11 @@ declare const AlertDialogPortal: React.FC<AlertDialogPrimitive.AlertDialogPortal
6
6
  declare const AlertDialogOverlay: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
7
7
  declare const AlertDialogContent: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
8
8
  declare const AlertDialogHeader: {
9
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
9
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
10
10
  displayName: string;
11
11
  };
12
12
  declare const AlertDialogFooter: {
13
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
13
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
14
14
  displayName: string;
15
15
  };
16
16
  declare const AlertDialogTitle: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
@@ -7,11 +7,11 @@ declare const DialogClose: React.ForwardRefExoticComponent<DialogPrimitive.Dialo
7
7
  declare const DialogOverlay: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
8
8
  declare const DialogContent: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
9
9
  declare const DialogHeader: {
10
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
10
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
11
11
  displayName: string;
12
12
  };
13
13
  declare const DialogFooter: {
14
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
14
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
15
15
  displayName: string;
16
16
  };
17
17
  declare const DialogTitle: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
@@ -21,7 +21,7 @@ declare const DropdownMenuLabel: React.ForwardRefExoticComponent<Omit<DropdownMe
21
21
  } & React.RefAttributes<HTMLDivElement>>;
22
22
  declare const DropdownMenuSeparator: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
23
23
  declare const DropdownMenuShortcut: {
24
- ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>): import("react/jsx-runtime").JSX.Element;
24
+ ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>): React.JSX.Element;
25
25
  displayName: string;
26
26
  };
27
27
  export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuGroup, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuRadioGroup, };
@@ -22,5 +22,5 @@ export type HazoUITooltipProps = {
22
22
  * @param props - Component props including message, icon size, and placement
23
23
  * @returns Tooltip component with question mark icon
24
24
  */
25
- export declare function HazoUITooltip({ message, iconSize, iconClassName, side, }: HazoUITooltipProps): import("react/jsx-runtime").JSX.Element;
25
+ export declare function HazoUITooltip({ message, iconSize, iconClassName, side, }: HazoUITooltipProps): import("react").JSX.Element;
26
26
  //# sourceMappingURL=hazo_ui_tooltip.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hazo_ui_tooltip.d.ts","sourceRoot":"","sources":["../../../src/components/ui/hazo_ui_tooltip.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC5C,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,QAAa,EACb,aAAqD,EACrD,IAAY,GACb,EAAE,kBAAkB,2CAyBpB"}
1
+ {"version":3,"file":"hazo_ui_tooltip.d.ts","sourceRoot":"","sources":["../../../src/components/ui/hazo_ui_tooltip.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC5C,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,QAAa,EACb,aAAqD,EACrD,IAAY,GACb,EAAE,kBAAkB,+BAyBpB"}
@@ -10,11 +10,11 @@ declare const SheetContent: React.ForwardRefExoticComponent<Omit<SheetPrimitive.
10
10
  side?: "top" | "right" | "bottom" | "left" | null | undefined;
11
11
  } & import("class-variance-authority/types").ClassProp) | undefined) => string> & React.RefAttributes<HTMLDivElement>>;
12
12
  declare const SheetHeader: {
13
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
13
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
14
14
  displayName: string;
15
15
  };
16
16
  declare const SheetFooter: {
17
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
17
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
18
18
  displayName: string;
19
19
  };
20
20
  declare const SheetTitle: React.ForwardRefExoticComponent<Omit<SheetPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
@@ -1,3 +1,3 @@
1
- declare function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
1
+ declare function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
2
2
  export { Skeleton };
3
3
  //# sourceMappingURL=skeleton.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skeleton.d.ts","sourceRoot":"","sources":["../../../src/components/ui/skeleton.tsx"],"names":[],"mappings":"AAEA,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,2CAOtC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
1
+ {"version":3,"file":"skeleton.d.ts","sourceRoot":"","sources":["../../../src/components/ui/skeleton.tsx"],"names":[],"mappings":"AAEA,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,+BAOtC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { Toaster as Sonner } from "sonner";
2
2
  type ToasterProps = React.ComponentProps<typeof Sonner>;
3
- declare const Toaster: ({ ...props }: ToasterProps) => import("react/jsx-runtime").JSX.Element;
3
+ declare const Toaster: ({ ...props }: ToasterProps) => import("react").JSX.Element;
4
4
  export { Toaster };
5
5
  //# sourceMappingURL=sonner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sonner.d.ts","sourceRoot":"","sources":["../../../src/components/ui/sonner.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE1C,KAAK,YAAY,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAA;AAEvD,QAAA,MAAM,OAAO,GAAI,cAAc,YAAY,4CAqB1C,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,CAAA"}
1
+ {"version":3,"file":"sonner.d.ts","sourceRoot":"","sources":["../../../src/components/ui/sonner.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE1C,KAAK,YAAY,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAA;AAEvD,QAAA,MAAM,OAAO,GAAI,cAAc,YAAY,gCAqB1C,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,CAAA"}
@@ -86,7 +86,7 @@ declare const TreeNode: ({ item, handleSelectChange, expandedItemIds, selectedIt
86
86
  draggedItem: TreeDataItem | null;
87
87
  renderItem?: (params: TreeRenderItemParams) => React.ReactNode;
88
88
  level?: number;
89
- }) => import("react/jsx-runtime").JSX.Element;
89
+ }) => React.JSX.Element;
90
90
  declare const TreeLeaf: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
91
91
  item: TreeDataItem;
92
92
  level: number;
@@ -1 +1 @@
1
- {"version":3,"file":"tree-view.d.ts","sourceRoot":"","sources":["../../../src/components/ui/tree-view.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tree-view.d.ts","sourceRoot":"","sources":["../../../src/components/ui/tree-view.tsx"],"names":[],"mappings":"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"}
@@ -19,5 +19,5 @@ export type UserTypeBadgeProps = {
19
19
  * // Using custom hex color
20
20
  * <UserTypeBadge label="VIP" color="#FFD700" />
21
21
  */
22
- export declare function UserTypeBadge({ label, color, className }: UserTypeBadgeProps): import("react/jsx-runtime").JSX.Element;
22
+ export declare function UserTypeBadge({ label, color, className }: UserTypeBadgeProps): import("react").JSX.Element;
23
23
  //# sourceMappingURL=user-type-badge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-type-badge.d.ts","sourceRoot":"","sources":["../../../src/components/ui/user-type-badge.tsx"],"names":[],"mappings":"AAiBA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAoBF;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,kBAAkB,2CAmC5E"}
1
+ {"version":3,"file":"user-type-badge.d.ts","sourceRoot":"","sources":["../../../src/components/ui/user-type-badge.tsx"],"names":[],"mappings":"AAiBA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAoBF;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,kBAAkB,+BAmC5E"}
@@ -6,6 +6,6 @@ interface CookieConsentBannerProps {
6
6
  /** Default: "bottom" */
7
7
  position?: "bottom" | "top";
8
8
  }
9
- export declare function CookieConsentBanner({ enableGTM, gtmContainerId, onChange, position, }: CookieConsentBannerProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function CookieConsentBanner({ enableGTM, gtmContainerId, onChange, position, }: CookieConsentBannerProps): import("react").JSX.Element;
10
10
  export {};
11
11
  //# sourceMappingURL=cookie_consent_banner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cookie_consent_banner.d.ts","sourceRoot":"","sources":["../../src/consent/cookie_consent_banner.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAKpD,UAAU,wBAAwB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACzC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,cAAc,EACd,QAAQ,EACR,QAAmB,GACpB,EAAE,wBAAwB,2CA4E1B"}
1
+ {"version":3,"file":"cookie_consent_banner.d.ts","sourceRoot":"","sources":["../../src/consent/cookie_consent_banner.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAKpD,UAAU,wBAAwB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACzC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,cAAc,EACd,QAAQ,EACR,QAAmB,GACpB,EAAE,wBAAwB,+BA4E1B"}
@@ -1,2 +1,2 @@
1
- export declare function ConsentManageModal(): import("react/jsx-runtime").JSX.Element;
1
+ export declare function ConsentManageModal(): import("react").JSX.Element;
2
2
  //# sourceMappingURL=manage_modal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manage_modal.d.ts","sourceRoot":"","sources":["../../src/consent/manage_modal.tsx"],"names":[],"mappings":"AAOA,wBAAgB,kBAAkB,4CA0GjC"}
1
+ {"version":3,"file":"manage_modal.d.ts","sourceRoot":"","sources":["../../src/consent/manage_modal.tsx"],"names":[],"mappings":"AAOA,wBAAgB,kBAAkB,gCA0GjC"}
@@ -1,4 +1,4 @@
1
- import { type ReactNode } from "react";
1
+ import React, { type ReactNode } from "react";
2
2
  import { type HazoAuthConfig } from "./hazo_auth_config.js";
3
3
  /**
4
4
  * Props for HazoAuthProvider component
@@ -48,7 +48,7 @@ export type HazoAuthProviderProps = {
48
48
  * }
49
49
  * ```
50
50
  */
51
- export declare function HazoAuthProvider({ apiBasePath, children }: HazoAuthProviderProps): import("react/jsx-runtime").JSX.Element;
51
+ export declare function HazoAuthProvider({ apiBasePath, children }: HazoAuthProviderProps): React.JSX.Element;
52
52
  /**
53
53
  * Hook to access hazo_auth runtime configuration
54
54
  *
@@ -1 +1 @@
1
- {"version":3,"file":"hazo_auth_provider.d.ts","sourceRoot":"","sources":["../../src/contexts/hazo_auth_provider.tsx"],"names":[],"mappings":"AAMA,OAAc,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClF,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAYnF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,WAAkD,EAClD,QAAQ,EACT,EAAE,qBAAqB,2CAcvB;AAID;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAMlD"}
1
+ {"version":3,"file":"hazo_auth_provider.d.ts","sourceRoot":"","sources":["../../src/contexts/hazo_auth_provider.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClF,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAYnF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,WAAkD,EAClD,QAAQ,EACT,EAAE,qBAAqB,qBAcvB;AAID;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAMlD"}
@@ -0,0 +1,18 @@
1
+ import 'server-only';
2
+ export interface DenyPermissionInput {
3
+ request: Request;
4
+ /** HazoAuthResult | TenantAuthResult | any auth-like shape */
5
+ auth: any;
6
+ missing_permissions: string[];
7
+ /** Defaults to missing_permissions */
8
+ required_permissions?: string[];
9
+ permission_descriptions?: Record<string, string>;
10
+ /** Falls back to X-Hazo-Action-Label header, then permission join */
11
+ action_label?: string;
12
+ /** Falls back to default message */
13
+ user_friendly_message?: string;
14
+ /** Falls back to new URL(request.url).pathname */
15
+ api_route?: string;
16
+ }
17
+ export declare function denyPermission(input: DenyPermissionInput): Response;
18
+ //# sourceMappingURL=deny_permission.server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deny_permission.server.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/deny_permission.server.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,CAAC;AASrB,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,8DAA8D;IAC9D,IAAI,EAAE,GAAG,CAAC;IACV,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,sCAAsC;IACtC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAqBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,QAAQ,CAuDnE"}
@@ -0,0 +1,66 @@
1
+ // file_description: standalone helper to return a 403 FORBIDDEN response and fire the permission-denied handler
2
+ import 'server-only';
3
+ import { buildDenialPayloadFromRequest, getPermissionDeniedHandler, } from './with_permission_issue_capture.server.js';
4
+ function extractUserId(auth) {
5
+ var _a, _b;
6
+ return (((_a = auth === null || auth === void 0 ? void 0 : auth.user) === null || _a === void 0 ? void 0 : _a.id) ||
7
+ ((_b = auth === null || auth === void 0 ? void 0 : auth.tenant) === null || _b === void 0 ? void 0 : _b.user_id) ||
8
+ (auth === null || auth === void 0 ? void 0 : auth.user_id) ||
9
+ '');
10
+ }
11
+ function extractScopeId(auth) {
12
+ var _a, _b, _c, _d, _e, _f;
13
+ return ((_f = (_e = (_c = (_b = (_a = auth === null || auth === void 0 ? void 0 : auth.tenant) === null || _a === void 0 ? void 0 : _a.scope_id) !== null && _b !== void 0 ? _b : auth === null || auth === void 0 ? void 0 : auth.scope_id) !== null && _c !== void 0 ? _c : (_d = auth === null || auth === void 0 ? void 0 : auth.organization) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : auth === null || auth === void 0 ? void 0 : auth.organization_id) !== null && _f !== void 0 ? _f : undefined);
14
+ }
15
+ export function denyPermission(input) {
16
+ var _a;
17
+ const user_id = extractUserId(input.auth);
18
+ const scope_id = extractScopeId(input.auth);
19
+ const payload = buildDenialPayloadFromRequest(input.request, {
20
+ user_id,
21
+ scope_id,
22
+ missing_permissions: input.missing_permissions,
23
+ required_permissions: input.required_permissions,
24
+ permission_descriptions: input.permission_descriptions,
25
+ action_label: input.action_label,
26
+ user_friendly_message: input.user_friendly_message,
27
+ api_route: input.api_route,
28
+ });
29
+ // Fire handler best-effort — do not await, must not delay the 403
30
+ Promise.resolve((_a = getPermissionDeniedHandler()) === null || _a === void 0 ? void 0 : _a(payload)).catch((e) => {
31
+ console.warn('[hazo_auth] denyPermission: permission denied handler failed', e);
32
+ });
33
+ // buildForbiddenResponse is async (dynamic import of hazo_api), but denyPermission must be
34
+ // synchronous to match the function signature. We build the fallback synchronously here
35
+ // and fire the async hazo_api path only when available. In practice, the caller immediately
36
+ // returns the Response so we use the sync fallback — consumers that need the hazo_api
37
+ // envelope can await a wrapping async function or use withPermissionIssueCapture instead.
38
+ const bodyJson = JSON.stringify({
39
+ ok: false,
40
+ error: {
41
+ code: 'FORBIDDEN',
42
+ message: payload.user_friendly_message,
43
+ details: {
44
+ missing_permissions: payload.missing_permissions,
45
+ permission_descriptions: payload.permission_descriptions,
46
+ action_label: payload.action_label,
47
+ origin_url: payload.origin_url,
48
+ user_friendly_message: payload.user_friendly_message,
49
+ },
50
+ },
51
+ });
52
+ // Kick off async hazo_api enhancement but return the sync response immediately.
53
+ // The returned Response object is the sync fallback; hazo_api is decorative for
54
+ // middleware use cases that don't need the exact envelope.
55
+ void import('hazo_api')
56
+ .then((m) => {
57
+ if (typeof (m === null || m === void 0 ? void 0 : m.fail) === 'function') {
58
+ // No-op: we already returned — this is a fire-and-forget; nothing to do with the result.
59
+ }
60
+ })
61
+ .catch(() => undefined);
62
+ return new Response(bodyJson, {
63
+ status: 403,
64
+ headers: { 'Content-Type': 'application/json' },
65
+ });
66
+ }
@@ -12,4 +12,6 @@ export { withAuth, withOptionalAuth, hasPermission, hasAllPermissions, hasAnyPer
12
12
  export type { AuthenticatedTenantAuth, AuthenticatedTenantAuthWithOrg, WithAuthOptions, } from "./with_auth.server";
13
13
  export { get_auth_cache, reset_auth_cache } from "./auth_cache.js";
14
14
  export { get_rate_limiter, reset_rate_limiter } from "./auth_rate_limiter.js";
15
+ export { withPermissionIssueCapture, setPermissionDeniedHandler, getPermissionDeniedHandler, } from "./with_permission_issue_capture.server.js";
16
+ export type { PermissionDeniedPayload } from "./with_permission_issue_capture.server";
15
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/index.ts"],"names":[],"mappings":"AAEA,cAAc,cAAc,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,aAAa,EACb,2BAA2B,EAC3B,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/index.ts"],"names":[],"mappings":"AAEA,cAAc,cAAc,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,aAAa,EACb,2BAA2B,EAC3B,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAG3E,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,wCAAwC,CAAC;AAChD,YAAY,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC"}
@@ -17,3 +17,5 @@ export { withAuth, withOptionalAuth, hasPermission, hasAllPermissions, hasAnyPer
17
17
  export { get_auth_cache, reset_auth_cache } from "./auth_cache.js";
18
18
  // section: rate_limiter_exports
19
19
  export { get_rate_limiter, reset_rate_limiter } from "./auth_rate_limiter.js";
20
+ // section: permission_issue_capture_exports
21
+ export { withPermissionIssueCapture, setPermissionDeniedHandler, getPermissionDeniedHandler, } from "./with_permission_issue_capture.server.js";
@@ -0,0 +1,49 @@
1
+ import 'server-only';
2
+ import { type NextRequest } from 'next/server';
3
+ export interface PermissionDeniedPayload {
4
+ user_id: string;
5
+ scope_id?: string;
6
+ missing_permissions: string[];
7
+ required_permissions: string[];
8
+ user_permissions: string[];
9
+ permission_descriptions: Record<string, string>;
10
+ user_friendly_message: string;
11
+ action_label: string;
12
+ origin_url: string;
13
+ api_route: string;
14
+ }
15
+ export declare function setPermissionDeniedHandler(fn: (payload: PermissionDeniedPayload) => void | Promise<void>): void;
16
+ export declare function getPermissionDeniedHandler(): ((payload: PermissionDeniedPayload) => void | Promise<void>) | null;
17
+ export interface BuildDenialPayloadParts {
18
+ user_id: string;
19
+ scope_id?: string;
20
+ missing_permissions: string[];
21
+ required_permissions?: string[];
22
+ permission_descriptions?: Record<string, string>;
23
+ action_label?: string;
24
+ user_friendly_message?: string;
25
+ api_route?: string;
26
+ user_permissions?: string[];
27
+ }
28
+ /**
29
+ * Shared helper: builds a PermissionDeniedPayload from a request + explicit parts.
30
+ * Called by both withPermissionIssueCapture and denyPermission.
31
+ */
32
+ export declare function buildDenialPayloadFromRequest(request: Request, parts: BuildDenialPayloadParts): PermissionDeniedPayload;
33
+ /** Builds the 403 Response, using hazo_api.fail() if available, otherwise hand-built. */
34
+ export declare function buildForbiddenResponse(payload: PermissionDeniedPayload): Promise<Response>;
35
+ /**
36
+ * Wraps a Next.js route handler. On PermissionError, returns a structured
37
+ * hazo_api fail() 403 with code FORBIDDEN and fires the registered
38
+ * onPermissionDenied callback best-effort.
39
+ *
40
+ * Usage:
41
+ * export const POST = withPermissionIssueCapture(
42
+ * async (request) => { ... },
43
+ * { required_permissions: ['edit_config'] }
44
+ * );
45
+ */
46
+ export declare function withPermissionIssueCapture(handler: (request: NextRequest) => Promise<Response>, opts: {
47
+ required_permissions: string[];
48
+ }): (request: NextRequest) => Promise<Response>;
49
+ //# sourceMappingURL=with_permission_issue_capture.server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_permission_issue_capture.server.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/with_permission_issue_capture.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAS/C,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,qBAAqB,EAAE,MAAM,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAUD,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC7D,IAAI,CAEN;AAED,wBAAgB,0BAA0B,eARN,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,SAUnF;AAID,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,uBAAuB,GAC7B,uBAAuB,CAoCzB;AAID,yFAAyF;AACzF,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAsChG;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,EACpD,IAAI,EAAE;IAAE,oBAAoB,EAAE,MAAM,EAAE,CAAA;CAAE,GACvC,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CA0D7C"}
@@ -0,0 +1,152 @@
1
+ // file_description: Route handler wrapper that catches PermissionError and returns a structured hazo_api fail() 403
2
+ // section: server-only-guard
3
+ import 'server-only';
4
+ import { createLogger } from 'hazo_core';
5
+ import { PermissionError } from './auth_types.js';
6
+ import { hazo_get_auth } from './hazo_get_auth.server.js';
7
+ const log = createLogger('hazo_auth:permission_capture');
8
+ // section: global_callback
9
+ /**
10
+ * Global callback, set once at app boot by the consuming app.
11
+ * DI: hazo_auth does NOT import hazo_admin; the app passes createOrBumpIssue here.
12
+ */
13
+ let _onPermissionDenied = null;
14
+ export function setPermissionDeniedHandler(fn) {
15
+ _onPermissionDenied = fn;
16
+ }
17
+ export function getPermissionDeniedHandler() {
18
+ return _onPermissionDenied;
19
+ }
20
+ /**
21
+ * Shared helper: builds a PermissionDeniedPayload from a request + explicit parts.
22
+ * Called by both withPermissionIssueCapture and denyPermission.
23
+ */
24
+ export function buildDenialPayloadFromRequest(request, parts) {
25
+ var _a, _b, _c, _d, _e;
26
+ const originUrl = request.headers.get('x-hazo-origin-url') ||
27
+ request.headers.get('referer') ||
28
+ '';
29
+ const actionLabelFromHeader = request.headers.get('x-hazo-action-label') || '';
30
+ const descriptions = (_a = parts.permission_descriptions) !== null && _a !== void 0 ? _a : {};
31
+ const actionLabel = parts.action_label ||
32
+ actionLabelFromHeader ||
33
+ parts.missing_permissions.map((p) => descriptions[p] || p).join(', ');
34
+ let apiRoute = (_b = parts.api_route) !== null && _b !== void 0 ? _b : '';
35
+ if (!apiRoute) {
36
+ try {
37
+ apiRoute = new URL(request.url).pathname;
38
+ }
39
+ catch (_f) {
40
+ /* ignore */
41
+ }
42
+ }
43
+ return {
44
+ user_id: parts.user_id,
45
+ scope_id: parts.scope_id,
46
+ missing_permissions: parts.missing_permissions,
47
+ required_permissions: (_c = parts.required_permissions) !== null && _c !== void 0 ? _c : parts.missing_permissions,
48
+ user_permissions: (_d = parts.user_permissions) !== null && _d !== void 0 ? _d : [],
49
+ permission_descriptions: descriptions,
50
+ user_friendly_message: (_e = parts.user_friendly_message) !== null && _e !== void 0 ? _e : "You don't have permission to perform this action.",
51
+ action_label: actionLabel,
52
+ origin_url: originUrl,
53
+ api_route: apiRoute,
54
+ };
55
+ }
56
+ // section: response_helper
57
+ /** Builds the 403 Response, using hazo_api.fail() if available, otherwise hand-built. */
58
+ export async function buildForbiddenResponse(payload) {
59
+ const apiMod = (await import('hazo_api').catch(() => null));
60
+ if (apiMod === null || apiMod === void 0 ? void 0 : apiMod.fail) {
61
+ return apiMod.fail('FORBIDDEN', payload.user_friendly_message, {
62
+ status: 403,
63
+ details: {
64
+ missing_permissions: payload.missing_permissions,
65
+ user_friendly_message: payload.user_friendly_message,
66
+ permission_descriptions: payload.permission_descriptions,
67
+ action_label: payload.action_label,
68
+ origin_url: payload.origin_url,
69
+ },
70
+ });
71
+ }
72
+ return new Response(JSON.stringify({
73
+ ok: false,
74
+ error: {
75
+ code: 'FORBIDDEN',
76
+ message: payload.user_friendly_message,
77
+ details: {
78
+ missing_permissions: payload.missing_permissions,
79
+ permission_descriptions: payload.permission_descriptions,
80
+ action_label: payload.action_label,
81
+ origin_url: payload.origin_url,
82
+ },
83
+ },
84
+ }), { status: 403, headers: { 'Content-Type': 'application/json' } });
85
+ }
86
+ // section: wrapper
87
+ /**
88
+ * Wraps a Next.js route handler. On PermissionError, returns a structured
89
+ * hazo_api fail() 403 with code FORBIDDEN and fires the registered
90
+ * onPermissionDenied callback best-effort.
91
+ *
92
+ * Usage:
93
+ * export const POST = withPermissionIssueCapture(
94
+ * async (request) => { ... },
95
+ * { required_permissions: ['edit_config'] }
96
+ * );
97
+ */
98
+ export function withPermissionIssueCapture(handler, opts) {
99
+ return async (request) => {
100
+ try {
101
+ // Run hazo_get_auth with strict=true so PermissionError is thrown on denial
102
+ await hazo_get_auth(request, {
103
+ required_permissions: opts.required_permissions,
104
+ strict: true,
105
+ });
106
+ // On success, hand off to the original handler
107
+ return await handler(request);
108
+ }
109
+ catch (err) {
110
+ if (err instanceof PermissionError) {
111
+ // Convert PermissionError.permission_descriptions Map → plain object
112
+ const descriptions = {};
113
+ if (err.permission_descriptions) {
114
+ err.permission_descriptions.forEach((v, k) => {
115
+ descriptions[k] = v;
116
+ });
117
+ }
118
+ // Try to extract user_id from session — best-effort, non-strict re-call
119
+ let userId = '';
120
+ try {
121
+ const lax = await hazo_get_auth(request, {
122
+ required_permissions: [],
123
+ strict: false,
124
+ });
125
+ if (lax.authenticated) {
126
+ userId = lax.user.id;
127
+ }
128
+ }
129
+ catch (_a) {
130
+ /* ignore — user_id stays '' */
131
+ }
132
+ const payload = buildDenialPayloadFromRequest(request, {
133
+ user_id: userId,
134
+ missing_permissions: err.missing_permissions,
135
+ required_permissions: err.required_permissions,
136
+ user_permissions: err.user_permissions,
137
+ permission_descriptions: descriptions,
138
+ user_friendly_message: err.user_friendly_message,
139
+ });
140
+ // Fire callback best-effort (do NOT await — must not delay the 403 response)
141
+ if (_onPermissionDenied) {
142
+ Promise.resolve(_onPermissionDenied(payload)).catch((cbErr) => {
143
+ log.warn('onPermissionDenied callback failed', { error: cbErr });
144
+ });
145
+ }
146
+ return buildForbiddenResponse(payload);
147
+ }
148
+ // Re-throw non-permission errors
149
+ throw err;
150
+ }
151
+ };
152
+ }