@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
@@ -59,11 +59,6 @@ export class EventService extends BaseService implements IEventService {
59
59
  this.appName = appName;
60
60
  this.selectedOrganisation = selectedOrganisation;
61
61
  this.setSelectedEventId = setSelectedEventId;
62
- logger.debug('EventService', `Instance created [ID:${this.instanceId}]`, {
63
- appName,
64
- hasUser: !!user,
65
- userId: user?.id
66
- });
67
62
  }
68
63
 
69
64
  getInstanceId(): number {
@@ -112,11 +107,6 @@ export class EventService extends BaseService implements IEventService {
112
107
  this.userClearedEventRef = false;
113
108
  this.hasAutoSelectedRef = false;
114
109
 
115
- logger.debug('EventService', `User changed [ID:${this.instanceId}]`, {
116
- previousUserId,
117
- newUserId,
118
- willInitialize: newUserId !== null
119
- });
120
110
  }
121
111
 
122
112
  this.supabaseClient = supabaseClient;
@@ -142,10 +132,6 @@ export class EventService extends BaseService implements IEventService {
142
132
 
143
133
  if (isRBACInitialized()) {
144
134
  this.isSuperAdmin = await checkSuperAdmin(user.id as UUID);
145
- logger.debug('EventService', 'Super admin status updated in updateDependencies', {
146
- userId: user.id,
147
- isSuperAdmin: this.isSuperAdmin
148
- });
149
135
  } else {
150
136
  // RBAC not initialized - this should be rare since UnifiedAuthProvider initializes it synchronously
151
137
  // Keep existing value (don't reset to false) to avoid clearing a previously determined super admin status
@@ -260,11 +246,6 @@ export class EventService extends BaseService implements IEventService {
260
246
  });
261
247
  // Reset the user cleared flag when selecting an event
262
248
  this.userClearedEventRef = false;
263
- logger.debug('EventService', 'Event selected', {
264
- eventId: event.event_id,
265
- eventName: event.event_name,
266
- userClearedEventRef: this.userClearedEventRef
267
- });
268
249
  } else {
269
250
  const previousEventId = this.selectedEvent?.event_id;
270
251
  this.selectedEvent = null;
@@ -277,11 +258,6 @@ export class EventService extends BaseService implements IEventService {
277
258
  this.hasAutoSelectedRef = false;
278
259
  // Mark that user explicitly cleared the event to prevent auto-selection
279
260
  this.userClearedEventRef = true;
280
- logger.debug('EventService', 'Event cleared via setSelectedEvent(null)', {
281
- previousEventId,
282
- userClearedEventRef: this.userClearedEventRef,
283
- stackTrace: new Error().stack
284
- });
285
261
  }
286
262
  this.notify();
287
263
  }
@@ -407,13 +383,11 @@ export class EventService extends BaseService implements IEventService {
407
383
  protected async doInitialize(): Promise<void> {
408
384
  // Skip if already initialized
409
385
  if (this.isInitializedRef) {
410
- logger.debug('EventService', 'Skipping initialization - already initialized');
411
386
  return;
412
387
  }
413
388
 
414
389
  // Skip if already fetching
415
390
  if (this.isFetchingRef) {
416
- logger.debug('EventService', 'Skipping initialization - already fetching');
417
391
  return;
418
392
  }
419
393
 
@@ -430,27 +404,14 @@ export class EventService extends BaseService implements IEventService {
430
404
  // For event-required apps, selectedOrganisation may be null (org derived from event)
431
405
  // For org-required apps, selectedOrganisation is required
432
406
  if (!this.user) {
433
- logger.debug('EventService', 'Skipping initialization - no user');
434
407
  return;
435
408
  }
436
409
 
437
- logger.debug('EventService', 'Initializing', {
438
- userId: this.user.id,
439
- appName: this.appName,
440
- hasSelectedOrganisation: !!this.selectedOrganisation,
441
- hasSupabaseClient: !!this.supabaseClient,
442
- hasSession: !!this.session
443
- });
444
-
445
410
  // Initial setup - fetch events on initialization
446
411
  await this.fetchEvents(false);
447
412
 
448
413
  // Mark as initialized after successful fetch
449
414
  this.isInitializedRef = true;
450
- logger.debug('EventService', 'Initialization complete', {
451
- eventsCount: this.events.length,
452
- hasError: !!this.error
453
- });
454
415
  }
455
416
 
456
417
  protected doCleanup(): void {
@@ -505,10 +466,6 @@ export class EventService extends BaseService implements IEventService {
505
466
  userIsSuperAdmin = await checkSuperAdmin(this.user.id as UUID);
506
467
  // Update cached value for future use
507
468
  this.isSuperAdmin = userIsSuperAdmin;
508
- logger.debug('EventService', 'Super admin check completed', {
509
- userId: this.user.id,
510
- isSuperAdmin: userIsSuperAdmin
511
- });
512
469
  } else {
513
470
  // RBAC not initialized - this should be rare since UnifiedAuthProvider initializes it synchronously
514
471
  // Use cached value from updateDependencies as fallback
@@ -544,10 +501,6 @@ export class EventService extends BaseService implements IEventService {
544
501
  } else {
545
502
  // No context available - pass null to get all accessible events via event-app roles
546
503
  // This allows users with event-app roles to see their events even without org context
547
- logger.debug('EventService', 'No organisation context available, fetching all accessible events', {
548
- hasSelectedEvent: !!this.selectedEvent,
549
- hasSelectedOrganisation: !!this.selectedOrganisation
550
- });
551
504
  organisationIdForRpc = null; // Will return events user has access to via event-app roles
552
505
  }
553
506
  }
@@ -580,14 +533,6 @@ export class EventService extends BaseService implements IEventService {
580
533
 
581
534
  // Call the RPC function following the established pattern
582
535
  // For super admins, pass null for p_organisation_id to see all events
583
- logger.debug('EventService', 'Fetching events', {
584
- userId: this.user.id,
585
- organisationIdForRpc,
586
- appName: this.appName,
587
- hasSelectedEvent: !!this.selectedEvent,
588
- hasSelectedOrganisation: !!this.selectedOrganisation,
589
- isSuperAdmin: userIsSuperAdmin
590
- });
591
536
 
592
537
  let { data, error: rpcError } = await this.supabaseClient.rpc('data_user_events_get', {
593
538
  p_user_id: this.user.id,
@@ -595,11 +540,6 @@ export class EventService extends BaseService implements IEventService {
595
540
  p_app_name: this.appName
596
541
  });
597
542
 
598
- logger.debug('EventService', 'RPC response', {
599
- dataLength: data?.length || 0,
600
- hasError: !!rpcError,
601
- error: rpcError
602
- });
603
543
 
604
544
  if (rpcError) {
605
545
  logger.error('EventService', 'RPC error fetching events:', rpcError);
@@ -671,10 +611,7 @@ export class EventService extends BaseService implements IEventService {
671
611
  this.setSelectedEventId?.(null);
672
612
  // Restore the previous userClearedEventRef value - this was an automatic clear, not user-initiated
673
613
  this.userClearedEventRef = previousUserClearedRef;
674
- logger.debug('EventService', 'Cleared selected event - no longer in events list', {
675
- previousEventId: selectedEventId,
676
- eventsCount: transformedEvents.length
677
- });
614
+ // Cleared selected event - no longer in events list
678
615
  }
679
616
  }
680
617
 
@@ -685,62 +622,32 @@ export class EventService extends BaseService implements IEventService {
685
622
  if (!skipLoadPersisted) {
686
623
  const persistedEventLoaded = await this.loadPersistedEvent(transformedEvents);
687
624
 
688
- logger.debug('EventService', 'Event selection check', {
689
- persistedEventLoaded,
690
- userClearedEventRef: this.userClearedEventRef,
691
- eventsCount: transformedEvents.length,
692
- hasSelectedEvent: !!this.selectedEvent
693
- });
694
-
695
625
  // If no persisted event was loaded and user hasn't explicitly cleared an event, auto-select the next event
696
626
  if (!persistedEventLoaded && !this.userClearedEventRef) {
697
627
  const nextEvent = this.getNextEventByDate(transformedEvents);
698
- logger.debug('EventService', 'Auto-selection attempt', {
699
- nextEventFound: !!nextEvent,
700
- nextEventId: nextEvent?.event_id,
701
- nextEventDate: nextEvent?.event_date
702
- });
703
628
  if (nextEvent) {
704
629
  this.hasAutoSelectedRef = true;
705
630
  // Use setSelectedEvent() to ensure consistent behavior
706
631
  // Theme will be applied by useEventTheme() hook
707
632
  this.setSelectedEvent(nextEvent);
708
- logger.debug('EventService', 'Auto-selected next event', {
709
- eventId: nextEvent.event_id,
710
- eventName: nextEvent.event_name,
711
- eventDate: nextEvent.event_date
712
- });
713
- } else {
714
- logger.debug('EventService', 'No next event found for auto-selection', {
715
- eventsCount: transformedEvents.length,
716
- eventsWithDates: transformedEvents.filter(e => e.event_date).length
717
- });
718
633
  }
719
634
  } else if (persistedEventLoaded) {
720
- logger.debug('EventService', 'Skipped auto-selection - persisted event loaded');
635
+ // Skipped auto-selection - persisted event loaded
721
636
  } else if (this.userClearedEventRef) {
722
- logger.debug('EventService', 'Skipped auto-selection - user explicitly cleared event');
637
+ // Skipped auto-selection - user explicitly cleared event
723
638
  }
724
639
  } else {
725
640
  // If skipping persisted event load, still do auto-selection for new users
726
641
  if (!this.userClearedEventRef) {
727
642
  const nextEvent = this.getNextEventByDate(transformedEvents);
728
- logger.debug('EventService', 'Auto-selection attempt (skip persisted)', {
729
- nextEventFound: !!nextEvent,
730
- nextEventId: nextEvent?.event_id
731
- });
732
643
  if (nextEvent) {
733
644
  this.hasAutoSelectedRef = true;
734
645
  // Use setSelectedEvent() to ensure consistent behavior
735
646
  // Theme will be applied by useEventTheme() hook
736
647
  this.setSelectedEvent(nextEvent);
737
- logger.debug('EventService', 'Auto-selected next event (skip persisted)', {
738
- eventId: nextEvent.event_id,
739
- eventName: nextEvent.event_name
740
- });
741
648
  }
742
649
  } else {
743
- logger.debug('EventService', 'Skipped auto-selection (skip persisted) - user explicitly cleared event');
650
+ // Skipped auto-selection (skip persisted) - user explicitly cleared event
744
651
  }
745
652
  }
746
653
  }
@@ -205,6 +205,14 @@ export class InactivityService extends BaseService implements IInactivityService
205
205
  logger.error('InactivityService', 'Error during idle logout:', error);
206
206
  }
207
207
 
208
+ // Clear sessionStorage on logout
209
+ try {
210
+ sessionStorage.clear();
211
+ } catch (storageError) {
212
+ // Ignore storage errors (e.g., in private browsing mode)
213
+ logger.warn('InactivityService', 'Failed to clear sessionStorage', { error: storageError });
214
+ }
215
+
208
216
  // Call app callback for navigation/redirect
209
217
  this.onIdleLogout?.('inactivity');
210
218
  this.notify();
@@ -231,6 +239,14 @@ export class InactivityService extends BaseService implements IInactivityService
231
239
  logger.error('InactivityService', 'Error during manual sign out:', error);
232
240
  }
233
241
 
242
+ // Clear sessionStorage on logout
243
+ try {
244
+ sessionStorage.clear();
245
+ } catch (storageError) {
246
+ // Ignore storage errors (e.g., in private browsing mode)
247
+ logger.warn('InactivityService', 'Failed to clear sessionStorage', { error: storageError });
248
+ }
249
+
234
250
  // Call app callback for navigation/redirect
235
251
  this.onIdleLogout?.('inactivity');
236
252
  this.notify();
@@ -70,10 +70,6 @@ export class OrganisationService extends BaseService implements IOrganisationSer
70
70
  this.supabaseClient = supabaseClient;
71
71
  this.user = user;
72
72
  this.session = session;
73
- logger.debug('OrganisationService', `Instance created [ID:${this.instanceId}]`, {
74
- hasUser: !!user,
75
- userId: user?.id
76
- });
77
73
  }
78
74
 
79
75
  getInstanceId(): number {
@@ -164,10 +160,6 @@ export class OrganisationService extends BaseService implements IOrganisationSer
164
160
 
165
161
  if (userChanged || needsRetry || isEmpty) {
166
162
  if (userChanged) {
167
- logger.debug('OrganisationService', `User changed [ID:${this.instanceId}], resetting initialization`, {
168
- previousUserId,
169
- newUserId
170
- });
171
163
  } else if (needsRetry) {
172
164
  logger.debug('OrganisationService', `Previous error detected [ID:${this.instanceId}], retrying initialization`);
173
165
  } else if (isEmpty) {
@@ -293,7 +285,6 @@ export class OrganisationService extends BaseService implements IOrganisationSer
293
285
  // SECURITY: Only initialize if we have an authenticated user
294
286
  // This prevents premature initialization during early auth states
295
287
  if (!this.user) {
296
- logger.debug('OrganisationService', 'Skipping initialization - no user');
297
288
  return;
298
289
  }
299
290
 
@@ -337,34 +328,13 @@ export class OrganisationService extends BaseService implements IOrganisationSer
337
328
  }
338
329
 
339
330
  private async setDatabaseOrganisationContext(organisation: Organisation): Promise<void> {
340
- if (!this.supabaseClient || !this.session) {
341
- logger.warn('OrganisationService', 'No Supabase client or session available for setting organisation context');
342
- this._isContextReady = false;
343
- this.notify();
344
- return;
345
- }
346
-
347
- try {
348
- // Add timeout to prevent hanging
349
- const timeoutPromise = new Promise((_, reject) => {
350
- setTimeout(() => reject(new Error('Context setting timeout after 5 seconds')), 5000);
351
- });
352
-
353
- const contextPromise = setOrganisationContext(this.supabaseClient, organisation.id);
354
-
355
- await Promise.race([contextPromise, timeoutPromise]);
356
-
357
- // Database organisation context set successfully
358
- this._isContextReady = true;
359
- this.notify();
360
- } catch (error) {
361
- logger.error('OrganisationService', 'Failed to set database organisation context:', error);
362
- // Set context ready to true anyway - this is a non-critical operation
363
- // The app should still work without database context
364
- this._isContextReady = true;
365
- this.notify();
366
- // Don't throw - this is a non-critical operation
367
- }
331
+ // Organisation context is now handled via secure client and explicit parameters
332
+ // This function is kept for backward compatibility but is effectively a no-op
333
+ // The setOrganisationContext function has been deprecated and no longer sets database context
334
+
335
+ // Mark context as ready immediately since context is handled elsewhere
336
+ this._isContextReady = true;
337
+ this.notify();
368
338
  }
369
339
 
370
340
  private async loadUserOrganisations(): Promise<void> {
@@ -416,9 +386,6 @@ export class OrganisationService extends BaseService implements IOrganisationSer
416
386
  this._error = null;
417
387
  this.notify();
418
388
 
419
- logger.debug('OrganisationService', 'Loading organisations for user', {
420
- userId: this.user.id
421
- });
422
389
 
423
390
  try {
424
391
  // Get user's organisation roles directly from rbac_organisation_roles table
@@ -500,10 +467,6 @@ export class OrganisationService extends BaseService implements IOrganisationSer
500
467
 
501
468
  organisations = Array.from(organisationsMap.values());
502
469
 
503
- logger.debug('OrganisationService', 'Query results', {
504
- membershipsCount: memberships.length,
505
- organisationsCount: organisations.length
506
- });
507
470
 
508
471
  // Extract organisations from join results
509
472
  } catch (queryError) {
@@ -866,10 +866,19 @@ describe('OrganisationService', () => {
866
866
  mockSession
867
867
  );
868
868
 
869
- serviceWithoutClient.setSelectedOrganisation(mockOrganisation);
870
-
871
- // Should handle gracefully
872
- await new Promise(resolve => setTimeout(resolve, 100));
869
+ // Initially context is not ready
870
+ expect(serviceWithoutClient.isContextReady()).toBe(false);
871
+
872
+ // setSelectedOrganisation requires a valid organisation in the organisations list
873
+ // Since we don't have a client, we can't load organisations, so this will throw
874
+ // or the organisation won't be in the list. The context ready state should remain false.
875
+ try {
876
+ await serviceWithoutClient.switchOrganisation(mockOrganisation.id);
877
+ } catch {
878
+ // Expected to fail
879
+ }
880
+
881
+ // Context should still be false since organisation switch failed
873
882
  expect(serviceWithoutClient.isContextReady()).toBe(false);
874
883
  });
875
884
 
@@ -880,10 +889,19 @@ describe('OrganisationService', () => {
880
889
  null
881
890
  );
882
891
 
883
- serviceWithoutSession.setSelectedOrganisation(mockOrganisation);
884
-
885
- // Should handle gracefully
886
- await new Promise(resolve => setTimeout(resolve, 100));
892
+ // Initially context is not ready
893
+ expect(serviceWithoutSession.isContextReady()).toBe(false);
894
+
895
+ // Without a session, loadUserOrganisations will return early and not load organisations
896
+ // So setSelectedOrganisation will fail because the organisation isn't in the list
897
+ // The context ready state should remain false
898
+ try {
899
+ await serviceWithoutSession.switchOrganisation(mockOrganisation.id);
900
+ } catch {
901
+ // Expected to fail
902
+ }
903
+
904
+ // Context should still be false since organisation switch failed
887
905
  expect(serviceWithoutSession.isContextReady()).toBe(false);
888
906
  });
889
907
  });
@@ -38,9 +38,6 @@ export abstract class BaseService {
38
38
  * This triggers React re-renders
39
39
  */
40
40
  protected notify(): void {
41
- const serviceName = this.constructor.name;
42
- const instanceId = (this as any).instanceId || 'unknown';
43
- logger.debug('BaseService', `[${serviceName} ID:${instanceId}] Notifying ${this.subscribers.length} subscribers`);
44
41
  this.subscribers.forEach(callback => {
45
42
  try {
46
43
  callback();
@@ -206,6 +206,13 @@
206
206
  dialog::backdrop {
207
207
  background-color: oklch(from var(--color-main-700) l c h / 0.5);
208
208
  }
209
+
210
+ progress::indeterminate {
211
+
212
+ background: var(--color-acc-600);
213
+ /*
214
+ background: linear-gradient(to right, var(--color-acc-700) 10%, var(--color-sec-200) 30%, var(--color-main-500) 70%, var(--color-acc-200) 90%); */
215
+ }
209
216
 
210
217
  .appGradient {
211
218
  background: linear-gradient(145deg, var(--color-main-100) 10%, var(--color-main-200) 30%, var(--color-main-200) 70%, var(--color-main-300) 90%);
@@ -88,7 +88,7 @@ describe('parseAndNormalizeEventColours', () => {
88
88
  });
89
89
 
90
90
  describe('Standard format only', () => {
91
- it('returns null for legacy format with ev-main, ev-sec, ev-acc keys', () => {
91
+ it('normalizes legacy format with ev-main, ev-sec, ev-acc keys to standard format', () => {
92
92
  const input = {
93
93
  'ev-main': { 500: { L: 0.5, C: 0.2, H: 0 } },
94
94
  'ev-sec': { 500: { L: 0.5, C: 0.2, H: 120 } },
@@ -96,8 +96,14 @@ describe('parseAndNormalizeEventColours', () => {
96
96
  };
97
97
 
98
98
  const result = parseAndNormalizeEventColours(input);
99
- // Legacy format is no longer supported - returns null
100
- expect(result).toBeNull();
99
+ // Legacy format is normalized to standard format (ev-main -> main, etc.)
100
+ expect(result).not.toBeNull();
101
+ expect(result).toHaveProperty('main');
102
+ expect(result).toHaveProperty('sec');
103
+ expect(result).toHaveProperty('acc');
104
+ expect(result?.main).toHaveProperty('500');
105
+ expect(result?.sec).toHaveProperty('500');
106
+ expect(result?.acc).toHaveProperty('500');
101
107
  });
102
108
 
103
109
  it('uses standard keys when provided', () => {
@@ -8,15 +8,13 @@
8
8
  * Handles multiple input formats and ensures consistent palette structure.
9
9
  */
10
10
 
11
- import { createLogger } from '../utils/core/logger';
12
-
13
- const log = createLogger('ParseEventColours');
14
11
 
15
12
  /**
16
13
  * Parse and normalize event_colours to PaletteData
17
14
  *
18
15
  * Supports input formats:
19
- * - Object with 'main', 'sec', 'acc' keys
16
+ * - Object with 'main', 'sec', 'acc' keys (standard format)
17
+ * - Object with 'ev-main', 'ev-sec', 'ev-acc' keys (database format with prefix)
20
18
  * - JSON string that will be parsed
21
19
  *
22
20
  * Only includes explicitly defined color values. Does not fill
@@ -38,6 +36,18 @@ const log = createLogger('ParseEventColours');
38
36
  * // Returns: { main: { 500: {...}, raw: {...} }, sec: { 500: {...} }, acc: { 500: {...} } }
39
37
  * ```
40
38
  *
39
+ * @example
40
+ * ```ts
41
+ * // Database format with ev- prefix
42
+ * const colours = {
43
+ * 'ev-main': { 500: { L: 0.5, C: 0.2, H: 0 } },
44
+ * 'ev-sec': { 500: { L: 0.5, C: 0.2, H: 120 } },
45
+ * 'ev-acc': { 500: { L: 0.5, C: 0.2, H: 240 } }
46
+ * };
47
+ * const palette = parseAndNormalizeEventColours(colours);
48
+ * // Returns: { main: { 500: {...} }, sec: { 500: {...} }, acc: { 500: {...} } }
49
+ * ```
50
+ *
41
51
  */
42
52
  export function parseAndNormalizeEventColours(input: unknown): { main: any; sec: any; acc: any } | null {
43
53
  try {
@@ -55,13 +65,16 @@ export function parseAndNormalizeEventColours(input: unknown): { main: any; sec:
55
65
  return null;
56
66
  }
57
67
 
58
- // Use standard 'main'/'sec'/'acc' keys
59
- const main = obj?.main || null;
60
- const sec = obj?.sec || null;
61
- const acc = obj?.acc || null;
68
+ // Support both standard keys (main/sec/acc) and prefixed keys (ev-main/ev-sec/ev-acc)
69
+ // Database may store with ev-* prefix, but we normalize to standard keys
70
+ const main = obj?.main || obj?.['ev-main'] || null;
71
+ const sec = obj?.sec || obj?.['ev-sec'] || null;
72
+ const acc = obj?.acc || obj?.['ev-acc'] || null;
62
73
 
63
74
  // If no palette data found, return null
64
- if (!main && !sec && !acc) return null;
75
+ if (!main && !sec && !acc) {
76
+ return null;
77
+ }
65
78
 
66
79
  // Helper: only include explicitly defined color values
67
80
  // This ensures we don't include undefined shades in the palette
@@ -88,7 +101,6 @@ export function parseAndNormalizeEventColours(input: unknown): { main: any; sec:
88
101
  acc: fill(acc)
89
102
  };
90
103
  } catch (error) {
91
- log.warn('Failed to parse/normalize event colours:', error);
92
104
  return null;
93
105
  }
94
106
  }