Commit graph

6 commits

Author SHA1 Message Date
60074fb015 feat(qualité): outillage de test complet, CI locale, annulation réelle des runs
Some checks are pending
CI / javascript (push) Waiting to run
CI / python (push) Waiting to run
CI / mutation (push) Waiting to run
Le dépôt n'avait aucun test, aucun linter, aucune vérification de types.

Outillage
- ESLint 9 (flat config) sur api + les deux frontends, Ruff sur le Python
- tsc --checkJs sur l'API (pas de TypeScript, juste la vérification)
- Vitest : 401 tests JS ; pytest : 43 tests Python
- Tests de mutation (Stryker), deux profils : logique pure et API complète
- Hook pre-push `npm run check` (~17 s) — le déploiement Coolify est sur webhook,
  c'est donc la seule porte de qualité avant la mise en ligne
- Workflow Forgejo Actions prêt (inerte tant qu'aucun runner n'est enregistré)

Sécurité
- Injection SQL authentifiée dans resolve-conflict : `field` était interpolé
  dans le SET sans allowlist
- timingSafeEqual levait sur un jeton multi-octets (500 au lieu de 401)
- setErrorHandler écrasait tous les 4xx en 500
- .env.example : ADMIN_JWT_SECRET et ADMIN_SEED_* n'étaient documentés nulle part
  alors que leur absence casse toute connexion admin

Annulation réelle des crawl_run (migration 014)
- L'API posait status='error' sans que le crawler en sache rien : le process
  continuait, et son UPDATE final ne matchait plus (run réussi affiché en erreur)
- Protocole coopératif : drapeau cancel_requested lu à chaque lot, le crawler
  écrit lui-même status='cancelled'

Cohérence géographique (migration 014)
- Le trigger 013 supprimait les band_locations sans purger le point dénormalisé
- L'édition admin de lat/lon n'atteignait jamais band_locations : la carte
  ignorait la correction. Override step_order = -1, dans une transaction

Corrections
- limit/offset NaN → 500 au lieu de 400
- OPTIONS sans `return reply` (Fastify poursuivait le cycle de vie)
- listen() sans catch, cast ::text en dur sur les colonnes numériques
- /admin/api/logs ne renvoyait pas sa pagination
- a11y : sélecteur de langue annoncé comme liste vide (role=option manquant)

Nettoyage
- apps/web/quizz-site supprimé (sans rapport avec le projet)
- Code mort : openModal(), LANG_NAMES, double import, variables inutilisées
- .dockerignore ajoutés ; node_modules racine n'était pas gitignoré

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-18 10:05:40 +02:00
39e6b2a66f feat(map): carte multi-localisations — un point par step géocodé
La carte clusterisait depuis bands.geom (un seul point par groupe). Désormais
/api/clusters source band_locations : un groupe multi-périodes (ex. Thessaloniki
puis Boston) apparaît comme plusieurs points distincts.

- migration 010: colonne geom générée (Point,4326) + index GIST sur
  band_locations (évite le seq-scan sur les requêtes bbox)
- /api/clusters: FROM band_locations bl JOIN bands b, bbox via geom && envelope,
  filtres (pays/statut/genre/année) sur b.*, points issus de bl.lat/lon ;
  la JSON des clusters porte location_raw + step_label
- web parseBandData: expose location_raw + step_label (base pour différencier
  plus tard un groupe qui a déménagé d'un groupe resté sur place)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 19:52:40 +02:00
a7d7bc94de feat(admin): dashboard admin complet (auth forte, API, monitoring)
Nouveau service apps/admin (admin.metalfrom.eu / admin.dev.metalfrom.eu) :
- Frontend statique vanilla JS/CSS reprenant le design system du site
  (login, dashboard stats, table bands éditable, queue d'enrichissement,
  historique crawl_run, logs live, checkpoints, journal d'audit)
- nginx reverse-proxy /admin/api/* et /admin/auth/* vers le service api
  interne (same-origin côté navigateur, pas de CORS cross-site nécessaire
  pour le cookie de session)

apps/api :
- Nouvelle auth dédiée au dashboard, séparée du token BM_IMPORT_TOKEN
  existant : login bcrypt + session JWT en cookie httpOnly/secure/
  sameSite=strict, rate-limit + lockout après 5 échecs/15min, seeding
  du compte admin via env vars (jamais de mot de passe en clair en DB
  ou en git)
- Routes /admin/api/* : stats, queue (breakdown priorité identique au
  crawler Python), bands (recherche/tri/pagination/édition + audit log),
  crawl-runs, crawl-checkpoints, logs, audit-log
- trustProxy activé (Traefik + nginx en amont)

apps/crawler :
- log_event() écrit dans la nouvelle table crawl_log (run start/finish/
  erreurs) pour que le dashboard affiche les logs sans exposer le socket
  Docker (choix délibéré : pas de docker.sock monté, accès DB only)

migration 006_admin_dashboard.sql : admin_users, admin_login_attempts,
admin_audit_log, crawl_log

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 22:15:13 +02:00
06a5bf2ef8 fix: geocoder/worker network + CORS configurable par env
- Ajoute geocoder-worker et worker sur le réseau coolify pour
  résoudre le hostname DB (lgrep99...) qui n'est accessible que
  depuis le réseau coolify
- CORS_ORIGINS env var optionnel pour configurer les origines
  autorisées (utilisé par l'env dev)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 12:37:09 +02:00
d241d168e3 feat: integrer override api en production (supprimer mecanisme override) 2026-06-27 11:35:06 +02:00
d4e1bf2e15 chore: initial commit — snapshot VPS 2026-06-27
- apps/api      : API REST Node.js/Fastify + PostgreSQL/PostGIS
- apps/geocoder : Worker Python géocodage Nominatim
- apps/worker   : Scraper Python Metal-Archives
- apps/web      : Frontend statique Leaflet/clustering/heatmap
- infra/        : docker-compose + init.sql

Déployé via Coolify + Traefik sur VPS OVH.
2026-06-27 08:53:39 +00:00