Skip to content
betagouvPublic

About

Mieux contrôler les dérogations d'espèces protégées

Resources

Stars

2 stars

Watchers

2 watching

Forks

Latest commit

 

History

713 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pitchou

Mieux contrôler les dérogations d'espèces protégées

Installer

Installer docker et docker-compose Peut-être via Docker Desktop, bonne chance !

Architecture

Front-end en Svelte Back-end en Node.js Base de données Postgres

Le serveur récupère les données des dossiers via l'API Démarche Numérique. Il en fait une sauvegarde régulière, parce que Démarches Simplfiées ne sauvegarde les données que temporairement (1 an pour le moment, nous allons demander 5 ans)

En dév

En dev, on peut lancer pnpm run dev pour lancer le tout.
Le repo est synchronisé dans le conteneur du serveur via un volume.
Les données de la base de données sont sauvegarder dans un volume dans le repo (pour faire des test facilement)

http://localhost:2648/ http://localhost:2648/saisie-especes

### Créer une migration

exécuter knex migrate:make <nom de la migration> modifier les fonction up() down() du fichier ./migrations/XXX-nom.js

documentation sur les migrations knex

Analyse statique

just check-lint lance Oxlint sur le JavaScript, le TypeScript et les blocs script des composants Svelte. Cette vérification fait partie de just check et de la CI. La configuration se trouve dans .oxlintrc.json. Les types générés et les fichiers DSFR copiés dans la documentation sont exclus.

just format applique Oxfmt et just check-format vérifie le formatage sans modifier les fichiers. La configuration se trouve dans .oxfmtrc.json, avec les exclusions des fichiers générés et des données locales. Le formatage Svelte est activé, avec une indentation de deux espaces pour les blocs script et style.

svelte-check vérifie les composants Svelte, y compris leurs templates. Oxlint utilise les règles de correction sans analyse des types pour le moment. Les règles supplémentaires imposent des objets Error, la conservation de leur cause, des comparaisons strictes sauf pour == null, et vérifient plusieurs usages des promesses.

Les fonctions sont limitées à 75 lignes, hors commentaires et lignes vides. Cette limite ne s'applique pas aux tests, à leurs helpers, aux migrations ni aux seeds.

Les règles Vitest ciblent les fichiers de test. Elles refusent notamment les tests .only ou .skip, les titres identiques et les assertions asynchrones sans attente. Les messages de diagnostic dans expect(valeur, message), le helper expectTracking et les assertions de nettoyage dans afterEach sont reconnus. Les règles sur les assertions conditionnelles et les types explicites de tous les mocks ne sont pas activées : nos tests paramétrés ont des attentes différentes selon le cas, et Vitest sait inférer les types des mocks.

Les commentaires de désactivation devenus inutiles font échouer le lint.

Types

Pour régénérer tous les types : just generate-types

Regénérer les types des tables SQL

exécuter just generate-types-db Les types sont crées dans le dossier ./scripts/types/database/public

Re-générer les types à partir du schéma DS

just generate-types-ds

Cette commande télécharge aussi la dernière version du schéma avant de créer les types.

Pour éviter le téléchargement et créer les types à partir du fichier schéma existant dans le repo : just generate-types-ds-local

Pour pgadmin

Pour se connecter au serveur postgres depuis un container : ce container doit être exposé au réseau et utiliser postgres_db (le container_name de la base de donnée Postgres) comme hostname

URL pour pgadmin en dev : http://localhost:5050/

Visualiser la documentation en local avec Jekyll

La documentation (dossier docs/) est déployée en production sur GitHub Pages, qui utilise Jekyll pour transformer les fichiers .md en site web statique.

Pour visualiser la documentation en local (avant de pousser sur GitHub), vous pouvez utiliser Docker pour lancer un serveur Jekyll identique à celui de GitHub Pages.

Construire l'image Docker Jekyll

cd docs
docker build -t mon-jekyll .
cd ..

Lancer le serveur Jekyll en local

Toujours depuis la racine du projet :

docker run --rm -p 4000:4000 -v "$PWD/docs":/srv/jekyll -e PAGES_REPO_NWO="dev" mon-jekyll

Le site sera accessible à l'adresse : http://localhost:4000/

Tests automatisés avec Playwright

  1. Installer le navigateur de test et les dépendances système: pnpm exec playwright install --with-deps firefox
  2. Lancer Pitchou en mode dev: pnpm run dev
  3. Lancer les tests pnpm exec playwright test tests/e2e

En prod

pnpm start:production

L'application est déployée sur Scalingo

Nous utilisons l'outil ligne de commande de Scalingo

Stockage objet (S3)

Les fichiers sont stockés dans un bucket S3 (Outscale OOS), variable S3_BUCKET. Les deux apps fonctionnent pareil : le navigateur demande une URL signée à l'app, envoie le fichier directement au bucket sous pending/, puis l'app le copie sous files/ (ou changelog/) quand la fiche qui le référence est enregistrée. La taille maximale par fichier est MAX_UPLOAD_SIZE (1 Go par défaut).

Le bucket de chaque environnement se prépare en passant les origines des deux sites dans la même commande. En local :

just aws-bucket-setup http://localhost:5173 http://localhost:5174

Sur Scalingo, avec l'app instructeur (exemple pour staging) :

scalingo --region osc-secnum-fr1 --app pitchou-staging run 'corepack pnpm --filter @pitchou/server exec node scripts/setup-bucket.ts https://staging.pitchou.incubateur.net https://staging.admin.pitchou.incubateur.net'

La commande agit sur le bucket $S3_BUCKET de l'environnement où elle tourne. Si l'app joint le stockage par une adresse que le navigateur ne peut pas atteindre, S3_PUBLIC_ENDPOINT_URL est l'adresse écrite dans les URL signées.

Authentification du webhook Brevo

Le webhook de suivi des mails CNPN accepte uniquement l'en-tête Authorization: Bearer <secret>. Le secret doit correspondre à la variable serveur BREVO_WEBHOOK_SECRET.

Brevo documente la configuration Bearer. Les champs correspondants lors de la création ou de la mise à jour du webhook sont :

{
  "url": "https://<hote-instructeur>/api/webhooks/brevo",
  "auth": {
    "type": "bearer",
    "token": "<valeur-de-BREVO_WEBHOOK_SECRET>"
  }
}

Conserver les événements transactionnels suivis : delivered, opened et uniqueOpened. Cette dernière valeur de configuration correspond à unique_opened dans les notifications reçues.

Les mails portent un tag pitchou-env-staging lorsque PUBLIC_PITCHOU_ENV=staging, pitchou-env-production sinon lorsque NODE_ENV=production, ou pitchou-env-development en local. Chaque webhook ignore les événements d'un autre environnement avec HTTP 204, sans accès à la base ni envoi d'accusé de lecture. Sans tag d'environnement, seuls les événements correspondant à un envoi enregistré localement sont traités ; les événements inconnus reçoivent HTTP 204 plutôt qu'une demande de nouvelle tentative. Brevo transmet toujours les notifications aux deux URL si elles utilisent le même compte.

Pour le test fonctionnel, utiliser un compte instructeur autre que le compte de démonstration, dont les envois CNPN sont bloqués sur staging. Envoyer vers une adresse de test, vérifier les destinataires en copie, puis contrôler les statuts de livraison et d'ouverture et l'accusé de lecture. Vérifier aussi que les outils de logs et de suivi d'erreurs masquent l'en-tête Authorization.

Base de données

On utilise une base de données Postgres 15.7 en prod

Backups

Scalingo fournit des backups https://doc.scalingo.com/databases/postgresql/backing-up

Actuellement, on a un backup quotidien des 7 derniers jours, un backup hebdomadaire des 4 dernières semaines et 10 backups manuels

Restorer un backup en local

Récupérer le dernier backup

cd backups

# Télécharger le dernier backup
scalingo --app especes-protegees --addon postgresql backups-download

# Dézipper le fichier .pgsql
tar -xf <nom_fichier>.tar.gz
# ignorer le message qui dit "tar: Suppression de « / » au début des noms des membres"

ll # afficher le nom du fichier .pgsql
cd -

Restore le dernier backup

# Supprimer la base de données existante
docker exec postgres_db dropdb -f --username=dev especes_pro_3731

# Recréer la base de données
docker exec postgres_db createdb --username=dev especes_pro_3731

# Restore des données
docker exec postgres_db pg_restore --no-owner --no-privileges --dbname=especes_pro_3731 --username=dev --jobs=6 /var/lib/pitchou/backups/<nom du fichier>.pgsql
Restorer un backup en prod

On peut faire un restore en un clic d'un backup dans l'onglet BACKUPS du dashboard de l'addon PostgreSQL

Sinon, on peut suivre la procédure de la documentation Scalingo

Outils

Migration base de données

knex migrate:latest (fait automatiquement à chaque déploiement, voir package.json scripts.prestart:prod-server)

Pour aller en arrière et en avant d'un cran dans la liste des migrations : pnpm run migrate:down pnpm run migrate:up

Fabriquer la liste des espèces protégées

pour les autocomplete de saisie espèces notamment

node outils/liste-espèces.js

### Ajouter une espèce manquante

Dans le fichier data/sources_especes/espèces_manquantes.ods ajouter l'espèce avec son identifiant INPN (CD_NOM), nom latin (LB_NOM), nom vernaculaire (NOM_VERN) et sa justification légale (LABEL_STATUT).

Puis lancer node outils/liste-espèces.js pour régénérer une liste d'espèces complétée.

### Ajouter une espèce ministérielle ou une espèce CNPN

Dans le fichier data/sources_especes/espèces_ministérielles_cnpn.ods ajouter l'espèce avec son nom scientifique et son nom vernaculaire dans la feuille correspondante. Attention, le nom scientifique doit être exactement le nom latin renseigné dans la colonne LB_NOM du fichier espèces_manquantes.ods.

Puis lancer node outils/liste-espèces.js pour régénérer une liste d'espèces à jour.

Synchroniser dossiers récemment modifiés de Démarche Numérique

En dev

just sync-ds (dernières heures par défaut)

just sync-ds 2025-06-01 (synchroniser les dossiers modifiés depuis le 1 juin 2025)

just sync-ds 2024-01-01 (synchroniser tous les dossiers, date très distantes)

En prod

Synchronisation régulière

Un crontab tourne régulièrement pour récupérer les dossiers récemment modifiés dans DS et les synchroniser en base de données

Pour modifier le cron : https://crontab.guru/

Synchronisation complète ponctuelle

Parfois, notamment après des changements dans le modèle de données, il est nécessaire de synchroniser tous les dossiers

Pour le faire, on peut utiliser un [one-off container}(https://doc.scalingo.com/platform/app/tasks) :

scalingo --region osc-secnum-fr1 --app pitchou run --size 2XL 'corepack pnpm --filter @pitchou/worker exec tsx sync-demarche-numerique.ts --IdSchemaDS derogation-especes-protegees --lastModified 2024-01-01'

Lister les liens de connexion en local

Utile pour tester rapidement en local après un restore de backup en tant qu'une personne en particulier

node outils/afficher-liens-de-connexion.js --emails adresse1@e.mail,adresse2@e.mail

Pour les lien de connexion en production :

node outils/afficher-liens-de-connexion.js --emails adresse1@e.mail,adresse2@e.mail --prod

Pour donner l'origine de manière libre :

node outils/afficher-liens-de-connexion.js --emails adresse1@e.mail,adresse2@e.mail --origin 'http://example.net'

GeoMCE

Pitchou maintient une API pour que GeoMCE puisse récupérer les données que Pitchou doit déclarer (GeoMCE ne peut pas ouvrir d'API pour des raisons techniques de leur côté)

Pitchou expose une capability url de la forme /declaration-geomce?secret=XXX

Un outil permet de récupérer la capability url pour la transmettre aux personnes de GeoMCE : scalingo --app especes-protegees run "node outils/geomce.js --capability-url"

En cas de compromission ou régulièrement, la capability-url peut être reset: scalingo --app especes-protegees run "node outils/geomce.js --reset-capability-url"

Outils AARRI

Nettoyage des données d'évènements

Les données de tracking nécessaires à AARRI sont stockées exclusivement dans la table evenement_metrique

Pour des raisons de minimisation des données, de protection des personnes et de conformité au RGPD, nous supprimons les données datant de plus d’un an.

Nous avons un outil qui permet de faire ça. En production : scalingo --app especes-protegees run "node outils/aarri/delete-evenements.js"

En dev : node outils/aarri/delete-evenements.js

Pour nettoyer tous les évènements concernant une personne spécifique :

node outils/aarri/delete-evenements.js --email david@example.net

Pour nettoyer tous les évènements plus vieux que x semaines

node outils/aarri/delete-evenements.js --conserver-dernières-semaines 20

About

Mieux contrôler les dérogations d'espèces protégées

Resources

Stars

2 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages