Skip to content

Repository files navigation

Dépôt Numérique

Application de dépôt automatisé de documents métier.

Le dépôt contient aujourd'hui le socle technique, l'authentification SSO SAML, le modèle de données, une première interface Angular et un worker BullMQ de démonstration. Le dépôt, l'analyse et l'automatisation Playwright décrits par la cible fonctionnelle ne sont pas encore implémentés. Cette distinction évite de confondre l'architecture prévue avec les fonctionnalités déjà disponibles.

Le projet est initialisé en monorepo avec pnpm et Turbo. Il contient actuellement :

  • apps/api : API NestJS ;
  • apps/web : frontend Angular ;
  • apps/worker : workers BullMQ ;
  • packages/database : schéma, migrations, seed et client Prisma partagés ;
  • docs : documentation VitePress ;
  • sso : simulateur SSO local avec Keycloak SAML et OpenLDAP ;
  • turbo.json : configuration des tâches monorepo ;
  • pnpm-workspace.yaml : déclaration des workspaces pnpm.

Prérequis

  • Node.js, via nvm.
  • pnpm 11.8.0.
  • Docker et Docker Compose, pour les services techniques locaux.
  • OpenSSL, pour générer les clés du Service Provider SAML.
  • mkcert et, sous Linux, libnss3-tools, pour faire confiance au certificat HTTPS local de la stack conteneurisée.

La version Node attendue est indiquée dans .nvmrc.

nvm use

Si la version n'est pas installée :

nvm install

Installation

Depuis la racine du dépôt :

pnpm install

Si pnpm demande d'approuver des scripts de build :

pnpm approve-builds

Puis relancer :

pnpm install

Installer les hooks Git locaux avec Lefthook :

pnpm exec lefthook install

La commande pnpm install exécute aussi le script prepare, qui installe Lefthook automatiquement. La commande ci-dessus reste utile si les hooks ne sont pas présents après un clone ou un changement d'environnement.

Créer les fichiers d'environnement locaux :

cp .env.example .env
cp apps/api/.env.example apps/api/.env
cp packages/database/.env.example packages/database/.env
cp apps/worker/.env.example apps/worker/.env

Le fichier racine configure Docker Compose : PostgreSQL, Redis, MinIO, le simulateur SSO local, Traefik, les noms d'hôtes et le secret Better Auth du conteneur API. Le fichier de l'API définit son port, ses connexions, Better Auth et SAML lors d'une exécution directe avec pnpm. Celui de Prisma fournit DATABASE_URL, et celui du worker définit WORKER_PORT et NODE_ENV. Ces fichiers ne doivent pas être commités.

Lancer le projet

Le développement local utilise deux terminaux afin de séparer les services Docker des applications.

Dans un premier terminal, démarrer les services techniques et attendre leur disponibilité :

pnpm infra:dev

À la première installation, appliquer les migrations et créer le bucket brut attendu par la readiness de l'API :

pnpm database:migrate:deploy
docker compose exec minio sh -c 'mc alias set app http://localhost:9000 "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null && mc mb --ignore-existing app/documents-raw'

Si MINIO_RAW_BUCKET a été modifié, remplacer documents-raw par la même valeur. Le seed Prisma est optionnel et ne doit pas être mélangé sans précaution avec un test SSO, car son arborescence de développement est différente du LDIF complet.

Dans un second terminal, lancer toutes les tâches de développement déclarées dans les workspaces :

pnpm dev

pnpm infra:dev lance PostgreSQL, Redis, MinIO, OpenLDAP, phpLDAPadmin et Keycloak avec Docker Compose. pnpm dev lance l'API, le frontend, le worker et la documentation avec Turbo.

Ce mode est adapté au développement isolé des workspaces. Le realm Keycloak fourni avec le dépôt enregistre les URLs SAML HTTPS de la stack conteneurisée ; le parcours SSO navigateur complet doit donc être testé avec pnpm stack:dev comme expliqué dans docs/getting-started/development.md.

Pour lancer l'API NestJS, le frontend Angular et le worker BullMQ sans démarrer l'infrastructure Docker ni la documentation :

pnpm apps:dev

Services exposés en développement :

  • API NestJS : http://localhost:3000
  • Swagger : http://localhost:3000/api/docs
  • Santé de l'API : http://localhost:3000/api/health/live et http://localhost:3000/api/health/ready
  • Frontend Angular : http://localhost:4200

En développement, le navigateur utilise l'origine publique du frontend (http://localhost:4200). Le proxy Angular transmet /api/** à l'API sur le port 3000, ce qui permet aux cookies de session de rester sur une même origine du point de vue du navigateur.

Stack HTTPS complète

Pour tester l'application, Better Auth et le simulateur SSO de bout en bout :

mkcert -install
pnpm tls:certificates:generate
pnpm sso:certificates:generate
pnpm stack:dev

pnpm stack:dev construit les images API et web, applique les migrations puis démarre toute la stack derrière Traefik. L'application est disponible sur https://depot-numerique.localhost et Keycloak sur https://idp.depot-numerique.localhost. Le fichier .env racine doit contenir un BETTER_AUTH_SECRET d'au moins 32 caractères.

Le profil app applique les migrations automatiquement, mais il ne crée pas le bucket MinIO. Si la readiness renvoie 503 avec MinIO en échec, créer documents-raw avec la commande ci-dessus.

SSO local

Le projet utilise en développement un simulateur SSO SAML local. OpenLDAP contient l'annuaire de test avec les utilisateurs, leurs rôles et leur rattachement métier (bureauIGC). Keycloak est configuré comme fournisseur d'identité SAML et expose ces attributs à l'application.

Les rôles applicatifs simulés sont :

  • DEPOT_NUMERIQUE:ADMINISTRATEUR_NATIONAL
  • DEPOT_NUMERIQUE:ADMINISTRATEUR_REGIONAL
  • DEPOT_NUMERIQUE:ADMINISTRATEUR_LOCAL
  • DEPOT_NUMERIQUE:AGENT

Ces quatre rôles sont mutuellement exclusifs pour l'application : une personne doit en posséder exactement un. L'attribut roles peut néanmoins contenir des profils d'autres applications.

L'arborescence LDAP locale simule notamment la DSJ, les cours d'appel, les tribunaux judiciaires, les CPH au niveau des cours d'appel et les tribunaux de proximité sous leur tribunal judiciaire. Les comptes de test et les attributs SAML exposés sont documentés dans docs/authentication/local-sso.md, avec le détail du simulateur dans sso/README.md.

Les attributs suivent la chaîne OpenLDAP -> Keycloak -> SAML -> Better Auth -> User :

  • igcid rapproche durablement l'identité SSO du profil métier ;
  • nom, prenom et mail synchronisent les informations affichées ;
  • roles fournit exactement un rôle Dépôt Numérique ;
  • bureauIGC fournit le chemin technique de rattachement ;
  • siteDescription fournit le libellé lisible de la structure finale ;
  • logonId sert à la connexion Keycloak locale mais n'est pas la clé de rapprochement métier ;
  • affectationOp2 à affectationOp4 sont prévus par les mappers et transmis lorsqu'ils existent, mais le jeu de comptes actuel ne les renseigne pas et l'application ne les exploite pas encore.

Pour les utilisateurs autres que l'administrateur national, bureauIGC et siteDescription sont obligatoires. Le premier permet de déterminer les codes des structures ; le second évite d'afficher un identifiant technique à la place du nom de la juridiction.

Lancer un service applicatif

API NestJS :

pnpm api:dev

Frontend Angular :

pnpm web:dev

Documentation VitePress :

pnpm docs:dev

Worker BullMQ :

pnpm worker:dev

Commandes utiles

Les commandes suivent une nomenclature simple :

  • pnpm <tâche> lance la tâche sur tous les workspaces concernés via Turbo.
  • pnpm <workspace>:<tâche> lance la même tâche sur un workspace précis.
  • Les workspaces disponibles sont api, web, worker, docs et database.
  • Les commandes dev sont des serveurs persistants et ne sont pas mises en cache par Turbo.

Exemples :

pnpm build
pnpm api:build
pnpm web:build
pnpm docs:build
pnpm database:build
pnpm worker:build

Lister les packages du workspace :

pnpm -r list --depth -1

Compiler tous les packages qui exposent une tâche build :

pnpm build

Compiler un workspace précis :

pnpm api:build
pnpm web:build
pnpm docs:build

Lancer les tests :

pnpm test

Lancer les tests d'un workspace précis :

pnpm api:test
pnpm api:test:e2e
pnpm web:test
pnpm worker:test

pnpm api:test:e2e vérifie les contrats HTTP avec des dépendances techniques simulées et ne nécessite pas Docker. Le test du worker couvre le processor de la queue de démonstration sans nécessiter Redis. Il n'y a pas de commande docs:test, car la documentation n'expose pas de script de test.

Lancer le lint Biome :

pnpm lint

Lancer le lint sur un workspace précis :

pnpm api:lint
pnpm web:lint
pnpm docs:lint
pnpm database:lint
pnpm worker:lint

Formater le code avec Biome :

pnpm format

Formater un workspace précis :

pnpm api:format
pnpm web:format
pnpm docs:format
pnpm database:format
pnpm worker:format

Vérifier le formatage sans modifier les fichiers :

pnpm format:check

Vérifier le formatage d'un workspace précis :

pnpm api:format:check
pnpm web:format:check
pnpm docs:format:check
pnpm database:format:check
pnpm worker:format:check

Vérifier le formatage, le lint et les règles Biome :

pnpm check

Vérifier un workspace précis :

pnpm api:check
pnpm web:check
pnpm docs:check
pnpm database:check
pnpm worker:check

Vérifier les types TypeScript :

pnpm typecheck

Vérifier les types d'un workspace précis :

pnpm api:typecheck
pnpm web:typecheck
pnpm database:typecheck
pnpm worker:typecheck

Il n'y a pas de commande docs:typecheck, car VitePress est vérifié via pnpm docs:build.

Corriger automatiquement ce qui peut l'être :

pnpm check:fix

Corriger automatiquement un workspace précis :

pnpm api:check:fix
pnpm web:check:fix
pnpm docs:check:fix
pnpm database:check:fix
pnpm worker:check:fix

Détecter les dépendances inutilisées et le code mort :

pnpm knip

Lancer tous les contrôles qualité avant une PR ou un push important :

pnpm verify

Cette commande enchaîne pnpm check, pnpm knip, pnpm typecheck et pnpm test.

Base de données

Le workspace @depot-numerique/database centralise Prisma pour l'API et les futurs workers. PostgreSQL stocke les métadonnées métier et les références MinIO ; les fichiers binaires restent dans MinIO.

Commandes principales :

pnpm database:build
pnpm database:lint
pnpm database:format
pnpm database:format:check
pnpm database:check
pnpm database:check:fix
pnpm database:typecheck
pnpm database:generate
pnpm database:validate
pnpm database:migrate:create --name description
pnpm database:migrate:dev --name description
pnpm database:migrate:deploy
pnpm database:migrate:status
pnpm database:seed
pnpm database:studio

Le script pnpm database:studio force Prisma Studio sur http://localhost:5555.

Le workspace database n'a pas encore de commande de test dédiée.

Les migrations créées en développement sont versionnées dans packages/database/prisma/migrations. En recette et en production, la CI/CD applique ces mêmes migrations avec pnpm database:migrate:deploy sur la base de l'environnement concerné. pnpm database:migrate:create --name description génère et permet de relire le SQL sans l'appliquer.

Le modèle Prisma représente les utilisateurs SSO et les structures judiciaires hiérarchisées : la cour d'appel, ses juridictions et leurs éventuelles sous-juridictions. Les services sont rattachés à une structure et sont créés localement par les administrateurs autorisés. Un utilisateur distingue sa structure de travail (workStructureId) de son éventuel périmètre d'administration (adminStructureId) ; son service est rattaché à sa structure de travail. Chaque document référence obligatoirement son utilisateur créateur. Les comptes sont désactivés plutôt que supprimés afin de conserver cet historique. Le périmètre d'administration est déduit du rôle et du niveau de la structure administrée : un administrateur régional voit la cour d'appel et ses descendants, tandis qu'un administrateur local placé sur une cour d'appel ne gère que les services de cette cour.

Les tables AuthIdentity, AuthSession, AuthAccount et AuthVerification sont réservées à Better Auth. AuthIdentity porte l'identité technique d'authentification et est reliée en un-à-un au profil métier User. La reconnexion SSO doit retrouver le profil avec l'identifiant annuaire stable User.igcId, jamais avec l'adresse électronique, qui peut changer. Cet identifiant n'est pas hashé ; il doit en revanche être traité comme une donnée interne et ne jamais être journalisé inutilement.

Le seed crée la cour d'appel de Douai, les tribunaux judiciaires de Lille, Arras et Douai, ainsi que le tribunal de proximité de Tourcoing rattaché à Lille. La cour d'appel et les trois tribunaux judiciaires reçoivent les services baj, bog, jaf et jap, identifiés par leur slug et accompagnés d'un libellé complet. Les structures utilisent des codes SSO uniques sur huit chiffres, par exemple 00000001 pour la cour et 00000002 pour le tribunal de Lille. Ce jeu de données est destiné au développement et aux tests.

La documentation détaillée se trouve dans docs/data/database.md.

Qualité de code

Le projet utilise une configuration centralisée à la racine du monorepo.

  • Biome : formatage et lint.
  • Knip : détection des dépendances inutilisées, exports inutilisés et fichiers morts.
  • Lefthook : hooks Git locaux.
  • Commitlint : validation des messages de commit au format Conventional Commits.

Avant de commit, Lefthook lance Biome sur les fichiers staged et réajoute automatiquement les fichiers corrigés.

Au commit, Lefthook lance aussi Commitlint sur le message de commit.

Avant un push, Lefthook lance en parallèle pnpm check, pnpm knip, pnpm typecheck et pnpm test.

Tester le dernier commit :

pnpm commitlint

Commandes principales :

pnpm format
pnpm format:check
pnpm lint
pnpm check
pnpm check:fix
pnpm verify
pnpm typecheck
pnpm knip
pnpm prepare

Docker

Docker Compose lance les services techniques utilisés en développement local. Le profil app ajoute les conteneurs applicatifs et l'exposition HTTPS.

Services disponibles :

  • PostgreSQL : base de données métier ;
  • Redis : cache et backend BullMQ ;
  • MinIO : stockage des documents ;
  • OpenLDAP : annuaire local simulant les utilisateurs et rattachements SRJ ;
  • phpLDAPadmin : interface graphique locale pour inspecter l'annuaire LDAP ;
  • Keycloak : fournisseur d'identité SAML local branché sur OpenLDAP ;
  • migrate : conteneur ponctuel qui applique les migrations Prisma avant l'API ;
  • API : image Node.js dédiée, disponible avec le profil app ;
  • frontend : image Nginx non privilégiée dédiée, disponible avec le profil app ;
  • Traefik : terminaison TLS et routage par nom d'hôte et chemin avec le profil app.

Le worker n'a pas encore de Dockerfile ni de service Compose. Il s'exécute actuellement avec pnpm. Nginx sert uniquement les fichiers statiques Angular et le fallback de la SPA ; Traefik reste le reverse proxy public qui choisit entre le frontend, l'API et Keycloak.

Les versions d'images sont volontairement fixées dans docker-compose.yml. Ne pas utiliser latest pour les services d'infrastructure.

Versions locales actuelles :

  • Traefik : traefik:v3.7.1
  • PostgreSQL : postgres:17.10-bookworm
  • Redis : redis:7.4.9-bookworm
  • MinIO : minio/minio:RELEASE.2025-09-07T16-13-09Z
  • OpenLDAP : osixia/openldap:1.5.0
  • phpLDAPadmin : osixia/phpldapadmin:0.9.0
  • Keycloak : quay.io/keycloak/keycloak:26.6.4
  • build API et web : node:24-bookworm-slim
  • runtime web : nginxinc/nginx-unprivileged:1.29-alpine

Dependabot surveille les mises à jour Docker Compose, GitHub Actions et npm/pnpm via .github/dependabot.yml.

Créer un fichier .env local à partir de l'exemple si nécessaire :

cp .env.example .env

Le fichier .env ne doit pas être commit. Il est ignoré par Git.

Lancer tous les services techniques :

pnpm infra:dev

Lancer uniquement PostgreSQL :

docker compose up -d postgres

Lancer uniquement Redis :

docker compose up -d redis

Lancer uniquement MinIO :

docker compose up -d minio

Lancer uniquement Keycloak et attendre sa disponibilité :

docker compose up -d --wait keycloak

Lancer uniquement l'annuaire LDAP et son interface graphique :

docker compose up -d --wait openldap phpldapadmin

Keycloak importe le realm depot-numerique depuis sso/keycloak/realm.json et lit les utilisateurs dans OpenLDAP. Les données LDAP locales sont initialisées depuis sso/openldap/schema et sso/openldap/ldif. Après une modification du realm, forcer la recréation du conteneur :

docker compose up -d --force-recreate --wait keycloak

Après une modification du schéma ou du LDIF OpenLDAP, il faut recréer les volumes OpenLDAP locaux pour réimporter l'annuaire. Keycloak utilise start-dev et une base H2 située dans son conteneur, sans volume nommé : ses données disparaissent lorsque le conteneur est supprimé et le realm est alors réimporté. Traefik chiffre le flux navigateur local, mais les échanges internes Docker avec Keycloak restent en HTTP. Les mots de passe sont publics et réservés à la démonstration. Consulter la documentation SSO SAML local pour les comptes, rôles, attributs SAML et procédures de test.

Vérifier leur état :

docker compose ps

Afficher les logs :

docker compose logs -f

Arrêter les services :

docker compose down

Supprimer aussi les volumes locaux :

docker compose down -v

Attention : docker compose down -v supprime les volumes PostgreSQL, Redis, MinIO et OpenLDAP. docker compose down supprime également le conteneur Keycloak et donc sa base H2 éphémère. Au prochain démarrage, OpenLDAP rejoue le schéma et le LDIF, tandis que Keycloak réimporte sso/keycloak/realm.json.

Accès locaux par défaut :

  • PostgreSQL : localhost:5432
  • Redis : localhost:6379
  • MinIO API : http://localhost:9000
  • MinIO Console : http://localhost:9001
  • Keycloak direct, infrastructure seule : http://localhost:8080
  • Keycloak via Traefik, profil app : https://idp.depot-numerique.localhost
  • OpenLDAP : ldap://localhost:389
  • phpLDAPadmin : http://localhost:8081

Les identifiants locaux sont définis dans .env.

Documentation

La documentation technique est dans docs/ et utilise VitePress.

Commandes disponibles :

pnpm docs:dev
pnpm docs:build
pnpm docs:preview

Le package documentation est déclaré comme workspace @depot-numerique/docs dans docs/package.json.

La configuration VitePress utilise base: '/depot-numerique/' pour une publication GitHub Pages sur ce dépôt.

Points d'entrée principaux :

Structure actuelle

apps/
  api/       # API NestJS et image applicative
  web/       # Frontend Angular, Nginx et image applicative
  worker/    # Worker NestJS/BullMQ de démonstration
docs/        # Documentation VitePress
infra/
  traefik/   # Configuration statique et dynamique du reverse proxy
packages/
  database/ # Schéma, migrations, seed et client Prisma
sso/         # Realm Keycloak, schéma et données OpenLDAP

Stack actuelle et cible

  • Monorepo : Turbo
  • Gestionnaire de paquets : pnpm
  • Backend : NestJS
  • Frontend : Angular
  • Documentation projet : VitePress
  • Base de données : PostgreSQL
  • ORM : Prisma
  • Queue et cache : BullMQ, Redis
  • Stockage fichiers : MinIO
  • SSO local : Keycloak, OpenLDAP, phpLDAPadmin
  • Automatisation web cible : Playwright — non intégrée à ce stade
  • Documentation API : Swagger / OpenAPI
  • Conteneurisation : Docker, Docker Compose
  • Qualité de code : Biome, Knip, Lefthook, Commitlint
  • CI/CD : GitHub Actions
  • Secrets cible : Vault — non intégré à ce stade
  • Supervision cible : Prometheus, Grafana — non intégrés à ce stade

About

Plateforme d'automatisation documentaire assurant la validation, la normalisation, la traçabilité et le dépôt automatisé de courriers sur la plateforme IMPRIM'FIP.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages