Skip to content

API Review Checklist

This checklist is the operational companion to API Review Guidelines.

Use it when reviewing backend PRs manually or when automating review prompts for AI agents.

Review Output Contract

  • Always report findings in this order: hard-fail, warn, pass
  • A hard-fail blocks merge unless the PR includes an explicit architectural reason and the docs are updated in the same change
  • A warn does not block merge by itself, but should request alignment when the change is still easy to correct
  • A pass means the reviewer checked the item and found no issue worth reporting
  • Every finding should include the file path, the violated rule, why it matters, and what the preferred fix looks like

Hard-Fail Checklist

  • [ ] No new direct dependency reaches into another feature module's private internals
  • [ ] New request and response contracts live in packages/schemas instead of ad hoc API-local DTOs
  • [ ] Every new body payload is validated at the controller boundary with @Body(new ZodValidationPipe(...))
  • [ ] Persistence logic stays in repositories, not in controllers or command/query handlers
  • [ ] Repository implementations handle persistence mapping explicitly and keep repository telemetry inside the repository when metrics exist
  • [ ] Commands with multiple related writes use a single transaction
  • [ ] Public endpoints do not leak private, draft, admin-only, or internal metadata when a public/private split is required by the domain
  • [ ] Not-found and similar domain errors match the actual aggregate or resource being loaded
  • [ ] New persistence entities extend BasePersistenceEntity cleanly without redefining inherited id, createdAt, or updatedAt
  • [ ] SQL table and column names stay in snake_case while TypeScript properties stay in camelCase
  • [ ] Shared repository, port, and service boundaries use I... interfaces plus Symbol DI tokens

Warn Checklist

  • [ ] Controllers stay thin: validate input, gather context, dispatch CQRS, unwrap results, and return the final HTTP contract
  • [ ] Mutation endpoints return an explicit response contract instead of leaving the response shape implicit
  • [ ] Presentation code owns DTO mapping, especially when deciding public vs private output
  • [ ] toDto methods accept options: IMapperOptions = DefaultMapperOptions and validate by default
  • [ ] toDto mappings whitelist response fields explicitly instead of spreading the whole entity or persistence object
  • [ ] Internal toDomain and toPersistence paths prefer safe helpers such as mapProperties(...) or controlled spread-based mapping when that reduces missed fields
  • [ ] Simple one-off command/query definitions stay in the same file as the handler unless reuse justifies a split
  • [ ] Cross-boundary imports prefer @api/* aliases over deep relative chains
  • [ ] New shared schema identifiers use explicit UUID v7 validation such as z.uuidv7()
  • [ ] Schema defaults match currently supported product behavior and do not introduce unsupported business states
  • [ ] Tests mirror the app structure and stay focused on the behavior under review

Common Fix Patterns

  • Controller contract: if a command endpoint currently returns nothing, return the updated DTO, a shared success payload, or an explicit empty object when that is the established API contract
  • Public/private mapping: create separate public and private controller flows and pass mapper options such as publicVersion from the presentation layer
  • Mapper safety: use broad mapping helpers only for internal transformations; keep toDto explicit and field-by-field
  • Persistence base model: keep business identifiers in dedicated columns like orgId; do not replace the semantic role of the base primary key
  • Repository save flow: return the saved aggregate when the caller needs the persisted state after update
  • CQRS file layout: keep the message type and handler together until a real reuse case appears
  • Schema constraints: tighten IDs and defaults in packages/schemas to match the real API contract, not placeholder assumptions

Suggested AI Review Response Shape

md
## Hard-Fail

- [ ] <file>: <rule> - <why this is a blocking issue> - <preferred fix>

## Warn

- [ ] <file>: <rule> - <why this should be aligned> - <preferred fix>

## Pass

- [x] Checked controller boundary validation
- [x] Checked repository/persistence ownership

Escalation Rule

  • If a PR intentionally breaks a hard-fail rule, ask for the architectural reason explicitly
  • If the change is accepted as a new convention, update apps/docs/conventions/backend/api-review-guidelines.md and this checklist in the same PR