# dataesr/paysage-api architecture

> Architecture diagram of the GitHub repository dataesr/paysage-api, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-05-13). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/dataesr/paysage-api
- Repository: https://github.com/dataesr/paysage-api

## Overview

1. This repository is a Node.js backend API for “Paysage”, centered on managing a large catalog of public-organization data: structures, persons, projects, terms, categories, relations, documents, and related metadata. The README and folder layout suggest an Express-style HTTP service exposed as a REST API with OpenAPI documentation.

2. The application entry points are split between `index.js`, `src/api/app.js`, and `src/api/index.js`. `src/config.js` and the `src/setup/*` modules indicate bootstrapping for external infrastructure before the API starts, especially MongoDB, Elasticsearch, and storage.

3. The HTTP layer is organized by domain under `src/api/*`. Each major business object has its own route bundle, for example `structures`, `persons`, `projects`, `terms`, `categories`, `relations`, `groups`, `documents`, `domains`, `officialtexts`, `prizes`, `legalcategories`, `email-types`, `followups`, `journal`, `search`, `auth`, `users`, `apikeys`, and `me`. This is the primary boundary for the architecture diagram.

4. Most domains have nested subresources that reflect the data model rather than generic CRUD only. Examples include identifiers, web links, social media, localisations, emails, names, logos, key numbers, geographical categories, and group members. That implies a hierarchical resource model with many child collections attached to a root entity.

5. Cross-cutting behavior is centralized in `src/api/commons/middlewares`. These middlewares cover authentication, RBAC, validation, file handling, event handling, CRUD orchestration, alternative IDs, context propagation, and error handling. In the architecture, these sit between route definitions and the service/repository layer.

6. Persistence is MongoDB-first. `src/services/mongo.service.js`, `src/setup/mongo.js`, and the repository helpers under `src/api/commons/libs` show a repository abstraction over Mongo collections, including base and nested repositories. This suggests most API operations read/write Mongo documents directly through a shared data-access layer.

7. Elasticsearch is a second major data store, but mainly for search and indexing rather than as the source of truth. The `search` routes, the various `*.elastic.js` query files, and `src/services/elastic.service.js` indicate a dedicated search/indexing path for autocomplete and aggregated lookup queries across entities such as structures, persons, projects, legal categories, and terms.

8. File and media handling are handled separately from core entity data. `src/services/storage.service.js`, `src/api/assets`, `src/api/files`, and the OpenAPI file schemas indicate that documents or binaries are stored outside MongoDB, while the API manages metadata and access to those files.

9. Authentication and authorization are explicit subsystems. `src/api/auth`, `src/api/apikeys`, `src/api/users`, and `src/api/me` point to sign-in/sign-out/token flows, API key management, and user profile access. These are backed by queries for user/admin/token views and enforced through auth/RBAC middlewares.

10. Background processing is substantial and part of the architecture, not a side detail. `src/jobs` contains indexing, email validation, Sirene synchronization, open-data imports, dump generation, key-number datasets, treatments, and notifications. These jobs likely act on MongoDB data, update Elasticsearch indexes, and call external services such as mail or Mattermost.

11. The `scripts/` directory contains operational import/reset utilities, especially for geographical categories and localisation status. Together with `mongo-init.js`, this indicates bootstrap and data-seeding workflows for local or fresh environments.

12. The repo is designed with strong API contract discipline. `src/openapi` contains the full API specification, path definitions, schemas, parameters, and error responses, while `docs/` provides human documentation. This makes the OpenAPI model a key architectural artifact alongside the code.

13. Tests are organized by domain and also cover shared infrastructure. There are unit/integration tests for categories, persons, projects, structures, legal categories, document types, official texts, search, and base repository behavior, plus dedicated test setup under `tests/`. GitHub Actions and Docker Compose files show the project is built and tested in containerized CI environments.

14. In diagram terms, the main flow is: client request -> route module -> shared middlewares -> domain logic/repository -> MongoDB and/or Elasticsearch -> optional storage/mail/external integrations -> response. Jobs and scripts operate alongside this path as asynchronous or operational pipelines over the same underlying data stores.

Main entry points: [`src/api/commons/middlewares/authenticate.middlewares.js`](https://github.com/dataesr/paysage-api/blob/main/src/api/commons/middlewares/authenticate.middlewares.js) (Middlewares), [`index.js`](https://github.com/dataesr/paysage-api/blob/main/index.js) (Entry), [`src/api/index.js`](https://github.com/dataesr/paysage-api/blob/main/src/api/index.js) (API index), [`src/jobs/index.js`](https://github.com/dataesr/paysage-api/blob/main/src/jobs/index.js) (Jobs)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_grp_api["HTTP API"]
  node_api_app["App<br/>[app.js]"]
  node_api_index["API index<br/>route assembly<br/>[index.js]"]
  node_domains_routes["Domains<br/>domain routes"]
  node_relations_routes["Relations<br/>domain routes"]
  node_support_routes["Support APIs<br/>aux routes<br/>[auth.routes.js]"]
  node_resource_subresources["Subresources<br/>nested resources"]
end

subgraph group_grp_core["Shared core"]
  node_index_js["Entry<br/>[index.js]"]
  node_common_mw["Middlewares<br/>cross-cutting"]
  node_repositories["Repositories<br/>data access"]
  node_queries["Queries<br/>read models"]
  node_config["Config<br/>[config.js]"]
end

subgraph group_grp_data["Data & integrations"]
  node_mongo_setup[("Mongo setup<br/>bootstrap<br/>[mongo.js]")]
  node_elastic_setup[("Search setup<br/>bootstrap<br/>[elastic.js]")]
  node_storage_setup[("Storage setup<br/>bootstrap<br/>[storage.js]")]
  node_mongo_service[("MongoDB<br/>primary store<br/>[mongo.service.js]")]
  node_elastic_service[("Elasticsearch<br/>search store<br/>[elastic.service.js]")]
  node_storage_service[("Storage<br/>blob store<br/>[storage.service.js]")]
  node_mailer_service["Mailer<br/>external service<br/>[mailer.service.js]"]
end

subgraph group_grp_async["Async ops"]
  node_jobs["Jobs<br/>background pipelines<br/>[index.js]"]
  node_scripts["Scripts"]
end

subgraph group_grp_contracts["Contracts & docs"]
  node_openapi["OpenAPI<br/>api contract<br/>[api.yml]"]
  node_docs["Docs<br/>[intro.md]"]
  node_tests["Tests<br/>test suite<br/>[globalSetup.js]"]
end

node_index_js -->|"loads"| node_config
node_index_js -->|"starts"| node_mongo_setup
node_index_js -->|"starts"| node_elastic_setup
node_index_js -->|"starts"| node_storage_setup
node_index_js -->|"mounts"| node_api_app
node_api_app -->|"routes"| node_api_index
node_api_index -->|"mounts"| node_domains_routes
node_api_index -->|"mounts"| node_relations_routes
node_api_index -->|"mounts"| node_support_routes
node_domains_routes -->|"nests"| node_resource_subresources
node_domains_routes -->|"uses"| node_common_mw
node_relations_routes -->|"uses"| node_common_mw
node_support_routes -->|"uses"| node_common_mw
node_common_mw -->|"calls"| node_repositories
node_common_mw -->|"calls"| node_queries
node_repositories -->|"reads/writes"| node_mongo_service
node_queries -->|"reads"| node_mongo_service
node_queries -->|"searches"| node_elastic_service
node_common_mw -->|"handles"| node_storage_service
node_support_routes -->|"sends"| node_mailer_service
node_jobs -->|"processes"| node_mongo_service
node_jobs -->|"indexes"| node_elastic_service
node_jobs -->|"notifies"| node_mailer_service
node_jobs -->|"exports"| node_storage_service
node_scripts -->|"seeds"| node_mongo_service
node_openapi -->|"describes"| node_api_index
node_docs -->|"explains"| node_openapi
node_tests -->|"verifies"| node_repositories
node_tests -->|"verifies"| node_domains_routes
node_tests -->|"verifies"| node_common_mw

click node_index_js "https://github.com/dataesr/paysage-api/blob/main/index.js"
click node_api_app "https://github.com/dataesr/paysage-api/blob/main/src/api/app.js"
click node_api_index "https://github.com/dataesr/paysage-api/blob/main/src/api/index.js"
click node_domains_routes "https://github.com/dataesr/paysage-api/blob/main/src/api/structures/structures.routes.js"
click node_relations_routes "https://github.com/dataesr/paysage-api/blob/main/src/api/relations/relations.routes.js"
click node_support_routes "https://github.com/dataesr/paysage-api/blob/main/src/api/auth/auth.routes.js"
click node_resource_subresources "https://github.com/dataesr/paysage-api/blob/main/src/api/structures/identifiers/identifiers.routes.js"
click node_common_mw "https://github.com/dataesr/paysage-api/blob/main/src/api/commons/middlewares/authenticate.middlewares.js"
click node_repositories "https://github.com/dataesr/paysage-api/blob/main/src/api/commons/libs/base.mongo.repository.js"
click node_queries "https://github.com/dataesr/paysage-api/blob/main/src/api/commons/queries/structures.query.js"
click node_config "https://github.com/dataesr/paysage-api/blob/main/src/config.js"
click node_mongo_setup "https://github.com/dataesr/paysage-api/blob/main/src/setup/mongo.js"
click node_elastic_setup "https://github.com/dataesr/paysage-api/blob/main/src/setup/elastic.js"
click node_storage_setup "https://github.com/dataesr/paysage-api/blob/main/src/setup/storage.js"
click node_mongo_service "https://github.com/dataesr/paysage-api/blob/main/src/services/mongo.service.js"
click node_elastic_service "https://github.com/dataesr/paysage-api/blob/main/src/services/elastic.service.js"
click node_storage_service "https://github.com/dataesr/paysage-api/blob/main/src/services/storage.service.js"
click node_mailer_service "https://github.com/dataesr/paysage-api/blob/main/src/services/mailer.service.js"
click node_jobs "https://github.com/dataesr/paysage-api/blob/main/src/jobs/index.js"
click node_scripts "https://github.com/dataesr/paysage-api/blob/main/scripts/import-geographical-categories-countries.js"
click node_openapi "https://github.com/dataesr/paysage-api/blob/main/src/openapi/api.yml"
click node_docs "https://github.com/dataesr/paysage-api/blob/main/docs/docs/intro.md"
click node_tests "https://github.com/dataesr/paysage-api/blob/main/tests/globalSetup.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_api_app,node_api_index,node_domains_routes,node_relations_routes,node_support_routes,node_resource_subresources toneBlue
class node_index_js,node_common_mw,node_repositories,node_queries,node_config toneAmber
class node_mongo_setup,node_elastic_setup,node_storage_setup,node_mongo_service,node_elastic_service,node_storage_service,node_mailer_service toneMint
class node_jobs,node_scripts toneRose
class node_openapi,node_docs,node_tests toneIndigo
```

## Components

### HTTP API

Request handling and domain routes

- [App](https://github.com/dataesr/paysage-api/blob/main/src/api/app.js): express app · HTTP application bootstrap · `src/api/app.js`
- [API index](https://github.com/dataesr/paysage-api/blob/main/src/api/index.js): route assembly · Main API router composition · `src/api/index.js`
- [Domains](https://github.com/dataesr/paysage-api/blob/main/src/api/structures/structures.routes.js): domain routes · Resource routes for structures, persons, projects, terms, and related entities · `src/api/structures/structures.routes.js`
- [Relations](https://github.com/dataesr/paysage-api/blob/main/src/api/relations/relations.routes.js): domain routes · Relations, relation groups, and relation types · `src/api/relations/relations.routes.js`
- [Support APIs](https://github.com/dataesr/paysage-api/blob/main/src/api/auth/auth.routes.js): aux routes · Auth, users, api keys, search, documents, files, jobs, and utilities · `src/api/auth/auth.routes.js`
- [Subresources](https://github.com/dataesr/paysage-api/blob/main/src/api/structures/identifiers/identifiers.routes.js): nested resources · Identifiers, web links, social media, emails, names, localisations, logos, key numbers, and members · `src/api/structures/identifiers/identifiers.routes.js`

### Shared core

Bootstrap, middlewares, repositories, and queries

- [Entry](https://github.com/dataesr/paysage-api/blob/main/index.js): node entry · Process startup and top-level wiring · `index.js`
- [Middlewares](https://github.com/dataesr/paysage-api/blob/main/src/api/commons/middlewares/authenticate.middlewares.js): cross-cutting · Auth, RBAC, validation, files, events, CRUD, context, and errors · `src/api/commons/middlewares/authenticate.middlewares.js`
- [Repositories](https://github.com/dataesr/paysage-api/blob/main/src/api/commons/libs/base.mongo.repository.js): data access · Mongo repository abstractions and shared catalog/tokens · `src/api/commons/libs/base.mongo.repository.js`
- [Queries](https://github.com/dataesr/paysage-api/blob/main/src/api/commons/queries/structures.query.js): read models · Mongo and Elasticsearch query builders for domain views · `src/api/commons/queries/structures.query.js`
- [Config](https://github.com/dataesr/paysage-api/blob/main/src/config.js): env config · Runtime configuration and startup settings · `src/config.js`

### Data & integrations

Persistent stores and external services

- [Mongo setup](https://github.com/dataesr/paysage-api/blob/main/src/setup/mongo.js): bootstrap · MongoDB connection and initialization · `src/setup/mongo.js`
- [Search setup](https://github.com/dataesr/paysage-api/blob/main/src/setup/elastic.js): bootstrap · Elasticsearch connection and indexing setup · `src/setup/elastic.js`
- [Storage setup](https://github.com/dataesr/paysage-api/blob/main/src/setup/storage.js): bootstrap · File storage initialization · `src/setup/storage.js`
- [MongoDB](https://github.com/dataesr/paysage-api/blob/main/src/services/mongo.service.js): primary store · System of record for domain data · `src/services/mongo.service.js`
- [Elasticsearch](https://github.com/dataesr/paysage-api/blob/main/src/services/elastic.service.js): search store · Search and autocomplete index · `src/services/elastic.service.js`
- [Storage](https://github.com/dataesr/paysage-api/blob/main/src/services/storage.service.js): blob store · Files and media persistence · `src/services/storage.service.js`
- [Mailer](https://github.com/dataesr/paysage-api/blob/main/src/services/mailer.service.js): external service · Email delivery integration · `src/services/mailer.service.js`

### Async ops

Jobs and operational pipelines

- [Jobs](https://github.com/dataesr/paysage-api/blob/main/src/jobs/index.js): background pipelines · Indexing, imports, sync, treatments, notifications, and dumps · `src/jobs/index.js`
- [Scripts](https://github.com/dataesr/paysage-api/blob/main/scripts/import-geographical-categories-countries.js): ops scripts · Operational import and reset utilities · `scripts/import-geographical-categories-countries.js`

### Contracts & docs

OpenAPI, docs, and test coverage

- [OpenAPI](https://github.com/dataesr/paysage-api/blob/main/src/openapi/api.yml): api contract · Specification, paths, schemas, parameters, and responses · `src/openapi/api.yml`
- [Docs](https://github.com/dataesr/paysage-api/blob/main/docs/docs/intro.md): human docs · Repository documentation for API usage and resources · `docs/docs/intro.md`
- [Tests](https://github.com/dataesr/paysage-api/blob/main/tests/globalSetup.js): test suite · Domain and infrastructure tests plus test bootstrap · `tests/globalSetup.js`

## Connections

- Entry → Config: loads · Reads runtime configuration before bootstrapping
- Entry → Mongo setup: starts · Initializes MongoDB on startup
- Entry → Search setup: starts · Initializes search infrastructure
- Entry → Storage setup: starts · Initializes file storage
- Entry → App: mounts · Creates the HTTP application
- App → API index: routes · Attaches the main API router
- API index → Domains: mounts · Registers core business resource routes
- API index → Relations: mounts · Registers relation-related routes
- API index → Support APIs: mounts · Registers auth, search, documents, jobs, and admin routes
- Domains → Subresources: nests · Exposes child collections under each root entity
- Domains → Middlewares: uses · Applies shared request orchestration and validation
- Relations → Middlewares: uses · Applies shared request orchestration and validation
- Support APIs → Middlewares: uses · Applies shared request orchestration and validation
- Middlewares → Repositories: calls · Delegates CRUD operations to repository layer
- Middlewares → Queries: calls · Uses read models and projections
- Repositories → MongoDB: reads/writes · Persists domain documents in MongoDB
- Queries → MongoDB: reads · Builds Mongo-backed views and lookups
- Queries → Elasticsearch: searches · Uses Elasticsearch for autocomplete and indexed search
- Middlewares → Storage: handles · Manages upload and file access flows
- Support APIs → Mailer: sends · Triggers mail flows for auth and notifications
- Jobs → MongoDB: processes · Runs async operations against source data
- Jobs → Elasticsearch: indexes · Updates search indexes and autocomplete data
- Jobs → Mailer: notifies · Sends email and operational notifications
- Jobs → Storage: exports · Produces dumps and file-based outputs
- Scripts → MongoDB: seeds · Operational import/reset actions on data
- OpenAPI → API index: describes · Documents the HTTP API surface
- Docs → OpenAPI: explains · Human documentation complements the contract
- Tests → Repositories: verifies · Covers shared repository behavior
- Tests → Domains: verifies · Covers major domain routes and nested resources
- Tests → Middlewares: verifies · Covers shared infrastructure behavior
