FXA Quick Review
Review the most recent commit (or the commit specified in $ARGUMENTS) in a single pass, using FXA-specific knowledge.
Step 1: Get Commit Info
COMMIT_REF="${ARGUMENTS:-HEAD}"
git show "$COMMIT_REF" --format="%H%n%an%n%ae%n%s%n%b"
COMMIT_REF="${ARGUMENTS:-HEAD}"
git show --stat "$COMMIT_REF"
Step 2: Read Changed Files
Use Read and Grep to examine the changed files and their surrounding context. Look at imports, callers, and related types to understand the full picture before judging.
Step 3: Review
Evaluate the diff through these lenses, in order of priority:
1. Security
- Hardcoded secrets, injection (SQL/XSS/command), missing input validation, auth bypasses
- Sensitive data in logs or error messages (PII: emails, UIDs, tokens) — note: UIDs and emails in API response bodies are expected, focus on logs and error messages
- Missing rate limiting on new public endpoints
- Session token handling that bypasses established Hapi auth schemes
- New endpoints missing
Content-Type validation
- User-controlled input passed to Redis keys without prefix/namespace
2. FXA Conventions
- Raw
Error thrown in route handlers instead of AppError from @fxa/accounts/errors
console.log instead of the log object (mozlog format)
- Cross-package imports using relative paths instead of
@fxa/<domain>/<package> aliases
- Circular or bi-directional dependencies between packages/libs — breaks build ordering
- Auth-server code importing from
fxa-auth-server/** (ESLint blocks this)
- New code added to legacy packages (
fxa-content-server, fxa-payments-server) — should be in fxa-settings or SubPlat 3.0
- No new GraphQL —
fxa-graphql-api was removed, admin-server GraphQL is legacy. Exception: CMS-related GraphQL.
- Hardcoded values that should come from Convict config
- New
require() in .ts files — use import instead. Existing CJS patterns in auth-server .js files are fine.
- Missing MPL-2.0 license header on new files
- Prefer
async/await over .then() promise chains
- Flag new
Container.get()/Container.set() usage — linting rules to disallow these are coming
3. Logic & Bugs
- Missing
await on async calls — note: some fire-and-forget patterns (metrics, logging) are intentional, check context before flagging
- Null/undefined mishandling
- Race conditions, shared mutable state
- Swallowed errors (empty catch blocks, catch-and-rethrow without context)
- Off-by-one, wrong comparisons, missing break/return in switch
- Hapi route handlers that catch and re-throw instead of letting the error pipeline handle it
4. Tests
- New auth-server source files without co-located
*.spec.ts; fxa-settings uses *.test.tsx convention
jest.clearAllMocks() in beforeEach — unnecessary, clearMocks: true is global
proxyquire in new test code — should use jest.mock()
- New Mocha tests in
test/local/ or test/remote/ — new tests must be Jest
- Over-mocked tests that only test mock wiring
- Prefer
jest.useFakeTimers() and jest.setSystemTime() over setTimeout or mocking Date.now directly
- Flag patterns likely to cause open handle warnings (unclosed connections, uncleared timers)
- Flag missing
act() wrapping in React test state updates
5. Database Migrations
- Edits to existing published migration files — CRITICAL, never allowed
- New migration without corresponding rollback file
- Verify test DB patches are aligned with current test DB state (
/fxa-shared/test/db/models/**/*.sql)
DELETE/UPDATE without WHERE clause
ALTER TABLE on large tables without online DDL consideration
- Index changes bundled with schema changes — should be separate migrations
- Data type changes that could truncate data
6. Migration Direction
- Mocha → Jest (no new Mocha tests)
proxyquire → jest.mock()
- Callbacks →
async/await
fxa-shared → libs/* (migration in progress, check both locations for existing code before adding new)
7. AI Slop Detection
- Overly verbose or obvious comments that describe what the code does, not why
- Unnecessary abstractions or helper functions for one-time operations
- Excessive error handling for scenarios that cannot happen
- Redundant validation or fallbacks that duplicate framework guarantees
- Generic variable names or boilerplate patterns that suggest auto-generated code
Step 4: Output
Commit Summary
Commit: hash
Author: name
Message: commit message
Files Changed: count
Changes Overview
Write a brief summary of what the commit does based on the diff. Do not repeat the commit message.
Issues Found
Use a table with columns: #, Severity, Category, File, Line, Issue, Recommendation.
Severity definitions:
- CRITICAL — security vulnerabilities, data loss, auth bypasses, editing published migrations. Must fix.
- HIGH — bugs that will cause production issues, missing auth schemes on routes. Should fix.
- MEDIUM — convention violations, code quality, moderate risk. Consider fixing.
- LOW — style, minor improvements. Optional.
If no issues are found, skip the table and write: "No issues found."
Verdict
Recommendation: APPROVE, REQUEST CHANGES, or NEEDS DISCUSSION.
Include blocking issue count (CRITICAL + HIGH) and total issue count.
If clean: "This commit is ready to merge."
If not: "Please address the CRITICAL and HIGH issues before merging."
Guidelines
- Be pragmatic, not pedantic. Flag real problems, not style preferences.
- Consider the context — read surrounding code before flagging something.
- Do not flag missing tests for trivial changes (config values, enum additions, comment updates).
- One or two missing edge-case tests is MEDIUM at most, not HIGH.
- Always explain WHY something is a problem, not just what.
- If the commit is clean, say so clearly and approve. A short review is a good review.
1---2name: fxa-review-quick3description: Fast single-pass FXA-specific commit review covering security, conventions, logic/bugs, tests, and migrations. No subagents — runs directly in the main context.4---5
6# FXA Quick Review
7
8Review the most recent commit (or the commit specified in `$ARGUMENTS`) in a single pass, using FXA-specific knowledge.
9
10## Step 1: Get Commit Info
11
12```bash
13COMMIT_REF="${ARGUMENTS:-HEAD}"
14git show "$COMMIT_REF" --format="%H%n%an%n%ae%n%s%n%b"
15```
16
17```bash
18COMMIT_REF="${ARGUMENTS:-HEAD}"
19git show --stat "$COMMIT_REF"
20```
21
22## Step 2: Read Changed Files
23
24Use Read and Grep to examine the changed files and their surrounding context. Look at imports, callers, and related types to understand the full picture before judging.
25
26## Step 3: Review
27
28Evaluate the diff through these lenses, in order of priority:
29
30**1. Security**
31- Hardcoded secrets, injection (SQL/XSS/command), missing input validation, auth bypasses
32- Sensitive data in logs or error messages (PII: emails, UIDs, tokens) — note: UIDs and emails in API response bodies are expected, focus on logs and error messages
33- Missing rate limiting on new public endpoints
34- Session token handling that bypasses established Hapi auth schemes
35- New endpoints missing `Content-Type` validation
36- User-controlled input passed to Redis keys without prefix/namespace
37
38**2. FXA Conventions**
39- Raw `Error` thrown in route handlers instead of `AppError` from `@fxa/accounts/errors`
40- `console.log` instead of the `log` object (mozlog format)
41- Cross-package imports using relative paths instead of `@fxa/<domain>/<package>` aliases
42- Circular or bi-directional dependencies between packages/libs — breaks build ordering
43- Auth-server code importing from `fxa-auth-server/**` (ESLint blocks this)
44- New code added to legacy packages (`fxa-content-server`, `fxa-payments-server`) — should be in `fxa-settings` or SubPlat 3.0
45- No new GraphQL — `fxa-graphql-api` was removed, `admin-server` GraphQL is legacy. Exception: CMS-related GraphQL.
46- Hardcoded values that should come from Convict config
47- New `require()` in `.ts` files — use `import` instead. Existing CJS patterns in auth-server `.js` files are fine.
48- Missing MPL-2.0 license header on new files
49- Prefer `async/await` over `.then()` promise chains
50- Flag new `Container.get()`/`Container.set()` usage — linting rules to disallow these are coming
51
52**3. Logic & Bugs**
53- Missing `await` on async calls — note: some fire-and-forget patterns (metrics, logging) are intentional, check context before flagging
54- Null/undefined mishandling
55- Race conditions, shared mutable state
56- Swallowed errors (empty catch blocks, catch-and-rethrow without context)
57- Off-by-one, wrong comparisons, missing break/return in switch
58- Hapi route handlers that catch and re-throw instead of letting the error pipeline handle it
59
60**4. Tests**
61- New auth-server source files without co-located `*.spec.ts`; fxa-settings uses `*.test.tsx` convention
62- `jest.clearAllMocks()` in `beforeEach` — unnecessary, `clearMocks: true` is global
63- `proxyquire` in new test code — should use `jest.mock()`
64- New Mocha tests in `test/local/` or `test/remote/` — new tests must be Jest
65- Over-mocked tests that only test mock wiring
66- Prefer `jest.useFakeTimers()` and `jest.setSystemTime()` over `setTimeout` or mocking `Date.now` directly
67- Flag patterns likely to cause open handle warnings (unclosed connections, uncleared timers)
68- Flag missing `act()` wrapping in React test state updates
69
70**5. Database Migrations**
71- Edits to existing published migration files — CRITICAL, never allowed
72- New migration without corresponding rollback file
73- Verify test DB patches are aligned with current test DB state (`/fxa-shared/test/db/models/**/*.sql`)
74- `DELETE`/`UPDATE` without `WHERE` clause
75- `ALTER TABLE` on large tables without online DDL consideration
76- Index changes bundled with schema changes — should be separate migrations
77- Data type changes that could truncate data
78
79**6. Migration Direction**
80- Mocha → Jest (no new Mocha tests)
81- `proxyquire` → `jest.mock()`
82- Callbacks → `async/await`
83- `fxa-shared` → `libs/*` (migration in progress, check both locations for existing code before adding new)
84
85**7. AI Slop Detection**
86- Overly verbose or obvious comments that describe what the code does, not why
87- Unnecessary abstractions or helper functions for one-time operations
88- Excessive error handling for scenarios that cannot happen
89- Redundant validation or fallbacks that duplicate framework guarantees
90- Generic variable names or boilerplate patterns that suggest auto-generated code
91
92## Step 4: Output
93
94## Commit Summary
95
96**Commit:** hash
97**Author:** name
98**Message:** commit message
99**Files Changed:** count
100
101## Changes Overview
102
103Write a brief summary of what the commit does based on the diff. Do not repeat the commit message.
104
105## Issues Found
106
107Use a table with columns: #, Severity, Category, File, Line, Issue, Recommendation.
108
109Severity definitions:
110- CRITICAL — security vulnerabilities, data loss, auth bypasses, editing published migrations. Must fix.
111- HIGH — bugs that will cause production issues, missing auth schemes on routes. Should fix.
112- MEDIUM — convention violations, code quality, moderate risk. Consider fixing.
113- LOW — style, minor improvements. Optional.
114
115If no issues are found, skip the table and write: "No issues found."
116
117## Verdict
118
119Recommendation: APPROVE, REQUEST CHANGES, or NEEDS DISCUSSION.
120
121Include blocking issue count (CRITICAL + HIGH) and total issue count.
122
123If clean: "This commit is ready to merge."
124If not: "Please address the CRITICAL and HIGH issues before merging."
125
126## Guidelines
127
128- Be pragmatic, not pedantic. Flag real problems, not style preferences.
129- Consider the context — read surrounding code before flagging something.
130- Do not flag missing tests for trivial changes (config values, enum additions, comment updates).
131- One or two missing edge-case tests is MEDIUM at most, not HIGH.
132- Always explain WHY something is a problem, not just what.
133- If the commit is clean, say so clearly and approve. A short review is a good review.