Skip to content

Commit 7309fd2

Browse files
authored
chore: improve guidelines for PR reviewer (#15073)
* chore: improve guidelines for PR reviewer * ignore tsdoc commits
1 parent cd8cc48 commit 7309fd2

File tree

4 files changed

+234
-37
lines changed

4 files changed

+234
-37
lines changed

.claude/skills/reviewing-prs/SKILL.md

Lines changed: 97 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Reviews GitHub pull requests for Medusa. Checks template compliance, contributio
1616

1717
- **Checking contribution guidelines?** → MUST load `reference/contribution-types.md` first
1818
- **Verifying code conventions?** → MUST load `reference/conventions.md` first
19-
- **Writing a review comment?** → MUST load `reference/comment-guidelines.md` first (includes bug reporting format)
19+
- **Writing a review comment?** → MUST load `reference/comment-guidelines.md` first (includes bug, security, and performance reporting formats)
2020

2121
**Minimum requirement:** Load at least the relevant reference file(s) before completing the review.
2222

@@ -112,21 +112,6 @@ bash scripts/get_linked_issues.sh <pr_number>
112112
```
113113
Check whether any linked issue carries a `help-wanted` label. If not, apply `requires-more` and comment explaining that large contributions should be scoped and pre-approved via an issue first (reference `CONTRIBUTING.md`).
114114

115-
**4b. Security scan:**
116-
117-
Review the changed file paths and PR body for:
118-
- Credentials, secrets, or API keys in code
119-
- Remote code execution vectors (`eval`, dynamic imports of remote URLs)
120-
- Suspicious package additions (`package.json` changes with unknown packages, unusual `scripts` entries)
121-
- Tampered lock files or build scripts
122-
123-
If **malicious code** is found → close the PR immediately with a clear explanation:
124-
```bash
125-
bash scripts/close_issue.sh <pr_number>
126-
```
127-
128-
If **potential security risks** (not clearly malicious) → include them as a concern in the review comment.
129-
130115
### Step 5 — Fetch Linked Issues
131116

132117
```bash
@@ -151,9 +136,87 @@ For mixed PRs, apply all relevant types.
151136

152137
Load `reference/conventions.md` and verify the changed files follow Medusa's conventions. Focus on the areas most relevant to the contribution type (e.g., API conventions for code changes, MDX structure for docs changes).
153138

154-
### Step 8 — Bug Detection
139+
### Step 8 — Security Analysis (ALL PRs)
140+
141+
> **CRITICAL:** This step applies to **all PRs**, including team members. Read the actual diff — do not rely only on file path inspection.
155142
156-
Read the actual code diff carefully and look for potential bugs. Focus on:
143+
Check for the following security issues:
144+
145+
**Authentication & Authorization:**
146+
- Missing or bypassed authentication middleware on new routes
147+
- Authorization checks missing — any route that accesses or mutates data scoped to a user/store must verify ownership
148+
- Privilege escalation — e.g., a non-admin route accepting admin-level operations
149+
150+
**Injection & Execution:**
151+
- Raw SQL constructed from user input (SQL injection)
152+
- Use of `eval()`, `new Function()`, or `vm.runInContext()` with untrusted data
153+
- Dynamic `require()`/`import()` with user-controlled paths
154+
- Shell command construction with user input (`exec`, `spawn`, `execSync`)
155+
156+
**Input Validation:**
157+
- User-controlled input passed to filesystem operations (`fs.readFile`, `path.join`) without sanitization → path traversal
158+
- Missing size/length limits on inputs that could cause DoS
159+
- Unvalidated external URLs used in server-side fetches → SSRF
160+
161+
**Data Exposure:**
162+
- Sensitive fields (passwords, secrets, internal IDs, PII) included in API responses or logs
163+
- Error messages leaking internal stack traces, SQL queries, or file paths to the client
164+
- Credentials, API keys, or secrets hardcoded or committed in any file
165+
166+
**Dependencies & Supply Chain:**
167+
- New packages added to `package.json` — verify they're well-known, not typosquats, and have a clear purpose
168+
- Unusual `scripts` entries in `package.json` (e.g., `postinstall`, `preinstall`) that execute commands
169+
- Lock file changes inconsistent with `package.json` changes
170+
171+
**Malicious code:**
172+
If clearly malicious code is found → close the PR immediately:
173+
```bash
174+
bash scripts/close_issue.sh <pr_number>
175+
```
176+
177+
For each confirmed or suspected security issue:
178+
- Note the **file, line/function, and the exact vulnerability class**
179+
- Explain the **attack scenario** in one sentence
180+
- Suggest a **concrete fix**
181+
182+
Security issues are always **blocking** — apply `requires-more` even if everything else looks good. Load `reference/comment-guidelines.md` for the Security Issues comment format.
183+
184+
### Step 9 — Performance Analysis (ALL PRs)
185+
186+
> **CRITICAL:** This step applies to **all PRs**. Only flag issues that would plausibly cause measurable degradation in production — not theoretical micro-optimizations.
187+
188+
Check for:
189+
190+
**Database / Query Performance:**
191+
- **N+1 queries** — a `query.graph()`, `query.index()`, or service call inside a loop over a result set. Flag the loop location and the repeated call.
192+
- **Unbounded queries**`query.graph()` / `remoteQueryObjectFromString()` / service list calls missing `pagination: req.queryConfig.pagination`. A missing pagination object means a full-table scan.
193+
- **Missing pagination in response** — list routes that omit `count`, `offset` (`metadata.skip`), and `limit` (`metadata.take`) from the response body, breaking client-side pagination.
194+
- **Missing database indexes** — new fields used in `filters` or `order` in a query call without a corresponding index in the entity decorator or migration.
195+
196+
**Async & Concurrency:**
197+
- Sequential `await` in a loop where `Promise.all()` would work
198+
- Heavy synchronous computation (sorting, transforming large arrays) on the main event loop in a hot path
199+
- Unthrottled parallel operations that could overwhelm the DB connection pool
200+
201+
**Memory & Payload:**
202+
- Loading large datasets entirely into memory before filtering/transforming
203+
- API responses including deeply nested or large objects that could be paginated or trimmed
204+
- Accumulating results in memory across paginated batches without streaming
205+
206+
For each performance issue found:
207+
- Note the **file and function/line**
208+
- Explain **why it's a problem** (e.g., "this query runs once per order item, which means N DB roundtrips for a cart with N items")
209+
- Suggest a **concrete fix**
210+
211+
Performance issues severity:
212+
- **Blocking (requires-more):** N+1 queries, unbounded queries on large tables, missing pagination on list endpoints
213+
- **Non-blocking (note only):** Suggestions that are improvements but don't introduce clear production risk
214+
215+
### Step 10 — Bug Detection (ALL PRs)
216+
217+
> **CRITICAL:** This step applies to **all PRs** including team members. Any potential bug — confirmed or suspected — is a **required change** and must result in `requires-more`. Do not leave bugs as notes.
218+
219+
Read the actual code diff carefully. Flag anything that would plausibly cause incorrect runtime behaviour. Focus on:
157220

158221
- **Logic errors** — off-by-one, wrong conditionals, inverted boolean checks
159222
- **Null / undefined access** — accessing properties on values that may be null/undefined without guards
@@ -163,37 +226,41 @@ Read the actual code diff carefully and look for potential bugs. Focus on:
163226
- **Edge cases not handled** — empty arrays, zero values, missing input validation
164227
- **Mutation side-effects** — mutating shared state or function arguments unexpectedly
165228
- **Incorrect error handling** — swallowed errors, rethrowing without context, wrong error types
229+
- **Wrong HTTP status codes** — returning 200 for errors, 201 for non-creation responses, etc.
230+
- **Workflow compensation gaps**`createStep` with side effects but no compensation function, meaning failed workflows leave orphaned data
166231

167232
For each potential bug found:
168233
- Note the **file and approximate location**
169-
- Briefly explain **why it's a bug or risk**
170-
- Suggest a **concrete fix** if one is obvious
234+
- Quote the **relevant code snippet** in a fenced code block
235+
- Briefly explain **why it's a bug or risk** — describe the failure scenario specifically
236+
- Suggest a **concrete fix**
171237

172-
> **CRITICAL:** Distinguish between confirmed bugs (clear logic/runtime errors) and code smell / style issues. Only flag something as a bug if it would plausibly cause incorrect behaviour at runtime.
238+
> Do NOT flag style issues, code smell, or naming preferences here. Only flag things that would plausibly cause incorrect behaviour at runtime. If you're uncertain, phrase it as a question but still add it to **Required changes** — it is the author's responsibility to confirm or disprove it.
173239
174-
### Step 9 — Contextual Assessment
240+
### Step 11 — Contextual Assessment
175241

176242
Before writing the review, assess whether the changes make sense in the broader context of the PR. Load `reference/comment-guidelines.md` (Contextual Assessment section) for the full checklist. Key questions:
177243

178244
- Does the implementation actually solve the problem in the PR/linked issue?
179245
- Could the change break or alter behaviour in other parts of the codebase?
180246
- Is the scope right — no unrelated changes included?
181247
- Are edge cases and potential regressions covered?
182-
- Are there obvious performance or correctness concerns?
183248

184249
Note any concerns to include in the review comment.
185250

186-
### Step 10 — Compose and Post Review
251+
### Step 12 — Compose and Post Review
187252

188253
Load `reference/comment-guidelines.md` for comment templates and tone guidance.
189254

190255
Decide the outcome:
191256

192257
| Label | When |
193258
|-------|------|
194-
| `initial-approval` | PR follows all guidelines; team will do the final review |
259+
| `initial-approval` | PR follows all guidelines, no security/performance blockers; team will do the final review |
195260
| `requires-more` | PR needs changes — list exactly what must change |
196261

262+
> **CRITICAL:** Any security issue, any potential bug, or any blocking performance issue (N+1, unbounded query) **must** result in `requires-more`, even if all other checks pass. Do not apply `initial-approval` with bugs or security issues as notes — they are always required changes.
263+
197264
Post the comment then apply the label:
198265
```bash
199266
bash scripts/add_comment.sh <pr_number> "<body>"
@@ -208,6 +275,11 @@ bash scripts/labels.sh <pr_number> add <label>
208275
- [ ] Forgetting the docs-ui test requirement for `www/packages/docs-ui/` changes
209276
- [ ] Skipping the integration test check for API route changes in `packages/medusa/src/api/`
210277
- [ ] Not fetching PR details when they weren't passed as arguments
278+
- [ ] Skipping security analysis for team member PRs — security analysis applies to ALL PRs
279+
- [ ] Skipping performance analysis — always check for N+1 queries and unbounded queries
280+
- [ ] Applying `initial-approval` when a confirmed security or blocking performance issue was found
281+
- [ ] Flagging style/code smell as bugs — only flag correctness/runtime issues in the Potential Bugs section
282+
- [ ] Omitting the code snippet when flagging a bug, security issue, or performance issue — always quote the relevant code
211283

212284
## Reference Files
213285

.claude/skills/reviewing-prs/reference/comment-guidelines.md

Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,39 @@ After reviewing this PR, we need a few things addressed before we can move forwa
4444
- [ ] <specific change 2>
4545
4646
<Optional: brief explanation of why each change is needed>
47+
48+
<Include one or more of the sections below when applicable — omit sections that have nothing to report>
49+
50+
**Security Issues:**
51+
52+
🔒 **`path/to/file.ts`** — <vulnerability class>
53+
```typescript
54+
// problematic snippet
55+
```
56+
<Attack scenario + fix>
57+
58+
**Performance Issues:**
59+
60+
**`path/to/file.ts`** — <issue description>
61+
```typescript
62+
// problematic snippet
63+
```
64+
<Impact + fix>
65+
66+
**Potential Bugs:**
67+
68+
⚠️ **`path/to/file.ts`** — <bug description>
69+
```typescript
70+
// problematic snippet
71+
```
72+
<Why it fails + fix>
4773
```
4874
4975
**Rules for the required changes list:**
5076
- Each item must be actionable — the contributor should know exactly what to do
5177
- Reference specific files or line numbers when relevant
5278
- Group related items together
79+
- Security issues and blocking performance issues **must** appear in Required changes AND in their dedicated section with code snippets
5380
5481
## Contextual Assessment
5582
@@ -75,10 +102,7 @@ Keep concerns concise and factual — describe the problem, not a lecture. If un
75102
76103
## Potential Bugs Section
77104
78-
When bugs are found in Step 8, include a **"Potential Bugs"** section in the review comment. This section is **always required** when bugs are found — for both `initial-approval` and `requires-more`.
79-
80-
- Confirmed bugs (will cause incorrect runtime behaviour) → add to **Required changes** and apply `requires-more`
81-
- Uncertain / possible bugs → include under **"Potential Bugs"** as a flagged concern, even on `initial-approval`
105+
When bugs are found in Step 10, include a **"Potential Bugs"** section in the review comment. **All bugs — confirmed or suspected — are required changes.** Always apply `requires-more` when this section is present.
82106
83107
**Format:**
84108
@@ -89,21 +113,79 @@ When bugs are found in Step 8, include a **"Potential Bugs"** section in the rev
89113
```typescript
90114
// the problematic snippet
91115
```
92-
<Explanation of why this is a problem and what could go wrong. If a fix is obvious, suggest it.>
116+
<Specific failure scenario — "this will throw if `items` is empty", not "this looks wrong". Suggest the fix.>
93117

94118
⚠️ **`path/to/other-file.ts`** — <another bug>
95119
...
96120
```
97121
98122
**Rules:**
99-
- Always quote the relevant code snippet in a fenced code block so the author knows exactly what line is flagged
100-
- Be specific about the failure scenario — *"this will throw if `items` is empty"* not *"this looks wrong"*
101-
- If unsure, phrase as a question: *"Should this also handle the case where X is undefined?"*
102-
- Do not flag style issues or code smell here — only actual correctness/runtime concerns
123+
- Every bug goes into **Required changes** as a checkbox item AND in this section with the code snippet
124+
- Always quote the relevant code snippet in a fenced code block
125+
- Be specific about the failure scenario
126+
- If uncertain, phrase as a question (*"Should this handle the case where X is undefined?"*) but still list it as a required change — the author must confirm or disprove it
127+
- Do not flag style issues or code smell — only correctness/runtime concerns
128+
129+
## Security Issues Section
130+
131+
When security issues are found in Step 8, include a **"Security Issues"** section in the review comment.
132+
133+
- Confirmed security vulnerabilities → add to **Required changes** and always apply `requires-more`
134+
- Suspected / uncertain risks → include under **"Security Issues"** with a question framing
135+
136+
**Format:**
137+
138+
```
139+
**Security Issues:**
140+
141+
🔒 **`path/to/file.ts`** — <vulnerability class, e.g., "Missing authorization check">
142+
```typescript
143+
// the problematic snippet
144+
```
145+
<Explain the attack scenario in one sentence. What can an attacker do? What data is exposed or operation is possible? Suggest the fix.>
146+
147+
🔒 **`path/to/file.ts`** — <another issue>
148+
...
149+
```
150+
151+
**Rules:**
152+
- Always name the vulnerability class (e.g., "SQL injection", "Missing auth", "Path traversal", "SSRF", "Sensitive data exposure")
153+
- Always include the relevant code snippet in a fenced code block
154+
- Describe the concrete attack scenario — *"an authenticated user could access another store's orders by passing a different `store_id`"* not *"this looks insecure"*
155+
- If unsure, phrase as a question: *"Should this route require `isAdmin` middleware?"*
156+
- Security issues are always **blocking** — do not apply `initial-approval` with a security issue in the Notes section
157+
158+
## Performance Issues Section
159+
160+
When performance issues are found in Step 9, include a **"Performance Issues"** section in the review comment.
161+
162+
- Blocking performance issues (N+1 queries, unbounded queries on large tables, missing pagination) → add to **Required changes** and apply `requires-more`
163+
- Non-blocking performance observations → include under **"Performance Issues"** as notes only
164+
165+
**Format:**
166+
167+
```
168+
**Performance Issues:**
169+
170+
**`path/to/file.ts`** — <one-line description, e.g., "N+1 query inside order item loop">
171+
```typescript
172+
// the problematic snippet
173+
```
174+
<Explain why this is a problem in production terms — e.g., "for a cart with 50 items, this executes 50 separate DB queries instead of one". Suggest the fix — e.g., "batch-load with `findMany({ where: { id: In(ids) } })` before the loop".>
175+
176+
**`path/to/file.ts`** — <another issue>
177+
...
178+
```
179+
180+
**Rules:**
181+
- Always include the relevant code snippet in a fenced code block
182+
- Quantify the impact where possible — *"N queries for N items"*, *"no LIMIT means entire table is fetched"*
183+
- Suggest a concrete fix
184+
- Do not flag theoretical micro-optimizations — only issues that would plausibly cause measurable degradation
103185
104-
## Security Risk Comment Template
186+
## Security Risk Comment Template (non-malicious, simple case)
105187
106-
Use when a potential (non-malicious) security risk is found. Include it as part of the review, not as a standalone comment.
188+
Use for a single, brief security concern when no full Security Issues section is needed:
107189
108190
```
109191
**Security note:** <brief description of the potential risk and which file/change introduces it>

.claude/skills/reviewing-prs/reference/conventions.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,42 @@ Conventions to verify when reviewing code contributions. Focus on areas relevant
4848
- Unit tests: `__tests__/` directories alongside source, `.spec.ts` or `.test.ts` suffix.
4949
- Integration tests for HTTP routes: `integration-tests/http/__tests__/`.
5050
- New functionality must have tests. Minor bug fixes may omit tests if the fix is trivial and clear, but tests are always preferred.
51+
52+
## Security Requirements
53+
54+
- **Authentication**: All new admin routes must include `authenticate("user", ["bearer", "session", "api-key"])` middleware. Store routes that require authentication must use `authenticate("customer", ...)`.
55+
- **Input validation**: All fields accepted from request bodies must be declared in the Zod schema. Unknown fields should be stripped, not passed through.
56+
- **No raw SQL**: Use the ORM query builder. Do not construct SQL strings from user-provided values.
57+
- **No sensitive fields in responses**: Passwords, secrets, and internal tokens must not appear in HTTP type definitions or serialized responses.
58+
- **No hardcoded secrets**: Credentials, API keys, and tokens must come from environment variables via `configModule` — never committed to source.
59+
- **Filesystem operations**: Paths constructed from user input must be normalized and validated to prevent path traversal (e.g., reject paths containing `..`).
60+
61+
## Performance Requirements
62+
63+
- **Pagination required**: List routes must pass `pagination: req.queryConfig.pagination` (which contains `{ skip, take, order? }`) to every query. Never omit pagination. The framework enforces a default `take` of 50; custom defaults must be set in the route's `queryConfig` — not hardcoded in the handler.
64+
65+
- **No unbounded queries**: Any call to `query.graph()`, `query.index()`, `remoteQueryObjectFromString()`, or a direct service method that fetches a list must include pagination. Omitting it means a full-table scan. Example of correct usage:
66+
67+
```typescript
68+
// ✅ Correct
69+
const { data, metadata } = await query.graph({
70+
entity: "order",
71+
fields: req.queryConfig.fields,
72+
filters: req.filterableFields,
73+
pagination: req.queryConfig.pagination,
74+
})
75+
76+
// ❌ Wrong — no pagination
77+
const { data } = await query.graph({
78+
entity: "order",
79+
fields: req.queryConfig.fields,
80+
})
81+
```
82+
83+
- **Response must include count/offset/limit**: List route responses must always return `count`, `offset` (`metadata.skip`), and `limit` (`metadata.take`) alongside the items array so clients can paginate. Omitting these is a bug.
84+
85+
- **No N+1 queries**: Do not call `query.graph()` or any service method inside a loop over a result set. Instead, batch-fetch all related records in a single query before the loop using `filters: { id: ids }`.
86+
87+
- **Async parallelism**: Use `Promise.all()` when multiple independent async operations can run concurrently. Sequential `await` in a loop is a red flag.
88+
89+
- **Database indexes**: New fields used in `filters` or `order` inside a `query.graph()` / `remoteQueryObjectFromString()` call must have a corresponding index in the entity decorator or migration.

0 commit comments

Comments
 (0)