ai-flow-dev 2.7.0 → 2.8.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/LICENSE +21 -21
- package/README.md +573 -570
- package/package.json +74 -74
- package/prompts/backend/flow-build-phase-0.md +535 -535
- package/prompts/backend/flow-build-phase-1.md +626 -626
- package/prompts/backend/flow-build-phase-10.md +340 -340
- package/prompts/backend/flow-build-phase-2.md +573 -573
- package/prompts/backend/flow-build-phase-3.md +834 -834
- package/prompts/backend/flow-build-phase-4.md +554 -554
- package/prompts/backend/flow-build-phase-5.md +703 -703
- package/prompts/backend/flow-build-phase-6.md +524 -524
- package/prompts/backend/flow-build-phase-7.md +1001 -1001
- package/prompts/backend/flow-build-phase-8.md +1407 -1407
- package/prompts/backend/flow-build-phase-9.md +477 -477
- package/prompts/backend/flow-build.md +137 -137
- package/prompts/backend/flow-check-review.md +656 -20
- package/prompts/backend/flow-check-test.md +526 -14
- package/prompts/backend/flow-check.md +725 -67
- package/prompts/backend/flow-commit.md +88 -119
- package/prompts/backend/flow-docs-sync.md +354 -354
- package/prompts/backend/flow-finish.md +919 -0
- package/prompts/backend/flow-release.md +949 -0
- package/prompts/backend/flow-work-feature.md +61 -61
- package/prompts/backend/flow-work-fix.md +46 -46
- package/prompts/backend/flow-work-refactor.md +48 -48
- package/prompts/backend/flow-work-resume.md +34 -34
- package/prompts/backend/flow-work.md +1098 -1286
- package/prompts/desktop/flow-build-phase-0.md +359 -359
- package/prompts/desktop/flow-build-phase-1.md +295 -295
- package/prompts/desktop/flow-build-phase-10.md +357 -357
- package/prompts/desktop/flow-build-phase-2.md +282 -282
- package/prompts/desktop/flow-build-phase-3.md +291 -291
- package/prompts/desktop/flow-build-phase-4.md +308 -308
- package/prompts/desktop/flow-build-phase-5.md +269 -269
- package/prompts/desktop/flow-build-phase-6.md +350 -350
- package/prompts/desktop/flow-build-phase-7.md +297 -297
- package/prompts/desktop/flow-build-phase-8.md +541 -541
- package/prompts/desktop/flow-build-phase-9.md +439 -439
- package/prompts/desktop/flow-build.md +156 -156
- package/prompts/desktop/flow-check-review.md +656 -20
- package/prompts/desktop/flow-check-test.md +526 -14
- package/prompts/desktop/flow-check.md +725 -67
- package/prompts/desktop/flow-commit.md +88 -119
- package/prompts/desktop/flow-docs-sync.md +354 -354
- package/prompts/desktop/flow-finish.md +910 -0
- package/prompts/desktop/flow-release.md +662 -0
- package/prompts/desktop/flow-work-feature.md +61 -61
- package/prompts/desktop/flow-work-fix.md +46 -46
- package/prompts/desktop/flow-work-refactor.md +48 -48
- package/prompts/desktop/flow-work-resume.md +34 -34
- package/prompts/desktop/flow-work.md +1202 -1390
- package/prompts/frontend/flow-build-phase-0.md +425 -425
- package/prompts/frontend/flow-build-phase-1.md +626 -626
- package/prompts/frontend/flow-build-phase-10.md +33 -33
- package/prompts/frontend/flow-build-phase-2.md +573 -573
- package/prompts/frontend/flow-build-phase-3.md +782 -782
- package/prompts/frontend/flow-build-phase-4.md +554 -554
- package/prompts/frontend/flow-build-phase-5.md +703 -703
- package/prompts/frontend/flow-build-phase-6.md +524 -524
- package/prompts/frontend/flow-build-phase-7.md +1001 -1001
- package/prompts/frontend/flow-build-phase-8.md +872 -872
- package/prompts/frontend/flow-build-phase-9.md +94 -94
- package/prompts/frontend/flow-build.md +137 -137
- package/prompts/frontend/flow-check-review.md +656 -20
- package/prompts/frontend/flow-check-test.md +526 -14
- package/prompts/frontend/flow-check.md +725 -67
- package/prompts/frontend/flow-commit.md +88 -119
- package/prompts/frontend/flow-docs-sync.md +550 -550
- package/prompts/frontend/flow-finish.md +910 -0
- package/prompts/frontend/flow-release.md +519 -0
- package/prompts/frontend/flow-work-api.md +1540 -0
- package/prompts/frontend/flow-work-feature.md +61 -61
- package/prompts/frontend/flow-work-fix.md +38 -38
- package/prompts/frontend/flow-work-refactor.md +48 -48
- package/prompts/frontend/flow-work-resume.md +34 -34
- package/prompts/frontend/flow-work.md +1583 -1320
- package/prompts/mobile/flow-build-phase-0.md +425 -425
- package/prompts/mobile/flow-build-phase-1.md +626 -626
- package/prompts/mobile/flow-build-phase-10.md +32 -32
- package/prompts/mobile/flow-build-phase-2.md +573 -573
- package/prompts/mobile/flow-build-phase-3.md +782 -782
- package/prompts/mobile/flow-build-phase-4.md +554 -554
- package/prompts/mobile/flow-build-phase-5.md +703 -703
- package/prompts/mobile/flow-build-phase-6.md +524 -524
- package/prompts/mobile/flow-build-phase-7.md +1001 -1001
- package/prompts/mobile/flow-build-phase-8.md +888 -888
- package/prompts/mobile/flow-build-phase-9.md +90 -90
- package/prompts/mobile/flow-build.md +135 -135
- package/prompts/mobile/flow-check-review.md +656 -20
- package/prompts/mobile/flow-check-test.md +526 -14
- package/prompts/mobile/flow-check.md +725 -67
- package/prompts/mobile/flow-commit.md +88 -119
- package/prompts/mobile/flow-docs-sync.md +620 -620
- package/prompts/mobile/flow-finish.md +910 -0
- package/prompts/mobile/flow-release.md +751 -0
- package/prompts/mobile/flow-work-api.md +1493 -0
- package/prompts/mobile/flow-work-feature.md +61 -61
- package/prompts/mobile/flow-work-fix.md +46 -46
- package/prompts/mobile/flow-work-refactor.md +48 -48
- package/prompts/mobile/flow-work-resume.md +34 -34
- package/prompts/mobile/flow-work.md +1593 -1329
- package/prompts/shared/mermaid-guidelines.md +102 -102
- package/prompts/shared/scope-levels.md +114 -114
- package/prompts/shared/smart-skip-preflight.md +214 -214
- package/prompts/shared/story-points.md +55 -55
- package/prompts/shared/task-format.md +74 -74
- package/prompts/shared/task-summary-template.md +277 -277
- package/templates/AGENT.template.md +443 -443
- package/templates/backend/.clauderules.template +112 -112
- package/templates/backend/.cursorrules.template +102 -102
- package/templates/backend/README.template.md +2 -2
- package/templates/backend/ai-instructions.template.md +2 -2
- package/templates/backend/copilot-instructions.template.md +2 -2
- package/templates/backend/docs/api.template.md +320 -320
- package/templates/backend/docs/business-flows.template.md +97 -97
- package/templates/backend/docs/code-standards.template.md +2 -2
- package/templates/backend/docs/contributing.template.md +3 -3
- package/templates/backend/docs/data-model.template.md +520 -520
- package/templates/backend/docs/testing.template.md +2 -2
- package/templates/backend/project-brief.template.md +2 -2
- package/templates/backend/specs/configuration.template.md +2 -2
- package/templates/backend/specs/security.template.md +2 -2
- package/templates/desktop/.clauderules.template +112 -112
- package/templates/desktop/.cursorrules.template +102 -102
- package/templates/desktop/README.template.md +170 -170
- package/templates/desktop/ai-instructions.template.md +366 -366
- package/templates/desktop/copilot-instructions.template.md +140 -140
- package/templates/desktop/docs/docs/api.template.md +320 -320
- package/templates/desktop/docs/docs/architecture.template.md +724 -724
- package/templates/desktop/docs/docs/business-flows.template.md +102 -102
- package/templates/desktop/docs/docs/code-standards.template.md +792 -792
- package/templates/desktop/docs/docs/contributing.template.md +149 -149
- package/templates/desktop/docs/docs/data-model.template.md +520 -520
- package/templates/desktop/docs/docs/operations.template.md +720 -720
- package/templates/desktop/docs/docs/testing.template.md +722 -722
- package/templates/desktop/project-brief.template.md +150 -150
- package/templates/desktop/specs/specs/configuration.template.md +121 -121
- package/templates/desktop/specs/specs/security.template.md +392 -392
- package/templates/frontend/README.template.md +2 -2
- package/templates/frontend/ai-instructions.template.md +2 -2
- package/templates/frontend/docs/api-integration.template.md +362 -362
- package/templates/frontend/docs/components.template.md +2 -2
- package/templates/frontend/docs/error-handling.template.md +360 -360
- package/templates/frontend/docs/operations.template.md +107 -107
- package/templates/frontend/docs/performance.template.md +124 -124
- package/templates/frontend/docs/pwa.template.md +119 -119
- package/templates/frontend/docs/state-management.template.md +2 -2
- package/templates/frontend/docs/styling.template.md +2 -2
- package/templates/frontend/docs/testing.template.md +2 -2
- package/templates/frontend/project-brief.template.md +2 -2
- package/templates/frontend/specs/accessibility.template.md +95 -95
- package/templates/frontend/specs/configuration.template.md +2 -2
- package/templates/frontend/specs/security.template.md +175 -175
- package/templates/fullstack/README.template.md +252 -252
- package/templates/fullstack/ai-instructions.template.md +444 -444
- package/templates/fullstack/project-brief.template.md +157 -157
- package/templates/fullstack/specs/configuration.template.md +340 -340
- package/templates/mobile/README.template.md +167 -167
- package/templates/mobile/ai-instructions.template.md +196 -196
- package/templates/mobile/docs/app-store.template.md +135 -135
- package/templates/mobile/docs/architecture.template.md +63 -63
- package/templates/mobile/docs/native-features.template.md +94 -94
- package/templates/mobile/docs/navigation.template.md +59 -59
- package/templates/mobile/docs/offline-strategy.template.md +65 -65
- package/templates/mobile/docs/permissions.template.md +56 -56
- package/templates/mobile/docs/state-management.template.md +85 -85
- package/templates/mobile/docs/testing.template.md +109 -109
- package/templates/mobile/project-brief.template.md +69 -69
- package/templates/mobile/specs/build-configuration.template.md +91 -91
- package/templates/mobile/specs/deployment.template.md +92 -92
- package/templates/work.template.md +47 -47
|
@@ -1,20 +1,656 @@
|
|
|
1
|
-
---
|
|
2
|
-
description:
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# AI Flow - Review
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
1
|
+
---
|
|
2
|
+
description: Technical Reference - Code Review Methodology for flow-check
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# AI Flow - Code Review Methodology
|
|
6
|
+
|
|
7
|
+
This document provides detailed technical reference for the 5-perspective code review within `/flow-check` workflow.
|
|
8
|
+
|
|
9
|
+
> **📝 Language-Agnostic Note:** This document uses examples in multiple programming languages (Java, Python, TypeScript, Go, etc.) to illustrate security vulnerabilities, performance issues, and code quality patterns. The principles and detection criteria apply universally to any language or framework. Adapt the syntax and tools to match your technology stack.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 🎯 Overview
|
|
14
|
+
|
|
15
|
+
Professional code review analyzes code quality from multiple perspectives. This reference covers:
|
|
16
|
+
|
|
17
|
+
- Review criteria for each perspective
|
|
18
|
+
- Detection patterns and examples
|
|
19
|
+
- Prioritization methodology
|
|
20
|
+
- Reporting standards
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Review Perspectives
|
|
25
|
+
|
|
26
|
+
### 1. 🔒 Security Analysis
|
|
27
|
+
|
|
28
|
+
**Objective:** Identify vulnerabilities that could lead to data breaches, unauthorized access, or system compromise.
|
|
29
|
+
|
|
30
|
+
#### A. SQL Injection
|
|
31
|
+
|
|
32
|
+
**Pattern to detect:**
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
❌ CRITICAL - String concatenation/interpolation:
|
|
36
|
+
→ TypeScript: 'SELECT * FROM users WHERE id = ' + userId
|
|
37
|
+
→ TypeScript: `DELETE FROM posts WHERE author = '${username}'`
|
|
38
|
+
→ Java: "SELECT * FROM users WHERE id = " + userId
|
|
39
|
+
→ Python: f"SELECT * FROM users WHERE id = {user_id}"
|
|
40
|
+
|
|
41
|
+
✅ SAFE - Parameterized queries/PreparedStatements:
|
|
42
|
+
→ TypeScript: db.query('... WHERE id = ?', [userId])
|
|
43
|
+
→ Java: PreparedStatement stmt = conn.prepareStatement("... WHERE id = ?"); stmt.setInt(1, userId);
|
|
44
|
+
→ Python: cursor.execute("... WHERE id = %s", (user_id,)) OR use ORM (SQLAlchemy, Django)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Priority:** 🔴 CRITICAL
|
|
48
|
+
**Impact:** Database compromise, data theft, data loss
|
|
49
|
+
|
|
50
|
+
#### B. XSS Vulnerabilities
|
|
51
|
+
|
|
52
|
+
**Pattern to detect:**
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
❌ CRITICAL - Unescaped user input in HTML:
|
|
56
|
+
→ TypeScript (Vanilla): element.innerHTML = userComment
|
|
57
|
+
→ TypeScript (React): <div dangerouslySetInnerHTML={{__html: userContent}} />
|
|
58
|
+
→ Python (Jinja2): {{ user_input | safe }} OR html = f"<div>{user_input}</div>"
|
|
59
|
+
→ Java (JSP): <%= request.getParameter("comment") %>
|
|
60
|
+
→ Java (Thymeleaf): <div th:utext="${userComment}"></div>
|
|
61
|
+
|
|
62
|
+
✅ SAFE - Auto-escaped or explicit escaping:
|
|
63
|
+
→ TypeScript: element.textContent = userComment OR <div>{userContent}</div> (React auto-escapes)
|
|
64
|
+
→ Python: {{ user_input }} (Jinja2 auto-escapes) OR escape(user_input)
|
|
65
|
+
→ Java (JSP): <c:out value="${param.comment}" /> (JSTL auto-escapes)
|
|
66
|
+
→ Java (Thymeleaf): <div th:text="${userComment}"></div> (th:text auto-escapes)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Priority:** 🔴 CRITICAL (stored XSS), 🟡 WARNING (reflected XSS)
|
|
70
|
+
**Impact:** Session hijacking, credential theft, malware injection
|
|
71
|
+
|
|
72
|
+
#### C. Secrets in Code
|
|
73
|
+
|
|
74
|
+
**Pattern to detect:**
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// ❌ CRITICAL - Hardcoded API keys
|
|
78
|
+
const API_KEY = 'your_stripe_key_here';
|
|
79
|
+
const DB_PASSWORD = 'supersecret123';
|
|
80
|
+
|
|
81
|
+
// ❌ CRITICAL - AWS credentials
|
|
82
|
+
aws.config.update({
|
|
83
|
+
accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
|
|
84
|
+
secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// ✅ SAFE - Environment variables
|
|
88
|
+
const API_KEY = process.env.API_KEY;
|
|
89
|
+
const DB_PASSWORD = process.env.DB_PASSWORD;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Patterns to grep:**
|
|
93
|
+
|
|
94
|
+
- `api_key\s*=\s*["']\w+`
|
|
95
|
+
- `password\s*=\s*["']\w+`
|
|
96
|
+
- `secret\s*=\s*["']\w+`
|
|
97
|
+
- `AKIA[0-9A-Z]{16}` (AWS access key)
|
|
98
|
+
- `sk_live_` (Stripe key)
|
|
99
|
+
|
|
100
|
+
**Priority:** 🔴 CRITICAL
|
|
101
|
+
**Impact:** Unauthorized access, account takeover, financial loss
|
|
102
|
+
|
|
103
|
+
#### D. Authentication/Authorization Issues
|
|
104
|
+
|
|
105
|
+
**Pattern to detect:**
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// ❌ WARNING - Missing auth check
|
|
109
|
+
app.delete('/api/users/:id', (req, res) => {
|
|
110
|
+
// No authentication check!
|
|
111
|
+
db.users.delete(req.params.id);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ❌ WARNING - Weak session config
|
|
115
|
+
session({
|
|
116
|
+
secret: 'keyboard cat', // Weak secret
|
|
117
|
+
cookie: { secure: false }, // No HTTPS requirement
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// ✅ SAFE - Proper auth middleware
|
|
121
|
+
app.delete('/api/users/:id', requireAuth, requireOwnership, (req, res) => {
|
|
122
|
+
db.users.delete(req.params.id);
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Priority:** 🔴 CRITICAL (no auth on sensitive ops), 🟡 WARNING (weak config)
|
|
127
|
+
|
|
128
|
+
#### E. CSRF Vulnerabilities
|
|
129
|
+
|
|
130
|
+
**Pattern to detect:**
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// ❌ WARNING - State-changing GET request
|
|
134
|
+
app.get('/api/users/:id/delete', (req, res) => {
|
|
135
|
+
db.users.delete(req.params.id);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// ❌ WARNING - POST without CSRF token
|
|
139
|
+
app.post('/api/transfer', (req, res) => {
|
|
140
|
+
// No CSRF protection
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// ✅ SAFE - POST with CSRF middleware
|
|
144
|
+
app.post('/api/transfer', csrfProtection, (req, res) => {
|
|
145
|
+
// Protected
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Priority:** 🟡 WARNING
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### 2. ⚡ Performance Analysis
|
|
154
|
+
|
|
155
|
+
**Objective:** Identify code that causes slow response times, high resource usage, or scalability issues.
|
|
156
|
+
|
|
157
|
+
#### A. N+1 Query Problem
|
|
158
|
+
|
|
159
|
+
**Pattern to detect:**
|
|
160
|
+
|
|
161
|
+
```text
|
|
162
|
+
❌ CRITICAL - Loop + query inside (N+1 pattern):
|
|
163
|
+
→ TypeScript: const posts = await db.posts.findAll(); for (post of posts) { post.author = await db.users.findById(post.authorId); }
|
|
164
|
+
→ Python: posts = Post.objects.all(); for post in posts: post.author = User.objects.get(id=post.author_id)
|
|
165
|
+
→ Java: List<Post> posts = query("SELECT p FROM Post p"); for (Post post : posts) { User author = post.getAuthor(); } // Lazy loading!
|
|
166
|
+
|
|
167
|
+
✅ OPTIMIZED - Single query with JOIN/eager loading:
|
|
168
|
+
→ TypeScript: await db.posts.findAll({ include: [{ model: User, as: 'author' }] })
|
|
169
|
+
→ Python: Post.objects.select_related('author').all() OR prefetch_related('tags') for M2M
|
|
170
|
+
→ Java: query("SELECT p FROM Post p JOIN FETCH p.author") OR @EntityGraph(attributePaths = {"author", "tags"})
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Detection heuristic:**
|
|
174
|
+
|
|
175
|
+
- Loop over query results
|
|
176
|
+
- Database query inside loop
|
|
177
|
+
- Could be replaced with JOIN/IN query
|
|
178
|
+
|
|
179
|
+
**Priority:** 🔴 CRITICAL (user-facing), 🟡 WARNING (background jobs)
|
|
180
|
+
**Impact:** Slow response times, database overload, poor scalability
|
|
181
|
+
|
|
182
|
+
#### B. Memory Leaks
|
|
183
|
+
|
|
184
|
+
**Pattern to detect:**
|
|
185
|
+
|
|
186
|
+
```text
|
|
187
|
+
❌ WARNING - Resources not cleaned up:
|
|
188
|
+
→ TypeScript: eventEmitter.on('update', handler) // Never removed with .off()
|
|
189
|
+
→ TypeScript: cache[key] = value // Unbounded cache, never cleared
|
|
190
|
+
→ Java: FileInputStream fis = new FileInputStream(path); // No try-with-resources, never closed
|
|
191
|
+
→ Java: static Map<String, Object> cache = new HashMap<>(); cache.put(key, value); // Grows unbounded
|
|
192
|
+
→ Python: f = open(path) // Never explicitly closed
|
|
193
|
+
→ Python: child.parent = self; self.children.append(child); // Circular reference prevents GC
|
|
194
|
+
|
|
195
|
+
✅ SAFE - Proper cleanup/resource management:
|
|
196
|
+
→ TypeScript: destroy() { eventEmitter.off('update', this.handler); } // Cleanup in destructor
|
|
197
|
+
→ Java: try (FileInputStream fis = new FileInputStream(path)) { ... } // Auto-closes
|
|
198
|
+
→ Java: Use WeakHashMap or implement eviction policy for caches
|
|
199
|
+
→ Python: with open(path) as f: ... // Auto-closes with context manager
|
|
200
|
+
→ Python: Use weakref.ref() for circular references
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Priority:** 🟡 WARNING
|
|
204
|
+
**Impact:** Increasing memory usage, eventual crashes
|
|
205
|
+
|
|
206
|
+
#### C. Blocking Operations
|
|
207
|
+
|
|
208
|
+
**Pattern to detect:**
|
|
209
|
+
|
|
210
|
+
```text
|
|
211
|
+
❌ WARNING - Synchronous I/O in request handlers:
|
|
212
|
+
→ TypeScript: app.get('/data', (req, res) => { const data = fs.readFileSync('./file.json'); ... }) // Blocks event loop!
|
|
213
|
+
→ Java: @GetMapping("/data") public ResponseEntity getData() { String content = Files.readString(path); ... } // Blocks thread!
|
|
214
|
+
→ Python: @app.get("/data") def get_data(): with open('file.json', 'r') as f: return json.load(f) // Blocks event loop!
|
|
215
|
+
|
|
216
|
+
✅ OPTIMIZED - Async I/O:
|
|
217
|
+
→ TypeScript: async (req, res) => { const data = await fs.promises.readFile('./file.json'); ... }
|
|
218
|
+
→ Java: CompletableFuture<ResponseEntity> getData() { return CompletableFuture.supplyAsync(() -> Files.readString(path)); }
|
|
219
|
+
→ Python: async def get_data(): async with aiofiles.open('file.json', 'r') as f: content = await f.read(); ...
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Priority:** 🔴 CRITICAL (request handlers), 🟡 WARNING (background tasks)
|
|
223
|
+
|
|
224
|
+
#### D. Inefficient Algorithms
|
|
225
|
+
|
|
226
|
+
**Pattern to detect:**
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
// ❌ WARNING - Nested loops (O(n²))
|
|
230
|
+
for (const item1 of list1) {
|
|
231
|
+
for (const item2 of list2) {
|
|
232
|
+
if (item1.id === item2.id) {
|
|
233
|
+
matches.push(item1);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ✅ OPTIMIZED - Hash map (O(n))
|
|
239
|
+
const map = new Map(list2.map((item) => [item.id, item]));
|
|
240
|
+
const matches = list1.filter((item) => map.has(item.id));
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Priority:** 🟡 WARNING (small datasets), 🔴 CRITICAL (large datasets)
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### 3. 🧪 Testing Quality
|
|
248
|
+
|
|
249
|
+
**Objective:** Ensure tests are effective, maintainable, and provide adequate coverage.
|
|
250
|
+
|
|
251
|
+
#### A. Missing Edge Cases
|
|
252
|
+
|
|
253
|
+
**Pattern to detect:**
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
// ❌ WARNING - Only happy path tested
|
|
257
|
+
describe('validateEmail', () => {
|
|
258
|
+
it('should accept valid email', () => {
|
|
259
|
+
expect(validateEmail('user@example.com')).toBe(true);
|
|
260
|
+
});
|
|
261
|
+
// Missing: null, undefined, empty string, invalid formats
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// ✅ COMPLETE - Edge cases covered
|
|
265
|
+
describe('validateEmail', () => {
|
|
266
|
+
it('should accept valid email', () => {
|
|
267
|
+
expect(validateEmail('user@example.com')).toBe(true);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('should reject null', () => {
|
|
271
|
+
expect(validateEmail(null)).toBe(false);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('should reject empty string', () => {
|
|
275
|
+
expect(validateEmail('')).toBe(false);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('should reject invalid format', () => {
|
|
279
|
+
expect(validateEmail('not-an-email')).toBe(false);
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Edge cases to check:**
|
|
285
|
+
|
|
286
|
+
- Null/undefined inputs
|
|
287
|
+
- Empty strings/arrays/objects
|
|
288
|
+
- Boundary values (0, -1, MAX_INT)
|
|
289
|
+
- Special characters
|
|
290
|
+
- Very long inputs
|
|
291
|
+
|
|
292
|
+
**Priority:** 🟡 WARNING (critical functions), 🟢 SUGGESTION (utils)
|
|
293
|
+
|
|
294
|
+
#### B. Weak Assertions
|
|
295
|
+
|
|
296
|
+
**Pattern to detect:**
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
// ❌ WARNING - Weak assertion
|
|
300
|
+
expect(response).toBeTruthy(); // Too vague!
|
|
301
|
+
expect(user.id).toBeDefined(); // Could be null
|
|
302
|
+
|
|
303
|
+
// ✅ STRONG - Specific assertions
|
|
304
|
+
expect(response.status).toBe(200);
|
|
305
|
+
expect(response.body).toEqual({
|
|
306
|
+
id: expect.any(Number),
|
|
307
|
+
email: 'user@example.com',
|
|
308
|
+
});
|
|
309
|
+
expect(user.id).toBeGreaterThan(0);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Priority:** 🟢 SUGGESTION
|
|
313
|
+
|
|
314
|
+
#### C. Test Independence
|
|
315
|
+
|
|
316
|
+
**Pattern to detect:**
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
// ❌ WARNING - Shared mutable state
|
|
320
|
+
let currentUser;
|
|
321
|
+
|
|
322
|
+
describe('Users', () => {
|
|
323
|
+
it('should create user', () => {
|
|
324
|
+
currentUser = createUser(); // Mutates shared state!
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('should update user', () => {
|
|
328
|
+
updateUser(currentUser); // Depends on previous test!
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// ✅ INDEPENDENT - Each test isolated
|
|
333
|
+
describe('Users', () => {
|
|
334
|
+
it('should create user', () => {
|
|
335
|
+
const user = createUser();
|
|
336
|
+
expect(user).toBeDefined();
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it('should update user', () => {
|
|
340
|
+
const user = createUser(); // Fresh state
|
|
341
|
+
updateUser(user);
|
|
342
|
+
expect(user.updatedAt).toBeDefined();
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Priority:** 🟡 WARNING
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
### 4. 📐 Architecture Analysis
|
|
352
|
+
|
|
353
|
+
**Objective:** Ensure code follows SOLID principles, has proper separation of concerns, and is maintainable.
|
|
354
|
+
|
|
355
|
+
#### A. Single Responsibility Principle (SRP)
|
|
356
|
+
|
|
357
|
+
**Pattern to detect:**
|
|
358
|
+
|
|
359
|
+
```text
|
|
360
|
+
❌ WARNING - Too many responsibilities (God class):
|
|
361
|
+
→ TypeScript: class UserService { createUser() { /* DB */ } sendWelcomeEmail() { /* Email */ } logUserActivity() { /* Logging */ } validateUserData() { /* Validation */ } generateReport() { /* Reporting */ } } // 5 different concerns!
|
|
362
|
+
→ Java: class OrderProcessor { saveOrder() {...} calculateTotal() {...} sendConfirmationEmail() {...} generateInvoice() {...} processPayment() {...} } // DB + Business + Email + PDF + Payment!
|
|
363
|
+
→ Python: class UserManager { def create_user(data): validate + save + email + log all mixed! } // 4 responsibilities in one method!
|
|
364
|
+
|
|
365
|
+
✅ PROPER - Single responsibility per class:
|
|
366
|
+
→ TypeScript: class UserRepository { createUser() {...} } class EmailService { sendWelcomeEmail() {...} } class UserValidator { validate() {...} }
|
|
367
|
+
→ Java: class OrderRepository { save() {...} } class OrderCalculator { calculateTotal() {...} } class EmailService { sendConfirmation() {...} }
|
|
368
|
+
→ Python: class UserRepository { def save(user): ... } class UserValidator { def validate(data): ... } class EmailService { def send_welcome(user): ... }
|
|
369
|
+
|
|
370
|
+
Detection heuristic: Class > 300 lines OR > 10 methods OR method names suggest different domains (send*, log*, validate*, generate*)
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**Priority:** 🟡 WARNING (large classes), 🟢 SUGGESTION (medium classes)
|
|
374
|
+
|
|
375
|
+
#### B. DRY Violations (Don't Repeat Yourself)
|
|
376
|
+
|
|
377
|
+
**Pattern to detect:**
|
|
378
|
+
|
|
379
|
+
```text
|
|
380
|
+
❌ WARNING - Duplicated logic across functions/handlers:
|
|
381
|
+
→ TypeScript: app.get('/users', (req, res) => { if (!req.headers.authorization) return 401; ... }); app.get('/posts', (req, res) => { if (!req.headers.authorization) return 401; ... }); // Same auth check!
|
|
382
|
+
→ Java: @PostMapping createUser(@RequestBody User u) { if (u.getEmail() == null || !u.getEmail().contains("@")) throw ...; } @PutMapping updateUser(...) { if (u.getEmail() == null || !u.getEmail().contains("@")) throw ...; } // Same validation!
|
|
383
|
+
→ Python: @app.route('/users') def get_users(): if not request.headers.get('Auth'): return 401; ... @app.route('/posts') def get_posts(): if not request.headers.get('Auth'): return 401; ... // Same check!
|
|
384
|
+
|
|
385
|
+
✅ DRY - Extract to middleware/decorator/validation:
|
|
386
|
+
→ TypeScript: const requireAuth = (req, res, next) => { if (!req.headers.auth) return 401; next(); }; app.get('/users', requireAuth, handler);
|
|
387
|
+
→ Java: class User { @NotNull @Email private String email; } @PostMapping createUser(@Valid @RequestBody User user) { ... }
|
|
388
|
+
→ Python: def require_auth(f): @wraps(f) def wrapper(): if not request.headers.get('Auth'): return 401; return f(); @app.route('/users') @require_auth def get_users(): ...
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
def get_users(): # ... handler logic
|
|
392
|
+
|
|
393
|
+
````
|
|
394
|
+
|
|
395
|
+
**Detection:** Code blocks with > 5 lines duplicated in 3+ locations
|
|
396
|
+
|
|
397
|
+
**Priority:** 🟡 WARNING (3+ duplications), 🟢 SUGGESTION (2 duplications)
|
|
398
|
+
|
|
399
|
+
#### C. High Coupling
|
|
400
|
+
|
|
401
|
+
**Pattern to detect:**
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
// ❌ WARNING - Tight coupling
|
|
405
|
+
class OrderService {
|
|
406
|
+
constructor() {
|
|
407
|
+
this.db = new PostgresDatabase(); // Direct dependency!
|
|
408
|
+
this.emailer = new SendGridEmailer(); // Direct dependency!
|
|
409
|
+
this.logger = new WinstonLogger(); // Direct dependency!
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// ✅ LOOSE COUPLING - Dependency injection
|
|
414
|
+
class OrderService {
|
|
415
|
+
constructor(
|
|
416
|
+
private db: Database, // Interface
|
|
417
|
+
private emailer: EmailService, // Interface
|
|
418
|
+
private logger: Logger // Interface
|
|
419
|
+
) {}
|
|
420
|
+
}
|
|
421
|
+
````
|
|
422
|
+
|
|
423
|
+
**Priority:** 🟡 WARNING
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
### 5. 🎨 Code Quality
|
|
428
|
+
|
|
429
|
+
**Objective:** Ensure code is readable, maintainable, and follows best practices.
|
|
430
|
+
|
|
431
|
+
#### A. Naming Clarity
|
|
432
|
+
|
|
433
|
+
**Pattern to detect:**
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
// ❌ SUGGESTION - Unclear names
|
|
437
|
+
const d = new Date();
|
|
438
|
+
function proc(x) {
|
|
439
|
+
return x * 2;
|
|
440
|
+
}
|
|
441
|
+
const arr = getData();
|
|
442
|
+
|
|
443
|
+
// ✅ CLEAR - Descriptive names
|
|
444
|
+
const currentDate = new Date();
|
|
445
|
+
function doubleValue(number) {
|
|
446
|
+
return number * 2;
|
|
447
|
+
}
|
|
448
|
+
const userRecords = getUserData();
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
**Priority:** 🟢 SUGGESTION
|
|
452
|
+
|
|
453
|
+
#### B. High Complexity
|
|
454
|
+
|
|
455
|
+
**Pattern to detect:**
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
// ❌ WARNING - High cyclomatic complexity (>10)
|
|
459
|
+
function processOrder(order) {
|
|
460
|
+
if (order.type === 'premium') {
|
|
461
|
+
if (order.amount > 1000) {
|
|
462
|
+
if (order.user.verified) {
|
|
463
|
+
if (order.paymentMethod === 'card') {
|
|
464
|
+
// ... nested logic continues
|
|
465
|
+
} else if (order.paymentMethod === 'paypal') {
|
|
466
|
+
// ...
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
} else if (order.type === 'standard') {
|
|
471
|
+
// ... more conditions
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// ✅ REFACTORED - Lower complexity
|
|
476
|
+
function processOrder(order) {
|
|
477
|
+
const processor = OrderProcessorFactory.create(order.type);
|
|
478
|
+
return processor.process(order);
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
**Cyclomatic complexity calculation:**
|
|
483
|
+
|
|
484
|
+
- Start at 1
|
|
485
|
+
- +1 for each: if, else if, for, while, case, &&, ||
|
|
486
|
+
- Target: < 10
|
|
487
|
+
|
|
488
|
+
**Priority:** 🟡 WARNING (>15), 🟢 SUGGESTION (10-15)
|
|
489
|
+
|
|
490
|
+
#### C. Magic Numbers/Strings
|
|
491
|
+
|
|
492
|
+
**Pattern to detect:**
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
// ❌ SUGGESTION - Magic numbers
|
|
496
|
+
if (user.age > 18) {
|
|
497
|
+
/* ... */
|
|
498
|
+
}
|
|
499
|
+
if (items.length > 100) {
|
|
500
|
+
/* ... */
|
|
501
|
+
}
|
|
502
|
+
setTimeout(callback, 5000);
|
|
503
|
+
|
|
504
|
+
// ✅ NAMED CONSTANTS
|
|
505
|
+
const LEGAL_AGE = 18;
|
|
506
|
+
const MAX_ITEMS_PER_PAGE = 100;
|
|
507
|
+
const RETRY_DELAY_MS = 5000;
|
|
508
|
+
|
|
509
|
+
if (user.age > LEGAL_AGE) {
|
|
510
|
+
/* ... */
|
|
511
|
+
}
|
|
512
|
+
if (items.length > MAX_ITEMS_PER_PAGE) {
|
|
513
|
+
/* ... */
|
|
514
|
+
}
|
|
515
|
+
setTimeout(callback, RETRY_DELAY_MS);
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
**Priority:** 🟢 SUGGESTION
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
## Prioritization Methodology
|
|
523
|
+
|
|
524
|
+
### 🔴 Critical Issues (Fix Immediately)
|
|
525
|
+
|
|
526
|
+
**Criteria:**
|
|
527
|
+
|
|
528
|
+
- Security vulnerabilities (SQLi, XSS, exposed secrets)
|
|
529
|
+
- N+1 queries in user-facing endpoints
|
|
530
|
+
- Authentication bypass
|
|
531
|
+
- Data loss risk
|
|
532
|
+
- Production-breaking bugs
|
|
533
|
+
|
|
534
|
+
**Action:** Block merge/deployment until fixed
|
|
535
|
+
|
|
536
|
+
### 🟡 Warnings (Fix Before Merge)
|
|
537
|
+
|
|
538
|
+
**Criteria:**
|
|
539
|
+
|
|
540
|
+
- Performance issues (blocking ops, memory leaks)
|
|
541
|
+
- Architecture violations (high coupling, SRP violations)
|
|
542
|
+
- Missing test coverage for critical paths
|
|
543
|
+
- Weak security practices (no HTTPS, weak sessions)
|
|
544
|
+
- Code duplication (3+ instances)
|
|
545
|
+
|
|
546
|
+
**Action:** Should fix before merging to main branch
|
|
547
|
+
|
|
548
|
+
### 🟢 Suggestions (Improvement Opportunities)
|
|
549
|
+
|
|
550
|
+
**Criteria:**
|
|
551
|
+
|
|
552
|
+
- Code style improvements
|
|
553
|
+
- Minor refactoring opportunities
|
|
554
|
+
- Naming improvements
|
|
555
|
+
- Missing edge case tests (non-critical)
|
|
556
|
+
- Magic numbers
|
|
557
|
+
|
|
558
|
+
**Action:** Nice to have, can be addressed in future PR
|
|
559
|
+
|
|
560
|
+
---
|
|
561
|
+
|
|
562
|
+
## Report Format
|
|
563
|
+
|
|
564
|
+
### Issue Template
|
|
565
|
+
|
|
566
|
+
````markdown
|
|
567
|
+
### [Priority] [Category] - [Title]
|
|
568
|
+
|
|
569
|
+
**File:** [path/to/file.ts](path/to/file.ts#L45)
|
|
570
|
+
**Category:** Security | Performance | Testing | Architecture | Quality
|
|
571
|
+
**Impact:** [Description of impact]
|
|
572
|
+
**Effort:** [Estimation - Quick/Medium/Large]
|
|
573
|
+
|
|
574
|
+
**Description:**
|
|
575
|
+
[Detailed description of the issue]
|
|
576
|
+
|
|
577
|
+
**Current Code:**
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
// Show problematic code
|
|
581
|
+
```
|
|
582
|
+
````
|
|
583
|
+
|
|
584
|
+
**Recommended Fix:**
|
|
585
|
+
|
|
586
|
+
```typescript
|
|
587
|
+
// Show improved code
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
**References:**
|
|
591
|
+
|
|
592
|
+
- [Link to docs/standards]
|
|
593
|
+
|
|
594
|
+
````
|
|
595
|
+
|
|
596
|
+
### Example Complete Issue
|
|
597
|
+
|
|
598
|
+
```markdown
|
|
599
|
+
### 🔴 CRITICAL - SQL Injection Vulnerability
|
|
600
|
+
|
|
601
|
+
**File:** [src/api/users.ts](src/api/users.ts#L45)
|
|
602
|
+
**Category:** Security
|
|
603
|
+
**Impact:** High - Database compromise, data theft possible
|
|
604
|
+
**Effort:** Quick (5 minutes)
|
|
605
|
+
|
|
606
|
+
**Description:**
|
|
607
|
+
Raw SQL query uses string concatenation with user-provided input, allowing SQL injection attacks.
|
|
608
|
+
|
|
609
|
+
**Current Code:**
|
|
610
|
+
```typescript
|
|
611
|
+
const userId = req.params.id;
|
|
612
|
+
const query = `SELECT * FROM users WHERE id = ${userId}`;
|
|
613
|
+
const result = await db.query(query);
|
|
614
|
+
````
|
|
615
|
+
|
|
616
|
+
**Recommended Fix:**
|
|
617
|
+
|
|
618
|
+
```typescript
|
|
619
|
+
const userId = req.params.id;
|
|
620
|
+
const query = 'SELECT * FROM users WHERE id = $1';
|
|
621
|
+
const result = await db.query(query, [userId]);
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
**References:**
|
|
625
|
+
|
|
626
|
+
- [OWASP SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection)
|
|
627
|
+
- [PostgreSQL Parameterized Queries](https://node-postgres.com/features/queries)
|
|
628
|
+
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
## Integration with flow-check
|
|
633
|
+
|
|
634
|
+
This methodology is executed in **Stage 2** of the `/flow-check` workflow:
|
|
635
|
+
|
|
636
|
+
1. Orchestrator (`flow-check.md`) determines scope (files to review)
|
|
637
|
+
2. For each perspective (Security, Performance, etc.):
|
|
638
|
+
- Apply detection patterns from this document
|
|
639
|
+
- Categorize findings by priority
|
|
640
|
+
- Format using issue template
|
|
641
|
+
3. Aggregate all issues into final report
|
|
642
|
+
4. Update `status.json` with review metrics
|
|
643
|
+
|
|
644
|
+
---
|
|
645
|
+
## Summary
|
|
646
|
+
|
|
647
|
+
This reference provides the technical foundation for code review in `/flow-check`. The orchestrator uses these criteria to:
|
|
648
|
+
|
|
649
|
+
1. Analyze code from 5 perspectives
|
|
650
|
+
2. Detect issues using pattern matching
|
|
651
|
+
3. Prioritize by severity and impact
|
|
652
|
+
4. Generate actionable recommendations
|
|
653
|
+
5. Format professional reports
|
|
654
|
+
|
|
655
|
+
For testing methodology, see `flow-check-test.md`.
|
|
656
|
+
```
|