@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
@@ -1,15 +1,13 @@
1
- ---
2
- lastUpdated: 2025-01-02T00:00:00+11:00
3
- version: 0.5.182
4
- reviewedBy: rls-audit-and-fixes
5
- ---
1
+ # Security & RBAC Standards
6
2
 
7
- # RBAC and RLS Standard
3
+ **🤖 Cursor Rule**: See [06-security-rbac.mdc](../../cursor-rules/06-security-rbac.mdc) for AI-optimized directives that automatically enforce RBAC contract compliance (ESLint-enforced).
8
4
 
9
5
  ## Purpose
10
6
 
11
7
  Define standards for Row-Level Security (RLS) policies and Role-Based Access Control (RBAC) integration to ensure security, performance, and maintainability.
12
8
 
9
+ **Note:** General performance optimization patterns (React, caching, bundle size) are covered in [Operations Standards](./9-operations-standards.md). This document focuses on RLS-specific performance requirements.
10
+
13
11
  ## Principles
14
12
 
15
13
  - **Performance First**: All RLS policies must use optimized helper functions
@@ -101,16 +99,36 @@ FOR SELECT USING (
101
99
  );
102
100
  ```
103
101
 
102
+ ## Helper Selection Quick Guide
103
+
104
+ | Scenario | Helper(s) to use | Notes |
105
+ |----------|------------------|-------|
106
+ | Organisation-scoped rows | `check_user_organisation_access(organisation_id)` | Always check `organisation_id IS NOT NULL` first. |
107
+ | Page-permission checks | `check_rbac_permission_with_context(..., get_app_id('APP'))` | Use the wrapper instead of inline `rbac_check_permission_simplified` + `auth.uid()`. |
108
+ | Event-scoped rows | `check_user_event_access(event_id)` | Combine with permission wrapper when pages require it. |
109
+ | Public rows | `check_public_event_access(event_id)` or `is_public = true` | Keep anonymous and authenticated policies separate. |
110
+ | User-owned rows | `get_effective_user_id() = user_id` | Use when `organisation_id IS NULL`. |
111
+ | Service role bypass | `is_service_role()` | Put first in OR chains; use sparingly. |
112
+
113
+ ## RLS Helper Requirements (enforced)
114
+
115
+ - Helper functions **must** be `STABLE`, `SECURITY DEFINER`, and `SET search_path TO public`.
116
+ - **Never** inline `auth.uid()`, `auth.role()`, or `current_setting()` inside policies.
117
+ - Use `get_app_id()` for app UUIDs (do not hardcode UUIDs or call legacy getters).
118
+ - Avoid subqueries inside policies; move lookups into helpers.
119
+
104
120
  ## Standard Helper Functions
105
121
 
106
122
  ### Core Helper Functions
107
123
 
108
124
  These functions are available for use in RLS policies:
109
125
 
110
- #### `is_super_admin()`
126
+ #### `is_super_admin(p_user_id UUID)`
111
127
  - **Returns**: `boolean`
112
- - **Purpose**: Checks if current user is a super admin
113
- - **Usage**: `is_super_admin()`
128
+ - **Purpose**: Checks if the specified user is a super admin
129
+ - **Usage**: `is_super_admin(safe_get_user_id_for_rls())`
130
+ - **⚠️ CRITICAL**: Always pass an explicit user ID parameter. Never call without parameters.
131
+ - **Security**: This function requires an explicit parameter to prevent fallback strategy vulnerabilities. Use `safe_get_user_id_for_rls()` to get the user ID in RLS policies.
114
132
 
115
133
  #### `check_user_organisation_access(p_organisation_id UUID)`
116
134
  - **Returns**: `boolean`
@@ -212,7 +230,7 @@ FOR SELECT TO authenticated
212
230
  USING (
213
231
  organisation_id IS NOT NULL
214
232
  AND (
215
- is_super_admin()
233
+ is_super_admin(safe_get_user_id_for_rls())
216
234
  OR check_user_organisation_access(organisation_id)
217
235
  )
218
236
  );
@@ -223,6 +241,7 @@ USING (
223
241
  **Notes:**
224
242
  - Always check `organisation_id IS NOT NULL` first
225
243
  - Super admin check comes before organisation access check
244
+ - **MUST** use `is_super_admin(safe_get_user_id_for_rls())` with explicit parameter
226
245
  - Use `check_user_organisation_access()` for basic membership checks
227
246
 
228
247
  ### RBAC Permission-Based Policy
@@ -236,7 +255,7 @@ FOR SELECT TO authenticated
236
255
  USING (
237
256
  organisation_id IS NOT NULL
238
257
  AND (
239
- is_super_admin()
258
+ is_super_admin(safe_get_user_id_for_rls())
240
259
  OR check_rbac_permission_with_context(
241
260
  'read:page.table_name',
242
261
  'table_name',
@@ -258,7 +277,7 @@ FOR SELECT TO authenticated
258
277
  USING (
259
278
  organisation_id IS NOT NULL
260
279
  AND (
261
- is_super_admin()
280
+ is_super_admin(safe_get_user_id_for_rls())
262
281
  OR check_rbac_permission_with_context(
263
282
  'read:page.table_name',
264
283
  'table_name',
@@ -275,7 +294,7 @@ FOR INSERT TO authenticated
275
294
  WITH CHECK (
276
295
  organisation_id IS NOT NULL
277
296
  AND (
278
- is_super_admin()
297
+ is_super_admin(safe_get_user_id_for_rls())
279
298
  OR check_rbac_permission_with_context(
280
299
  'create:page.table_name',
281
300
  'table_name',
@@ -292,7 +311,7 @@ FOR UPDATE TO authenticated
292
311
  USING (
293
312
  organisation_id IS NOT NULL
294
313
  AND (
295
- is_super_admin()
314
+ is_super_admin(safe_get_user_id_for_rls())
296
315
  OR check_rbac_permission_with_context(
297
316
  'update:page.table_name',
298
317
  'table_name',
@@ -305,7 +324,7 @@ USING (
305
324
  WITH CHECK (
306
325
  organisation_id IS NOT NULL
307
326
  AND (
308
- is_super_admin()
327
+ is_super_admin(safe_get_user_id_for_rls())
309
328
  OR check_rbac_permission_with_context(
310
329
  'update:page.table_name',
311
330
  'table_name',
@@ -322,7 +341,7 @@ FOR DELETE TO authenticated
322
341
  USING (
323
342
  organisation_id IS NOT NULL
324
343
  AND (
325
- is_super_admin()
344
+ is_super_admin(safe_get_user_id_for_rls())
326
345
  OR check_rbac_permission_with_context(
327
346
  'delete:page.table_name',
328
347
  'table_name',
@@ -351,7 +370,7 @@ FOR SELECT TO authenticated
351
370
  USING (
352
371
  organisation_id IS NOT NULL
353
372
  AND (
354
- is_super_admin()
373
+ is_super_admin(safe_get_user_id_for_rls())
355
374
  OR check_user_event_access(event_id)
356
375
  )
357
376
  );
@@ -387,7 +406,7 @@ USING (
387
406
  organisation_id IS NOT NULL
388
407
  AND is_authenticated_user()
389
408
  AND (
390
- is_super_admin()
409
+ is_super_admin(safe_get_user_id_for_rls())
391
410
  OR check_user_organisation_access(organisation_id)
392
411
  )
393
412
  )
@@ -403,6 +422,52 @@ USING (
403
422
 
404
423
  **Example:** `file_references`, `pace_address` (can be either organisation or user-scoped)
405
424
 
425
+ **Real-World Example: File References Table**
426
+
427
+ ```sql
428
+ -- Real-world example: file_references table supports both organisation and user-scoped files
429
+ CREATE POLICY "rbac_select_file_references" ON file_references
430
+ FOR SELECT
431
+ USING (
432
+ -- Service role can access all files (for system operations)
433
+ is_service_role()
434
+ OR
435
+ -- Organisation-scoped files (shared within organisation)
436
+ (
437
+ organisation_id IS NOT NULL
438
+ AND is_authenticated_user()
439
+ AND (
440
+ is_super_admin(safe_get_user_id_for_rls())
441
+ OR check_user_organisation_access(organisation_id)
442
+ )
443
+ )
444
+ OR
445
+ -- User-scoped files (personal files)
446
+ (
447
+ organisation_id IS NULL
448
+ AND is_authenticated_user()
449
+ AND get_effective_user_id() = user_id
450
+ )
451
+ );
452
+
453
+ -- INSERT policy: Users can upload files to their organisation or personal storage
454
+ CREATE POLICY "rbac_insert_file_references" ON file_references
455
+ FOR INSERT TO authenticated
456
+ WITH CHECK (
457
+ -- Organisation-scoped: Must have organisation access
458
+ (
459
+ organisation_id IS NOT NULL
460
+ AND check_user_organisation_access(organisation_id)
461
+ )
462
+ OR
463
+ -- User-scoped: Must be own user_id
464
+ (
465
+ organisation_id IS NULL
466
+ AND get_effective_user_id() = user_id
467
+ )
468
+ );
469
+ ```
470
+
406
471
  ### Service Role Policy
407
472
 
408
473
  **Use Case:** Allow service_role to bypass RLS for system operations.
@@ -453,6 +518,66 @@ USING (
453
518
 
454
519
  **Example:** `event` (public events), `forms` (published forms)
455
520
 
521
+ **Real-World Example: Public Event Registration**
522
+
523
+ ```sql
524
+ -- Real-world example: Events table with public registration
525
+ -- Public users can view and register for public events
526
+ -- Authenticated users can view all events in their organisation
527
+
528
+ -- Public access: Anonymous users can view public events
529
+ CREATE POLICY "public_select_events" ON events
530
+ FOR SELECT TO anon
531
+ USING (
532
+ is_public = true
533
+ AND organisation_id IS NOT NULL
534
+ AND status = 'published'
535
+ );
536
+
537
+ -- Authenticated access: Users can view events in their organisation
538
+ CREATE POLICY "rbac_select_events" ON events
539
+ FOR SELECT TO authenticated
540
+ USING (
541
+ -- Public events (anyone can see)
542
+ (is_public = true AND organisation_id IS NOT NULL)
543
+ OR
544
+ -- Organisation events (members can see)
545
+ (
546
+ organisation_id IS NOT NULL
547
+ AND (
548
+ is_super_admin(safe_get_user_id_for_rls())
549
+ OR check_user_organisation_access(organisation_id)
550
+ )
551
+ )
552
+ );
553
+
554
+ -- Public registration: Anonymous users can create registrations for public events
555
+ CREATE POLICY "public_insert_event_registrations" ON event_registrations
556
+ FOR INSERT TO anon
557
+ WITH CHECK (
558
+ -- Only for public events
559
+ event_id IN (
560
+ SELECT id FROM events
561
+ WHERE is_public = true AND status = 'published'
562
+ )
563
+ );
564
+
565
+ -- Authenticated registration: Users can register for events in their organisation
566
+ CREATE POLICY "rbac_insert_event_registrations" ON event_registrations
567
+ FOR INSERT TO authenticated
568
+ WITH CHECK (
569
+ -- Must have access to the event's organisation
570
+ event_id IN (
571
+ SELECT id FROM events
572
+ WHERE organisation_id IS NOT NULL
573
+ AND (
574
+ is_super_admin(safe_get_user_id_for_rls())
575
+ OR check_user_organisation_access(organisation_id)
576
+ )
577
+ )
578
+ );
579
+ ```
580
+
456
581
  **Combined Public + Authenticated Pattern:**
457
582
  ```sql
458
583
  -- Public access
@@ -471,7 +596,7 @@ USING (
471
596
  OR (
472
597
  organisation_id IS NOT NULL
473
598
  AND (
474
- is_super_admin()
599
+ is_super_admin(safe_get_user_id_for_rls())
475
600
  OR check_user_organisation_access(organisation_id)
476
601
  )
477
602
  )
@@ -496,7 +621,7 @@ USING (
496
621
  is_authenticated_user()
497
622
  AND organisation_id IS NOT NULL
498
623
  AND (
499
- is_super_admin()
624
+ is_super_admin(safe_get_user_id_for_rls())
500
625
  OR check_user_organisation_access(organisation_id)
501
626
  )
502
627
  )
@@ -542,7 +667,7 @@ USING (is_authenticated_user());
542
667
  ```sql
543
668
  CREATE POLICY "rbac_select_table_name" ON table_name
544
669
  FOR SELECT TO authenticated
545
- USING (is_super_admin());
670
+ USING (is_super_admin(safe_get_user_id_for_rls()));
546
671
  ```
547
672
 
548
673
  **Example:** `rbac_global_roles`, `rbac_policy_configs`
@@ -552,20 +677,20 @@ USING (is_super_admin());
552
677
  -- All operations restricted to super admin
553
678
  CREATE POLICY "rbac_select_table_name" ON table_name
554
679
  FOR SELECT TO authenticated
555
- USING (is_super_admin());
680
+ USING (is_super_admin(safe_get_user_id_for_rls()));
556
681
 
557
682
  CREATE POLICY "rbac_insert_table_name" ON table_name
558
683
  FOR INSERT TO authenticated
559
- WITH CHECK (is_super_admin());
684
+ WITH CHECK (is_super_admin(safe_get_user_id_for_rls()));
560
685
 
561
686
  CREATE POLICY "rbac_update_table_name" ON table_name
562
687
  FOR UPDATE TO authenticated
563
- USING (is_super_admin())
564
- WITH CHECK (is_super_admin());
688
+ USING (is_super_admin(safe_get_user_id_for_rls()))
689
+ WITH CHECK (is_super_admin(safe_get_user_id_for_rls()));
565
690
 
566
691
  CREATE POLICY "rbac_delete_table_name" ON table_name
567
692
  FOR DELETE TO authenticated
568
- USING (is_super_admin());
693
+ USING (is_super_admin(safe_get_user_id_for_rls()));
569
694
  ```
570
695
 
571
696
  ### Common Patterns Summary
@@ -579,19 +704,122 @@ USING (is_super_admin());
579
704
  | Service Role | System operations | `is_service_role()` |
580
705
  | Public Access | Anonymous users | `check_public_event_access()` or `is_public` flag |
581
706
  | Read-Only Types | Reference tables | `is_authenticated_user()` |
582
- | Super Admin Only | Admin-only tables | `is_super_admin()` |
707
+ | Super Admin Only | Admin-only tables | `is_super_admin(safe_get_user_id_for_rls())` |
583
708
 
584
709
  ### Policy Best Practices
585
710
 
586
711
  1. **Always use helper functions** - Never inline `auth.uid()`, `auth.role()`, or `current_setting()`
587
712
  2. **Check NULL first** - Always check `organisation_id IS NOT NULL` before using it
588
- 3. **Super admin first** - Super admin checks should come before other checks in OR conditions
713
+ 3. **Super admin first** - Super admin checks should come before other checks in OR conditions. **MUST** use `is_super_admin(safe_get_user_id_for_rls())` with explicit parameter - never call without parameters.
589
714
  4. **Service role first** - Service role checks should be the first condition in multi-condition policies
590
715
  5. **Consistent naming** - Follow the naming convention: `rbac_{operation}_{table}_{scope}`
591
716
  6. **Document exceptions** - If a policy deviates from standard patterns, add a comment explaining why
592
717
  7. **Test thoroughly** - Test with different user roles (super_admin, org_admin, member, anon)
593
718
  8. **Avoid `true OR ...`** - Never use `true OR ...` conditions as they bypass all security checks
594
719
 
720
+ ## Edge Functions and Serverless Functions
721
+
722
+ **Edge Functions (Deno serverless functions) MUST use pace-core's `isPermitted()` API function.** Edge Functions cannot use React hooks, but pace-core provides programmatic APIs that work outside React.
723
+
724
+ ### ✅ CORRECT - Edge Function Pattern
725
+
726
+ ```typescript
727
+ // supabase/functions/my-function/index.ts
728
+ import { createClient } from 'jsr:@supabase/supabase-js@2';
729
+ import { setupRBAC, isPermitted } from 'npm:@jmruthers/pace-core@^0.6.0/rbac';
730
+
731
+ Deno.serve(async (req: Request) => {
732
+ // 1. Create Supabase client from request headers
733
+ const authHeader = req.headers.get('Authorization');
734
+ if (!authHeader) {
735
+ return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
736
+ }
737
+
738
+ const supabase = createClient(
739
+ Deno.env.get('SUPABASE_URL') ?? '',
740
+ Deno.env.get('SUPABASE_ANON_KEY') ?? '',
741
+ {
742
+ global: {
743
+ headers: { Authorization: authHeader },
744
+ },
745
+ }
746
+ );
747
+
748
+ // 2. Get user from session
749
+ const { data: { user } } = await supabase.auth.getUser();
750
+ if (!user) {
751
+ return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
752
+ }
753
+
754
+ // 3. Setup RBAC (required before using isPermitted)
755
+ setupRBAC(supabase);
756
+
757
+ // 4. Extract organisation context from request
758
+ const organisationId = req.headers.get('x-organisation-id') ||
759
+ (await req.json()).organisationId;
760
+
761
+ if (!organisationId) {
762
+ return new Response(JSON.stringify({ error: 'Organisation context required' }), { status: 400 });
763
+ }
764
+
765
+ // 5. Check permission using pace-core API
766
+ const hasPermission = await isPermitted({
767
+ userId: user.id,
768
+ scope: { organisationId },
769
+ permission: 'read:dashboard',
770
+ pageId: 'dashboard'
771
+ });
772
+
773
+ if (!hasPermission) {
774
+ return new Response(JSON.stringify({ error: 'Permission denied' }), { status: 403 });
775
+ }
776
+
777
+ // 6. Proceed with function logic
778
+ return new Response(JSON.stringify({ success: true }));
779
+ });
780
+ ```
781
+
782
+ ### ❌ FORBIDDEN - Custom RBAC Helper in Edge Functions
783
+
784
+ **Creating custom RBAC helper functions in Edge Functions is FORBIDDEN.** pace-core provides all necessary APIs.
785
+
786
+ ```typescript
787
+ // ❌ FORBIDDEN - Custom RBAC helper
788
+ // supabase/functions/_shared/rbac.ts
789
+ export async function checkPermission(userId: string, permission: string) {
790
+ // Custom logic that bypasses pace-core
791
+ const { data } = await supabase.rpc('rbac_check_permission_simplified', {
792
+ p_user_id: userId,
793
+ p_permission: permission
794
+ });
795
+ return data;
796
+ }
797
+ ```
798
+
799
+ ### Why No Exceptions
800
+
801
+ - pace-core provides `isPermitted()` API that works outside React
802
+ - `setupRBAC()` initializes the engine with a Supabase client
803
+ - No custom helpers needed - use pace-core APIs directly
804
+ - Custom helpers bypass security validation, caching, and audit logging
805
+
806
+ ### Edge Function Requirements
807
+
808
+ 1. **MUST** call `setupRBAC(supabase)` before using `isPermitted()`
809
+ 2. **MUST** extract `userId` from Supabase auth session
810
+ 3. **MUST** extract `organisationId` from request (headers, body, or query params)
811
+ 4. **MUST** use `isPermitted()` with complete `PermissionCheck` input
812
+ 5. **MUST NOT** create custom RBAC helper functions
813
+ 6. **MUST NOT** call `rbac_check_permission_simplified` RPC directly
814
+
815
+ ## Security Baseline
816
+
817
+ - Never bypass RLS; validate all inputs and sanitize logs (no tokens/PII).
818
+ - Use safe, user-friendly error messaging.
819
+ - Prefer pace-core security helpers and secure clients (`useSecureSupabase`, RBAC helpers) over custom implementations.
820
+ - Monitor RLS performance (avoid subqueries/InitPlan); keep helpers `STABLE SECURITY DEFINER` with `SET search_path TO public`.
821
+ - **Edge Functions MUST use pace-core `isPermitted()` API - no exceptions allowed.**
822
+
595
823
  ### Common Pitfalls to Avoid
596
824
 
597
825
  **❌ DON'T:**
@@ -648,29 +876,23 @@ Tables are assigned to specific apps for RBAC permission checking:
648
876
 
649
877
  ### Before Merging RLS Changes
650
878
 
651
- 1. **Run RLS Compliance Audit**:
652
- ```bash
653
- npm run audit:rls
654
- ```
655
- This checks for violations and should pass with zero violations.
656
-
657
- 2. **Run Supabase Advisors**:
879
+ 1. **Run Supabase Advisors**:
658
880
  ```bash
659
881
  supabase advisors performance
660
882
  supabase advisors security
661
883
  ```
662
884
 
663
- 3. **Run Database Tests**:
885
+ 2. **Run Database Tests**:
664
886
  ```bash
665
887
  timeout 120 npm run test:db
666
888
  ```
667
889
 
668
- 4. **Run Application Tests**:
890
+ 3. **Run Application Tests**:
669
891
  ```bash
670
892
  timeout 60 npm run test
671
893
  ```
672
894
 
673
- 5. **Verify Performance**:
895
+ 4. **Verify Performance**:
674
896
  - Use EXPLAIN ANALYZE to verify no InitPlan nodes
675
897
  - Verify queries complete in < 1 second
676
898
  - Check Supabase Advisors show zero `auth_rls_initplan` warnings
@@ -686,32 +908,9 @@ Tables are assigned to specific apps for RBAC permission checking:
686
908
 
687
909
  ### Ongoing RLS Compliance Monitoring
688
910
 
689
- **Run RLS audit regularly** to catch any rogue policies that violate standards:
690
-
691
- ```bash
692
- # Quick audit (recommended before merging PRs)
693
- npm run audit:rls
694
-
695
- # Or use test database
696
- npm run audit:rls:test
697
-
698
- # For CI/CD (fails on violations)
699
- npm run audit:rls:ci
700
- ```
701
-
702
- The audit checks for:
703
- - Tables with RLS enabled but no policies
704
- - Policies using inline `auth.uid()` calls
705
- - Policies using `current_setting()` directly
706
- - Helper functions missing STABLE/SECURITY DEFINER
707
-
708
- ### Weekly Health Checks
911
+ **Run Supabase advisors regularly** to catch any rogue policies that violate standards:
709
912
 
710
- Run weekly:
711
913
  ```bash
712
- # RLS compliance audit
713
- npm run audit:rls
714
-
715
914
  # Performance advisors
716
915
  supabase advisors performance
717
916
 
@@ -772,8 +971,12 @@ date +"%Y%m%d%H%M%S"
772
971
 
773
972
  ## Related Documentation
774
973
 
775
- - [Security Standard](./05-security-standard.md)
776
- - [RLS Policy Remediation Plan](../troubleshooting/rls-policy-remediation-plan-combined.md)
777
- - [Database Unhealthiness Diagnosis](../troubleshooting/database-unhealthiness-diagnosis.md)
778
- - [RBAC-RLS Integration Guide](../rbac/rbac-rls-integration.md)
974
+ - [Standards Overview](./0-standards-overview.md) - Standards system overview
975
+ - [pace-core Compliance](./1-pace-core-compliance-standards.md) - Secure Supabase client usage
976
+ - [Operations](./9-operations-standards.md) - General performance patterns (React, caching, etc.)
977
+
978
+ ---
779
979
 
980
+ **Last Updated:** 2025-01-28
981
+ **Version:** 2.0.0
982
+ **Applies to:** All pace-core and consuming apps