@jmruthers/pace-core 0.5.39 → 0.5.41

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 (101) hide show
  1. package/dist/rbac/cli/policy-manager.js +278 -0
  2. package/dist/rbac/cli/policy-manager.js.map +1 -0
  3. package/docs/api/classes/ErrorBoundary.md +1 -1
  4. package/docs/api/classes/InvalidScopeError.md +1 -1
  5. package/docs/api/classes/MissingUserContextError.md +1 -1
  6. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  7. package/docs/api/classes/PermissionDeniedError.md +1 -1
  8. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  9. package/docs/api/classes/RBACAuditManager.md +1 -1
  10. package/docs/api/classes/RBACCache.md +1 -1
  11. package/docs/api/classes/RBACEngine.md +1 -1
  12. package/docs/api/classes/RBACError.md +1 -1
  13. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  14. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  15. package/docs/api/interfaces/AggregateConfig.md +1 -1
  16. package/docs/api/interfaces/ButtonProps.md +1 -1
  17. package/docs/api/interfaces/CardProps.md +1 -1
  18. package/docs/api/interfaces/ColorPalette.md +1 -1
  19. package/docs/api/interfaces/ColorShade.md +1 -1
  20. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  21. package/docs/api/interfaces/DataTableAction.md +1 -1
  22. package/docs/api/interfaces/DataTableColumn.md +1 -1
  23. package/docs/api/interfaces/DataTableProps.md +1 -1
  24. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  25. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  26. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  27. package/docs/api/interfaces/EventContextType.md +1 -1
  28. package/docs/api/interfaces/EventLogoProps.md +1 -1
  29. package/docs/api/interfaces/EventProviderProps.md +1 -1
  30. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  31. package/docs/api/interfaces/FileUploadProps.md +1 -1
  32. package/docs/api/interfaces/FooterProps.md +1 -1
  33. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  34. package/docs/api/interfaces/InputProps.md +1 -1
  35. package/docs/api/interfaces/LabelProps.md +1 -1
  36. package/docs/api/interfaces/LoginFormProps.md +1 -1
  37. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  38. package/docs/api/interfaces/NavigationContextType.md +1 -1
  39. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  40. package/docs/api/interfaces/NavigationItem.md +1 -1
  41. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  42. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  43. package/docs/api/interfaces/Organisation.md +1 -1
  44. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  45. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  46. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  47. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  48. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  49. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  50. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  51. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  52. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  53. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  54. package/docs/api/interfaces/PaletteData.md +1 -1
  55. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  56. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  57. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  58. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  59. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  60. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  61. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  62. package/docs/api/interfaces/RBACConfig.md +1 -1
  63. package/docs/api/interfaces/RBACContextType.md +1 -1
  64. package/docs/api/interfaces/RBACLogger.md +1 -1
  65. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  66. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  67. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  68. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  69. package/docs/api/interfaces/RouteConfig.md +1 -1
  70. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  71. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  72. package/docs/api/interfaces/StorageConfig.md +1 -1
  73. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  74. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  75. package/docs/api/interfaces/StorageListOptions.md +1 -1
  76. package/docs/api/interfaces/StorageListResult.md +1 -1
  77. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  78. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  79. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  80. package/docs/api/interfaces/StyleImport.md +1 -1
  81. package/docs/api/interfaces/ToastActionElement.md +1 -1
  82. package/docs/api/interfaces/ToastProps.md +1 -1
  83. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  84. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  85. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  86. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  87. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  88. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  89. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  90. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  91. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  92. package/docs/api/interfaces/UserEventAccess.md +1 -1
  93. package/docs/api/interfaces/UserMenuProps.md +1 -1
  94. package/docs/api/interfaces/UserProfile.md +1 -1
  95. package/docs/api/modules.md +2 -2
  96. package/docs/implementation-guides/data-tables.md +189 -0
  97. package/docs/rbac/README-rbac-rls-integration.md +358 -0
  98. package/docs/rbac/examples/rbac-rls-integration-example.md +332 -0
  99. package/docs/rbac/rbac-rls-integration.md +377 -0
  100. package/package.json +19 -3
  101. package/src/rbac/cli/policy-manager.ts +443 -0
@@ -0,0 +1,377 @@
1
+ # RBAC-RLS Integration: Dynamic Permission Enforcement
2
+
3
+ This document explains how to use the new RBAC-RLS integration system that allows dynamic permission enforcement based on configurable RBAC settings instead of hardcoded RLS policies.
4
+
5
+ ## Overview
6
+
7
+ The RBAC-RLS integration solves the critical architectural issue where:
8
+ - **RBAC permissions are configurable** - Organizations can set which roles have which CRUD permissions for each page
9
+ - **RLS policies were hardcoded** - Database-level security policies were static and didn't respect the dynamic RBAC configuration
10
+ - **Result:** Users with valid RBAC permissions were blocked by RLS policies, breaking core functionality
11
+
12
+ ## Key Features
13
+
14
+ ### 1. Dynamic Permission Checking
15
+ - **`check_rbac_permission()`** - Checks permissions for basic operations
16
+ - **`check_rbac_permission_with_context()`** - Checks permissions with resource context
17
+ - Both functions respect the current RBAC configuration in real-time
18
+
19
+ ### 2. Automatic Policy Management
20
+ - **`create_rbac_rls_policy()`** - Creates RBAC-aware RLS policies
21
+ - **`update_rbac_policies_for_table()`** - Updates policies for a specific table
22
+ - **`update_all_rbac_policies()`** - Updates all registered policies
23
+
24
+ ### 3. Change Detection
25
+ - Automatic policy updates when RBAC permissions change
26
+ - Audit logging of all policy changes
27
+ - Health monitoring and validation
28
+
29
+ ## Quick Start
30
+
31
+ ### 1. Basic Usage
32
+
33
+ ```sql
34
+ -- Check if current user can delete meals
35
+ SELECT check_rbac_permission_with_context(
36
+ 'delete', -- operation
37
+ 'meals', -- page name
38
+ 'org-uuid-here', -- organisation_id
39
+ 'event-123', -- event_id (optional)
40
+ 'CAKE' -- app name
41
+ );
42
+ ```
43
+
44
+ ### 2. Creating RBAC-Aware Policies
45
+
46
+ ```sql
47
+ -- Create policies for a table
48
+ SELECT create_rbac_rls_policy(
49
+ 'cake_meal', -- table name
50
+ 'delete', -- operation
51
+ 'meals', -- page name
52
+ 'rbac_delete_meals', -- policy name (optional)
53
+ 'organisation_id', -- organisation column
54
+ 'meal_event_id', -- event column (optional)
55
+ 'CAKE' -- app name
56
+ );
57
+ ```
58
+
59
+ ### 3. Registering Tables for Management
60
+
61
+ ```sql
62
+ -- Register a table for automatic policy management
63
+ SELECT register_rbac_table(
64
+ 'cake_meal', -- table name
65
+ 'meals', -- page name
66
+ 'CAKE', -- app name
67
+ 'organisation_id', -- organisation column
68
+ 'meal_event_id', -- event column (optional)
69
+ ARRAY['read', 'create', 'update', 'delete'] -- operations
70
+ );
71
+ ```
72
+
73
+ ## API Reference
74
+
75
+ ### Core Functions
76
+
77
+ #### `check_rbac_permission(operation, page_name, event_id, organisation_id, app_name)`
78
+
79
+ Checks if the current user has permission for a specific operation on a page.
80
+
81
+ **Parameters:**
82
+ - `operation` (text): The operation to check ('read', 'create', 'update', 'delete')
83
+ - `page_name` (text): The page name to check permissions for
84
+ - `event_id` (text, optional): Event context for event-scoped permissions
85
+ - `organisation_id` (uuid, optional): Organisation context
86
+ - `app_name` (text, optional): App name (defaults to 'CAKE')
87
+
88
+ **Returns:** boolean
89
+
90
+ **Example:**
91
+ ```sql
92
+ SELECT check_rbac_permission('delete', 'meals', 'event-123', 'org-uuid', 'CAKE');
93
+ ```
94
+
95
+ #### `check_rbac_permission_with_context(operation, page_name, resource_organisation_id, resource_event_id, app_name)`
96
+
97
+ Checks RBAC permission with resource context, ensuring user has access to the specific resource.
98
+
99
+ **Parameters:**
100
+ - `operation` (text): The operation to check
101
+ - `page_name` (text): The page name to check permissions for
102
+ - `resource_organisation_id` (uuid): The organisation ID of the resource
103
+ - `resource_event_id` (text, optional): The event ID of the resource
104
+ - `app_name` (text, optional): App name (defaults to 'CAKE')
105
+
106
+ **Returns:** boolean
107
+
108
+ **Example:**
109
+ ```sql
110
+ SELECT check_rbac_permission_with_context(
111
+ 'delete', 'meals', resource.organisation_id, resource.meal_event_id, 'CAKE'
112
+ );
113
+ ```
114
+
115
+ ### Policy Management Functions
116
+
117
+ #### `create_rbac_rls_policy(table_name, operation, page_name, policy_name, organisation_column, event_column, app_name)`
118
+
119
+ Creates or replaces an RLS policy with RBAC-aware permission checking.
120
+
121
+ **Parameters:**
122
+ - `table_name` (text): Name of the table
123
+ - `operation` (text): Operation ('SELECT', 'INSERT', 'UPDATE', 'DELETE')
124
+ - `page_name` (text): Page name for permission checking
125
+ - `policy_name` (text, optional): Custom policy name
126
+ - `organisation_column` (text, optional): Organisation column name (defaults to 'organisation_id')
127
+ - `event_column` (text, optional): Event column name
128
+ - `app_name` (text, optional): App name (defaults to 'CAKE')
129
+
130
+ **Returns:** boolean
131
+
132
+ #### `update_rbac_policies_for_table(table_name, page_name, app_name)`
133
+
134
+ Updates all RBAC policies for a specific table.
135
+
136
+ **Parameters:**
137
+ - `table_name` (text): Name of the table
138
+ - `page_name` (text): Page name
139
+ - `app_name` (text, optional): App name (defaults to 'CAKE')
140
+
141
+ **Returns:** boolean
142
+
143
+ #### `update_all_rbac_policies()`
144
+
145
+ Updates RBAC policies for all registered tables.
146
+
147
+ **Returns:** Table with results for each table
148
+
149
+ ### Management Functions
150
+
151
+ #### `register_rbac_table(table_name, page_name, app_name, organisation_column, event_column, operations)`
152
+
153
+ Registers a table for RBAC policy management.
154
+
155
+ **Parameters:**
156
+ - `table_name` (text): Name of the table
157
+ - `page_name` (text): Page name
158
+ - `app_name` (text, optional): App name (defaults to 'CAKE')
159
+ - `organisation_column` (text, optional): Organisation column name (defaults to 'organisation_id')
160
+ - `event_column` (text, optional): Event column name
161
+ - `operations` (text[], optional): Array of operations (defaults to ['read', 'create', 'update', 'delete'])
162
+
163
+ **Returns:** boolean
164
+
165
+ ### Validation Functions
166
+
167
+ #### `validate_rbac_rls_consistency()`
168
+
169
+ Validates that RLS policies are consistent with RBAC configuration.
170
+
171
+ **Returns:** Table with validation results
172
+
173
+ #### `check_rbac_policy_health()`
174
+
175
+ Checks the health and consistency of RBAC policies.
176
+
177
+ **Returns:** Table with health check results
178
+
179
+ ## Migration Guide
180
+
181
+ ### From Hardcoded to Dynamic Policies
182
+
183
+ #### Before (Hardcoded)
184
+ ```sql
185
+ -- Old hardcoded policy
186
+ CREATE POLICY "Users can delete meals for their events" ON cake_meal
187
+ FOR DELETE TO public
188
+ USING (EXISTS (SELECT 1 FROM rbac_event_app_roles r
189
+ WHERE r.user_id = auth.uid()
190
+ AND r.event_id::text = cake_meal.meal_event_id::text
191
+ AND r.role = 'event_admin'::rbac_event_app_role));
192
+ ```
193
+
194
+ #### After (Dynamic)
195
+ ```sql
196
+ -- New RBAC-aware policy
197
+ CREATE POLICY "rbac_delete_meals" ON cake_meal
198
+ FOR DELETE
199
+ USING (
200
+ check_rbac_permission_with_context(
201
+ 'delete',
202
+ 'meals',
203
+ organisation_id,
204
+ meal_event_id,
205
+ 'CAKE'
206
+ )
207
+ );
208
+ ```
209
+
210
+ ### Migration Steps
211
+
212
+ 1. **Register your table:**
213
+ ```sql
214
+ SELECT register_rbac_table('your_table', 'your_page', 'YOUR_APP');
215
+ ```
216
+
217
+ 2. **Update policies:**
218
+ ```sql
219
+ SELECT update_rbac_policies_for_table('your_table', 'your_page', 'YOUR_APP');
220
+ ```
221
+
222
+ 3. **Verify the migration:**
223
+ ```sql
224
+ SELECT * FROM check_rbac_policy_health();
225
+ ```
226
+
227
+ ## Best Practices
228
+
229
+ ### 1. Policy Naming
230
+ - Use consistent naming: `rbac_{operation}_{page_name}`
231
+ - Example: `rbac_delete_meals`, `rbac_read_deliveries`
232
+
233
+ ### 2. Error Handling
234
+ - Always check return values from policy management functions
235
+ - Monitor the `rbac_policy_audit` table for errors
236
+ - Use health checks regularly
237
+
238
+ ### 3. Performance
239
+ - The RBAC functions are optimized for performance
240
+ - Consider caching for frequently accessed permissions
241
+ - Monitor query performance with large datasets
242
+
243
+ ### 4. Security
244
+ - Always use `check_rbac_permission_with_context()` for resource-specific operations
245
+ - Validate organisation and event context
246
+ - Test permission changes thoroughly
247
+
248
+ ## Troubleshooting
249
+
250
+ ### Common Issues
251
+
252
+ #### 1. Policies Not Created
253
+ **Problem:** `create_rbac_rls_policy()` returns false
254
+ **Solution:** Check that the table exists and you have proper permissions
255
+
256
+ #### 2. Permission Checks Fail
257
+ **Problem:** `check_rbac_permission()` returns false when it should return true
258
+ **Solution:**
259
+ - Verify the user has the correct role in `rbac_event_app_roles`
260
+ - Check that the page permissions exist in `rbac_page_permissions`
261
+ - Ensure the app and page are properly configured
262
+
263
+ #### 3. Policies Not Updating
264
+ **Problem:** Changes to RBAC permissions don't reflect in RLS policies
265
+ **Solution:**
266
+ - Check that the table is registered in `rbac_policy_configs`
267
+ - Verify the trigger is working: `SELECT * FROM rbac_policy_audit ORDER BY changed_at DESC LIMIT 10;`
268
+ - Manually update: `SELECT update_rbac_policies_for_table('table_name', 'page_name');`
269
+
270
+ ### Debugging
271
+
272
+ #### Check Policy Health
273
+ ```sql
274
+ SELECT * FROM check_rbac_policy_health();
275
+ ```
276
+
277
+ #### View Policy Audit Log
278
+ ```sql
279
+ SELECT * FROM rbac_policy_audit
280
+ ORDER BY changed_at DESC
281
+ LIMIT 20;
282
+ ```
283
+
284
+ #### Test Permission Check
285
+ ```sql
286
+ -- Test with specific user context
287
+ SELECT check_rbac_permission_with_context(
288
+ 'delete', 'meals', 'org-uuid', 'event-123', 'CAKE'
289
+ );
290
+ ```
291
+
292
+ ## Examples
293
+
294
+ ### Complete Table Migration
295
+
296
+ ```sql
297
+ -- 1. Register the table
298
+ SELECT register_rbac_table(
299
+ 'cake_meal',
300
+ 'meals',
301
+ 'CAKE',
302
+ 'organisation_id',
303
+ 'meal_event_id',
304
+ ARRAY['read', 'create', 'update', 'delete']
305
+ );
306
+
307
+ -- 2. Update policies
308
+ SELECT update_rbac_policies_for_table('cake_meal', 'meals', 'CAKE');
309
+
310
+ -- 3. Verify
311
+ SELECT * FROM check_rbac_policy_health()
312
+ WHERE table_name = 'cake_meal';
313
+ ```
314
+
315
+ ### Dynamic Permission Testing
316
+
317
+ ```sql
318
+ -- Test different scenarios
319
+ SELECT
320
+ 'planner delete meals' as test_case,
321
+ check_rbac_permission_with_context('delete', 'meals', 'org-uuid', 'event-123', 'CAKE') as result
322
+ UNION ALL
323
+ SELECT
324
+ 'planner delete deliveries',
325
+ check_rbac_permission_with_context('delete', 'deliveries', 'org-uuid', 'event-123', 'CAKE')
326
+ UNION ALL
327
+ SELECT
328
+ 'event_admin delete deliveries',
329
+ check_rbac_permission_with_context('delete', 'deliveries', 'org-uuid', 'event-123', 'CAKE');
330
+ ```
331
+
332
+ ## Monitoring and Maintenance
333
+
334
+ ### Regular Health Checks
335
+ ```sql
336
+ -- Run this regularly to ensure system health
337
+ SELECT * FROM validate_rbac_rls_consistency();
338
+ ```
339
+
340
+ ### Policy Audit
341
+ ```sql
342
+ -- Monitor policy changes
343
+ SELECT
344
+ table_name,
345
+ policy_name,
346
+ action,
347
+ changed_at,
348
+ success,
349
+ error_message
350
+ FROM rbac_policy_audit
351
+ ORDER BY changed_at DESC;
352
+ ```
353
+
354
+ ### Performance Monitoring
355
+ ```sql
356
+ -- Check for slow permission checks
357
+ SELECT
358
+ query,
359
+ calls,
360
+ total_time,
361
+ mean_time
362
+ FROM pg_stat_statements
363
+ WHERE query LIKE '%check_rbac_permission%'
364
+ ORDER BY mean_time DESC;
365
+ ```
366
+
367
+ ## Conclusion
368
+
369
+ The RBAC-RLS integration provides a robust, dynamic permission enforcement system that:
370
+
371
+ 1. **Respects RBAC configuration** - Policies automatically adapt to permission changes
372
+ 2. **Maintains security** - All permission checks are validated at the database level
373
+ 3. **Provides auditability** - Complete audit trail of all policy changes
374
+ 4. **Enables flexibility** - Organizations can configure permissions without code changes
375
+ 5. **Ensures consistency** - RBAC and RLS are always in sync
376
+
377
+ This system solves the critical architectural issue and provides a foundation for scalable, maintainable permission management across the entire pace suite.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmruthers/pace-core",
3
- "version": "0.5.39",
3
+ "version": "0.5.41",
4
4
  "description": "Clean, modern React component library with Tailwind v4 styling and native utilities",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -104,6 +104,10 @@
104
104
  "./source/rbac": {
105
105
  "import": "./src/rbac/index.ts",
106
106
  "default": "./src/rbac/index.ts"
107
+ },
108
+ "./rbac/cli": {
109
+ "import": "./dist/rbac/cli/policy-manager.js",
110
+ "default": "./dist/rbac/cli/policy-manager.js"
107
111
  }
108
112
  },
109
113
  "files": [
@@ -151,7 +155,15 @@
151
155
  "docs:generate": "node scripts/generate-docs.js generate",
152
156
  "docs:update-index": "node scripts/generate-docs.js update-index",
153
157
  "docs:generate-api": "node scripts/generate-docs.js generate-api",
154
- "docs:all": "node scripts/generate-docs.js all"
158
+ "docs:all": "node scripts/generate-docs.js all",
159
+ "_comment_rbac": "RBAC policy management utilities",
160
+ "rbac:list": "node dist/rbac/cli/policy-manager.js list",
161
+ "rbac:register": "node dist/rbac/cli/policy-manager.js register",
162
+ "rbac:update": "node dist/rbac/cli/policy-manager.js update",
163
+ "rbac:update-all": "node dist/rbac/cli/policy-manager.js update-all",
164
+ "rbac:health": "node dist/rbac/cli/policy-manager.js health",
165
+ "rbac:audit": "node dist/rbac/cli/policy-manager.js audit",
166
+ "rbac:test": "node dist/rbac/cli/policy-manager.js test"
155
167
  },
156
168
  "keywords": [
157
169
  "react",
@@ -209,6 +221,10 @@
209
221
  },
210
222
  "dependencies": {
211
223
  "@supabase/supabase-js": "^2.49.10",
212
- "@tanstack/react-query": "^5.56.2"
224
+ "@tanstack/react-query": "^5.56.2",
225
+ "commander": "^12.0.0",
226
+ "chalk": "^5.3.0",
227
+ "ora": "^8.0.1",
228
+ "cli-table3": "^0.6.3"
213
229
  }
214
230
  }