@jmruthers/pace-core 0.6.5 → 0.6.7

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 (473) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +5 -403
  3. package/audit-tool/00-dependencies.cjs +394 -0
  4. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  5. package/audit-tool/audits/02-project-structure.cjs +255 -0
  6. package/audit-tool/audits/03-architecture.cjs +196 -0
  7. package/audit-tool/audits/04-code-quality.cjs +149 -0
  8. package/audit-tool/audits/05-styling.cjs +224 -0
  9. package/audit-tool/audits/06-security-rbac.cjs +544 -0
  10. package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
  11. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  12. package/audit-tool/audits/09-operations.cjs +208 -0
  13. package/audit-tool/index.cjs +291 -0
  14. package/audit-tool/utils/code-utils.cjs +218 -0
  15. package/audit-tool/utils/file-utils.cjs +230 -0
  16. package/audit-tool/utils/report-utils.cjs +241 -0
  17. package/core-usage-manifest.json +93 -0
  18. package/cursor-rules/00-standards-overview.mdc +156 -0
  19. package/cursor-rules/01-pace-core-compliance.mdc +586 -0
  20. package/cursor-rules/02-project-structure.mdc +42 -4
  21. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +126 -10
  22. package/cursor-rules/04-code-quality.mdc +419 -0
  23. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +104 -34
  24. package/cursor-rules/06-security-rbac.mdc +518 -0
  25. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  26. package/cursor-rules/08-testing-documentation.mdc +324 -0
  27. package/cursor-rules/09-operations.mdc +365 -0
  28. package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
  29. package/dist/DataTable-7PMH7XN7.js +15 -0
  30. package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  31. package/dist/{PublicPageProvider-QTFVrL-Z.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +33 -72
  32. package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
  33. package/dist/api-Y4MQWOFW.js +4 -0
  34. package/dist/audit-MYQXYZFU.js +3 -0
  35. package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
  36. package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
  37. package/dist/{chunk-UPPMRMYG.js → chunk-5X4QLXRG.js} +73 -151
  38. package/dist/chunk-6F3IILHI.js +62 -0
  39. package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
  40. package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
  41. package/dist/{chunk-FMUCXFII.js → chunk-7ILTDCL2.js} +9 -5
  42. package/dist/{chunk-M43Y4SSO.js → chunk-A3W6LW53.js} +15 -13
  43. package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
  44. package/dist/{chunk-HU2C6SSC.js → chunk-BM4CQ5P3.js} +606 -559
  45. package/dist/chunk-C7NSAPTL.js +1 -0
  46. package/dist/{chunk-J36DSWQK.js → chunk-FEJLJNWA.js} +7 -41
  47. package/dist/{chunk-IHB5DR3H.js → chunk-FTCRZOG2.js} +188 -387
  48. package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
  49. package/dist/chunk-GHYHJTYV.js +994 -0
  50. package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
  51. package/dist/{chunk-FFQEQTNW.js → chunk-IUBRCBSY.js} +134 -45
  52. package/dist/{chunk-6COVEUS7.js → chunk-JGWDVX64.js} +983 -1034
  53. package/dist/{chunk-RGAWHO7N.js → chunk-L4XMVJKY.js} +77 -222
  54. package/dist/chunk-MBADTM7L.js +64 -0
  55. package/dist/{chunk-M7MPQISP.js → chunk-OJ4SKRSV.js} +3 -16
  56. package/dist/{chunk-IVOFDYWT.js → chunk-Q7Q7V5NV.js} +2109 -1604
  57. package/dist/{chunk-JGRYX5UX.js → chunk-S7DKJPLT.js} +29 -58
  58. package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
  59. package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
  60. package/dist/{chunk-NTM7ZSB6.js → chunk-VBCS3DUA.js} +261 -168
  61. package/dist/{chunk-EFN2EIMK.js → chunk-ZFYPMX46.js} +271 -87
  62. package/dist/{chunk-L4OXEN46.js → chunk-ZKAWKYT4.js} +10 -24
  63. package/dist/components.d.ts +7 -5
  64. package/dist/components.js +46 -257
  65. package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
  66. package/dist/eslint-rules/index.cjs +35 -0
  67. package/{src/eslint-rules/pace-core-compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +234 -235
  68. package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
  69. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  70. package/dist/eslint-rules/rules/06-security-rbac.cjs +806 -0
  71. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
  72. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  73. package/dist/eslint-rules/utils/helpers.cjs +42 -0
  74. package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
  75. package/dist/hooks.d.ts +6 -6
  76. package/dist/hooks.js +62 -172
  77. package/dist/icons/index.d.ts +1 -0
  78. package/dist/icons/index.js +1 -0
  79. package/dist/index.d.ts +12 -11
  80. package/dist/index.js +67 -660
  81. package/dist/providers.d.ts +2 -2
  82. package/dist/providers.js +8 -35
  83. package/dist/rbac/eslint-rules.d.ts +46 -44
  84. package/dist/rbac/eslint-rules.js +7 -4
  85. package/dist/rbac/index.d.ts +109 -586
  86. package/dist/rbac/index.js +14 -207
  87. package/dist/styles/index.js +2 -12
  88. package/dist/theming/runtime.d.ts +14 -1
  89. package/dist/theming/runtime.js +3 -19
  90. package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
  91. package/dist/{types-CkbwOr4Y.d.ts → types-DXstZpNI.d.ts} +4 -17
  92. package/dist/types-t9H8qKRw.d.ts +55 -0
  93. package/dist/types.d.ts +1 -1
  94. package/dist/types.js +7 -94
  95. package/dist/{usePublicRouteParams-ClnV4tnv.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +20 -20
  96. package/dist/utils.d.ts +24 -117
  97. package/dist/utils.js +54 -392
  98. package/docs/README.md +17 -7
  99. package/docs/api/README.md +4 -402
  100. package/docs/api/modules.md +301 -871
  101. package/docs/api-reference/components.md +21 -21
  102. package/docs/api-reference/deprecated.md +31 -6
  103. package/docs/api-reference/hooks.md +80 -80
  104. package/docs/api-reference/rpc-functions.md +78 -3
  105. package/docs/api-reference/types.md +1 -1
  106. package/docs/api-reference/utilities.md +1 -1
  107. package/docs/architecture/README.md +1 -1
  108. package/docs/core-concepts/events.md +3 -3
  109. package/docs/core-concepts/organisations.md +6 -6
  110. package/docs/core-concepts/permissions.md +6 -6
  111. package/docs/documentation-index.md +12 -18
  112. package/docs/getting-started/cursor-rules.md +3 -23
  113. package/docs/getting-started/dependencies.md +650 -0
  114. package/docs/getting-started/documentation-index.md +1 -1
  115. package/docs/getting-started/examples/README.md +4 -4
  116. package/docs/getting-started/examples/full-featured-app.md +1 -1
  117. package/docs/getting-started/faq.md +2 -2
  118. package/docs/getting-started/installation-guide.md +20 -7
  119. package/docs/getting-started/quick-reference.md +4 -4
  120. package/docs/getting-started/quick-start.md +23 -12
  121. package/docs/implementation-guides/authentication.md +15 -15
  122. package/docs/implementation-guides/component-styling.md +1 -1
  123. package/docs/implementation-guides/data-tables.md +126 -33
  124. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  125. package/docs/implementation-guides/dynamic-colors.md +3 -3
  126. package/docs/implementation-guides/file-upload-storage.md +2 -2
  127. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  128. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  129. package/docs/implementation-guides/large-datasets.md +3 -2
  130. package/docs/implementation-guides/organisation-security.md +2 -2
  131. package/docs/implementation-guides/performance.md +2 -2
  132. package/docs/implementation-guides/permission-enforcement.md +5 -1
  133. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  134. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  135. package/docs/rbac/MIGRATION_GUIDE.md +819 -0
  136. package/docs/rbac/RBAC_CONTRACT.md +724 -0
  137. package/docs/rbac/README.md +17 -8
  138. package/docs/rbac/advanced-patterns.md +6 -6
  139. package/docs/rbac/api-reference.md +20 -20
  140. package/docs/rbac/edge-functions-guide.md +376 -0
  141. package/docs/rbac/event-based-apps.md +3 -3
  142. package/docs/rbac/examples.md +41 -41
  143. package/docs/rbac/getting-started.md +37 -37
  144. package/docs/rbac/performance.md +1 -1
  145. package/docs/rbac/quick-start.md +52 -52
  146. package/docs/rbac/secure-client-protection.md +1 -35
  147. package/docs/rbac/troubleshooting.md +1 -1
  148. package/docs/security/README.md +5 -5
  149. package/docs/standards/0-standards-overview.md +220 -0
  150. package/docs/standards/1-pace-core-compliance-standards.md +986 -0
  151. package/docs/standards/2-project-structure-standards.md +949 -0
  152. package/docs/standards/3-architecture-standards.md +606 -0
  153. package/docs/standards/4-code-quality-standards.md +728 -0
  154. package/docs/standards/5-styling-standards.md +348 -0
  155. package/docs/standards/{07-rbac-and-rls-standard.md → 6-security-rbac-standards.md} +269 -66
  156. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  157. package/docs/standards/8-testing-documentation-standards.md +401 -0
  158. package/docs/standards/9-operations-standards.md +1102 -0
  159. package/docs/standards/README.md +185 -57
  160. package/docs/troubleshooting/README.md +4 -4
  161. package/docs/troubleshooting/common-issues.md +2 -2
  162. package/docs/troubleshooting/debugging.md +9 -9
  163. package/docs/troubleshooting/migration.md +4 -4
  164. package/docs/troubleshooting/organisation-context-setup.md +42 -19
  165. package/eslint-config-pace-core.cjs +33 -6
  166. package/package.json +35 -23
  167. package/scripts/install-cursor-rules.cjs +25 -6
  168. package/scripts/install-eslint-config.cjs +284 -0
  169. package/src/__tests__/fixtures/supabase.ts +1 -1
  170. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +3 -3
  171. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
  172. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
  173. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  174. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +13 -13
  175. package/src/__tests__/helpers/component-test-utils.tsx +1 -1
  176. package/src/__tests__/helpers/supabaseMock.ts +2 -2
  177. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  178. package/src/__tests__/public-recipe-view.test.ts +38 -9
  179. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  180. package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
  181. package/src/__tests__/templates/component.test.template.tsx +18 -15
  182. package/src/components/Button/Button.tsx +5 -1
  183. package/src/components/Calendar/Calendar.tsx +201 -47
  184. package/src/components/ContextSelector/ContextSelector.tsx +106 -119
  185. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  186. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
  187. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
  188. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  189. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  190. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  191. package/src/components/DataTable/components/DataTableCore.tsx +186 -13
  192. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  193. package/src/components/DataTable/components/DataTableLayout.tsx +35 -21
  194. package/src/components/DataTable/components/EditFields.tsx +23 -3
  195. package/src/components/DataTable/components/EditableRow.tsx +12 -9
  196. package/src/components/DataTable/components/EmptyState.tsx +10 -9
  197. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  198. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  199. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  200. package/src/components/DataTable/components/RowComponent.tsx +12 -0
  201. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  202. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  203. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  204. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  205. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  206. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  207. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
  208. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
  209. package/src/components/DataTable/components/index.ts +2 -1
  210. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
  211. package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
  212. package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
  213. package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
  214. package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
  215. package/src/components/DataTable/types.ts +5 -18
  216. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  217. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
  218. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  219. package/src/components/DateTimeField/DateTimeField.tsx +10 -9
  220. package/src/components/Dialog/Dialog.test.tsx +128 -104
  221. package/src/components/Dialog/Dialog.tsx +742 -24
  222. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  223. package/src/components/FileDisplay/FileDisplay.test.tsx +4 -2
  224. package/src/components/FileDisplay/FileDisplay.tsx +23 -17
  225. package/src/components/FileUpload/FileUpload.test.tsx +52 -14
  226. package/src/components/FileUpload/FileUpload.tsx +112 -130
  227. package/src/components/Form/Form.test.tsx +6 -8
  228. package/src/components/Form/Form.tsx +365 -4
  229. package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
  230. package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
  231. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
  232. package/src/components/PaceAppLayout/PaceAppLayout.tsx +11 -15
  233. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
  234. package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
  235. package/src/components/Progress/Progress.tsx +2 -4
  236. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  237. package/src/components/Select/Select.tsx +109 -98
  238. package/src/components/Select/types.ts +4 -1
  239. package/src/components/UserMenu/UserMenu.tsx +9 -6
  240. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  241. package/src/hooks/__tests__/hooks.integration.test.tsx +55 -57
  242. package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
  243. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
  244. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
  245. package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
  246. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
  247. package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
  248. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
  249. package/src/hooks/public/usePublicEvent.ts +67 -195
  250. package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
  251. package/src/hooks/public/usePublicEventLogo.ts +24 -14
  252. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  253. package/src/hooks/public/usePublicRouteParams.ts +5 -5
  254. package/src/hooks/useAppConfig.ts +28 -26
  255. package/src/hooks/useEventTheme.test.ts +217 -239
  256. package/src/hooks/useEventTheme.ts +16 -28
  257. package/src/hooks/useFileDisplay.ts +2 -2
  258. package/src/hooks/useOrganisationPermissions.ts +5 -7
  259. package/src/hooks/useQueryCache.ts +0 -1
  260. package/src/hooks/useSessionDraft.ts +380 -0
  261. package/src/hooks/useSessionRestoration.ts +3 -1
  262. package/src/icons/index.ts +27 -0
  263. package/src/index.ts +5 -0
  264. package/src/providers/OrganisationProvider.tsx +23 -14
  265. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  266. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  267. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  268. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  269. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  270. package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
  271. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  272. package/src/providers/services/EventServiceProvider.tsx +1 -24
  273. package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
  274. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  275. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +13 -10
  276. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
  277. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
  278. package/src/rbac/adapters.tsx +7 -295
  279. package/src/rbac/api.test.ts +44 -56
  280. package/src/rbac/api.ts +10 -17
  281. package/src/rbac/cache-invalidation.ts +0 -1
  282. package/src/rbac/compliance/index.ts +10 -0
  283. package/src/rbac/compliance/pattern-detector.ts +553 -0
  284. package/src/rbac/compliance/runtime-compliance.ts +22 -0
  285. package/src/rbac/components/AccessDenied.tsx +150 -0
  286. package/src/rbac/components/NavigationGuard.tsx +12 -20
  287. package/src/rbac/components/PagePermissionGuard.tsx +4 -24
  288. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
  289. package/src/rbac/components/index.ts +3 -41
  290. package/src/rbac/eslint-rules.js +1 -1
  291. package/src/rbac/hooks/index.ts +0 -3
  292. package/src/rbac/hooks/permissions/index.ts +0 -3
  293. package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
  294. package/src/rbac/hooks/usePermissions.ts +0 -3
  295. package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
  296. package/src/rbac/hooks/useResolvedScope.ts +58 -140
  297. package/src/rbac/hooks/useResourcePermissions.test.ts +124 -38
  298. package/src/rbac/hooks/useResourcePermissions.ts +139 -48
  299. package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
  300. package/src/rbac/hooks/useRoleManagement.ts +147 -19
  301. package/src/rbac/hooks/useSecureSupabase.ts +4 -8
  302. package/src/rbac/index.ts +7 -9
  303. package/src/rbac/utils/contextValidator.ts +9 -7
  304. package/src/services/AuthService.ts +130 -18
  305. package/src/services/EventService.ts +4 -97
  306. package/src/services/InactivityService.ts +16 -0
  307. package/src/services/OrganisationService.ts +7 -44
  308. package/src/services/__tests__/OrganisationService.test.ts +26 -8
  309. package/src/services/base/BaseService.ts +0 -3
  310. package/src/styles/core.css +7 -0
  311. package/src/theming/__tests__/parseEventColours.test.ts +9 -3
  312. package/src/theming/parseEventColours.ts +22 -10
  313. package/src/types/database.generated.ts +4733 -3809
  314. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  315. package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
  316. package/src/utils/context/organisationContext.test.ts +13 -28
  317. package/src/utils/context/organisationContext.ts +21 -52
  318. package/src/utils/dynamic/dynamicUtils.ts +1 -1
  319. package/src/utils/file-reference/index.ts +39 -15
  320. package/src/utils/formatting/formatDateTime.test.ts +3 -2
  321. package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
  322. package/src/utils/index.ts +4 -1
  323. package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
  324. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
  325. package/src/utils/persistence/keyDerivation.ts +304 -0
  326. package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
  327. package/src/utils/security/secureStorage.ts +5 -5
  328. package/src/utils/storage/README.md +1 -1
  329. package/src/utils/storage/helpers.ts +3 -3
  330. package/src/utils/supabase/createBaseClient.ts +147 -0
  331. package/src/utils/timezone/timezone.test.ts +1 -2
  332. package/src/utils/timezone/timezone.ts +1 -1
  333. package/src/utils/validation/csrf.ts +4 -4
  334. package/cursor-rules/00-pace-core-compliance.mdc +0 -331
  335. package/cursor-rules/01-standards-compliance.mdc +0 -244
  336. package/cursor-rules/04-testing-standards.mdc +0 -268
  337. package/cursor-rules/05-bug-reports-and-features.mdc +0 -246
  338. package/cursor-rules/06-code-quality.mdc +0 -309
  339. package/cursor-rules/07-tech-stack-compliance.mdc +0 -214
  340. package/cursor-rules/CHANGELOG.md +0 -119
  341. package/cursor-rules/README.md +0 -192
  342. package/dist/DataTable-AOVNCPTX.js +0 -175
  343. package/dist/DataTable-AOVNCPTX.js.map +0 -1
  344. package/dist/UnifiedAuthProvider-4SBX4LU5.js +0 -18
  345. package/dist/UnifiedAuthProvider-4SBX4LU5.js.map +0 -1
  346. package/dist/api-O6HTBX5Y.js +0 -52
  347. package/dist/api-O6HTBX5Y.js.map +0 -1
  348. package/dist/audit-V53FV5AG.js +0 -17
  349. package/dist/audit-V53FV5AG.js.map +0 -1
  350. package/dist/chunk-5DRSZLL2.js.map +0 -1
  351. package/dist/chunk-63FOKYGO.js.map +0 -1
  352. package/dist/chunk-6COVEUS7.js.map +0 -1
  353. package/dist/chunk-AFVQODI2.js +0 -263
  354. package/dist/chunk-AFVQODI2.js.map +0 -1
  355. package/dist/chunk-DGUM43GV.js.map +0 -1
  356. package/dist/chunk-E66EQZE6.js.map +0 -1
  357. package/dist/chunk-EFN2EIMK.js.map +0 -1
  358. package/dist/chunk-FFQEQTNW.js.map +0 -1
  359. package/dist/chunk-FMUCXFII.js.map +0 -1
  360. package/dist/chunk-G37KK66H.js.map +0 -1
  361. package/dist/chunk-G7QEZTYQ.js +0 -2053
  362. package/dist/chunk-G7QEZTYQ.js.map +0 -1
  363. package/dist/chunk-HU2C6SSC.js.map +0 -1
  364. package/dist/chunk-IHB5DR3H.js.map +0 -1
  365. package/dist/chunk-IVOFDYWT.js.map +0 -1
  366. package/dist/chunk-J36DSWQK.js.map +0 -1
  367. package/dist/chunk-JGRYX5UX.js.map +0 -1
  368. package/dist/chunk-KQCRWDSA.js +0 -1
  369. package/dist/chunk-KQCRWDSA.js.map +0 -1
  370. package/dist/chunk-L4OXEN46.js.map +0 -1
  371. package/dist/chunk-LMC26NLJ.js +0 -84
  372. package/dist/chunk-LMC26NLJ.js.map +0 -1
  373. package/dist/chunk-M43Y4SSO.js.map +0 -1
  374. package/dist/chunk-M7MPQISP.js.map +0 -1
  375. package/dist/chunk-NTM7ZSB6.js.map +0 -1
  376. package/dist/chunk-PWLANIRT.js.map +0 -1
  377. package/dist/chunk-QXHPKYJV.js.map +0 -1
  378. package/dist/chunk-RGAWHO7N.js.map +0 -1
  379. package/dist/chunk-UPPMRMYG.js.map +0 -1
  380. package/dist/chunk-VBXEHIUJ.js.map +0 -1
  381. package/dist/chunk-ZSAAAMVR.js.map +0 -1
  382. package/dist/components.js.map +0 -1
  383. package/dist/contextValidator-5OGXSPKS.js +0 -9
  384. package/dist/contextValidator-5OGXSPKS.js.map +0 -1
  385. package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
  386. package/dist/hooks.js.map +0 -1
  387. package/dist/index.js.map +0 -1
  388. package/dist/providers.js.map +0 -1
  389. package/dist/rbac/eslint-rules.js.map +0 -1
  390. package/dist/rbac/index.js.map +0 -1
  391. package/dist/styles/index.js.map +0 -1
  392. package/dist/theming/runtime.js.map +0 -1
  393. package/dist/types.js.map +0 -1
  394. package/dist/utils.js.map +0 -1
  395. package/docs/best-practices/README.md +0 -472
  396. package/docs/best-practices/accessibility.md +0 -601
  397. package/docs/best-practices/common-patterns.md +0 -516
  398. package/docs/best-practices/deployment.md +0 -1103
  399. package/docs/best-practices/performance.md +0 -1328
  400. package/docs/best-practices/security.md +0 -940
  401. package/docs/best-practices/testing.md +0 -1034
  402. package/docs/rbac/compliance/compliance-guide.md +0 -544
  403. package/docs/standards/01-architecture-standard.md +0 -44
  404. package/docs/standards/02-api-and-rpc-standard.md +0 -39
  405. package/docs/standards/03-component-standard.md +0 -32
  406. package/docs/standards/04-code-style-standard.md +0 -32
  407. package/docs/standards/05-security-standard.md +0 -44
  408. package/docs/standards/06-testing-and-docs-standard.md +0 -29
  409. package/docs/standards/pace-core-compliance.md +0 -432
  410. package/scripts/audit/core/checks/accessibility.cjs +0 -197
  411. package/scripts/audit/core/checks/api-usage.cjs +0 -191
  412. package/scripts/audit/core/checks/bundle.cjs +0 -142
  413. package/scripts/audit/core/checks/compliance.cjs +0 -2706
  414. package/scripts/audit/core/checks/config.cjs +0 -54
  415. package/scripts/audit/core/checks/coverage.cjs +0 -84
  416. package/scripts/audit/core/checks/dependencies.cjs +0 -994
  417. package/scripts/audit/core/checks/documentation.cjs +0 -268
  418. package/scripts/audit/core/checks/environment.cjs +0 -116
  419. package/scripts/audit/core/checks/error-handling.cjs +0 -340
  420. package/scripts/audit/core/checks/forms.cjs +0 -172
  421. package/scripts/audit/core/checks/heuristics.cjs +0 -68
  422. package/scripts/audit/core/checks/hooks.cjs +0 -334
  423. package/scripts/audit/core/checks/imports.cjs +0 -244
  424. package/scripts/audit/core/checks/performance.cjs +0 -325
  425. package/scripts/audit/core/checks/routes.cjs +0 -117
  426. package/scripts/audit/core/checks/state.cjs +0 -130
  427. package/scripts/audit/core/checks/structure.cjs +0 -65
  428. package/scripts/audit/core/checks/style.cjs +0 -584
  429. package/scripts/audit/core/checks/testing.cjs +0 -122
  430. package/scripts/audit/core/checks/typescript.cjs +0 -61
  431. package/scripts/audit/core/scanner.cjs +0 -199
  432. package/scripts/audit/core/utils.cjs +0 -137
  433. package/scripts/audit/index.cjs +0 -223
  434. package/scripts/audit/reporters/console.cjs +0 -151
  435. package/scripts/audit/reporters/json.cjs +0 -54
  436. package/scripts/audit/reporters/markdown.cjs +0 -124
  437. package/scripts/audit-consuming-app.cjs +0 -86
  438. package/src/components/DataTable/components/DataTableBody.tsx +0 -454
  439. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  440. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  441. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  442. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  443. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  444. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  445. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  446. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  447. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  448. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  449. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  450. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  451. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  452. package/src/components/DataTable/utils/debugTools.ts +0 -514
  453. package/src/eslint-rules/pace-core-compliance.js +0 -638
  454. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
  455. package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
  456. package/src/rbac/components/NavigationProvider.test.tsx +0 -481
  457. package/src/rbac/components/NavigationProvider.tsx +0 -345
  458. package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
  459. package/src/rbac/components/PagePermissionProvider.tsx +0 -279
  460. package/src/rbac/components/PermissionEnforcer.tsx +0 -312
  461. package/src/rbac/components/RoleBasedRouter.tsx +0 -440
  462. package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
  463. package/src/rbac/components/SecureDataProvider.tsx +0 -339
  464. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
  465. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
  466. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
  467. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
  468. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
  469. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
  470. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
  471. package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
  472. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
  473. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
@@ -4,254 +4,17 @@
4
4
  * @module RBAC/Adapters
5
5
  * @since 1.0.0
6
6
  *
7
- * This module provides adapters for different frameworks and server runtimes.
8
- */
9
-
10
- import React, { ReactNode } from 'react';
11
- import { UUID, Permission } from './types';
12
- import { useCan } from './hooks';
13
- import { rbacCache, RBACCache } from './cache';
14
- import { getRBACLogger } from './config';
15
- import { useUnifiedAuth } from '../providers/services/UnifiedAuthProvider';
16
-
17
- // ============================================================================
18
- // REACT COMPONENTS
19
- // ============================================================================
20
-
21
- /**
22
- * Permission Guard Component
23
- *
24
- * A React component that conditionally renders children based on permissions.
25
- * Can auto-infer userId from context if not provided.
7
+ * This module provides server-side adapters for different frameworks and server runtimes.
26
8
  *
27
- * @example
28
- * ```tsx
29
- * // With explicit userId and scope
30
- * <PermissionGuard
31
- * userId="user-123"
32
- * scope={{ organisationId: 'org-456' }}
33
- * permission="update:events"
34
- * pageId="page-789"
35
- * fallback={<AccessDenied />}
36
- * >
37
- * <AdminPanel />
38
- * </PermissionGuard>
9
+ * NOTE: React components (PermissionGuard, AccessLevelGuard) have been removed.
10
+ * Use PagePermissionGuard from @jmruthers/pace-core/rbac for all client-side permission enforcement.
11
+ * Use useAccessLevel hook + conditional rendering for access level checks.
39
12
  *
40
- * // With context inference (requires auth context)
41
- * <PermissionGuard
42
- * permission="update:events"
43
- * scope={{ organisationId: 'org-456' }}
44
- * fallback={<AccessDenied />}
45
- * >
46
- * <AdminPanel />
47
- * </PermissionGuard>
48
- * ```
13
+ * Server adapters are provided for server-side route protection (Next.js, Express, etc.).
14
+ * These are optional utilities for server-side applications.
49
15
  */
50
- export function PermissionGuard({
51
- userId,
52
- scope,
53
- permission,
54
- pageId,
55
- children,
56
- fallback = null,
57
- onDenied,
58
- loading = null,
59
- // NEW: Phase 1 - Enhanced Security Features
60
- strictMode = true,
61
- auditLog = true,
62
- enforceAudit = true,
63
- }: {
64
- userId?: UUID;
65
- scope: { organisationId: UUID; eventId?: string; appId?: UUID };
66
- permission: Permission;
67
- pageId?: UUID;
68
- children: ReactNode;
69
- fallback?: ReactNode;
70
- onDenied?: () => void;
71
- loading?: ReactNode;
72
- // NEW: Phase 1 - Enhanced Security Features
73
- strictMode?: boolean;
74
- auditLog?: boolean;
75
- enforceAudit?: boolean;
76
- }): React.ReactNode {
77
- const logger = getRBACLogger();
78
-
79
- let authContext: ReturnType<typeof useUnifiedAuth> | null = null;
80
- try {
81
- authContext = useUnifiedAuth();
82
- } catch (error) {
83
- if (error instanceof Error && error.message.includes('must be used within')) {
84
- authContext = null;
85
- } else {
86
- throw error;
87
- }
88
- }
89
-
90
- const effectiveUserId = userId ?? authContext?.user?.id ?? null;
91
-
92
- // Always call useCan hook, but handle the case where userId might be undefined
93
- // Pass null for super admin status (not checked yet - hook will check if needed)
94
- const { can, isLoading, error } = useCan(
95
- effectiveUserId || '',
96
- scope,
97
- permission,
98
- pageId,
99
- true, // useCache
100
- null, // precomputedSuperAdmin - not checked yet
101
- undefined // appName
102
- );
103
-
104
- // If still no userId, show helpful error
105
- if (!effectiveUserId) {
106
- logger.error('PermissionGuard: No userId provided and could not infer from context');
107
- return fallback ?? null;
108
- }
109
-
110
- // Handle loading state
111
- if (isLoading) {
112
- return loading || (
113
- <div className="rbac-loading" role="status" aria-live="polite">
114
- <span className="sr-only">Checking permissions...</span>
115
- </div>
116
- );
117
- }
118
-
119
- // Handle error state
120
- if (error) {
121
- logger.error('Permission check failed:', error);
122
- // NEW: Phase 1 - Record failed permission check for audit
123
- if (auditLog) {
124
- // Permission check failed logged
125
- }
126
- return fallback;
127
- }
128
-
129
- // Handle permission denied
130
- if (!can) {
131
- // NEW: Phase 1 - Record denied permission check for audit
132
- if (auditLog) {
133
- // Permission denied logged
134
- }
135
-
136
- // NEW: Phase 1 - Handle strict mode violations
137
- if (strictMode) {
138
- logger.error(`[PermissionGuard] STRICT MODE VIOLATION: User attempted to access protected resource without permission`, {
139
- userId: effectiveUserId,
140
- scope,
141
- permission,
142
- pageId,
143
- timestamp: new Date().toISOString()
144
- });
145
- }
146
-
147
- if (onDenied) {
148
- onDenied();
149
- }
150
- return <>{fallback}</>;
151
- }
152
-
153
- // NEW: Phase 1 - Record successful permission check for audit
154
- if (auditLog) {
155
- // Permission granted logged
156
- }
157
16
 
158
- // Render children if permission granted
159
- return <>{children}</>;
160
- }
161
-
162
- /**
163
- * Access Level Guard Component
164
- *
165
- * A React component that conditionally renders children based on access level.
166
- * Can auto-infer userId from context if not provided.
167
- *
168
- * @example
169
- * ```tsx
170
- * // With explicit userId and scope
171
- * <AccessLevelGuard
172
- * userId="user-123"
173
- * scope={{ organisationId: 'org-456' }}
174
- * minLevel="admin"
175
- * fallback={<AccessDenied />}
176
- * >
177
- * <AdminPanel />
178
- * </AccessLevelGuard>
179
- *
180
- * // With context inference (requires auth context)
181
- * <AccessLevelGuard
182
- * minLevel="admin"
183
- * scope={{ organisationId: 'org-456' }}
184
- * fallback={<AccessDenied />}
185
- * >
186
- * <AdminPanel />
187
- * </AccessLevelGuard>
188
- * ```
189
- */
190
- export function AccessLevelGuard({
191
- userId,
192
- scope,
193
- minLevel,
194
- children,
195
- fallback = null,
196
- loading = null,
197
- }: {
198
- userId?: UUID;
199
- scope: { organisationId: UUID; eventId?: string; appId?: UUID };
200
- minLevel: 'viewer' | 'participant' | 'planner' | 'admin' | 'super';
201
- children: ReactNode;
202
- fallback?: ReactNode;
203
- loading?: ReactNode;
204
- }): React.ReactNode {
205
- const logger = getRBACLogger();
206
-
207
- let authContext: ReturnType<typeof useUnifiedAuth> | null = null;
208
- try {
209
- authContext = useUnifiedAuth();
210
- } catch (error) {
211
- if (error instanceof Error && error.message.includes('must be used within')) {
212
- authContext = null;
213
- } else {
214
- throw error;
215
- }
216
- }
217
-
218
- const effectiveUserId = userId ?? authContext?.user?.id ?? null;
219
-
220
- // Always call useAccessLevel hook, but handle the case where userId might be undefined
221
- const { accessLevel, isLoading, error } = useAccessLevel(effectiveUserId || '', scope);
222
-
223
- // If still no userId, show helpful error
224
- if (!effectiveUserId) {
225
- logger.error('AccessLevelGuard: No userId provided and could not infer from context');
226
- return fallback ?? null;
227
- }
228
-
229
- // Handle loading state
230
- if (isLoading) {
231
- return loading || (
232
- <div className="rbac-loading" role="status" aria-live="polite">
233
- <span className="sr-only">Checking access level...</span>
234
- </div>
235
- );
236
- }
237
-
238
- // Handle error state
239
- if (error) {
240
- logger.error('Access level check failed:', error);
241
- return fallback;
242
- }
243
-
244
- // Check access level
245
- const levelHierarchy = ['viewer', 'participant', 'planner', 'admin', 'super'];
246
- const userLevelIndex = accessLevel ? levelHierarchy.indexOf(accessLevel) : -1;
247
- const requiredLevelIndex = levelHierarchy.indexOf(minLevel);
248
-
249
- if (userLevelIndex < requiredLevelIndex) {
250
- return <>{fallback}</>;
251
- }
252
-
253
- return <>{children}</>;
254
- }
17
+ import { UUID, Permission } from './types';
255
18
 
256
19
  // ============================================================================
257
20
  // SERVER ADAPTERS
@@ -620,54 +383,3 @@ export function createRBACExpressMiddleware(config: {
620
383
  };
621
384
  }
622
385
 
623
- // ============================================================================
624
- // UTILITY FUNCTIONS
625
- // ============================================================================
626
-
627
- /**
628
- * Check if a user has a permission (synchronous cache check only)
629
- *
630
- * @param userId - User ID
631
- * @param scope - Permission scope
632
- * @param permission - Permission to check
633
- * @param pageId - Optional page ID
634
- * @returns True if permission is cached and granted
635
- */
636
- export function hasPermissionCached(
637
- userId: UUID,
638
- scope: { organisationId: UUID; eventId?: string; appId?: UUID },
639
- _permission: Permission,
640
- _pageId?: UUID
641
- ): boolean {
642
- const cacheKey = RBACCache.generatePermissionKey({
643
- userId,
644
- organisationId: scope.organisationId,
645
- eventId: scope.eventId,
646
- appId: scope.appId,
647
- });
648
-
649
- return rbacCache.get<boolean>(cacheKey) || false;
650
- }
651
-
652
- /**
653
- * Check if a user has any of the specified permissions (synchronous cache check only)
654
- *
655
- * @param userId - User ID
656
- * @param scope - Permission scope
657
- * @param permissions - Array of permissions to check
658
- * @param pageId - Optional page ID
659
- * @returns True if any permission is cached and granted
660
- */
661
- export function hasAnyPermissionCached(
662
- userId: UUID,
663
- scope: { organisationId: UUID; eventId?: string; appId?: UUID },
664
- permissions: Permission[],
665
- pageId?: UUID
666
- ): boolean {
667
- return permissions.some(permission =>
668
- hasPermissionCached(userId, scope, permission, pageId)
669
- );
670
- }
671
-
672
- // Import useAccessLevel for AccessLevelGuard
673
- import { useAccessLevel } from './hooks';
@@ -471,38 +471,50 @@ describe('RBAC API', () => {
471
471
 
472
472
  beforeEach(() => {
473
473
  // Create a mock Supabase client that can handle getPageScopeType queries
474
- const mockSupabaseForEngine = {
475
- from: vi.fn((table: string) => {
476
- if (table === 'rbac_apps') {
477
- return {
478
- select: vi.fn(() => ({
479
- eq: vi.fn(() => ({
480
- eq: vi.fn(() => ({
481
- single: vi.fn().mockResolvedValue({ data: { id: 'app-123' }, error: null })
482
- }))
483
- }))
484
- }))
485
- };
486
- }
487
- if (table === 'rbac_app_pages') {
488
- return {
489
- select: vi.fn(() => ({
490
- eq: vi.fn(() => ({
491
- eq: vi.fn(() => ({
492
- maybeSingle: vi.fn().mockResolvedValue({ data: { id: '123e4567-e89b-12d3-a456-426614174000' }, error: null })
493
- }))
494
- }))
495
- }))
496
- };
474
+ // This needs to handle multiple query patterns:
475
+ // 1. from('rbac_apps').select('name').eq('id', ...).eq('is_active', true).single()
476
+ // 2. from('rbac_apps').select('id').eq('name', ...).eq('is_active', true).single()
477
+ // 3. from('rbac_app_pages').select('id').eq('app_id', ...).eq('page_name', ...).maybeSingle()
478
+ // 4. from('rbac_app_pages').select('scope_type').eq('id', ...).single()
479
+
480
+ const createQueryBuilder = (table: string, selectField?: string) => {
481
+ const builder: any = {
482
+ select: vi.fn().mockReturnThis(),
483
+ eq: vi.fn().mockReturnThis(),
484
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
485
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
486
+ };
487
+
488
+ // Handle different query patterns based on table and select field
489
+ if (table === 'rbac_apps') {
490
+ if (selectField === 'name') {
491
+ // Pattern: select('name').eq('id', ...).eq('is_active', true).single()
492
+ builder.single = vi.fn().mockResolvedValue({ data: { name: 'test-app' }, error: null });
493
+ } else if (selectField === 'id') {
494
+ // Pattern: select('id').eq('name', ...).eq('is_active', true).single()
495
+ builder.single = vi.fn().mockResolvedValue({ data: { id: 'app-123' }, error: null });
497
496
  }
498
- return mockSupabase.from(table);
499
- }),
500
- rpc: vi.fn((fnName: string, params: any) => {
501
- if (fnName === 'get_page_scope_type') {
502
- return Promise.resolve({ data: 'organisation', error: null });
497
+ } else if (table === 'rbac_app_pages') {
498
+ if (selectField === 'id') {
499
+ // Pattern: select('id').eq('app_id', ...).eq('page_name', ...).maybeSingle()
500
+ builder.maybeSingle = vi.fn().mockResolvedValue({ data: { id: '123e4567-e89b-12d3-a456-426614174000' }, error: null });
501
+ } else if (selectField === 'scope_type') {
502
+ // Pattern: select('scope_type').eq('id', ...).single()
503
+ builder.single = vi.fn().mockResolvedValue({ data: { scope_type: 'organisation' }, error: null });
503
504
  }
504
- return Promise.resolve({ data: null, error: null });
505
- }),
505
+ }
506
+
507
+ // Make select() return builder with the selectField tracked
508
+ builder.select = vi.fn((fields: string) => {
509
+ return createQueryBuilder(table, fields);
510
+ });
511
+
512
+ return builder;
513
+ };
514
+
515
+ const mockSupabaseForEngine = {
516
+ from: vi.fn((table: string) => createQueryBuilder(table)),
517
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
506
518
  auth: mockSupabase.auth
507
519
  };
508
520
 
@@ -736,32 +748,8 @@ describe('RBAC API', () => {
736
748
  });
737
749
  });
738
750
 
739
- describe('hasPermission', () => {
740
- it('calls isPermitted', async () => {
741
- const { hasPermission } = await import('./api');
742
-
743
- mockEngine.isPermitted.mockResolvedValue(true);
744
-
745
- const result = await hasPermission({
746
- userId: 'user-123',
747
- scope: { organisationId: 'org-456' },
748
- permission: 'read:users'
749
- });
750
-
751
- expect(result).toBe(true);
752
- expect(mockEngine.isPermitted).toHaveBeenCalledWith(
753
- {
754
- userId: 'user-123',
755
- scope: { organisationId: 'org-456' },
756
- permission: 'read:users'
757
- },
758
- expect.objectContaining({
759
- userId: 'user-123',
760
- organisationId: 'org-456'
761
- })
762
- );
763
- });
764
- });
751
+ // hasPermission was removed - use isPermitted directly
752
+ // Tests for isPermitted are covered in the isPermitted describe block above
765
753
 
766
754
  describe('hasAnyPermission', () => {
767
755
  it('returns true if user has any permission', async () => {
package/src/rbac/api.ts CHANGED
@@ -490,16 +490,6 @@ export async function isPermittedCached(
490
490
  });
491
491
  }
492
492
 
493
- /**
494
- * Check if a user has a specific permission (alias for isPermitted)
495
- *
496
- * @param input - Permission check parameters
497
- * @returns Promise<boolean> - True if user has permission
498
- */
499
- export async function hasPermission(input: PermissionCheck): Promise<boolean> {
500
- return isPermitted(input);
501
- }
502
-
503
493
  /**
504
494
  * Check if user has any of the specified permissions
505
495
  *
@@ -623,22 +613,25 @@ export async function getPageScopeType(
623
613
  throw new Error(`Could not resolve pageId ${pageId} to a valid UUID`);
624
614
  }
625
615
 
626
- // Call the database function to get scope type (always returns a value)
627
- const { data, error } = await engine['supabase']
628
- .rpc('get_page_scope_type' as any, {
629
- p_page_id: resolvedPageId
630
- }) as { data: 'event' | 'organisation' | 'both' | null; error: any };
616
+ // Query scope type directly from rbac_app_pages (removed legacy RPC get_page_scope_type)
617
+ const { data: pageData, error } = await engine['supabase']
618
+ .from('rbac_app_pages')
619
+ .select('scope_type')
620
+ .eq('id', resolvedPageId)
621
+ .single();
631
622
 
632
623
  if (error) {
633
624
  log.error('Error fetching page scope type:', { pageId, appId, error });
634
625
  throw new Error(`Failed to get page scope type: ${error.message}`);
635
626
  }
636
627
 
637
- if (!data) {
628
+ if (!pageData || !pageData.scope_type) {
638
629
  throw new Error(`Page ${resolvedPageId} does not have scope_type set`);
639
630
  }
640
631
 
641
- return data;
632
+ // Type assertion to narrow string to the specific union type
633
+ // The database constraint ensures it's one of these values
634
+ return pageData.scope_type as 'event' | 'organisation' | 'both';
642
635
  } catch (err) {
643
636
  log.error('Error fetching page scope type:', err);
644
637
  throw err instanceof Error ? err : new Error(`Failed to get page scope type: ${String(err)}`);
@@ -357,7 +357,6 @@ let globalCacheInvalidationManager: RBACCacheInvalidationManager | null = null;
357
357
  export function initializeCacheInvalidation(supabase: SupabaseClient<Database>): RBACCacheInvalidationManager {
358
358
  // Clean up existing manager if it exists (e.g., when switching Supabase clients)
359
359
  if (globalCacheInvalidationManager) {
360
- log.debug('Cleaning up existing cache invalidation manager before creating new one');
361
360
  globalCacheInvalidationManager.cleanup();
362
361
  }
363
362
 
@@ -36,3 +36,13 @@ export {
36
36
  type QuickFix,
37
37
  } from './quick-fix-suggestions';
38
38
 
39
+ export {
40
+ detectDirectRpcCalls,
41
+ detectDirectTableQueries,
42
+ detectCustomAccessDeniedComponents,
43
+ detectPatternViolations,
44
+ logPatternViolations,
45
+ type PatternViolation,
46
+ type PatternDetectionResult,
47
+ } from './pattern-detector';
48
+