# Anti-patterns — Common Mistakes to Avoid

A short list of things that have hurt teams before. If the AI agent is about to do any of these, stop.

## Architecture

- **God service** — a service that does everything. Split by cohesion (a service per use-case or per aggregate root).
- **Bypassing layers** — controllers calling EF directly, services calling other services' internals. Respect Clean Architecture deps.
- **Cross-app import** — `apps/foo` importing from `apps/bar`. Promote to `packages/` or `enterprise-modules/`.
- **Premature abstraction** — a generic `<T> BaseRepository<T>` before two concrete repositories exist. Three similar lines beat a premature abstraction.

## Data

- **Fetch-entity-then-map** — `var x = await db.X.FirstAsync(); return _mapper.Map<Dto>(x);`. Use `.AsNoTracking().Select(...)` projections.
- **Hard delete where soft delete applies** — never `prisma.user.delete(...)` for end-user data; the schema is built for `deletedAt`.
- **Plain unique index on a soft-deletable column** — soft-deleted rows collide. Use a filtered unique on `deletedAt IS NULL`.
- **DB mocks in integration tests** — per `CLAUDE.md`, integration tests hit a real DB (Testcontainers).

## API

- **Different response shapes per endpoint** — every endpoint returns `{ success, message, data }` (+ paging fields for lists).
- **Missing authz on a mutation** — every mutating endpoint MUST have `[Authorize]` + a permission/role.
- **Throwing raw exceptions to the client** — go through `ProblemDetails` / `AllExceptionsFilter`.

## Auth + Security

- **Logging tokens** — never log access or refresh tokens, even in dev.
- **Storing refresh tokens plaintext** — store the SHA-256 hash.
- **Trusting client-side authz** — frontend hiding a button is UX; the API must still enforce.
- **Editing `.env*`** — denied by `.claude/settings.json`; route through the secret manager.

## UI

- **Hardcoded colors/spacing** — every value comes from a design token.
- **`HttpClient` in a component** — go through `BaseApiService`.
- **Hardcoded user-facing strings** — use Transloco/next-intl.
- **Removing focus outlines** — accessibility regression.

## Process

- **`--no-verify` on commit** — bypasses secret-scan + format + commitlint. Never use it.
- **Editing an applied migration** — roll forward with a new one.
- **Single-deploy breaking schema change** — use expand→contract over two deploys.

## When in doubt

Ask. The cost of confirming once is much lower than the cost of any of the above.
