workflow-agent-cli 2.1.0 → 2.2.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.
- package/README.md +33 -17
- package/dist/{chunk-B27W7GWP.js → chunk-IPMSSOXR.js} +55 -21
- package/dist/chunk-IPMSSOXR.js.map +1 -0
- package/dist/{chunk-X2NQJ2ZY.js → chunk-NMHWD2GA.js} +11 -6
- package/dist/chunk-NMHWD2GA.js.map +1 -0
- package/dist/cli/index.js +455 -137
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/index.js +2 -2
- package/dist/scripts/postinstall.js +6 -2
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/validators/index.js +1 -1
- package/package.json +15 -15
- package/templates/AGENT_EDITING_INSTRUCTIONS.md +226 -39
- package/templates/COMPONENT_LIBRARY.md +23 -17
- package/templates/CUSTOM_SCOPE_TEMPLATE.md +5 -4
- package/templates/LIBRARY_INVENTORY.md +20 -20
- package/templates/SCOPE_CREATION_WORKFLOW.md +39 -11
- package/templates/SELF_IMPROVEMENT_MANDATE.md +24 -18
- package/templates/SINGLE_SOURCE_OF_TRUTH.md +59 -42
- package/templates/TESTING_STRATEGY.md +79 -69
- package/templates/_TEMPLATE_EXAMPLE.md +2 -1
- package/LICENSE +0 -21
- package/dist/chunk-B27W7GWP.js.map +0 -1
- package/dist/chunk-X2NQJ2ZY.js.map +0 -1
|
@@ -84,13 +84,13 @@
|
|
|
84
84
|
|
|
85
85
|
```typescript
|
|
86
86
|
// Browser client (singleton)
|
|
87
|
-
import { getSupabaseClient } from
|
|
87
|
+
import { getSupabaseClient } from "@/lib/supabase/client";
|
|
88
88
|
|
|
89
89
|
// Server client (for server components/actions)
|
|
90
|
-
import { createServerClient } from
|
|
90
|
+
import { createServerClient } from "@/lib/supabase/server";
|
|
91
91
|
|
|
92
92
|
// Admin client (bypasses RLS)
|
|
93
|
-
import { createAdminClient } from
|
|
93
|
+
import { createAdminClient } from "@/lib/supabase/admin";
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
**Files:**
|
|
@@ -112,11 +112,11 @@ import { createAdminClient } from '@/lib/supabase/admin';
|
|
|
112
112
|
**Usage Patterns:**
|
|
113
113
|
|
|
114
114
|
```typescript
|
|
115
|
-
import { useQuery, useMutation, useQueryClient } from
|
|
115
|
+
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
116
116
|
|
|
117
117
|
// Fetching data
|
|
118
118
|
const { data, isLoading, error } = useQuery({
|
|
119
|
-
queryKey: [
|
|
119
|
+
queryKey: ["tasks", boardId],
|
|
120
120
|
queryFn: () => getTasks(boardId),
|
|
121
121
|
});
|
|
122
122
|
|
|
@@ -125,7 +125,7 @@ const queryClient = useQueryClient();
|
|
|
125
125
|
const mutation = useMutation({
|
|
126
126
|
mutationFn: createTask,
|
|
127
127
|
onSuccess: () => {
|
|
128
|
-
queryClient.invalidateQueries({ queryKey: [
|
|
128
|
+
queryClient.invalidateQueries({ queryKey: ["tasks"] });
|
|
129
129
|
},
|
|
130
130
|
});
|
|
131
131
|
```
|
|
@@ -197,9 +197,9 @@ const mutation = useMutation({
|
|
|
197
197
|
**Usage Pattern:**
|
|
198
198
|
|
|
199
199
|
```typescript
|
|
200
|
-
import { Button } from
|
|
201
|
-
import { Dialog, DialogContent, DialogHeader } from
|
|
202
|
-
import { Input } from
|
|
200
|
+
import { Button } from "@/components/ui/button";
|
|
201
|
+
import { Dialog, DialogContent, DialogHeader } from "@/components/ui/dialog";
|
|
202
|
+
import { Input } from "@/components/ui/input";
|
|
203
203
|
```
|
|
204
204
|
|
|
205
205
|
### Lucide React (Icons)
|
|
@@ -234,11 +234,11 @@ import { Plus, Trash, Settings, ChevronDown } from "lucide-react";
|
|
|
234
234
|
**Usage Pattern:**
|
|
235
235
|
|
|
236
236
|
```typescript
|
|
237
|
-
import { toast } from
|
|
237
|
+
import { toast } from "sonner";
|
|
238
238
|
|
|
239
|
-
toast.success(
|
|
240
|
-
toast.error(
|
|
241
|
-
toast.loading(
|
|
239
|
+
toast.success("Task created successfully");
|
|
240
|
+
toast.error("Failed to delete task");
|
|
241
|
+
toast.loading("Saving changes...");
|
|
242
242
|
```
|
|
243
243
|
|
|
244
244
|
### Vaul (Drawer)
|
|
@@ -273,12 +273,12 @@ toast.loading('Saving changes...');
|
|
|
273
273
|
**Usage Pattern:**
|
|
274
274
|
|
|
275
275
|
```typescript
|
|
276
|
-
import { useForm } from
|
|
277
|
-
import { zodResolver } from
|
|
276
|
+
import { useForm } from "react-hook-form";
|
|
277
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
278
278
|
|
|
279
279
|
const form = useForm<FormData>({
|
|
280
280
|
resolver: zodResolver(formSchema),
|
|
281
|
-
defaultValues: { title:
|
|
281
|
+
defaultValues: { title: "", description: "" },
|
|
282
282
|
});
|
|
283
283
|
```
|
|
284
284
|
|
|
@@ -294,13 +294,13 @@ const form = useForm<FormData>({
|
|
|
294
294
|
**Usage Patterns:**
|
|
295
295
|
|
|
296
296
|
```typescript
|
|
297
|
-
import { z } from
|
|
297
|
+
import { z } from "zod";
|
|
298
298
|
|
|
299
299
|
// Define schema
|
|
300
300
|
export const TaskSchema = z.object({
|
|
301
301
|
id: z.string().uuid(),
|
|
302
302
|
title: z.string().min(1).max(255),
|
|
303
|
-
priority: z.enum([
|
|
303
|
+
priority: z.enum(["low", "medium", "high", "critical"]),
|
|
304
304
|
});
|
|
305
305
|
|
|
306
306
|
// Infer type from schema
|
|
@@ -520,9 +520,9 @@ pnpm test:e2e # Run E2E tests
|
|
|
520
520
|
**Usage Pattern:**
|
|
521
521
|
|
|
522
522
|
```typescript
|
|
523
|
-
import { format, parseISO, differenceInDays } from
|
|
523
|
+
import { format, parseISO, differenceInDays } from "date-fns";
|
|
524
524
|
|
|
525
|
-
format(new Date(),
|
|
525
|
+
format(new Date(), "MMM d, yyyy"); // "Jan 8, 2026"
|
|
526
526
|
differenceInDays(endDate, startDate);
|
|
527
527
|
```
|
|
528
528
|
|
|
@@ -5,6 +5,7 @@ This document provides a structured workflow for AI agents creating custom scope
|
|
|
5
5
|
## Critical Rule: Zero-Assumption Principle
|
|
6
6
|
|
|
7
7
|
**Never assume or infer details about:**
|
|
8
|
+
|
|
8
9
|
- Project domain or industry
|
|
9
10
|
- Feature areas or scope names
|
|
10
11
|
- Naming conventions
|
|
@@ -20,6 +21,7 @@ This document provides a structured workflow for AI agents creating custom scope
|
|
|
20
21
|
### 1. Project Domain Clarification
|
|
21
22
|
|
|
22
23
|
**Prompt:**
|
|
24
|
+
|
|
23
25
|
> "What is the primary domain or industry for this project? For example: fintech, healthcare, gaming, education, e-commerce, etc."
|
|
24
26
|
|
|
25
27
|
**Purpose:** Understand the context to suggest relevant scope categories.
|
|
@@ -31,6 +33,7 @@ This document provides a structured workflow for AI agents creating custom scope
|
|
|
31
33
|
### 2. Feature Area Enumeration
|
|
32
34
|
|
|
33
35
|
**Prompt:**
|
|
36
|
+
|
|
34
37
|
> "What are the main feature areas or functional components of your project? Please list them (aim for 8-15 areas). For example, for a SaaS app: authentication, user profiles, billing, notifications, analytics."
|
|
35
38
|
|
|
36
39
|
**Purpose:** Identify specific scopes that map to actual functionality.
|
|
@@ -38,6 +41,7 @@ This document provides a structured workflow for AI agents creating custom scope
|
|
|
38
41
|
**Expected Response:** List of feature areas (comma-separated or numbered).
|
|
39
42
|
|
|
40
43
|
**Follow-up:** If fewer than 8 or more than 20 features listed:
|
|
44
|
+
|
|
41
45
|
> "You listed [N] features. The recommended range is 8-15 scopes. Would you like to add more detail, consolidate some areas, or proceed as is?"
|
|
42
46
|
|
|
43
47
|
---
|
|
@@ -45,11 +49,13 @@ This document provides a structured workflow for AI agents creating custom scope
|
|
|
45
49
|
### 3. Naming Convention Preferences
|
|
46
50
|
|
|
47
51
|
**Prompt:**
|
|
52
|
+
|
|
48
53
|
> "What naming style do you prefer for your scopes? Examples:
|
|
54
|
+
>
|
|
49
55
|
> - Single words (auth, billing, users)
|
|
50
56
|
> - Kebab-case (user-management, api-endpoints)
|
|
51
57
|
> - Descriptive phrases (subscription-billing, email-notifications)
|
|
52
|
-
>
|
|
58
|
+
>
|
|
53
59
|
> Note: All scope names must be lowercase alphanumeric with hyphens only."
|
|
54
60
|
|
|
55
61
|
**Purpose:** Ensure consistent naming that matches team conventions.
|
|
@@ -61,11 +67,13 @@ This document provides a structured workflow for AI agents creating custom scope
|
|
|
61
67
|
### 4. Scope-to-Structure Mapping
|
|
62
68
|
|
|
63
69
|
**Prompt:**
|
|
70
|
+
|
|
64
71
|
> "Do your scopes map to:
|
|
72
|
+
>
|
|
65
73
|
> 1. **Folders/modules** in your codebase (e.g., src/auth, src/billing)
|
|
66
74
|
> 2. **Feature areas** regardless of folder structure
|
|
67
75
|
> 3. **Both** - they align with both features and folders
|
|
68
|
-
>
|
|
76
|
+
>
|
|
69
77
|
> This helps determine how granular the scopes should be."
|
|
70
78
|
|
|
71
79
|
**Purpose:** Align scopes with actual codebase organization.
|
|
@@ -77,10 +85,12 @@ This document provides a structured workflow for AI agents creating custom scope
|
|
|
77
85
|
### 5. Migration vs. New Creation
|
|
78
86
|
|
|
79
87
|
**Prompt:**
|
|
88
|
+
|
|
80
89
|
> "Are you:
|
|
90
|
+
>
|
|
81
91
|
> 1. **Migrating** existing scopes from workflow.config.json to a package
|
|
82
92
|
> 2. **Creating** a new custom scope package from scratch
|
|
83
|
-
>
|
|
93
|
+
>
|
|
84
94
|
> If migrating, I can use your existing scope definitions. If creating new, we'll define them together."
|
|
85
95
|
|
|
86
96
|
**Purpose:** Determine whether to use existing data or start fresh.
|
|
@@ -88,9 +98,10 @@ This document provides a structured workflow for AI agents creating custom scope
|
|
|
88
98
|
**Expected Response:** "migrate" or "create new"
|
|
89
99
|
|
|
90
100
|
**Follow-up if "migrate":**
|
|
101
|
+
|
|
91
102
|
> "I found [N] scopes in your workflow.config.json:
|
|
92
103
|
> [List scopes]
|
|
93
|
-
>
|
|
104
|
+
>
|
|
94
105
|
> Should I use these as-is, or would you like to review/modify them first?"
|
|
95
106
|
|
|
96
107
|
---
|
|
@@ -98,11 +109,13 @@ This document provides a structured workflow for AI agents creating custom scope
|
|
|
98
109
|
### 6. Package Publishing Intent
|
|
99
110
|
|
|
100
111
|
**Prompt:**
|
|
112
|
+
|
|
101
113
|
> "Do you plan to:
|
|
114
|
+
>
|
|
102
115
|
> 1. **Publish** this scope package to npm for reuse across projects
|
|
103
116
|
> 2. **Keep it local** to this workspace only
|
|
104
117
|
> 3. **Undecided** - create it now, decide later
|
|
105
|
-
>
|
|
118
|
+
>
|
|
106
119
|
> This affects whether we include publishing configuration."
|
|
107
120
|
|
|
108
121
|
**Purpose:** Include appropriate publishing metadata and instructions.
|
|
@@ -130,22 +143,27 @@ Before generating the package, confirm:
|
|
|
130
143
|
For each scope, ask:
|
|
131
144
|
|
|
132
145
|
**Prompt:**
|
|
146
|
+
|
|
133
147
|
> "Scope #[N] - Name: (lowercase, alphanumeric, hyphens only)"
|
|
134
148
|
|
|
135
149
|
After name is provided:
|
|
136
150
|
|
|
137
151
|
**Prompt:**
|
|
152
|
+
|
|
138
153
|
> "Description for '[scope-name]': (minimum 10 characters, be specific)"
|
|
139
154
|
|
|
140
155
|
After description:
|
|
141
156
|
|
|
142
157
|
**Prompt:**
|
|
158
|
+
|
|
143
159
|
> "Emoji for '[scope-name]': (optional, press Enter to skip)"
|
|
144
160
|
|
|
145
161
|
After emoji:
|
|
146
162
|
|
|
147
163
|
**Prompt:**
|
|
164
|
+
|
|
148
165
|
> "Category for '[scope-name]':
|
|
166
|
+
>
|
|
149
167
|
> 1. auth - Authentication & Authorization
|
|
150
168
|
> 2. features - Features & Functionality
|
|
151
169
|
> 3. infrastructure - Infrastructure & DevOps
|
|
@@ -154,14 +172,15 @@ After emoji:
|
|
|
154
172
|
> 6. performance - Performance & Optimization
|
|
155
173
|
> 7. other - Other
|
|
156
174
|
> 8. (none) - No category
|
|
157
|
-
>
|
|
175
|
+
>
|
|
158
176
|
> Choose 1-8:"
|
|
159
177
|
|
|
160
178
|
After each scope:
|
|
161
179
|
|
|
162
180
|
**Prompt:**
|
|
181
|
+
|
|
163
182
|
> "✓ Added scope: [scope-name]
|
|
164
|
-
>
|
|
183
|
+
>
|
|
165
184
|
> You have [N] scopes. Add another? (y/n)"
|
|
166
185
|
|
|
167
186
|
---
|
|
@@ -172,9 +191,9 @@ After each scope:
|
|
|
172
191
|
Agent: What is the primary domain or industry for this project?
|
|
173
192
|
User: Healthcare SaaS platform
|
|
174
193
|
|
|
175
|
-
Agent: What are the main feature areas of your healthcare SaaS?
|
|
194
|
+
Agent: What are the main feature areas of your healthcare SaaS?
|
|
176
195
|
(aim for 8-15 areas)
|
|
177
|
-
User: patient records, appointments, billing, insurance,
|
|
196
|
+
User: patient records, appointments, billing, insurance,
|
|
178
197
|
prescriptions, lab results, messaging, reports
|
|
179
198
|
|
|
180
199
|
Agent: What naming style do you prefer?
|
|
@@ -215,18 +234,22 @@ User: y
|
|
|
215
234
|
If user provides invalid input:
|
|
216
235
|
|
|
217
236
|
**For invalid scope name:**
|
|
237
|
+
|
|
218
238
|
> "The name '[name]' is invalid. Scope names must be:
|
|
239
|
+
>
|
|
219
240
|
> - Lowercase letters, numbers, and hyphens only
|
|
220
241
|
> - Maximum 32 characters
|
|
221
242
|
> - Not a reserved word (init, create, build, test, config, docs, ci, deps)
|
|
222
|
-
>
|
|
243
|
+
>
|
|
223
244
|
> Please provide a different name:"
|
|
224
245
|
|
|
225
246
|
**For short description:**
|
|
226
|
-
|
|
247
|
+
|
|
248
|
+
> "The description must be at least 10 characters to be meaningful.
|
|
227
249
|
> Please provide more detail about what '[scope-name]' covers:"
|
|
228
250
|
|
|
229
251
|
**For duplicate name:**
|
|
252
|
+
|
|
230
253
|
> "A scope named '[name]' already exists. Please choose a different name:"
|
|
231
254
|
|
|
232
255
|
---
|
|
@@ -236,10 +259,13 @@ If user provides invalid input:
|
|
|
236
259
|
After successfully creating the package, provide:
|
|
237
260
|
|
|
238
261
|
1. **Location confirmation:**
|
|
262
|
+
|
|
239
263
|
> "✨ Custom scope package created at: [path]"
|
|
240
264
|
|
|
241
265
|
2. **Next steps:**
|
|
266
|
+
|
|
242
267
|
> "Next steps:
|
|
268
|
+
>
|
|
243
269
|
> 1. cd [path]
|
|
244
270
|
> 2. pnpm install
|
|
245
271
|
> 3. pnpm build
|
|
@@ -247,7 +273,9 @@ After successfully creating the package, provide:
|
|
|
247
273
|
> 5. Update repository URL in package.json"
|
|
248
274
|
|
|
249
275
|
3. **Publishing instructions** (if user indicated intent):
|
|
276
|
+
|
|
250
277
|
> "To publish to npm:
|
|
278
|
+
>
|
|
251
279
|
> 1. npm login
|
|
252
280
|
> 2. Update version in package.json as needed
|
|
253
281
|
> 3. pnpm publish --access public"
|
|
@@ -42,6 +42,7 @@ ANY time a developer, AI agent, or team member receives an "ask" or suggestion t
|
|
|
42
42
|
### Improvement Suggestion Template
|
|
43
43
|
|
|
44
44
|
\`\`\`markdown
|
|
45
|
+
|
|
45
46
|
# Improvement Suggestion
|
|
46
47
|
|
|
47
48
|
**ID**: <unique-id>
|
|
@@ -69,11 +70,13 @@ ANY time a developer, AI agent, or team member receives an "ask" or suggestion t
|
|
|
69
70
|
## Implementation Plan
|
|
70
71
|
|
|
71
72
|
### Changes Required
|
|
73
|
+
|
|
72
74
|
- [ ] File/component to modify — `path/to/file.ts`
|
|
73
75
|
- [ ] Update documentation — `docs/section.md`
|
|
74
76
|
- [ ] Add tests — `tests/improvement.test.ts`
|
|
75
77
|
|
|
76
78
|
### Testing
|
|
79
|
+
|
|
77
80
|
- [ ] Unit tests added
|
|
78
81
|
- [ ] Integration tests added
|
|
79
82
|
- [ ] Manual testing completed
|
|
@@ -88,7 +91,7 @@ ANY time a developer, AI agent, or team member receives an "ask" or suggestion t
|
|
|
88
91
|
|
|
89
92
|
---
|
|
90
93
|
|
|
91
|
-
|
|
94
|
+
_To submit this improvement to the workflow-agent community:_
|
|
92
95
|
\`\`\`bash
|
|
93
96
|
workflow suggest "$(cat .workflow/improvements/YYYY-MM-DD-<id>.md)"
|
|
94
97
|
\`\`\`
|
|
@@ -128,23 +131,24 @@ The workflow system MUST proactively analyze usage patterns and offer suggestion
|
|
|
128
131
|
<One-line summary of the issue>
|
|
129
132
|
|
|
130
133
|
Details:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
• <Specific observation or pattern detected>
|
|
135
|
+
• <Impact or frequency data>
|
|
136
|
+
• <Concrete example from git history>
|
|
134
137
|
|
|
135
138
|
Recommendation:
|
|
136
|
-
|
|
139
|
+
<Actionable suggestion with exact command or config change>
|
|
137
140
|
|
|
138
141
|
To apply automatically:
|
|
139
|
-
|
|
142
|
+
workflow apply-suggestion <id>
|
|
140
143
|
|
|
141
144
|
To provide feedback:
|
|
142
|
-
|
|
145
|
+
workflow suggest "Alternative approach: ..."
|
|
143
146
|
\`\`\`
|
|
144
147
|
|
|
145
148
|
### Pattern Detection Examples
|
|
146
149
|
|
|
147
150
|
**Example 1: Common Typo**
|
|
151
|
+
|
|
148
152
|
```
|
|
149
153
|
💡 Workflow Optimization Suggestion
|
|
150
154
|
|
|
@@ -170,6 +174,7 @@ To apply automatically:
|
|
|
170
174
|
```
|
|
171
175
|
|
|
172
176
|
**Example 2: Scope Consolidation**
|
|
177
|
+
|
|
173
178
|
```
|
|
174
179
|
💡 Workflow Optimization Suggestion
|
|
175
180
|
|
|
@@ -211,6 +216,7 @@ ALL implemented improvements MUST be documented in `WORKFLOW_CHANGELOG.md` with:
|
|
|
211
216
|
### Changelog Template
|
|
212
217
|
|
|
213
218
|
\`\`\`markdown
|
|
219
|
+
|
|
214
220
|
## {{VERSION}} - {{DATE}}
|
|
215
221
|
|
|
216
222
|
### {{CATEGORY}} Improvements
|
|
@@ -244,15 +250,15 @@ Edit `workflow.config.ts`:
|
|
|
244
250
|
|
|
245
251
|
\`\`\`typescript
|
|
246
252
|
export default {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
253
|
+
projectName: '{{PROJECT_NAME}}',
|
|
254
|
+
scopes: [...],
|
|
255
|
+
|
|
256
|
+
// Enable community improvement syncing
|
|
257
|
+
syncRemote: 'https://workflow-improvements.dev/registry',
|
|
258
|
+
analytics: {
|
|
259
|
+
enabled: true,
|
|
260
|
+
shareAnonymous: true, // Help improve the tool!
|
|
261
|
+
},
|
|
256
262
|
};
|
|
257
263
|
\`\`\`
|
|
258
264
|
|
|
@@ -294,5 +300,5 @@ Every suggestion makes the workflow better for everyone. Your feedback matters!
|
|
|
294
300
|
|
|
295
301
|
---
|
|
296
302
|
|
|
297
|
-
|
|
298
|
-
|
|
303
|
+
_Generated by @hawkinside_out/workflow-agent - a self-evolving workflow management system_
|
|
304
|
+
_Learn more: https://workflow.dev/docs/self-improvement_
|
|
@@ -33,20 +33,20 @@ All Supabase client creation MUST go through these files. Never create clients d
|
|
|
33
33
|
|
|
34
34
|
```typescript
|
|
35
35
|
// ❌ WRONG - Never create clients directly
|
|
36
|
-
import { createClient } from
|
|
36
|
+
import { createClient } from "@supabase/supabase-js";
|
|
37
37
|
const supabase = createClient(url, key);
|
|
38
38
|
|
|
39
39
|
// ✅ CORRECT - Use the appropriate helper
|
|
40
40
|
// In client components:
|
|
41
|
-
import { getSupabaseClient } from
|
|
41
|
+
import { getSupabaseClient } from "@/lib/supabase/client";
|
|
42
42
|
const supabase = getSupabaseClient();
|
|
43
43
|
|
|
44
44
|
// In server actions/components:
|
|
45
|
-
import { createServerClient } from
|
|
45
|
+
import { createServerClient } from "@/lib/supabase/server";
|
|
46
46
|
const supabase = await createServerClient();
|
|
47
47
|
|
|
48
48
|
// For admin operations (bypasses RLS):
|
|
49
|
-
import { createAdminClient } from
|
|
49
|
+
import { createAdminClient } from "@/lib/supabase/admin";
|
|
50
50
|
const supabase = createAdminClient();
|
|
51
51
|
```
|
|
52
52
|
|
|
@@ -66,27 +66,38 @@ Authorization logic is centralized in these files. Never implement permission ch
|
|
|
66
66
|
|
|
67
67
|
```typescript
|
|
68
68
|
// Role types
|
|
69
|
-
export type OrgRole =
|
|
69
|
+
export type OrgRole =
|
|
70
|
+
| "super_admin"
|
|
71
|
+
| "owner"
|
|
72
|
+
| "admin"
|
|
73
|
+
| "manager"
|
|
74
|
+
| "developer"
|
|
75
|
+
| "viewer";
|
|
70
76
|
|
|
71
77
|
// Role hierarchy (higher index = more permissions)
|
|
72
78
|
export const ROLE_HIERARCHY: OrgRole[] = [
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
"viewer",
|
|
80
|
+
"developer",
|
|
81
|
+
"manager",
|
|
82
|
+
"admin",
|
|
83
|
+
"owner",
|
|
84
|
+
"super_admin",
|
|
79
85
|
];
|
|
80
86
|
|
|
81
87
|
// Role groups for permission checks
|
|
82
|
-
export const ADMIN_ROLES: OrgRole[] = [
|
|
83
|
-
export const PRIVILEGED_ROLES: OrgRole[] = [
|
|
88
|
+
export const ADMIN_ROLES: OrgRole[] = ["super_admin", "owner", "admin"];
|
|
89
|
+
export const PRIVILEGED_ROLES: OrgRole[] = [
|
|
90
|
+
"super_admin",
|
|
91
|
+
"owner",
|
|
92
|
+
"admin",
|
|
93
|
+
"manager",
|
|
94
|
+
];
|
|
84
95
|
export const CONTRIBUTOR_ROLES: OrgRole[] = [
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
"super_admin",
|
|
97
|
+
"owner",
|
|
98
|
+
"admin",
|
|
99
|
+
"manager",
|
|
100
|
+
"developer",
|
|
90
101
|
];
|
|
91
102
|
```
|
|
92
103
|
|
|
@@ -100,13 +111,13 @@ import {
|
|
|
100
111
|
requireAdminAccess,
|
|
101
112
|
requirePrivilegedAccess,
|
|
102
113
|
requireContributorAccess,
|
|
103
|
-
} from
|
|
114
|
+
} from "@/utils/authorization.server";
|
|
104
115
|
|
|
105
116
|
// In server actions - always verify access FIRST
|
|
106
117
|
export async function getTask(taskId: string) {
|
|
107
118
|
const access = await verifyTaskAccess(taskId);
|
|
108
119
|
if (!access.hasAccess) {
|
|
109
|
-
return { data: null, error: access.error ||
|
|
120
|
+
return { data: null, error: access.error || "Access denied" };
|
|
110
121
|
}
|
|
111
122
|
// ... proceed with data access
|
|
112
123
|
}
|
|
@@ -179,19 +190,19 @@ export type TaskType = "story" | "task" | "bug" | "epic";
|
|
|
179
190
|
|
|
180
191
|
```typescript
|
|
181
192
|
// lib/validations/task.schema.ts
|
|
182
|
-
import { z } from
|
|
193
|
+
import { z } from "zod";
|
|
183
194
|
|
|
184
195
|
export const TaskSchema = z.object({
|
|
185
196
|
id: z.string().uuid(),
|
|
186
197
|
ticketId: z.string().regex(/^[A-Z]{1,6}-\d{4}$/),
|
|
187
198
|
title: z.string().min(1).max(255),
|
|
188
|
-
priority: z.enum([
|
|
199
|
+
priority: z.enum(["low", "medium", "high", "critical"]),
|
|
189
200
|
});
|
|
190
201
|
|
|
191
202
|
export type Task = z.infer<typeof TaskSchema>;
|
|
192
203
|
|
|
193
204
|
// lib/validations/index.ts
|
|
194
|
-
export { TaskSchema, type Task } from
|
|
205
|
+
export { TaskSchema, type Task } from "./task.schema";
|
|
195
206
|
```
|
|
196
207
|
|
|
197
208
|
---
|
|
@@ -233,7 +244,7 @@ app/providers/
|
|
|
233
244
|
|
|
234
245
|
```typescript
|
|
235
246
|
// Always import hooks from the providers module
|
|
236
|
-
import { useAuth, useOrganization, useNotifications } from
|
|
247
|
+
import { useAuth, useOrganization, useNotifications } from "@/app/providers";
|
|
237
248
|
|
|
238
249
|
function MyComponent() {
|
|
239
250
|
const { user, loading } = useAuth();
|
|
@@ -277,11 +288,11 @@ Every action file MUST:
|
|
|
277
288
|
4. Transform snake_case DB fields to camelCase
|
|
278
289
|
|
|
279
290
|
```typescript
|
|
280
|
-
|
|
291
|
+
"use server";
|
|
281
292
|
|
|
282
|
-
import { createServerClient } from
|
|
283
|
-
import { verifyBoardAccess } from
|
|
284
|
-
import { revalidatePath } from
|
|
293
|
+
import { createServerClient } from "@/lib/supabase/server";
|
|
294
|
+
import { verifyBoardAccess } from "@/utils/authorization.server";
|
|
295
|
+
import { revalidatePath } from "next/cache";
|
|
285
296
|
|
|
286
297
|
export async function getTasks(boardId: string) {
|
|
287
298
|
const access = await verifyBoardAccess(boardId);
|
|
@@ -290,7 +301,10 @@ export async function getTasks(boardId: string) {
|
|
|
290
301
|
}
|
|
291
302
|
|
|
292
303
|
const supabase = await createServerClient();
|
|
293
|
-
const { data, error } = await supabase
|
|
304
|
+
const { data, error } = await supabase
|
|
305
|
+
.from("tasks")
|
|
306
|
+
.select("*")
|
|
307
|
+
.eq("board_id", boardId);
|
|
294
308
|
|
|
295
309
|
if (error) return { data: null, error: error.message };
|
|
296
310
|
|
|
@@ -317,7 +331,7 @@ Custom React hooks live in `hooks/`.
|
|
|
317
331
|
### Hook Pattern
|
|
318
332
|
|
|
319
333
|
```typescript
|
|
320
|
-
import { useState, useEffect, useCallback } from
|
|
334
|
+
import { useState, useEffect, useCallback } from "react";
|
|
321
335
|
|
|
322
336
|
export function useHookName(param: string) {
|
|
323
337
|
const [data, setData] = useState<DataType | null>(null);
|
|
@@ -457,30 +471,33 @@ export function useHookName(param: string) {
|
|
|
457
471
|
|
|
458
472
|
```typescript
|
|
459
473
|
// Supabase clients
|
|
460
|
-
import { getSupabaseClient } from
|
|
461
|
-
import { createServerClient } from
|
|
462
|
-
import { createAdminClient } from
|
|
474
|
+
import { getSupabaseClient } from "@/lib/supabase/client";
|
|
475
|
+
import { createServerClient } from "@/lib/supabase/server";
|
|
476
|
+
import { createAdminClient } from "@/lib/supabase/admin";
|
|
463
477
|
|
|
464
478
|
// Authorization
|
|
465
|
-
import { ROLE_HIERARCHY, ADMIN_ROLES } from
|
|
466
|
-
import {
|
|
467
|
-
|
|
479
|
+
import { ROLE_HIERARCHY, ADMIN_ROLES } from "@/utils/authorization";
|
|
480
|
+
import {
|
|
481
|
+
verifyBoardAccess,
|
|
482
|
+
requireAdminAccess,
|
|
483
|
+
} from "@/utils/authorization.server";
|
|
484
|
+
import { useAuthorization } from "@/hooks/useAuthorization";
|
|
468
485
|
|
|
469
486
|
// Types
|
|
470
|
-
import type { Task, Board, Sprint, Organization } from
|
|
471
|
-
import type { Database } from
|
|
487
|
+
import type { Task, Board, Sprint, Organization } from "@/types";
|
|
488
|
+
import type { Database } from "@/types/supabase";
|
|
472
489
|
|
|
473
490
|
// Providers/Context
|
|
474
|
-
import { useAuth, useOrganization, useTeams } from
|
|
491
|
+
import { useAuth, useOrganization, useTeams } from "@/app/providers";
|
|
475
492
|
|
|
476
493
|
// UI Components
|
|
477
|
-
import { Button, Input, Dialog } from
|
|
494
|
+
import { Button, Input, Dialog } from "@/components/ui";
|
|
478
495
|
|
|
479
496
|
// Schemas
|
|
480
|
-
import { TaskSchema, CreateTaskSchema } from
|
|
497
|
+
import { TaskSchema, CreateTaskSchema } from "@/lib/validations";
|
|
481
498
|
|
|
482
499
|
// Test utilities
|
|
483
|
-
import { mockTasks, createMockTask, seedTasks } from
|
|
500
|
+
import { mockTasks, createMockTask, seedTasks } from "@test/fixtures";
|
|
484
501
|
```
|
|
485
502
|
|
|
486
503
|
---
|