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