@prmichaelsen/acp-visualizer 0.1.0

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 (180) hide show
  1. package/README.md +68 -0
  2. package/agent/commands/acp.clarification-address.md +417 -0
  3. package/agent/commands/acp.clarification-capture.md +386 -0
  4. package/agent/commands/acp.clarification-create.md +437 -0
  5. package/agent/commands/acp.clarifications-research.md +326 -0
  6. package/agent/commands/acp.command-create.md +432 -0
  7. package/agent/commands/acp.design-create.md +286 -0
  8. package/agent/commands/acp.design-reference.md +355 -0
  9. package/agent/commands/acp.handoff.md +270 -0
  10. package/agent/commands/acp.index.md +423 -0
  11. package/agent/commands/acp.init.md +546 -0
  12. package/agent/commands/acp.package-create.md +895 -0
  13. package/agent/commands/acp.package-info.md +212 -0
  14. package/agent/commands/acp.package-install.md +539 -0
  15. package/agent/commands/acp.package-list.md +280 -0
  16. package/agent/commands/acp.package-publish.md +541 -0
  17. package/agent/commands/acp.package-remove.md +293 -0
  18. package/agent/commands/acp.package-search.md +307 -0
  19. package/agent/commands/acp.package-update.md +361 -0
  20. package/agent/commands/acp.package-validate.md +540 -0
  21. package/agent/commands/acp.pattern-create.md +386 -0
  22. package/agent/commands/acp.plan.md +587 -0
  23. package/agent/commands/acp.proceed.md +882 -0
  24. package/agent/commands/acp.project-create.md +675 -0
  25. package/agent/commands/acp.project-info.md +312 -0
  26. package/agent/commands/acp.project-list.md +226 -0
  27. package/agent/commands/acp.project-remove.md +379 -0
  28. package/agent/commands/acp.project-set.md +227 -0
  29. package/agent/commands/acp.project-update.md +307 -0
  30. package/agent/commands/acp.projects-restore.md +228 -0
  31. package/agent/commands/acp.projects-sync.md +347 -0
  32. package/agent/commands/acp.report.md +407 -0
  33. package/agent/commands/acp.resume.md +239 -0
  34. package/agent/commands/acp.sessions.md +301 -0
  35. package/agent/commands/acp.status.md +293 -0
  36. package/agent/commands/acp.sync.md +364 -0
  37. package/agent/commands/acp.task-create.md +500 -0
  38. package/agent/commands/acp.update.md +302 -0
  39. package/agent/commands/acp.validate.md +466 -0
  40. package/agent/commands/acp.version-check-for-updates.md +276 -0
  41. package/agent/commands/acp.version-check.md +191 -0
  42. package/agent/commands/acp.version-update.md +289 -0
  43. package/agent/commands/command.template.md +339 -0
  44. package/agent/commands/git.commit.md +526 -0
  45. package/agent/commands/git.init.md +514 -0
  46. package/agent/commands/tanstack-cloudflare.deploy.md +272 -0
  47. package/agent/commands/tanstack-cloudflare.tail.md +275 -0
  48. package/agent/design/.gitkeep +0 -0
  49. package/agent/design/design.template.md +154 -0
  50. package/agent/design/local.dashboard-layout-routing.md +288 -0
  51. package/agent/design/local.data-model-yaml-parsing.md +310 -0
  52. package/agent/design/local.search-filtering.md +331 -0
  53. package/agent/design/local.server-api-auto-refresh.md +235 -0
  54. package/agent/design/local.table-tree-views.md +299 -0
  55. package/agent/design/local.visualizer-requirements.md +349 -0
  56. package/agent/design/requirements.template.md +387 -0
  57. package/agent/index/.gitkeep +0 -0
  58. package/agent/index/acp.core.yaml +137 -0
  59. package/agent/index/local.main.template.yaml +37 -0
  60. package/agent/manifest.template.yaml +13 -0
  61. package/agent/manifest.yaml +302 -0
  62. package/agent/milestones/.gitkeep +0 -0
  63. package/agent/milestones/milestone-1-project-scaffold-data-pipeline.md +67 -0
  64. package/agent/milestones/milestone-1-{title}.template.md +206 -0
  65. package/agent/milestones/milestone-2-dashboard-views-interaction.md +79 -0
  66. package/agent/package.template.yaml +86 -0
  67. package/agent/patterns/.gitkeep +0 -0
  68. package/agent/patterns/bootstrap.template.md +1237 -0
  69. package/agent/patterns/pattern.template.md +382 -0
  70. package/agent/patterns/tanstack-cloudflare.acl-permissions.md +332 -0
  71. package/agent/patterns/tanstack-cloudflare.action-bar-item.md +416 -0
  72. package/agent/patterns/tanstack-cloudflare.api-route-handlers.md +401 -0
  73. package/agent/patterns/tanstack-cloudflare.auth-session-management.md +387 -0
  74. package/agent/patterns/tanstack-cloudflare.card-and-list.md +271 -0
  75. package/agent/patterns/tanstack-cloudflare.chat-engine.md +353 -0
  76. package/agent/patterns/tanstack-cloudflare.confirmation-tokens.md +346 -0
  77. package/agent/patterns/tanstack-cloudflare.durable-objects-websocket.md +516 -0
  78. package/agent/patterns/tanstack-cloudflare.email-service.md +431 -0
  79. package/agent/patterns/tanstack-cloudflare.expander.md +98 -0
  80. package/agent/patterns/tanstack-cloudflare.fcm-push.md +115 -0
  81. package/agent/patterns/tanstack-cloudflare.firebase-anonymous-sessions.md +441 -0
  82. package/agent/patterns/tanstack-cloudflare.firebase-auth.md +348 -0
  83. package/agent/patterns/tanstack-cloudflare.firebase-firestore.md +550 -0
  84. package/agent/patterns/tanstack-cloudflare.firebase-storage.md +369 -0
  85. package/agent/patterns/tanstack-cloudflare.form-controls.md +145 -0
  86. package/agent/patterns/tanstack-cloudflare.global-search-context.md +93 -0
  87. package/agent/patterns/tanstack-cloudflare.image-carousel.md +126 -0
  88. package/agent/patterns/tanstack-cloudflare.library-services.md +553 -0
  89. package/agent/patterns/tanstack-cloudflare.lightbox.md +169 -0
  90. package/agent/patterns/tanstack-cloudflare.markdown-content.md +115 -0
  91. package/agent/patterns/tanstack-cloudflare.mention-suggestions.md +98 -0
  92. package/agent/patterns/tanstack-cloudflare.modal.md +156 -0
  93. package/agent/patterns/tanstack-cloudflare.nextjs-to-tanstack-routing.md +461 -0
  94. package/agent/patterns/tanstack-cloudflare.notifications-engine.md +151 -0
  95. package/agent/patterns/tanstack-cloudflare.oauth-token-refresh.md +90 -0
  96. package/agent/patterns/tanstack-cloudflare.og-metadata.md +296 -0
  97. package/agent/patterns/tanstack-cloudflare.pagination.md +442 -0
  98. package/agent/patterns/tanstack-cloudflare.pill-input.md +220 -0
  99. package/agent/patterns/tanstack-cloudflare.provider-adapter.md +401 -0
  100. package/agent/patterns/tanstack-cloudflare.rate-limiting.md +323 -0
  101. package/agent/patterns/tanstack-cloudflare.scheduled-tasks.md +338 -0
  102. package/agent/patterns/tanstack-cloudflare.searchable-settings.md +375 -0
  103. package/agent/patterns/tanstack-cloudflare.slide-over.md +129 -0
  104. package/agent/patterns/tanstack-cloudflare.ssr-preload.md +571 -0
  105. package/agent/patterns/tanstack-cloudflare.third-party-api-integration.md +508 -0
  106. package/agent/patterns/tanstack-cloudflare.toast-system.md +142 -0
  107. package/agent/patterns/tanstack-cloudflare.unified-header.md +280 -0
  108. package/agent/patterns/tanstack-cloudflare.user-scoped-collections.md +628 -0
  109. package/agent/patterns/tanstack-cloudflare.websocket-manager.md +237 -0
  110. package/agent/patterns/tanstack-cloudflare.wrangler-configuration.md +358 -0
  111. package/agent/patterns/tanstack-cloudflare.zod-schema-validation.md +336 -0
  112. package/agent/progress.template.yaml +161 -0
  113. package/agent/progress.yaml +145 -0
  114. package/agent/schemas/package.schema.yaml +276 -0
  115. package/agent/scripts/acp.common.sh +1781 -0
  116. package/agent/scripts/acp.install.sh +333 -0
  117. package/agent/scripts/acp.package-create.sh +924 -0
  118. package/agent/scripts/acp.package-info.sh +288 -0
  119. package/agent/scripts/acp.package-install.sh +893 -0
  120. package/agent/scripts/acp.package-list.sh +311 -0
  121. package/agent/scripts/acp.package-publish.sh +420 -0
  122. package/agent/scripts/acp.package-remove.sh +348 -0
  123. package/agent/scripts/acp.package-search.sh +156 -0
  124. package/agent/scripts/acp.package-update.sh +517 -0
  125. package/agent/scripts/acp.package-validate.sh +1018 -0
  126. package/agent/scripts/acp.uninstall.sh +85 -0
  127. package/agent/scripts/acp.version-check-for-updates.sh +98 -0
  128. package/agent/scripts/acp.version-check.sh +47 -0
  129. package/agent/scripts/acp.version-update.sh +176 -0
  130. package/agent/scripts/acp.yaml-parser.sh +985 -0
  131. package/agent/scripts/acp.yaml-validate.sh +205 -0
  132. package/agent/tasks/.gitkeep +0 -0
  133. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-1-initialize-tanstack-start-project.md +210 -0
  134. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-2-implement-data-model-yaml-parser.md +294 -0
  135. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-3-build-server-api-data-loading.md +193 -0
  136. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-4-add-auto-refresh-sse.md +262 -0
  137. package/agent/tasks/milestone-2-dashboard-views-interaction/task-10-polish-integration-testing.md +156 -0
  138. package/agent/tasks/milestone-2-dashboard-views-interaction/task-5-build-dashboard-layout-routing.md +178 -0
  139. package/agent/tasks/milestone-2-dashboard-views-interaction/task-6-build-overview-page.md +141 -0
  140. package/agent/tasks/milestone-2-dashboard-views-interaction/task-7-implement-milestone-table-view.md +153 -0
  141. package/agent/tasks/milestone-2-dashboard-views-interaction/task-8-implement-milestone-tree-view.md +174 -0
  142. package/agent/tasks/milestone-2-dashboard-views-interaction/task-9-implement-search-filtering.md +233 -0
  143. package/agent/tasks/task-1-{title}.template.md +244 -0
  144. package/bin/visualize.mjs +84 -0
  145. package/package.json +48 -0
  146. package/src/components/ExtraFieldsBadge.tsx +15 -0
  147. package/src/components/FilterBar.tsx +33 -0
  148. package/src/components/Header.tsx +23 -0
  149. package/src/components/MilestoneTable.tsx +167 -0
  150. package/src/components/MilestoneTree.tsx +84 -0
  151. package/src/components/ProgressBar.tsx +20 -0
  152. package/src/components/SearchInput.tsx +22 -0
  153. package/src/components/Sidebar.tsx +54 -0
  154. package/src/components/StatusBadge.tsx +23 -0
  155. package/src/components/StatusDot.tsx +12 -0
  156. package/src/components/TaskList.tsx +36 -0
  157. package/src/components/ViewToggle.tsx +31 -0
  158. package/src/lib/config.ts +8 -0
  159. package/src/lib/file-watcher.ts +43 -0
  160. package/src/lib/search.ts +48 -0
  161. package/src/lib/types.ts +73 -0
  162. package/src/lib/useAutoRefresh.ts +31 -0
  163. package/src/lib/useCollapse.ts +31 -0
  164. package/src/lib/useFilteredData.ts +55 -0
  165. package/src/lib/yaml-loader-real.spec.ts +47 -0
  166. package/src/lib/yaml-loader.spec.ts +201 -0
  167. package/src/lib/yaml-loader.ts +265 -0
  168. package/src/routeTree.gen.ts +140 -0
  169. package/src/router.tsx +10 -0
  170. package/src/routes/__root.tsx +75 -0
  171. package/src/routes/api/watch.ts +29 -0
  172. package/src/routes/index.tsx +115 -0
  173. package/src/routes/milestones.tsx +50 -0
  174. package/src/routes/search.tsx +84 -0
  175. package/src/routes/tasks.tsx +63 -0
  176. package/src/services/progress-database.service.ts +46 -0
  177. package/src/styles.css +25 -0
  178. package/tsconfig.json +24 -0
  179. package/vite.config.ts +16 -0
  180. package/vitest.config.ts +27 -0
@@ -0,0 +1,382 @@
1
+ # {Pattern Name}
2
+
3
+ **Category**: [Architecture | Design | Code | Testing | Deployment]
4
+ **Applicable To**: [What types of projects or components this pattern applies to]
5
+ **Status**: [Stable | Experimental | Deprecated]
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ [Provide a high-level description of what this pattern is and when to use it. Include the problem space it addresses and the general approach it takes.]
12
+
13
+ **Example**: "The Service Layer Pattern provides a clear separation between business logic and data access, enabling better testability, maintainability, and code reuse across different interfaces (API, CLI, etc.)."
14
+
15
+ ---
16
+
17
+ ## When to Use This Pattern
18
+
19
+ [Describe the scenarios where this pattern is appropriate:]
20
+
21
+ ✅ **Use this pattern when:**
22
+ - Condition 1
23
+ - Condition 2
24
+ - Condition 3
25
+
26
+ ❌ **Don't use this pattern when:**
27
+ - Condition 1
28
+ - Condition 2
29
+ - Condition 3
30
+
31
+ **Example**:
32
+
33
+ ✅ **Use this pattern when:**
34
+ - You have complex business logic that needs to be shared across multiple interfaces
35
+ - You want to isolate business logic from infrastructure concerns
36
+ - You need to test business logic independently of data access
37
+
38
+ ❌ **Don't use this pattern when:**
39
+ - Your application is very simple with minimal business logic
40
+ - You're building a thin wrapper around a database
41
+ - The overhead of additional layers outweighs the benefits
42
+
43
+ ---
44
+
45
+ ## Core Principles
46
+
47
+ [List the fundamental concepts that underpin this pattern:]
48
+
49
+ 1. **Principle 1**: [Description]
50
+ 2. **Principle 2**: [Description]
51
+ 3. **Principle 3**: [Description]
52
+ 4. **Principle 4**: [Description]
53
+
54
+ **Example**:
55
+
56
+ 1. **Separation of Concerns**: Business logic is isolated from data access and presentation
57
+ 2. **Single Responsibility**: Each service handles one domain concept
58
+ 3. **Dependency Injection**: Services receive their dependencies rather than creating them
59
+ 4. **Interface-Based Design**: Services depend on abstractions, not concrete implementations
60
+
61
+ ---
62
+
63
+ ## Implementation
64
+
65
+ [Provide detailed implementation guidance with code examples:]
66
+
67
+ ### Structure
68
+
69
+ [Describe the overall structure of the pattern]
70
+
71
+ ```
72
+ directory-structure/
73
+ ├── component1/
74
+ │ └── file1.ext
75
+ └── component2/
76
+ └── file2.ext
77
+ ```
78
+
79
+ ### Code Example
80
+
81
+ [Provide a complete, working example:]
82
+
83
+ ```typescript
84
+ // Example implementation
85
+ interface ExampleInterface {
86
+ method(): Promise<Result>;
87
+ }
88
+
89
+ class ExampleImplementation implements ExampleInterface {
90
+ constructor(private dependency: Dependency) {}
91
+
92
+ async method(): Promise<Result> {
93
+ // Implementation
94
+ return result;
95
+ }
96
+ }
97
+ ```
98
+
99
+ ### Key Components
100
+
101
+ [Break down the major components:]
102
+
103
+ #### Component 1: [Name]
104
+ [Description and purpose]
105
+
106
+ ```typescript
107
+ // Code example for this component
108
+ ```
109
+
110
+ #### Component 2: [Name]
111
+ [Description and purpose]
112
+
113
+ ```typescript
114
+ // Code example for this component
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Examples
120
+
121
+ [Provide multiple real-world examples showing different use cases:]
122
+
123
+ ### Example 1: [Use Case Name]
124
+
125
+ [Description of the scenario]
126
+
127
+ ```typescript
128
+ // Complete code example
129
+ class ConcreteExample {
130
+ // Implementation
131
+ }
132
+
133
+ // Usage
134
+ const example = new ConcreteExample();
135
+ const result = await example.doSomething();
136
+ ```
137
+
138
+ ### Example 2: [Use Case Name]
139
+
140
+ [Description of the scenario]
141
+
142
+ ```typescript
143
+ // Complete code example
144
+ ```
145
+
146
+ ---
147
+
148
+ ## Benefits
149
+
150
+ [List the advantages of using this pattern:]
151
+
152
+ ### 1. [Benefit Name]
153
+ [Detailed explanation of this benefit and why it matters]
154
+
155
+ ### 2. [Benefit Name]
156
+ [Detailed explanation of this benefit and why it matters]
157
+
158
+ ### 3. [Benefit Name]
159
+ [Detailed explanation of this benefit and why it matters]
160
+
161
+ **Example**:
162
+
163
+ ### 1. Testability
164
+ Business logic can be tested in isolation without requiring database connections or external services. Mock dependencies can be easily injected for unit testing.
165
+
166
+ ### 2. Reusability
167
+ The same business logic can be used across multiple interfaces (REST API, GraphQL, CLI, etc.) without duplication.
168
+
169
+ ### 3. Maintainability
170
+ Changes to business logic are centralized in service classes, making the codebase easier to understand and modify.
171
+
172
+ ---
173
+
174
+ ## Trade-offs
175
+
176
+ [Honestly assess the downsides and limitations:]
177
+
178
+ ### 1. [Trade-off Name]
179
+ **Downside**: [Description]
180
+ **Mitigation**: [How to minimize this downside]
181
+
182
+ ### 2. [Trade-off Name]
183
+ **Downside**: [Description]
184
+ **Mitigation**: [How to minimize this downside]
185
+
186
+ **Example**:
187
+
188
+ ### 1. Additional Complexity
189
+ **Downside**: Adds extra layers and files to the codebase, which can feel like over-engineering for simple applications.
190
+ **Mitigation**: Only apply this pattern when complexity justifies it. Start simple and refactor to this pattern as needs grow.
191
+
192
+ ### 2. Performance Overhead
193
+ **Downside**: Additional function calls and abstractions can add minor performance overhead.
194
+ **Mitigation**: In most applications, this overhead is negligible. Profile before optimizing.
195
+
196
+ ---
197
+
198
+ ## Anti-Patterns
199
+
200
+ [Document what NOT to do - common mistakes and misuses:]
201
+
202
+ ### ❌ Anti-Pattern 1: [Name]
203
+
204
+ **Description**: [What people do wrong]
205
+
206
+ **Why it's bad**: [Consequences]
207
+
208
+ **Instead, do this**: [Correct approach]
209
+
210
+ ```typescript
211
+ // ❌ Bad example
212
+ class BadExample {
213
+ // What not to do
214
+ }
215
+
216
+ // ✅ Good example
217
+ class GoodExample {
218
+ // Correct approach
219
+ }
220
+ ```
221
+
222
+ ### ❌ Anti-Pattern 2: [Name]
223
+
224
+ [Similar structure as above]
225
+
226
+ **Example**:
227
+
228
+ ### ❌ Anti-Pattern 1: God Service
229
+
230
+ **Description**: Creating a single service class that handles all business logic for the entire application.
231
+
232
+ **Why it's bad**: Violates single responsibility principle, becomes difficult to test and maintain, creates tight coupling.
233
+
234
+ **Instead, do this**: Create focused services, each handling a specific domain concept.
235
+
236
+ ```typescript
237
+ // ❌ Bad: Everything in one service
238
+ class ApplicationService {
239
+ createUser() {}
240
+ deleteUser() {}
241
+ createProduct() {}
242
+ deleteProduct() {}
243
+ processPayment() {}
244
+ sendEmail() {}
245
+ }
246
+
247
+ // ✅ Good: Focused services
248
+ class UserService {
249
+ createUser() {}
250
+ deleteUser() {}
251
+ }
252
+
253
+ class ProductService {
254
+ createProduct() {}
255
+ deleteProduct() {}
256
+ }
257
+
258
+ class PaymentService {
259
+ processPayment() {}
260
+ }
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Key Design Decisions (Optional)
266
+
267
+ <!-- This section is populated by @acp.clarification-capture when
268
+ create commands are invoked with --from-clar, --from-chat, or
269
+ --from-context. It can also be manually authored.
270
+ Omit this section entirely if no decisions to capture.
271
+
272
+ Group decisions by agent-inferred category using tables:
273
+
274
+ ### {Category}
275
+
276
+ | Decision | Choice | Rationale |
277
+ |---|---|---|
278
+ | {decision} | {choice} | {rationale} |
279
+ -->
280
+
281
+ ---
282
+
283
+ ## Testing Strategy
284
+
285
+ [Describe how to test code that uses this pattern:]
286
+
287
+ ### Unit Testing
288
+ [Approach for unit tests]
289
+
290
+ ```typescript
291
+ // Example unit test
292
+ describe('ExampleService', () => {
293
+ it('should do something', async () => {
294
+ // Test implementation
295
+ });
296
+ });
297
+ ```
298
+
299
+ ### Integration Testing
300
+ [Approach for integration tests]
301
+
302
+ ```typescript
303
+ // Example integration test
304
+ ```
305
+
306
+ ---
307
+
308
+ ## Related Patterns
309
+
310
+ [Link to related patterns and explain relationships:]
311
+
312
+ - **[Pattern Name](./pattern-name.md)**: [How it relates]
313
+ - **[Pattern Name](./pattern-name.md)**: [How it relates]
314
+ - **[Pattern Name](./pattern-name.md)**: [How it relates]
315
+
316
+ **Example**:
317
+ - **[Repository Pattern](./repository-pattern.md)**: Often used together; services use repositories for data access
318
+ - **[Factory Pattern](./factory-pattern.md)**: Can be used to create service instances with proper dependencies
319
+ - **[Dependency Injection](./dependency-injection.md)**: Essential for implementing this pattern correctly
320
+
321
+ ---
322
+
323
+ ## Migration Guide
324
+
325
+ [If adopting this pattern in an existing codebase, provide migration steps:]
326
+
327
+ ### Step 1: [Action]
328
+ [Detailed description]
329
+
330
+ ### Step 2: [Action]
331
+ [Detailed description]
332
+
333
+ ### Step 3: [Action]
334
+ [Detailed description]
335
+
336
+ **Example**:
337
+
338
+ ### Step 1: Identify Business Logic
339
+ Review existing code and identify business logic that's currently mixed with data access or presentation code.
340
+
341
+ ### Step 2: Extract to Services
342
+ Create service classes and move business logic into them. Start with the most complex or frequently used logic.
343
+
344
+ ### Step 3: Refactor Dependencies
345
+ Update calling code to use the new services. Inject dependencies rather than creating them directly.
346
+
347
+ ---
348
+
349
+ ## References
350
+
351
+ [Link to external resources, papers, books, or articles:]
352
+
353
+ - [Resource 1](URL): Description
354
+ - [Resource 2](URL): Description
355
+ - [Resource 3](URL): Description
356
+
357
+ **Example**:
358
+ - [Martin Fowler - Service Layer](https://martinfowler.com/eaaCatalog/serviceLayer.html): Original pattern description
359
+ - [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html): Related architectural concepts
360
+ - [Domain-Driven Design](https://www.domainlanguage.com/ddd/): Context for service design
361
+
362
+ ---
363
+
364
+ ## Checklist for Implementation
365
+
366
+ [Provide a checklist to ensure proper implementation:]
367
+
368
+ - [ ] Services are focused on single domain concepts
369
+ - [ ] Dependencies are injected, not created internally
370
+ - [ ] Business logic is isolated from infrastructure concerns
371
+ - [ ] Services have clear, well-documented interfaces
372
+ - [ ] Unit tests cover business logic in isolation
373
+ - [ ] Integration tests verify end-to-end functionality
374
+ - [ ] Error handling is consistent and appropriate
375
+ - [ ] Logging provides adequate visibility
376
+
377
+ ---
378
+
379
+ **Status**: [Current status of this pattern document]
380
+ **Recommendation**: [When and how to use this pattern]
381
+ **Last Updated**: [YYYY-MM-DD]
382
+ **Contributors**: [Names or "Community"]
@@ -0,0 +1,332 @@
1
+ # ACL Permissions Pattern
2
+
3
+ **Category**: Architecture
4
+ **Applicable To**: TanStack Start + Cloudflare Workers applications with multi-user authorization
5
+ **Status**: Stable
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ The ACL (Access Control List) Permissions pattern provides fine-grained, flag-based authorization for multi-user features like groups, channels, and shared spaces. Instead of using coarse role-based access (owner/admin/member), each user gets a set of boolean permission flags that control exactly what actions they can perform.
12
+
13
+ Permission presets (OWNER, ADMIN, EDITOR, MEMBER) provide sensible defaults while allowing per-user customization. An `auth_level` numeric hierarchy enables authority-based checks (lower number = more authority), preventing members from elevating their own privileges or acting on users with higher authority.
14
+
15
+ ---
16
+
17
+ ## When to Use This Pattern
18
+
19
+ ✅ **Use this pattern when:**
20
+ - Building multi-user features (groups, channels, shared spaces)
21
+ - Need granular control over who can do what
22
+ - Want to support custom permission configurations beyond simple roles
23
+ - Need authority hierarchy (owners can't be kicked by members)
24
+ - Building moderation features (kick, mute, ban)
25
+
26
+ ❌ **Don't use this pattern when:**
27
+ - Application has only single-user data (no shared resources)
28
+ - Simple owner/non-owner distinction is sufficient
29
+ - Using an external authorization service (Auth0 FGA, etc.)
30
+
31
+ ---
32
+
33
+ ## Core Principles
34
+
35
+ 1. **Flag-Based Permissions**: Boolean flags for each capability, not string roles
36
+ 2. **Authority Hierarchy**: Numeric `auth_level` (0 = owner, higher = less authority)
37
+ 3. **Presets for Convenience**: OWNER, ADMIN, EDITOR, MEMBER presets with sensible defaults
38
+ 4. **Stored on Entity**: Permissions stored directly on the group/channel document as `member_permissions[userId]`
39
+ 5. **Thin ACL Service**: Validation logic in a dedicated service, not scattered across handlers
40
+ 6. **Check Before Act**: Always validate permissions before performing any action
41
+
42
+ ---
43
+
44
+ ## Implementation
45
+
46
+ ### Step 1: Define Permission Schema
47
+
48
+ ```typescript
49
+ // src/schemas/group-conversation.ts
50
+ import { z } from 'zod'
51
+
52
+ export const MemberPermissionsSchema = z.object({
53
+ auth_level: z.number().int().min(0),
54
+ can_read: z.boolean(),
55
+ can_publish: z.boolean(),
56
+ can_revise: z.boolean(),
57
+ can_propose: z.boolean(),
58
+ can_overwrite: z.boolean(),
59
+ can_comment: z.boolean(),
60
+ can_retract_own: z.boolean(),
61
+ can_retract_any: z.boolean(),
62
+ can_manage_members: z.boolean(),
63
+ can_update_properties: z.boolean(),
64
+ can_moderate: z.boolean(),
65
+ can_kick: z.boolean(),
66
+ can_mute: z.boolean(),
67
+ can_ban: z.boolean(),
68
+ })
69
+
70
+ export type MemberPermissions = z.infer<typeof MemberPermissionsSchema>
71
+ ```
72
+
73
+ ### Step 2: Define Permission Presets
74
+
75
+ ```typescript
76
+ // src/schemas/group-conversation.ts (continued)
77
+
78
+ export const OWNER_PRESET: MemberPermissions = {
79
+ auth_level: 0,
80
+ can_read: true, can_publish: true, can_revise: true,
81
+ can_propose: true, can_overwrite: true, can_comment: true,
82
+ can_retract_own: true, can_retract_any: true, can_manage_members: true,
83
+ can_update_properties: true, can_moderate: true,
84
+ can_kick: true, can_mute: true, can_ban: true,
85
+ }
86
+
87
+ export const ADMIN_PRESET: MemberPermissions = {
88
+ auth_level: 1,
89
+ can_read: true, can_publish: true, can_revise: true,
90
+ can_propose: true, can_overwrite: true, can_comment: true,
91
+ can_retract_own: true, can_retract_any: true, can_manage_members: true,
92
+ can_update_properties: true, can_moderate: true,
93
+ can_kick: true, can_mute: true, can_ban: true,
94
+ }
95
+
96
+ export const EDITOR_PRESET: MemberPermissions = {
97
+ auth_level: 3,
98
+ can_read: true, can_publish: true, can_revise: true,
99
+ can_propose: true, can_overwrite: false, can_comment: true,
100
+ can_retract_own: true, can_retract_any: false, can_manage_members: false,
101
+ can_update_properties: false, can_moderate: false,
102
+ can_kick: false, can_mute: false, can_ban: false,
103
+ }
104
+
105
+ export const MEMBER_PRESET: MemberPermissions = {
106
+ auth_level: 5,
107
+ can_read: true, can_publish: true, can_revise: false,
108
+ can_propose: true, can_overwrite: false, can_comment: true,
109
+ can_retract_own: true, can_retract_any: false, can_manage_members: false,
110
+ can_update_properties: false, can_moderate: false,
111
+ can_kick: false, can_mute: false, can_ban: false,
112
+ }
113
+ ```
114
+
115
+ ### Step 3: Store Permissions on Entity
116
+
117
+ ```typescript
118
+ // src/schemas/group-conversation.ts (continued)
119
+
120
+ export const GroupConversationSchema = z.object({
121
+ id: z.string(),
122
+ type: z.literal('group'),
123
+ name: z.string(),
124
+ description: z.string().nullable().optional(),
125
+ owner_user_id: z.string(),
126
+ participant_user_ids: z.array(z.string()),
127
+ // Permissions stored per-user on the document itself
128
+ member_permissions: z.record(z.string(), MemberPermissionsSchema),
129
+ created_at: z.string().datetime(),
130
+ updated_at: z.string().datetime(),
131
+ })
132
+
133
+ export type GroupConversation = z.infer<typeof GroupConversationSchema>
134
+ ```
135
+
136
+ ### Step 4: Create ACL Service
137
+
138
+ ```typescript
139
+ // src/services/group-acl.service.ts
140
+ import { GroupConversationDatabaseService } from './group-conversation-database.service'
141
+ import type { MemberPermissions } from '@/schemas/group-conversation'
142
+
143
+ /**
144
+ * Group ACL Service
145
+ *
146
+ * Thin access-control layer over GroupConversationDatabaseService.
147
+ * Provides permission-based access validation and membership queries.
148
+ */
149
+ export class GroupAclService {
150
+ /**
151
+ * Validate a user has access to a group.
152
+ * Returns their permissions if granted, null otherwise.
153
+ */
154
+ static async validateGroupAccess(
155
+ userId: string,
156
+ groupId: string
157
+ ): Promise<MemberPermissions | null> {
158
+ const group = await GroupConversationDatabaseService.getGroupConversation(userId, groupId)
159
+ if (!group) return null
160
+ return group.member_permissions[userId] ?? null
161
+ }
162
+
163
+ /**
164
+ * Get all group IDs the user belongs to.
165
+ */
166
+ static async getGroupMemberships(userId: string): Promise<string[]> {
167
+ const groups = await GroupConversationDatabaseService.listGroupConversations(userId)
168
+ return groups.map(g => g.id)
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### Step 5: Use in API Routes
174
+
175
+ ```typescript
176
+ // src/routes/api/groups/$id/index.tsx
177
+ PATCH: async ({ params, request }) => {
178
+ const { id } = params
179
+ const user = await getAuthSession()
180
+ if (!user) return Response.json({ error: 'Unauthorized' }, { status: 401 })
181
+
182
+ // Check permission
183
+ const permissions = await GroupAclService.validateGroupAccess(user.uid, id)
184
+ if (!permissions) return Response.json({ error: 'Not found' }, { status: 404 })
185
+
186
+ if (!permissions.can_update_properties) {
187
+ return Response.json({ error: 'Forbidden: insufficient permissions' }, { status: 403 })
188
+ }
189
+
190
+ // Proceed with update...
191
+ const body = await request.json()
192
+ await GroupConversationDatabaseService.updateGroupConversation(user.uid, id, body)
193
+ return Response.json({ success: true })
194
+ }
195
+ ```
196
+
197
+ ### Step 6: Authority-Based Checks
198
+
199
+ ```typescript
200
+ // src/routes/api/groups/$id/members/$userId.tsx
201
+ DELETE: async ({ params, request }) => {
202
+ const { id, userId: targetUserId } = params
203
+ const user = await getAuthSession()
204
+
205
+ const myPermissions = await GroupAclService.validateGroupAccess(user.uid, id)
206
+ if (!myPermissions?.can_kick) {
207
+ return Response.json({ error: 'Forbidden: cannot kick members' }, { status: 403 })
208
+ }
209
+
210
+ // Authority check: can't kick someone with equal or higher authority
211
+ const targetPermissions = await GroupAclService.validateGroupAccess(targetUserId, id)
212
+ if (targetPermissions && targetPermissions.auth_level <= myPermissions.auth_level) {
213
+ return Response.json({
214
+ error: 'Forbidden: cannot kick a user with equal or higher authority'
215
+ }, { status: 403 })
216
+ }
217
+
218
+ await GroupConversationDatabaseService.removeMember(user.uid, id, targetUserId)
219
+ return Response.json({ success: true })
220
+ }
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Permission Presets Summary
226
+
227
+ | Preset | auth_level | Key Capabilities |
228
+ |--------|-----------|------------------|
229
+ | OWNER | 0 | Everything — full control |
230
+ | ADMIN | 1 | Everything except cannot override owner |
231
+ | EDITOR | 3 | Read, publish, revise, comment, retract own |
232
+ | MEMBER | 5 | Read, publish, propose, comment, retract own |
233
+
234
+ ---
235
+
236
+ ## Moderation Actions
237
+
238
+ ```typescript
239
+ // src/schemas/group-conversation.ts
240
+ export const ModerationActionSchema = z.object({
241
+ action: z.enum(['kick', 'mute', 'ban', 'message_delete', 'memory_moderate']),
242
+ target_user_id: z.string(),
243
+ acted_by_user_id: z.string(),
244
+ acted_by_auth_level: z.number().int().min(0),
245
+ created_at: z.string().datetime(),
246
+ reversed_at: z.string().datetime().optional(),
247
+ reversed_by_user_id: z.string().optional(),
248
+ })
249
+
250
+ // Authority rule: can only reverse actions by users at your level or below
251
+ // (higher auth_level number = less authority)
252
+ ```
253
+
254
+ ---
255
+
256
+ ## Benefits
257
+
258
+ ### 1. Granular Control
259
+ 15 individual flags enable precise permission configurations beyond simple roles.
260
+
261
+ ### 2. Authority Hierarchy
262
+ Numeric `auth_level` prevents privilege escalation (members can't kick admins).
263
+
264
+ ### 3. Stored on Entity
265
+ No separate permissions table — permissions live on the group document itself.
266
+
267
+ ### 4. Preset Templates
268
+ OWNER/ADMIN/EDITOR/MEMBER presets provide quick setup while allowing customization.
269
+
270
+ ---
271
+
272
+ ## Trade-offs
273
+
274
+ ### 1. Schema Size
275
+ **Downside**: 15 boolean flags per member adds document size.
276
+ **Mitigation**: Minimal overhead per member (~200 bytes). Only relevant for very large groups.
277
+
278
+ ### 2. No Inheritance
279
+ **Downside**: Each group manages its own permissions — no global roles.
280
+ **Mitigation**: Use presets for consistency. Global admin features can check a separate admin flag.
281
+
282
+ ---
283
+
284
+ ## Anti-Patterns
285
+
286
+ ### ❌ Anti-Pattern 1: String-Based Roles
287
+
288
+ ```typescript
289
+ // ❌ BAD: Coarse roles — no way to customize
290
+ member_roles: { 'user1': 'admin', 'user2': 'member' }
291
+
292
+ // ✅ GOOD: Fine-grained flags
293
+ member_permissions: { 'user1': ADMIN_PRESET, 'user2': { ...MEMBER_PRESET, can_revise: true } }
294
+ ```
295
+
296
+ ### ❌ Anti-Pattern 2: Checking Permissions in Components
297
+
298
+ ```typescript
299
+ // ❌ BAD: Permission check on client (can be bypassed)
300
+ if (userRole === 'admin') showDeleteButton()
301
+
302
+ // ✅ GOOD: Server-side validation in API route
303
+ if (!permissions.can_retract_any) return Response.json({ error: 'Forbidden' }, { status: 403 })
304
+ ```
305
+
306
+ ---
307
+
308
+ ## Related Patterns
309
+
310
+ - **[Zod Schema Validation](./tanstack-cloudflare.zod-schema-validation.md)**: Permission schemas defined with Zod
311
+ - **[API Route Handlers](./tanstack-cloudflare.api-route-handlers.md)**: ACL checks in API routes
312
+ - **[Library Services Pattern](./tanstack-cloudflare.library-services.md)**: ACL service as thin wrapper over database service
313
+
314
+ ---
315
+
316
+ ## Checklist for Implementation
317
+
318
+ - [ ] Permission schema defined with Zod
319
+ - [ ] Presets for OWNER, ADMIN, EDITOR, MEMBER
320
+ - [ ] `auth_level` hierarchy enforced (lower = more authority)
321
+ - [ ] Permissions stored on entity document as `member_permissions[userId]`
322
+ - [ ] ACL service validates access before any operation
323
+ - [ ] Authority checks prevent privilege escalation
324
+ - [ ] API routes return 403 for insufficient permissions
325
+ - [ ] Moderation actions stamped with `acted_by_auth_level`
326
+
327
+ ---
328
+
329
+ **Status**: Stable - Proven permission model for multi-user features
330
+ **Recommendation**: Use for all shared resources requiring granular authorization
331
+ **Last Updated**: 2026-02-28
332
+ **Contributors**: Patrick Michaelsen