create-lego-one 2.0.12 → 2.0.13

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 (78) hide show
  1. package/dist/index.cjs +34 -0
  2. package/dist/index.cjs.map +1 -1
  3. package/package.json +1 -1
  4. package/template/.cursor/rules/rules.mdc +639 -0
  5. package/template/.dockerignore +58 -0
  6. package/template/.env.example +18 -0
  7. package/template/.eslintignore +5 -0
  8. package/template/.eslintrc.js +28 -0
  9. package/template/.prettierignore +6 -0
  10. package/template/.prettierrc +11 -0
  11. package/template/CLAUDE.md +634 -0
  12. package/template/Dockerfile +67 -0
  13. package/template/PROMPT.md +457 -0
  14. package/template/README.md +325 -0
  15. package/template/docker-compose.yml +48 -0
  16. package/template/docker-entrypoint.sh +23 -0
  17. package/template/docs/checkpoints/.template.md +64 -0
  18. package/template/docs/checkpoints/framework/01-infrastructure-setup.md +132 -0
  19. package/template/docs/checkpoints/framework/02-pocketbase-setup.md +155 -0
  20. package/template/docs/checkpoints/framework/03-host-kernel.md +170 -0
  21. package/template/docs/checkpoints/framework/04-auth-system.md +163 -0
  22. package/template/docs/checkpoints/framework/phase-05-multitenancy-rbac.md +223 -0
  23. package/template/docs/checkpoints/framework/phase-06-ui-components.md +260 -0
  24. package/template/docs/checkpoints/framework/phase-07-communication-system.md +276 -0
  25. package/template/docs/checkpoints/framework/phase-08-plugin-system.md +91 -0
  26. package/template/docs/checkpoints/framework/phase-09-dashboard-plugin.md +111 -0
  27. package/template/docs/checkpoints/framework/phase-10-todo-plugin.md +169 -0
  28. package/template/docs/checkpoints/framework/phase-11-testing.md +264 -0
  29. package/template/docs/checkpoints/framework/phase-12-deployment.md +294 -0
  30. package/template/docs/checkpoints/framework/phase-13-documentation.md +312 -0
  31. package/template/docs/framework/plans/00-index.md +164 -0
  32. package/template/docs/framework/plans/01-infrastructure-setup.md +855 -0
  33. package/template/docs/framework/plans/02-pocketbase-setup.md +1374 -0
  34. package/template/docs/framework/plans/03-host-kernel.md +1518 -0
  35. package/template/docs/framework/plans/04-auth-system.md +1466 -0
  36. package/template/docs/framework/plans/05-multitenancy-rbac.md +1527 -0
  37. package/template/docs/framework/plans/06-ui-components.md +1478 -0
  38. package/template/docs/framework/plans/07-communication-system.md +1106 -0
  39. package/template/docs/framework/plans/08-plugin-system.md +1179 -0
  40. package/template/docs/framework/plans/09-dashboard-plugin.md +1137 -0
  41. package/template/docs/framework/plans/10-todo-plugin.md +1343 -0
  42. package/template/docs/framework/plans/11-testing.md +935 -0
  43. package/template/docs/framework/plans/12-deployment.md +896 -0
  44. package/template/docs/framework/prompts/0-boilerplate-modernjs.md +151 -0
  45. package/template/docs/framework/research/00-modernjs-audit.md +488 -0
  46. package/template/docs/framework/research/01-system-blueprint.md +721 -0
  47. package/template/docs/framework/research/02-data-migration-protocol.md +699 -0
  48. package/template/docs/framework/research/03-host-setup.md +714 -0
  49. package/template/docs/framework/research/04-plugin-architecture.md +645 -0
  50. package/template/docs/framework/research/05-slot-injection-pattern.md +671 -0
  51. package/template/docs/framework/research/06-cli-strategy.md +615 -0
  52. package/template/docs/framework/research/07-deployment.md +629 -0
  53. package/template/docs/framework/research/README.md +282 -0
  54. package/template/docs/framework/setup/00-index.md +210 -0
  55. package/template/docs/framework/setup/01-framework-structure.md +308 -0
  56. package/template/docs/framework/setup/02-development-workflow.md +405 -0
  57. package/template/docs/framework/setup/03-environment-setup.md +215 -0
  58. package/template/docs/framework/setup/04-kernel-architecture.md +499 -0
  59. package/template/docs/framework/setup/05-plugin-system.md +620 -0
  60. package/template/docs/framework/setup/06-communication-patterns.md +451 -0
  61. package/template/docs/framework/setup/07-plugin-development.md +582 -0
  62. package/template/docs/framework/setup/08-component-library.md +658 -0
  63. package/template/docs/framework/setup/09-data-integration.md +609 -0
  64. package/template/docs/framework/setup/10-auth-rbac.md +497 -0
  65. package/template/docs/framework/setup/11-hooks-api.md +393 -0
  66. package/template/docs/framework/setup/12-components-api.md +665 -0
  67. package/template/docs/framework/setup/13-deployment-guide.md +566 -0
  68. package/template/docs/framework/setup/README.md +548 -0
  69. package/template/host/package.json +1 -1
  70. package/template/nginx.conf +72 -0
  71. package/template/package.json +1 -1
  72. package/template/packages/plugins/@lego/plugin-dashboard/package.json +1 -1
  73. package/template/packages/plugins/@lego/plugin-todo/package.json +1 -1
  74. package/template/pocketbase/CHANGELOG.md +911 -0
  75. package/template/pocketbase/LICENSE.md +17 -0
  76. package/template/scripts/create-plugin.js +221 -0
  77. package/template/scripts/deploy.sh +56 -0
  78. package/template/tsconfig.base.json +26 -0
@@ -0,0 +1,497 @@
1
+ # Authentication & RBAC
2
+
3
+ **Authentication, Authorization, and Permission Management**
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ Lego-One provides complete authentication via PocketBase and Role-Based Access Control (RBAC) with organizations, roles, and permissions. All features are multi-tenant aware.
10
+
11
+ ---
12
+
13
+ ## Authentication System
14
+
15
+ ### PocketBase Auth
16
+
17
+ **Collection:** `users`
18
+
19
+ **Auth Methods:**
20
+ - Email/password (via PocketBase)
21
+ - Token persistence (localStorage)
22
+ - Auto-refresh on app load
23
+
24
+ ### Auth Hooks
25
+
26
+ #### useAuth()
27
+
28
+ **Import:** `import { useAuth } from '@lego/kernel/auth'`
29
+
30
+ **Returns:**
31
+ ```typescript
32
+ {
33
+ user: User | null; // Current user
34
+ token: string | null; // Auth token
35
+ isAuthenticated: boolean; // Auth status
36
+ isLoading: boolean; // Loading state
37
+ login: (email, password) => Promise<void>;
38
+ register: (data) => Promise<void>;
39
+ logout: () => void;
40
+ updateProfile: (data) => Promise<void>;
41
+ }
42
+ ```
43
+
44
+ **Usage:**
45
+ ```typescript
46
+ function MyComponent() {
47
+ const { user, isAuthenticated, logout } = useAuth();
48
+
49
+ if (!isAuthenticated) {
50
+ return <div>Please log in</div>;
51
+ }
52
+
53
+ return (
54
+ <div>
55
+ Welcome, {user?.name}
56
+ <button onClick={logout}>Logout</button>
57
+ </div>
58
+ );
59
+ }
60
+ ```
61
+
62
+ ---
63
+
64
+ #### useRequireAuth()
65
+
66
+ **Purpose:** Automatically redirects to sign-in if not authenticated
67
+
68
+ ```typescript
69
+ function ProtectedPage() {
70
+ useRequireAuth(); // Redirects to /sign-in if not authenticated
71
+
72
+ return <div>Protected content</div>;
73
+ }
74
+ ```
75
+
76
+ ---
77
+
78
+ ### Protected Routes
79
+
80
+ **In Host (modern.runtime.ts):**
81
+ Routes with `protected: true` require authentication.
82
+
83
+ ```typescript
84
+ routes: [
85
+ {
86
+ path: '/dashboard',
87
+ component: () => import('./pages/DashboardPage'),
88
+ protected: true, // Requires auth
89
+ },
90
+ ]
91
+ ```
92
+
93
+ **In Plugins:**
94
+ Plugins declare route protection in `plugin.config.ts`:
95
+
96
+ ```typescript
97
+ routes: [
98
+ {
99
+ path: '/my-plugin',
100
+ component: () => import('./pages/MyPluginPage'),
101
+ protected: true, // Host will enforce this
102
+ },
103
+ ]
104
+ ```
105
+
106
+ ---
107
+
108
+ ## RBAC System
109
+
110
+ ### System Roles
111
+
112
+ | Role | Description | Permissions |
113
+ |------|-------------|-------------|
114
+ | `Owner` | Organization owner | Full access (all:all) |
115
+ | `Admin` | Organization admin | Users, roles, todos, settings |
116
+ | `Member` | Regular member | Todos, read-only access |
117
+ | `Guest` | Limited access | Read-only todos |
118
+
119
+ ### Permission Format
120
+
121
+ **Resource:** What you're accessing (e.g., 'todos', 'users', 'settings')
122
+
123
+ **Action:** What you're doing (e.g., 'read', 'write', 'delete', 'manage')
124
+
125
+ **Examples:**
126
+ - `todos.read` - Can view todos
127
+ - `todos.write` - Can create/edit todos
128
+ - `todos.delete` - Can delete todos
129
+ - `users.manage` - Full user management
130
+ - `settings.read` - Can view settings
131
+
132
+ ---
133
+
134
+ ### RBAC Hooks
135
+
136
+ #### useCurrentOrganization()
137
+
138
+ **Purpose:** Get/set current organization context
139
+
140
+ ```typescript
141
+ import { useCurrentOrganization } from '@lego/kernel/rbac';
142
+
143
+ function OrgSelector() {
144
+ const { organization, setCurrentOrganization } = useCurrentOrganization();
145
+
146
+ return (
147
+ <select value={organization?.id} onChange={(e) => {
148
+ const org = organizations.find(o => o.id === e.target.value);
149
+ setCurrentOrganization(org);
150
+ }}>
151
+ {organizations.map(org => (
152
+ <option key={org.id} value={org.id}>{org.name}</option>
153
+ ))}
154
+ </select>
155
+ );
156
+ }
157
+ ```
158
+
159
+ ---
160
+
161
+ #### useHasPermission()
162
+
163
+ **Purpose:** Check if user has specific permission
164
+
165
+ ```typescript
166
+ import { useHasPermission } from '@lego/kernel/rbac';
167
+
168
+ function DeleteButton({ todoId }: { todoId: string }) {
169
+ const checkPermission = useHasPermission();
170
+ const [hasPermission, setHasPermission] = useState(false);
171
+
172
+ useEffect(() => {
173
+ checkPermission('todos', 'delete').then(setHasPermission);
174
+ }, [checkPermission]);
175
+
176
+ if (!hasPermission) return null;
177
+
178
+ return <button>Delete Todo</button>;
179
+ }
180
+ ```
181
+
182
+ ---
183
+
184
+ #### useRequirePermission()
185
+
186
+ **Purpose:** Check permission and return loading state
187
+
188
+ ```typescript
189
+ import { useRequirePermission } from '@lego/kernel/rbac';
190
+
191
+ function AdminPanel() {
192
+ const { hasPermission, isLoading } = useRequirePermission('users', 'write');
193
+
194
+ if (isLoading) return <div>Loading...</div>;
195
+ if (!hasPermission) return <div>Access denied</div>;
196
+
197
+ return <div>Admin content</div>;
198
+ }
199
+ ```
200
+
201
+ ---
202
+
203
+ #### useUserPermissions()
204
+
205
+ **Purpose:** Get all user permissions for current organization
206
+
207
+ ```typescript
208
+ import { useUserPermissions } from '@lego/kernel/rbac';
209
+
210
+ function PermissionDebug() {
211
+ const { data: permissions } = useUserPermissions();
212
+
213
+ return (
214
+ <div>
215
+ <h4>Your Permissions:</h4>
216
+ <ul>
217
+ {permissions?.map(p => (
218
+ <li key={`${p.resource}:${p.action}`}>
219
+ {p.resource}:{p.action}
220
+ </li>
221
+ ))}
222
+ </ul>
223
+ </div>
224
+ );
225
+ }
226
+ ```
227
+
228
+ ---
229
+
230
+ #### useOrganizations()
231
+
232
+ **Purpose:** Get all user's organizations
233
+
234
+ ```typescript
235
+ import { useOrganizations } from '@lego/kernel/rbac';
236
+
237
+ function OrganizationSwitcher() {
238
+ const { data: organizations } = useOrganizations();
239
+ const { setCurrentOrganization } = useCurrentOrganization();
240
+
241
+ return (
242
+ <select onChange={(e) => {
243
+ const org = organizations?.find(o => o.id === e.target.value);
244
+ setCurrentOrganization(org);
245
+ }}>
246
+ {organizations?.map(org => (
247
+ <option key={org.id} value={org.id}>{org.name}</option>
248
+ ))}
249
+ </select>
250
+ );
251
+ }
252
+ ```
253
+
254
+ ---
255
+
256
+ ### Permission Gate Component
257
+
258
+ **Purpose:** Conditionally render based on permission
259
+
260
+ ```typescript
261
+ import { PermissionGate } from '@lego/kernel/rbac';
262
+
263
+ function MyComponent() {
264
+ return (
265
+ <PermissionGate resource="todos" action="write">
266
+ <Button>Create Todo</Button>
267
+ </PermissionGate>
268
+ );
269
+ }
270
+ ```
271
+
272
+ **With Custom Fallback:**
273
+ ```typescript
274
+ <PermissionGate
275
+ resource="todos"
276
+ action="delete"
277
+ fallback={<span className="text-muted-foreground">Insufficient permissions</span>}
278
+ >
279
+ <Button>Delete Todo</Button>
280
+ </PermissionGate>
281
+ ```
282
+
283
+ ---
284
+
285
+ ## Organization Management
286
+
287
+ ### Creating Organizations
288
+
289
+ ```typescript
290
+ import { useCreateOrganization } from '@lego/kernel/rbac';
291
+
292
+ function CreateOrganizationForm() {
293
+ const { mutate: createOrg, isPending } = useCreateOrganization();
294
+
295
+ const handleSubmit = (data: { name: string; slug: string }) => {
296
+ createOrg(data, {
297
+ onSuccess: (org) => {
298
+ console.log('Organization created:', org);
299
+ // Switch to new organization
300
+ setCurrentOrganization(org);
301
+ },
302
+ });
303
+ };
304
+
305
+ return (
306
+ <form onSubmit={handleSubmit}>
307
+ <input name="name" placeholder="Organization Name" />
308
+ <input name="slug" placeholder="Slug" />
309
+ <button disabled={isPending}>
310
+ {isPending ? 'Creating...' : 'Create Organization'}
311
+ </button>
312
+ </form>
313
+ );
314
+ }
315
+ ```
316
+
317
+ ### Organization Selector Component
318
+
319
+ **Built-in component:** `OrganizationSelector`
320
+
321
+ **Import:** `import { OrganizationSelector } from '@lego/kernel/rbac'`
322
+
323
+ ```typescript
324
+ import { OrganizationSelector } from '@lego/kernel/rbac';
325
+
326
+ function Topbar() {
327
+ return (
328
+ <header>
329
+ <OrganizationSelector />
330
+ </header>
331
+ );
332
+ }
333
+ ```
334
+
335
+ ---
336
+
337
+ ## User Management
338
+
339
+ ### Getting Organization Users
340
+
341
+ ```typescript
342
+ import { useOrganizationUsers } from '@lego/kernel/rbac';
343
+
344
+ function UserList() {
345
+ const { data: users } = useOrganizationUsers(orgId);
346
+
347
+ return (
348
+ <table>
349
+ <thead>
350
+ <tr>
351
+ <th>Name</th>
352
+ <th>Email</th>
353
+ <th>Roles</th>
354
+ </tr>
355
+ </thead>
356
+ <tbody>
357
+ {users?.map(user => (
358
+ <tr key={user.id}>
359
+ <td>{user.name}</td>
360
+ <td>{user.email}</td>
361
+ <td>{user.roles.map(r => r.name).join(', ')}</td>
362
+ </tr>
363
+ ))}
364
+ </tbody>
365
+ </table>
366
+ );
367
+ }
368
+ ```
369
+
370
+ ### Assigning Roles
371
+
372
+ ```typescript
373
+ import { useAssignRole } from '@lego/kernel/rbac';
374
+
375
+ function RoleSelector({ userId, organizationId }: Props) {
376
+ const { mutate: assignRole } = useAssignRole();
377
+ const { data: roles } = useOrganizationRoles(organizationId);
378
+
379
+ return (
380
+ <select onChange={(e) => {
381
+ assignRole({
382
+ userId,
383
+ roleId: e.target.value,
384
+ organizationId,
385
+ });
386
+ }}>
387
+ {roles?.map(role => (
388
+ <option key={role.id} value={role.id}>{role.name}</option>
389
+ ))}
390
+ </select>
391
+ );
392
+ }
393
+ ```
394
+
395
+ ---
396
+
397
+ ## Plugin Permissions
398
+
399
+ ### Declaring Required Permissions
400
+
401
+ In `plugin.config.ts`:
402
+
403
+ ```typescript
404
+ export const pluginConfig: PluginConfig = {
405
+ manifest: {
406
+ name: '@lego/plugin-todo',
407
+ permissions: [
408
+ 'todos.read', // Required to view todos
409
+ 'todos.write', // Required to create/edit todos
410
+ 'todos.delete', // Required to delete todos
411
+ ],
412
+ },
413
+ // ...
414
+ };
415
+ ```
416
+
417
+ ### Checking Permissions in Plugins
418
+
419
+ ```typescript
420
+ import { useRequirePermission } from '@lego/kernel/rbac';
421
+
422
+ function TodoPage() {
423
+ const { hasPermission: canRead } = useRequirePermission('todos', 'read');
424
+ const { hasPermission: canWrite } = useRequirePermission('todos', 'write');
425
+ const { hasPermission: canDelete } = useRequirePermission('todos', 'delete');
426
+
427
+ if (!canRead) {
428
+ return <div>You don't have permission to view todos</div>;
429
+ }
430
+
431
+ return (
432
+ <div>
433
+ {canWrite && <Button>Create Todo</Button>}
434
+ {/* Todo list */}
435
+ {canDelete && <Button>Delete Selected</Button>}
436
+ </div>
437
+ );
438
+ }
439
+ ```
440
+
441
+ ---
442
+
443
+ ## PocketBase API Rules
444
+
445
+ ### Collection API Rules
446
+
447
+ **These rules enforce data isolation and permissions at the database level:**
448
+
449
+ ```javascript
450
+ {
451
+ name: 'todos',
452
+
453
+ // List: Users can view todos if they're in the org
454
+ listRule: '@request.auth.id != "" && organizationId = @request.auth.membership.organizations',
455
+
456
+ // View: Same as list
457
+ viewRule: '@request.auth.id != "" && organizationId = @request.auth.memberships.organizations',
458
+
459
+ // Create: Users can create todos in their orgs
460
+ createRule: '@request.auth.id != "" && organizationId = @request.auth.memberships.organizations',
461
+
462
+ // Update: Only todo owner can update
463
+ updateRule: '@request.auth.id != "" && organizationId = @request.auth.memberships.organizations && ownerId = @request.auth.id',
464
+
465
+ // Delete: Only todo owner can delete
466
+ deleteRule: '@request.auth.id != "" && organizationId = @request.auth.memberships.organizations && ownerId = @request.auth.id',
467
+ }
468
+ ```
469
+
470
+ ---
471
+
472
+ ## Best Practices
473
+
474
+ ### Authentication
475
+
476
+ 1. **Always check `isAuthenticated`** before showing protected content
477
+ 2. **Use `useRequireAuth()`** for protected pages
478
+ 3. **Handle loading states** during auth checks
479
+ 4. **Clear sensitive data** on logout
480
+
481
+ ### Authorization
482
+
483
+ 1. **Scope all data to organization** - Always filter by `organizationId`
484
+ 2. **Check permissions before actions** - Use `useHasPermission()` or `PermissionGate`
485
+ 3. **Declare plugin permissions** - In `plugin.config.ts`
486
+ 4. **Use system roles** - Don't create roles unless needed
487
+
488
+ ### Multi-Tenancy
489
+
490
+ 1. **Always get org from kernel state** - Don't hardcode org IDs
491
+ 2. **Subscribe to org changes** - Refresh data when org changes
492
+ 3. **Include org in all queries** - Filter by `organizationId`
493
+ 4. **Set org on create** - Always set `organizationId` when creating records
494
+
495
+ ---
496
+
497
+ **Next:** Read [`11-hooks-api.md`](./11-hooks-api.md) for complete hooks reference.