agentleFS
MrCipherSmithMrCipherSmith/goodai-base/skills/review-backend/SKILL.md

review-backend

Skill0 starsChanged 5 months agoMITView on GitHub

Use when: reviewing NestJS backend changes — API design, service layer, DTO validation, database patterns, and TypeScript correctness. Covers "review backend", "backend review", "review API", "review NestJS", or dispatched by review-orchestrator with --backend flag. NOT for: frontend patterns, MobX, React components, general security vulnerabilities (use review-security-code for XSS/injection/auth-bypass), or performance profiling (use review-performance).

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

13 rules. About 0 are common, 4 are distinctive, and 9 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 9

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Run that script to determine BASE_SHA before collecting the diff.

    line 64
  2. Distinctive:

    Only review files changed in scope.

    line 76
  3. Very specific:

    Default scope is Singleton — correct for stateless services

    line 90
  4. Very specific:

    All controller methods accepting user input (body, query, param) have a DTO class decorated with class-validator decorators

    line 95
  5. Very specific:

    If business logic is in a controller method, flag as major ("move to service layer")

    line 109
  6. Very specific:

    All endpoints in a controller return the same envelope shape (e.g., { data, meta }) — inconsistency (sometimes object, sometimes raw array) …

    line 128
  7. Very specific:

    Use parameterized queries: query('SELECT * FROM users WHERE id = $1', [id])

    line 156
  8. Very specific:

    If the project schema uses deletedAt / @DeleteDateColumn(), deletions must use .softRemove() / .softDelete(), not .remove() / .delete()

    line 160
  9. Very specific:

    When dispatched by review-orchestrator, follow the provided reviewer-input.schema.json payload.

    line 199
  10. Very specific:

    When dispatched by job-orchestrator or called with an explicit context path, the prompt MAY include:

    line 287
  11. Distinctive:

    If provided and the file exists, read the context document before running scope detection.

    line 294
  12. Distinctive:

    Use it to understand:

    line 295
  13. Distinctive:

    If absent, proceed normally — context is optional and non-blocking.

    line 300

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Review — Backend (NestJS / API / DB)

Focused backend reviewer covering NestJS patterns, REST API design, database access patterns, and TypeScript correctness for service-layer code. This skill does NOT duplicate security or performance checks — those belong to review-security-code and review-performance.


Workflow

review-backend Progress:
- [ ] Step 1: Read Job Context (if CONTEXT_PATH provided)
- [ ] Step 2: Determine git scope (merge-base) — see skills/shared/git-merge-base.md
- [ ] Step 3: Collect diff and changed file list
- [ ] Step 4: NestJS patterns check
- [ ] Step 5: API design check
- [ ] Step 6: Database patterns check
- [ ] Step 7: TypeScript correctness check
- [ ] Step 8: Emit findings in unified format, sorted by severity

Input Contract

FieldTypeRequiredDescription
branchstringnoBranch to review. Defaults to current branch.
commit_rangestringnoExplicit range (e.g., abc123..HEAD). Overrides merge-base detection.
context_docstringnoPath to job context document (e.g., <JOBS_ROOT>/<job>/ai/context.md).
issue_urlstringnoGitHub issue or task URL for spec compliance reference.

Scope Detection

See shared script: skills/shared/git-merge-base.md

Run that script to determine BASE_SHA before collecting the diff.

# Default mode — all changes from merge-base to working tree
git diff --name-only "${BASE_SHA}"
git diff "${BASE_SHA}"

# Explicit range mode
git diff --name-only <FROM_SHA>..<TO_SHA>
git diff <FROM_SHA>..<TO_SHA>

Only review files changed in scope. Do not comment on legacy code outside the diff.


Review Checklist

1. NestJS Patterns

Module structure

  • @Module() declaration present; providers, imports, exports are correctly listed
  • Circular dependency risk: two modules importing each other — flag as major if detected; suggest forwardRef()
  • Feature modules do not import AppModule

Provider scope

  • Default scope is Singleton — correct for stateless services
  • REQUEST-scoped provider injected into a Singleton provider is a blocker (creates hidden state sharing)
  • TRANSIENT scope used unnecessarily when singleton would suffice — flag as minor

DTO validation

  • All controller methods accepting user input (body, query, param) have a DTO class decorated with class-validator decorators
  • Required fields: @IsString(), @IsNumber(), @IsEmail(), etc. present and accurate
  • @IsOptional() used only on truly optional fields; non-optional fields must not have @IsOptional()
  • ValidationPipe applied globally (in main.ts) or explicitly via @UsePipes(ValidationPipe) — blocker if missing on any endpoint accepting user input
  • @Transform() used where input coercion is needed (e.g., string → number from query params)

Guards and roles

  • Protected endpoints have @UseGuards(...) with appropriate guard(s)
  • Role-based access uses @Roles(...) decorator with a roles guard — missing guard on an endpoint that should be protected is a blocker
  • Public endpoints explicitly marked with @Public() or equivalent decorator, not just left unguarded

Controller responsibilities

  • Controllers are thin: no business logic, no direct ORM calls, no computation
  • Controller methods do: parse input → delegate to service → return response
  • If business logic is in a controller method, flag as major ("move to service layer")

Service layer

  • Business logic lives in services
  • Services do not directly call the ORM in complex multi-step ways — that belongs in a repository or query object
  • Services do not import Request/Response from HTTP framework (except for streaming or special cases)
  • Services declare return types on all public methods

2. API Design

HTTP method conventions

  • GET requests carry no body (flag as major if present)
  • POST used for resource creation
  • PUT for full replacement, PATCH for partial update — mixed usage without clear reason flagged as minor
  • DELETE on correct resource path

Response shape consistency

  • All endpoints in a controller return the same envelope shape (e.g., { data, meta }) — inconsistency (sometimes object, sometimes raw array) flagged as major
  • HTTP status codes match semantics: 201 for create, 200 for read/update, 204 for no-content delete, 404 for not found, 422 for validation failure

Pagination

  • List endpoints that could return unbounded datasets must have pagination (limit/offset or cursor)
  • Missing pagination on a list endpoint flagged as major when no obvious bound exists

Error handling

  • Async controller methods must have error handling: either try/catch or a global exception filter
  • Unhandled promise rejections (async method without try/catch, no global filter) — blocker
  • Exception messages must not leak internal details (stack traces, ORM error strings) to the HTTP response — leaking is a blocker
  • NestJS built-in exceptions (NotFoundException, BadRequestException, etc.) preferred over generic Error

3. Database Patterns (ORM)

N+1 queries

  • Relation loaded inside a loop without eager loading (relations, leftJoinAndSelect) or a DataLoader — always major
  • Example: for (const user of users) { user.orders = await orderRepo.find(...) } — flag with concrete suggestion to use relations: ['orders'] or batch query

Transactions

  • Multi-step operations that must be atomic (e.g., create + update + delete across tables) must use a transaction
  • Missing transaction on a multi-step mutation is a major finding
  • NestJS TypeORM: use dataSource.transaction(async (manager) => { ... }) or @Transaction() decorator pattern

Raw query safety

  • String interpolation in raw queries is a blocker (SQL injection risk)
  • Use parameterized queries: query('SELECT * FROM users WHERE id = $1', [id])
  • Flag createQueryBuilder().where('id = ' + id) as blocker

Soft deletes

  • If the project schema uses deletedAt / @DeleteDateColumn(), deletions must use .softRemove() / .softDelete(), not .remove() / .delete()
  • Hard delete on a soft-delete entity flagged as major

Migration safety

  • Column removed in migration — check that no application code still references it
  • Dropping a column without a deprecation period in a live system flagged as major
  • NOT NULL column added without a default value to a populated table — blocker

4. TypeScript Correctness

  • No any in new code — suggest unknown with type guards, or correct typed return
  • Public service methods must have explicit return types (Promise<UserDto>, not inferred)
  • Service contracts expressed as interfaces (IUserService), not just class implementations
  • No as any or unsafe casts (as unknown as T) without a comment explaining why
  • @ts-ignore / @ts-expect-error without explanation comment — flag as minor

Iron Laws

ConditionSeverity
Missing DTO validation on an endpoint accepting user inputblocker
REQUEST-scoped provider injected into Singletonblocker
Leaking stack trace / raw ORM error to API responseblocker
Unhandled promise rejection in controller methodblocker
String interpolation in raw SQL queryblocker
N+1 query (relation loaded in a loop)major (minimum)
Missing transaction on multi-step atomic mutationmajor
Business logic in controllermajor
Missing pagination on unbounded list endpointmajor
NOT NULL column added without default to populated table (migration)blocker

Orchestrated Review Contract

When dispatched by review-orchestrator, follow the provided reviewer-input.schema.json payload. Return a REVIEW_RESULT object compatible with skills/review-orchestrator/reviewer-finding.schema.json, then a concise markdown summary. Keep findings evidence-based, include concrete suggested_fix for every blocker/major, and return NEEDS_CONTEXT instead of guessing when required context is missing.


Finding Format

### [F-001] Title

- **Severity**: blocker | major | minor | info
- **File**: path/to/file.ts:line
- **Problem**: what is wrong
- **Why it matters**: impact on correctness / safety / maintainability
- **Fix**: concrete suggestion
- **Patch** (optional):
  ```diff
  - old line
  + new line

---

## Output Contract

STATUS: DONE | DONE_WITH_CONCERNS | NEEDS_CONTEXT | BLOCKED


- `DONE` — no blockers or majors found
- `DONE_WITH_CONCERNS` — one or more blocker or major findings present
- `NEEDS_CONTEXT` — cannot determine intent without context doc or issue; state what is missing
- `BLOCKED` — cannot access diff or required files; state reason

```markdown
# Backend Review Report

## Verdict: APPROVE | APPROVE_WITH_SUGGESTIONS | REQUEST_CHANGES

## Summary
<2-4 sentences covering what changed, overall backend health, key concerns.>

## Review Scope
- Branch: `<BRANCH>`
- Parent ref: `<PARENT>`
- Merge-base: `<BASE_SHA>`
- Scope mode: `<default-with-uncommitted | explicit-hash-range>`
- Changed files: <count>

## Stats
- blocker: N
- major: N
- minor: N
- info: N

## Blockers (must fix before merge)
<[F-NNN] findings>

## Major Issues
<[F-NNN] findings>

## Minor & Info
<[F-NNN] findings>

## Positive Notes
<Optional. Things done well.>

Scope Boundaries

ConcernThis skillUse instead
NestJS module / provider / DTO / controller / serviceYES—
REST API shape, HTTP methods, error handlingYES—
Database ORM patterns, N+1, transactions, migrationsYES—
TypeScript strictness in service layerYES—
XSS, injection (beyond SQL in raw queries), auth bypassNOreview-security-code
Bundle size, query latency profilingNOreview-performance
Frontend, React, MobXNOreview-frontend
Architectural layer violations (cross-module)NOreview-architecture
Naming, style, import orderNOreview-style

Job Context Awareness

When dispatched by job-orchestrator or called with an explicit context path, the prompt MAY include:

JOB_NAME:     <job-name>
CONTEXT_PATH: <JOBS_ROOT>/<job-name>/ai/context.md

If provided and the file exists, read the context document before running scope detection. Use it to understand:

  • Which ORM, validation library, or guard strategy was intentionally chosen
  • Project-level architectural decisions (e.g., no repository pattern by design)
  • Acceptance criteria to verify spec compliance

If absent, proceed normally — context is optional and non-blocking.


Red Flags

RationalizationWhy it is wrong
"ValidationPipe is probably configured somewhere"Always verify it is applied; assumption lets injection reach service layer
"The N+1 only runs on small datasets now"Data grows; flag it now with a clear fix, not after the incident
"The controller has some logic but it's minor"The line is binary — logic in controller = untestable without HTTP stack
"Stack trace in response only shows in dev"Config can be wrong in prod; treat it as blocker always
"I'll skip the migration check — it's just a column rename"Column renames without fallback break zero-downtime deploys

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.