# AI Agent Project Rules

Project: **Zafirra** (`package.json` → `"name": "zafirra"`)
Stack: Node.js 18 · Express 5 · MongoDB/Mongoose 8 · EJS · Socket.IO
Applies to: Claude Code, Codex, Cursor, and any other AI coding agent.

---

## Base Codebase vs New Business Domain

This codebase is used as a base project. Existing files define architecture and
conventions, but they are not necessarily the final business domain.

When implementing new features, agents must:

- follow existing technical patterns
- create new business models when needed
- not force new features into unrelated old models
- not assume old modules are part of the new product unless explicitly required
- design new Mongoose models based on the business analysis
- keep model names, routes, validations, and swagger consistent

### What that means in practice

| | Base Codebase (`src/`) | New Business Domain |
|---|---|---|
| Authority | **How** to build — the technical spine | **What** to build — the product |
| Reuse | Copy the pattern | Design from the analysis |
| Examples | `ApiResponse`, `ApiError`, `errorHandler`, `getValidationChain`, route classes, `@returnObj`, passport/JWT, upload helpers, i18n, cron, socket | `Client`, `Provider`, `Product`, `ProductAttribute`, `ProductVariant`, `Category`, `Order`, `Auction`, `Wallet`, `Review`, `Notification`, … |

**Reuse from the base (always):** routing class shape · validation chains · the
`{ key, message, status }` response envelope · error handling · auth · upload handling ·
enum style · i18n · the test style.

**Do not reuse (unless explicitly asked):** the old domain models and their logic —
`harajRequestsModel`, `advertisementModel`, `settlementModel`, `providerMetaModel`,
`otoTokenModel`, `adEditRequestModel`, and similar. They belong to the previous product.

**Do not assume a model exists.** The new domain's models are being created from scratch.
Before using any model name, verify it exists *and* that it is part of the new domain:

```bash
ls src/models | grep -i <entity>
```

If it does not exist, design it Production-Grade from the analysis following
`docs/DOMAIN_MODELING_GUIDE.md` — do not bend the feature to fit an unrelated old model,
and do not copy an old model just because it is there.

Every new business module ships as a complete vertical slice:
**model · validation · route · controller · service · swagger · tests (where applicable).**

Full guidance: **`docs/DOMAIN_MODELING_GUIDE.md`**.

---

## Purpose

This file defines how any AI coding agent must work inside this project.
It is binding. If a request conflicts with these rules, stop and ask the human first.

**Rule precedence:** `AGENTS.md` > `docs/*.md` > `.cursorrules` / `.cursor/rules/*.mdc`.
`.cursorrules` is older and describes a slightly different folder layout (e.g. it lists
`listeners/socketManger/helper.js` and `validation.js`, which are now the directories
`callHelper/`, `chatHelper/`, `liveHelper/`, `auctionHelper/`, `*Validation/`). Where the
two disagree, this file and the code win.

---

## Quick Commands

| Purpose | Command | Safe? |
|---|---|---|
| Run locally (HTTP, no TLS certs needed) | `npm run start:dev` | ✅ |
| Run unit tests | `npm test` | ✅ |
| Regenerate the permission catalogue | `npm run listPermissions` | ✅ writes source files |
| Production-style run (needs TLS cert paths from `.env`) | `npm start` | ⚠️ |
| Seed reference data | `npm run seed` | ⛔ writes to DB |
| Destroy seeds | `npm run destroy` | ⛔ **destructive** |
| Drop every collection | `npm run delete-all-collections` | ⛔ **destructive** |
| Export/import collections | `npm run export` / `npm run import` | ⛔ `src/collections/` is gitignored/absent |

Agents run only the ✅ rows. The ⛔ rows require an explicit, per-occasion human instruction.

---

## Required First Step

Before implementing any real feature **for the first time**, the agent must read:

- `AGENTS.md` (this file)
- `docs/PROJECT_ARCHITECTURE.md` — what the base actually contains
- `docs/DOMAIN_MODELING_GUIDE.md` — how to design the new domain's models
- `docs/API_WORKFLOW.md`
- `docs/SWAGGER_GUIDE.md`

Related existing material worth knowing about (do not re-read on every task):

- `.cursorrules` — legacy Cursor ruleset, largely consistent with this file
- `.cursor/skills/*/SKILL.md` — per-domain how-tos (add-api-resource, create-mongoose-model, auction-cycle)
- `.cursor/implementation-plan/EP-*.md` — original epic specs
- `.cursor/postman/` and `scripts/*.postman_collection.json` — the current de-facto API contract
- `docs/notification-types-actions.md` — notification type/action matrix

---

## Project Scan Rule

A full project scan is required **once** at the beginning of working on this codebase.
Its result is already captured in `docs/PROJECT_ARCHITECTURE.md`.

After that, **each task must use targeted discovery only**. Do not re-scan the whole
repository per task. `src/helpers/returnObject/returnObject.js` alone is ~5.9k lines and
`src/routes/dashboard/adminRoute/adminRoute.js` is ~1.7k lines — reading them whole on
every task is waste, not diligence.

---

## Core Rules

- Do not change the stack.
- Do not introduce new architecture unless requested.
- Do not add packages. `package.json` is frozen unless the human explicitly approves.
- Do not refactor unrelated modules.
- Do not modify unrelated files.
- Do not rename, move, or delete existing files without an explicit instruction.
- Do not expose secrets. Never print, echo, commit, or paste values from `.env`.
  Variable **names** may be referenced; **values** never.
- Do not log passwords, tokens, OTPs, `activationCode`, cookies, session ids, or credentials.
- Do not return sensitive fields in API responses.
- Do not return raw Mongoose documents. Always map through `src/helpers/returnObject/returnObject.js`.
- Do not return stack traces in production. Errors go through
  `src/services/errorHandler/error.handler.js` / `ApiError` only.
- Do not accept unknown fields in API requests. Controllers consume
  `checkValidations(req)` → `matchedData(req)`, so anything not declared in a validator
  is dropped by design. Keep it that way.
- Do not run migrations, seeders, `npm run destroy`, `delete-all-collections`, or any
  destructive script.
- Do not touch `.env`, `.htaccess`, `.gitlab-cd.yml`, or certificate paths.
- Follow existing project **technical** patterns even when you personally would write it
  differently.
- Do not treat the existing **business** models as the new product's domain. The base is
  authoritative for *how*, the analysis is authoritative for *what*.
- Do not force a new feature into an unrelated old model. If the right model does not
  exist, design it (`docs/DOMAIN_MODELING_GUIDE.md`).
- Do not copy an old model wholesale. Copy its *style*; derive its *fields* from the analysis.
- Do not invent the domain. If there is no analysis for an entity, ask the human before
  designing it.

---

## Non-Negotiable Project Conventions

| Layer | Convention |
|---|---|
| API route | Class in `src/routes/api/<Domain>Route/<Domain>Route.js`, exported as `new XRoutes()`, with `unRequireAuthRoutes()` (public) and `registerRoutes()` (authenticated) |
| API controller | `src/controllers/api/<domain>Controller.js` — **thin wrapper only**, delegates to `src/helpers/api/<Domain>.js` |
| API business logic | `src/helpers/api/<Domain>.js` (class, exported as instance) |
| Validation | `src/utils/validations/api/<domain>.js`, static methods returning `express-validator` chains, wired via `Validator.getValidationChain(Validator.validateX())` |
| Model | `src/models/<entity>Model.js`, flat directory, class-extends-`Schema` style, `{ timestamps: true, versionKey: false }`. **New models additionally follow `docs/DOMAIN_MODELING_GUIDE.md`**: declared indexes, `select: false` on sensitive fields, no `pre(/^find/)` auto-populate |
| Response | `new ApiResponse(key, message, status, data)` |
| Error | `throw errorHandler({ res, statusName, i18nMessage, lang })` |
| Serialization | `@returnObj` (`src/helpers/returnObject/returnObject.js`) |
| Enums | `src/helpers/enums/<name>.enum.js`, `Object.freeze` |
| i18n | Keys in `src/locales/ar/*.json` **and** `src/locales/en/*.json` — both, always |
| Path aliases | `@root` → `src/`, `@returnObj`, `@src-routes`, `@listeners` |

New API endpoints must be registered inside the correct route class and reach the app
through `src/routes/api/indexRoute/indexRoute.js`. Public endpoints go in
`unRequireAuthRoutes()` (registered **before** `requireAuth`); everything else in
`registerRoutes()`.

---

## Before Any Task After Initial Scan

### Step 0 — Does it exist, and does it belong to the new domain?

The base is mature (15 API route classes, 40 dashboard controller folders, 67 models), but
most of those models belong to the **previous** product. Two questions, not one:

```bash
grep -rn "signup-client" src/routes/api/          # 1a. is the endpoint already registered?
grep -rn "signupClient"  src/helpers/api/         # 1b. is the logic already written?
ls src/models | grep -i <entity>                  # 2.  does a model with this name exist?
```

Then classify the result:

| Finding | Action |
|---|---|
| Exists **and** is part of the new domain | Reframe the task as a **modification**. Never re-implement under a new name. |
| Exists but belongs to the **old** domain | Do **not** reuse it. Note the name collision and design the new model per `docs/DOMAIN_MODELING_GUIDE.md`. Raise the naming conflict with the human before creating a second model with a similar name. |
| Does not exist | This is a **new business module** → go to Step 0b. |

### Step 0b — Domain Design (new modules only)

Before any Targeted Discovery of implementation files, produce a short domain design:

1. Entity name + who it faces (client / provider / admin / shared)
2. Fields (type, required, default)
3. Relationships and their direction
4. Status values → which enum file
5. Indexes implied by the endpoints you are about to build
6. Sensitive fields and what the DTO will omit
7. Which existing models (if any) it legitimately relates to

Follow `docs/DOMAIN_MODELING_GUIDE.md` § *Before Creating a Model* and § *Model Creation
Workflow*. This design is reviewed **before** any schema file is written.

### Step 1 — Targeted Discovery

Perform **Targeted Discovery** only for the task scope.

Example — if the task is *Client Signup + Provider Signup*, inspect only:

- `src/routes/api/AuthRoute/AuthRoute.js`
- `src/routes/api/indexRoute/indexRoute.js`
- `src/controllers/api/authController.js`
- `src/helpers/api/Auth.js`
- `src/utils/validations/api/auth.js`, `src/utils/validations/api/global.js`
- `src/models/userModel.js`, `clientModel.js`, `providerModel.js`, `providerMetaModel.js`
- `src/utils/token/token.js`, `src/utils/generateCode/generateCode.js`
- `src/services/sendSMS/sendSMS.js`, `src/services/passport/passport.js`
- `src/helpers/returnObject/returnObject.js` → `exports.client`, `exports.provider` only
- `src/helpers/api/ApiResponse.js`, `ApiError.js`, `src/services/errorHandler/error.handler.js`
- `src/utils/showErrors/showErrorsApi.js`
- `src/locales/{ar,en}/auth.json`
- API contract files for Auth (Postman collection; OpenAPI once it exists)
- `package.json` scripts

Do not inspect unrelated modules again unless the task genuinely needs them.

---

## Targeted Discovery Report

Before implementation, output:

1. Task scope.
2. Files inspected.
3. Existing patterns found.
4. Files to create.
5. Files to modify.
6. Implementation plan.
7. Risks.

Do not write a single line of production code before this report is on screen.

---

## API Implementation Standard

Every API task must include:

- Domain Design if the module is new (Step 0b) — reviewed before any schema is written
- Model — new one designed per `docs/DOMAIN_MODELING_GUIDE.md`, or a justified update to
  an existing **new-domain** model
- Route (in the correct route class, correct auth bucket)
- Validation (`express-validator` chain + `getValidationChain`)
- Controller (thin delegate)
- Service/business logic in `src/helpers/api/<Domain>.js`
- Safe response DTO via `@returnObj`
- Error handling via `errorHandler` / `ApiError` keys
- i18n keys added to **both** `ar` and `en`
- API documentation (see `docs/SWAGGER_GUIDE.md`) for touched endpoints only
- Tests if available (`test/*.test.js`, plain Node + `assert`)
- Manual QA notes

---

## Dashboard Implementation Standard

Roughly half this project is the admin dashboard (411 EJS views, 40 controller folders,
one ~1.7k-line route file). Dashboard tasks follow a **different** standard from API tasks.

Every dashboard task must include:

- Route in `src/routes/dashboard/adminRoute/adminRoute.js`, in the correct section comment,
  with the correct chain:
  - GET page → `csrfProtection, authentication, authorization, controller.fn`
  - Mutation/AJAX → `authentication, authorizationAjax, [uploadsFiles()], <validator>(), csrfProtection, showErrorsApi, controller.fn`
  - Multipart → `uploadsFiles()` **before** `csrfProtection` (otherwise `_csrf` is not parsed out of the body)
  - `/<group>/filter` must be registered **before** any `/<group>` regex route
- Validator in `src/utils/validations/dashboard/<module>.js`
- Controller in `src/controllers/dashboard/<module>Controller/<module>Controller.js`
- Views under `views/admin/<module>/` following the existing 6-file CRUD set
  (`index`, `create`, `edit`, `show`, `dataTable`, `tds`), reusing partials from
  `views/admin/includes/`
- Every `res.render` passes: `title`, `currentMenu`, `user: req.admin`,
  `csrfToken: req.csrfToken()`, `lang`, `i18n`, `moment`
- Mutations respond with **JSON**, not a redirect:
  `res.send(new ApiResponse("success", i18n.__("common.editSuccessful"), 200, { url: "/dashboard/<module>/all" }))`
- AJAX filter renders the table fragment with `layout: false`
- Audit trail: `report(req.admin._id, { ar, en, ur }, req.method, req.url)` on every mutation
- i18n keys in both `ar` and `en`
- If routes were added/renamed: run `npm run listPermissions` to regenerate
  `src/helpers/permissions/permissions.js` and the `permissions.json` locale keys

---

## Socket & Cron Standard

**Socket** (`listeners/socketManger/`): handler in `<domain>Helper/index.js`, input rules in
`<domain>Validation/index.js`, wired in `socket.js`. Payloads use the same `ApiResponse`
envelope as HTTP. Never trust the handshake query beyond what `socketValidation` checks.

**Cron** (`src/helpers/cronJopFn/cronJobFn.js` + `src/services/CronManger/cronJob.js`):
schedules are one-shot `Date` deadlines, not cron expressions. A new job needs (a) an
exported handler in `cronJobFn`, and (b) an `addCronJobToDB` call. If you add a `fn` name
to the DB without exporting a matching handler, `scheduleCronJobs()` silently marks the row
FINISHED at boot — this already happened twice in this codebase. Handlers must be
idempotent: on restart, past-due jobs fire immediately.

---

## Swagger Rule

Swagger/OpenAPI is **not installed today** — see `docs/SWAGGER_GUIDE.md` for the current
state and the approved zero-dependency path.

When API documentation exists, it must be updated **only for endpoints touched by the
current task**. Never bulk-document the whole project in one pass.

Never document: passwords, OTP/`activationCode`, tokens beyond the auth token field
itself, secrets, stack traces, or endpoints that do not exist in code.

---

## Security Rules (project-specific)

- Passwords are HMAC-SHA256 with `CRYPTO_HASH` (`src/models/userModel.js`). Do not
  weaken it; do not silently swap the algorithm without an approved migration plan.
- OTP (`activationCode`) must never be returned in a response or logged. Note:
  `returnObject.client` currently exposes `activationCode` — do not copy that pattern
  into new DTOs, and flag it rather than propagating it.
- Auth tokens are issued by `src/utils/token/token.js` and persisted in `UserToken`.
  Signing out must delete the row, not just drop the client-side copy.
- Dashboard mutations require `csurf` (`csrfProtection`). For multipart routes,
  `uploadsFiles()` must run **before** `csrfProtection`.
- Dashboard RBAC (`authorization.js` / `authorizationAjax.js`) is currently a **no-op** —
  the enforcement blocks are commented out. Do not assume route-level permission
  checks protect anything. Do not re-enable them as a side effect of another task.
- File uploads must go through `uploadAnyFile` / `FileHandler` and validate the file
  signature with `GlobalValidator.validateImageFile` (magic bytes), not the client MIME.

---

## Git & Delivery

- Do not `git commit`, `git push`, create branches, or open MRs unless explicitly asked.
- Never stage `.env`, certificates, `public/assets/uploads/`, or anything under `.gitignore`.
- Never paste an `.env` value into a commit message, a PR description, or a test fixture.
- Current working branch is `dev`; `main` is the default branch. Do not switch branches
  on your own initiative.
- `.gitlab-cd.yml` is deployment config — treat it as read-only.

---

## Final Report

After every task, output:

1. Files inspected.
2. Files created.
3. Files modified.
4. Endpoints added/changed.
5. Validation rules.
6. Documentation updates (Swagger/OpenAPI/Postman).
7. Security checks performed.
8. Manual QA steps.
9. Automated test results (real output, including failures).
10. Anything not implemented and why.

Report outcomes faithfully. If tests fail, say so and paste the output. If a step was
skipped, say it was skipped.

---

## Definition of Done

A task is complete only if:

- Discovery was done and reported.
- For a new business module: the Domain Design was produced and reviewed **before** the
  schema was written, and the model follows `docs/DOMAIN_MODELING_GUIDE.md`
  (declared indexes, enum-backed statuses, `select: false` on sensitive fields,
  no `pre(/^find/)` auto-populate).
- No old-domain model was reused or extended to host new-product behaviour.
- The module is a complete vertical slice: model · validation · route · controller ·
  service · swagger · tests where applicable.
- Code follows existing patterns (route class → thin controller → `helpers/api` logic).
- No unrelated files were modified.
- Validation exists for every new input field.
- Responses are built from `@returnObj` + `ApiResponse`, with no sensitive fields.
- i18n keys exist in both `ar` and `en`.
- API documentation updated for touched endpoints only.
- Tests and/or manual QA are documented.
- No secrets leaked, no credentials logged.
