# enpassant-chess-forum-abesec/en-passant-backend architecture

> Architecture diagram of the GitHub repository enpassant-chess-forum-abesec/en-passant-backend, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/enpassant-chess-forum-abesec/en-passant-backend
- Repository: https://github.com/enpassant-chess-forum-abesec/en-passant-backend

## Overview

En-Passant is an Express backend for club membership, recruitment, payments and chess community services. A typical member is provisioned from Clerk, updates a profile and chess accounts, applies to recruitment, pays or submits payment evidence, then completes department tasks; admins manage the lifecycle. Background jobs sync chess ratings and send email, with rankings exposed through Redis. The tree documents additional event, contact, settings, submission, storage and webhook capabilities. Sampled controller and worker source supports the shown calls; unsampled route wiring and some service internals are represented only at their owning module level.

Main entry points: [`src/app.js`](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/app.js) (Express API), [`src/features/sync/sync.engine.js`](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/sync.engine.js) (Rating sync), [`src/features/payments/payment.controller.js`](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/payments/payment.controller.js) (Payment API), [`src/features/users/user.controller.js`](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/users/user.controller.js) (Profile API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_identity["Identity &amp; profiles"]
  node_userctl["Profile API<br/>[user.controller.js]"]
  node_userrepo["User repository<br/>[user.repository.js]"]
  node_usermodel[("User records<br/>[user.model.js]")]
  node_webhook["Clerk webhook"]
end

subgraph group_recruitment["Recruitment lifecycle"]
  node_recruitctl["Application API"]
  node_recruitservice["Application lifecycle"]
  node_recruitmodel[("Applications")]
  node_paymentctl["Payment API"]
  node_paymentrepo["Payment records"]
  node_paymentmodel[("Payments<br/>[payment.model.js]")]
  node_gateway["Razorpay gateway"]
  node_taskctl["Task API<br/>[task.controller.js]"]
  node_taskrepo["Task repository<br/>[task.repository.js]"]
  node_taskmodel[("Task definitions<br/>[task.model.js]")]
  node_submissionctl["Submission API"]
end

subgraph group_community["Club services"]
  node_leaderboard["Leaderboard"]
end

subgraph group_async["Background services"]
  node_syncqueue["Sync queue<br/>[sync.queue.js]"]
  node_syncworker["Sync worker<br/>[sync.worker.js]"]
  node_syncengine["Rating sync<br/>[sync.engine.js]"]
  node_chesscomadapter["Chess.com adapter"]
  node_lichessadapter["Lichess adapter<br/>[lichess.adapter.js]"]
end

subgraph group_platform["Runtime infrastructure"]
  node_api["Express API<br/>[app.js]"]
  node_server["Server startup<br/>[server.js]"]
  node_auth["Authentication<br/>[auth.middleware.js]"]
  node_mongo[("MongoDB<br/>[db.js]")]
  node_redis[("Redis<br/>[redis.client.js]")]
end

node_member(("Member"))
node_admin(("Admin"))
node_clerk{{"Clerk"}}
node_razorpay{{"Razorpay"}}
node_chesscom{{"Chess.com"}}
node_lichess{{"Lichess"}}
node_cloudinary{{"Cloudinary"}}
node_emailvendor{{"Resend"}}

node_member -->|"uses"| node_api
node_admin -->|"manages"| node_api
node_api -->|"authenticates"| node_auth
node_api -->|"routes"| node_userctl
node_api -->|"routes"| node_recruitctl
node_api -->|"routes"| node_paymentctl
node_api -->|"routes"| node_taskctl
node_server -->|"starts"| node_api
node_userctl -->|"calls"| node_userrepo
node_userrepo -->|"reads/writes"| node_usermodel
node_userctl -->|"reads ranks"| node_leaderboard
node_userctl -->|"enqueues"| node_syncqueue
node_clerk -->|"sends events"| node_webhook
node_webhook -->|"provisions"| node_usermodel
node_webhook -->|"queues welcome"| node_syncqueue
node_syncqueue -->|"dispatches"| node_syncworker
node_syncworker -->|"calls"| node_syncengine
node_syncengine -->|"loads/saves"| node_usermodel
node_syncengine -->|"fetches ratings"| node_chesscomadapter
node_syncengine -->|"fetches ratings"| node_lichessadapter
node_chesscomadapter -->|"queries"| node_chesscom
node_lichessadapter -->|"queries"| node_lichess
node_syncengine -->|"updates"| node_leaderboard
node_leaderboard -->|"stores rankings"| node_redis
node_recruitctl -->|"calls"| node_recruitservice
node_recruitservice -->|"manages applications"| node_recruitmodel
node_paymentctl -->|"checks/transitions"| node_recruitservice
node_paymentctl -->|"creates orders"| node_gateway
node_paymentctl -->|"records payment"| node_paymentrepo
node_paymentrepo -->|"reads/writes"| node_paymentmodel
node_razorpay -->|"payment webhook"| node_paymentctl
node_taskctl -->|"queries tasks"| node_taskrepo
node_taskrepo -->|"reads definitions"| node_taskmodel
node_submissionctl -->|"checks application"| node_recruitservice
node_submissionctl -->|"checks task"| node_taskrepo
node_submissionctl -->|"uploads files"| node_cloudinary

click node_api "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/app.js"
click node_server "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/server.js"
click node_auth "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/middleware/auth.middleware.js"
click node_mongo "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/config/db.js"
click node_redis "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/redis/redis.client.js"
click node_userctl "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/users/user.controller.js"
click node_userrepo "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/users/user.repository.js"
click node_usermodel "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/users/user.model.js"
click node_webhook "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/webhooks/webhook.controller.js"
click node_syncqueue "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/sync.queue.js"
click node_syncworker "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/sync.worker.js"
click node_syncengine "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/sync.engine.js"
click node_chesscomadapter "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/adapters/chesscom.adapter.js"
click node_lichessadapter "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/adapters/lichess.adapter.js"
click node_leaderboard "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/leaderboard/leaderboard.service.js"
click node_recruitctl "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/recruitment/recruitment.controller.js"
click node_recruitservice "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/recruitment/recruitment.service.js"
click node_recruitmodel "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/recruitment/recruitment.model.js"
click node_paymentctl "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/payments/payment.controller.js"
click node_paymentrepo "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/payments/payment.repository.js"
click node_paymentmodel "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/payments/payment.model.js"
click node_gateway "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/payments/gateways/razorpay.gateway.js"
click node_taskctl "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/tasks/task.controller.js"
click node_taskrepo "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/tasks/task.repository.js"
click node_taskmodel "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/tasks/task.model.js"
click node_submissionctl "https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/submissions/submission.controller.js"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_userctl,node_userrepo,node_usermodel,node_webhook toneBlue
class node_recruitctl,node_recruitservice,node_recruitmodel,node_paymentctl,node_paymentrepo,node_paymentmodel,node_gateway,node_taskctl,node_taskrepo,node_taskmodel,node_submissionctl toneAmber
class node_leaderboard toneMint
class node_syncqueue,node_syncworker,node_syncengine,node_chesscomadapter,node_lichessadapter toneRose
class node_api,node_server,node_auth,node_mongo,node_redis,node_member,node_admin,node_clerk,node_razorpay,node_chesscom,node_lichess,node_cloudinary,node_emailvendor toneIndigo
```

## Components

### Identity & profiles

- [Profile API](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/users/user.controller.js): `src/features/users/user.controller.js`
- [User repository](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/users/user.repository.js): `src/features/users/user.repository.js`
- [User records](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/users/user.model.js): `src/features/users/user.model.js`
- [Clerk webhook](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/webhooks/webhook.controller.js): `src/features/webhooks/webhook.controller.js`

### Recruitment lifecycle

- [Application API](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/recruitment/recruitment.controller.js): `src/features/recruitment/recruitment.controller.js`
- [Application lifecycle](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/recruitment/recruitment.service.js): `src/features/recruitment/recruitment.service.js`
- [Applications](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/recruitment/recruitment.model.js): `src/features/recruitment/recruitment.model.js`
- [Payment API](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/payments/payment.controller.js): `src/features/payments/payment.controller.js`
- [Payment records](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/payments/payment.repository.js): `src/features/payments/payment.repository.js`
- [Payments](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/payments/payment.model.js): `src/features/payments/payment.model.js`
- [Razorpay gateway](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/payments/gateways/razorpay.gateway.js): `src/features/payments/gateways/razorpay.gateway.js`
- [Task API](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/tasks/task.controller.js): `src/features/tasks/task.controller.js`
- [Task repository](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/tasks/task.repository.js): `src/features/tasks/task.repository.js`
- [Task definitions](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/tasks/task.model.js): `src/features/tasks/task.model.js`
- [Submission API](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/submissions/submission.controller.js): `src/features/submissions/submission.controller.js`

### Club services

- [Leaderboard](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/leaderboard/leaderboard.service.js): `src/features/leaderboard/leaderboard.service.js`

### Background services

- [Sync queue](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/sync.queue.js): `src/features/sync/sync.queue.js`
- [Sync worker](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/sync.worker.js): `src/features/sync/sync.worker.js`
- [Rating sync](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/sync.engine.js): `src/features/sync/sync.engine.js`
- [Chess.com adapter](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/adapters/chesscom.adapter.js): `src/features/sync/adapters/chesscom.adapter.js`
- [Lichess adapter](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/features/sync/adapters/lichess.adapter.js): `src/features/sync/adapters/lichess.adapter.js`

### Runtime infrastructure

- [Express API](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/app.js): `src/app.js`
- [Server startup](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/server.js): `src/server.js`
- [Authentication](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/middleware/auth.middleware.js): `src/middleware/auth.middleware.js`
- [MongoDB](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/config/db.js): `src/config/db.js`
- [Redis](https://github.com/enpassant-chess-forum-abesec/en-passant-backend/blob/main/src/redis/redis.client.js): `src/redis/redis.client.js`

### Other components

- **Member**
- **Admin**
- **Clerk**
- **Razorpay**
- **Chess.com**
- **Lichess**
- **Cloudinary**
- **Resend**

## Connections

- Member → Express API: uses
- Admin → Express API: manages
- Express API → Authentication: authenticates
- Express API → Profile API: routes
- Express API → Application API: routes
- Express API → Payment API: routes
- Express API → Task API: routes
- Server startup → Express API: starts
- Profile API → User repository: calls
- User repository → User records: reads/writes
- Profile API → Leaderboard: reads ranks
- Profile API → Sync queue: enqueues
- Clerk → Clerk webhook: sends events
- Clerk webhook → User records: provisions
- Clerk webhook → Sync queue: queues welcome
- Sync queue → Sync worker: dispatches
- Sync worker → Rating sync: calls
- Rating sync → User records: loads/saves
- Rating sync → Chess.com adapter: fetches ratings
- Rating sync → Lichess adapter: fetches ratings
- Chess.com adapter → Chess.com: queries
- Lichess adapter → Lichess: queries
- Rating sync → Leaderboard: updates
- Leaderboard → Redis: stores rankings
- Application API → Application lifecycle: calls
- Application lifecycle → Applications: manages applications
- Payment API → Application lifecycle: checks/transitions
- Payment API → Razorpay gateway: creates orders
- Payment API → Payment records: records payment
- Payment records → Payments: reads/writes
- Razorpay → Payment API: payment webhook
- Task API → Task repository: queries tasks
- Task repository → Task definitions: reads definitions
- Submission API → Application lifecycle: checks application
- Submission API → Task repository: checks task
- Submission API → Cloudinary: uploads files
