# API Domain Module Guide

> This guide describes the target API adapter inside the approved domain-first modular
> monolith. During migration, `AGENTS.md` and the existing endpoint contracts remain
> authoritative.

## 1. Target folder contract

```text
src/modules/<domain>/
  domain/
    <domain>.model.js
    <domain>.repository.js
    <domain>.service.js
    <domain>.policy.js
    <domain>.constants.js
  interfaces/api/
    <domain>.api.controller.js
    <domain>.api.routes.js
    <domain>.api.validation.js
    <domain>.dto.js
  index.js
```

Optional files are added only for real complexity: query builders, uploads, transactions,
or domain events. A folder is not made “clean” by adding empty layers.

## 2. Migration compatibility

Current API paths follow:

```text
src/routes/api/<Domain>Route/<Domain>Route.js
  -> src/controllers/api/<domain>Controller.js
  -> src/helpers/api/<Domain>.js
  -> src/models/* + @returnObj
```

The migration preserves those paths until consumers are updated safely. Compatibility
files delegate to the module public index; they do not duplicate implementation.

Example transitional shape:

```js
// src/controllers/api/exampleController.js
module.exports = require('@root/modules/examples').api.controller;
```

The existing API route class may remain the registrar while it imports the module's
public validator/controller exports. Route relocation comes later and requires route
snapshot proof.

## 3. Responsibilities

### API controller

- accepts Express `req`/`res` and nothing persistence-specific;
- consumes already validated/matched input;
- calls one application/domain use-case;
- returns the existing `ApiResponse` envelope or delegates errors to the existing error
  path;
- never imports Mongoose models, performs populate/query work, or decides permissions.

### Validation

- defines every accepted header/query/param/body/file field;
- preserves `express-validator` and the existing `getValidationChain` behavior;
- ensures unknown fields remain dropped through `matchedData`;
- validates file signatures through the established upload security helpers;
- has no persistence mutation side effects.

### Domain/application service

- receives plain input plus an explicit actor/context;
- orchestrates policies, repositories, transactions, notifications, jobs, and files;
- does not know Express response objects, EJS, or Socket instances;
- returns domain results or typed project errors.

### Repository

- owns Mongoose access, projections, populations, write options, and transactions;
- returns records/domain data, not HTTP DTOs;
- does not call response helpers, i18n, or render functions.

### Policy/constants

- owns role/status/type decisions and allowed transitions;
- consumes authoritative existing enums rather than recreating values;
- is deterministic and unit-testable;
- never queries the database directly.

### DTO mapper

- maps only safe, explicit fields;
- never returns passwords, hashes, OTPs, token versions, reset fields, secrets, raw
  Mongoose documents, or internal errors;
- preserves the existing response contract exactly during migration;
- owns localization/display mapping for the API, not dashboard presentation.

## 4. Public and authenticated buckets

Every route retains its current bucket in `indexRoute.js`:

- `unRequireAuthRoutes()` is public;
- `registerRoutes()` or the domain's authenticated registrar runs after `requireAuth`.

Moving a route between buckets is an auth-contract change and is not authorized by an
architecture migration.

## 5. Route contract snapshot

Before moving an API route, capture:

- method and exact path;
- registration order and collision-sensitive neighbors;
- public/authenticated placement;
- `authorize(...)` actor types;
- validators and their order;
- upload parser behavior;
- handler name;
- status/envelope/message keys;
- request and response OpenAPI/Postman examples.

The post-move snapshot must be byte-for-byte or semantically identical for every public
contract field.

## 6. Model migration rule

Models move only after import, registration, index, hook, populate, and DTO tests exist.
The old `src/models/<entity>Model.js` path stays as a compatibility re-export. Never
compile the same Mongoose model twice.

Schema, index, enum, hook, and migration changes are separate business/data phases.

## 7. Cross-domain collaboration

An API service may call another domain only through its public contract. Examples:

- Orders requests a payment authorization from Payments;
- Auctions requests notification delivery from Notifications;
- Provider approval asks Accounts to link the accepted profile.

It must not import the other domain's private model or repository. Existing cross-domain
direct imports are migration debt and are removed one tested use-case at a time.

## 8. Errors, localization, and response envelope

Architecture work preserves:

```json
{ "key": "...", "message": "...", "status": 200, "data": {} }
```

Errors continue through the existing `errorHandler`/`ApiError` path. Message keys remain
available in Arabic and English. A mapper cannot invent a new envelope or leak stack
traces.

## 9. OpenAPI and Postman

The repository now contains modular OpenAPI YAML under `docs/openapi/`, generated public
JSON, manual BR1/BR2 checks, and Postman exports. For every touched endpoint:

- update only its domain path/schema documents;
- preserve security schemes and actor-token behavior;
- run OpenAPI/Postman tests and export diff checks;
- restore generated timestamp-only metadata before delivery;
- never document passwords, OTPs, hashes, secrets, or internal tokens.

## 10. Required tests per API domain wave

1. route method/path/order and auth bucket;
2. validator accepted/rejected/unknown-field behavior;
3. controller delegates without DB access;
4. repository owns all model access;
5. policy transition/authorization matrix;
6. DTO snapshot and sensitive-field absence;
7. response envelope/status/message compatibility;
8. pagination/filter compatibility;
9. upload lifecycle where relevant;
10. OpenAPI/Postman endpoint parity;
11. focused tests, full `npm test`, changed-JS `node --check`, `git diff --check`.

## 11. Domain migration template

```text
Inventory current routes/controllers/helpers/models/validators/DTOs/tests/docs.
Freeze contract tests.
Extract constants and pure policies.
Extract repository without query changes.
Extract service orchestration.
Extract DTO mapper with response snapshots.
Delegate old controller/helper paths to module index.
Optionally delegate route class after route snapshot proof.
Run focused/full/API-documentation gates.
Record compatibility paths and rollback.
```

High-risk domains (identity, providers, products, orders, auctions, payments) migrate
only after low-risk domains demonstrate this pattern.

