feat: retire API publique + dedupe load-balancing MF + maj pages
Some checks are pending
Deploy info-canicule / deploy (push) Waiting to run

API publique retirée :
- /api/vigilance et /api/vigilance/dept/[code] supprimés
- Mentions retirées dans footer, /mentions-legales, /embed
- /api/health garde, sans CORS (usage interne UptimeRobot + cron HC.io)
- Tests E2E mis à jour (vérifient 404 sur les endpoints retirés)

Pages :
- /dependances : entièrement mise à jour (Sentry, sharp, Playwright,
  sitemap, typography ajoutés ; API MF officielle DPObs+DPVigilance,
  normales 1991-2020 listées ; section Services tiers ajoutée pour
  Opendatasoft en fallback ; section Infrastructure complétée avec
  GlitchTip + CrowdSec).
- /soutenir : "~7€/mois mutualisés" → "~30€/mois", suppression du
  détail VPS OVH (juste "infra"), suppression du bloc "Réutiliser
  les données via API".

Vigilance Météo France load-balancing :
- lib/vigilance.ts : fetch parallèle x3 et garde la réponse au
  update_time le plus récent. Constat 2026-05-26 : le gateway MF
  load-balance entre instances désynchronisées (~60% renvoyaient
  bulletin J-1, ~40% bulletin J). Cette mitigation atteint >95%
  de probabilité d'avoir le bulletin frais.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian 2026-05-26 02:16:04 +02:00
parent 0a1f11aa00
commit 27441cdbb8
10 changed files with 139 additions and 148 deletions

View file

@ -3,35 +3,26 @@ import { test, expect } from '@playwright/test';
test.describe('API', () => {
test('/api/health retourne status ok et cache true', async ({ request }) => {
const res = await request.get('/api/health');
expect(res.status()).toBeLessThan(600); // accepte 200 ou 503 selon Valkey
expect(res.status()).toBeLessThan(600);
const body = await res.json();
expect(body).toHaveProperty('status');
expect(body).toHaveProperty('cache');
expect(body).toHaveProperty('time');
});
test('/api/vigilance retourne snapshot JSON valide CORS *', async ({ request }) => {
test('/api/health pas de CORS (interne uniquement)', async ({ request }) => {
const res = await request.get('/api/health');
const cors = res.headers()['access-control-allow-origin'];
expect(cors).toBeUndefined();
});
test('/api/vigilance retourne 404 (API publique retirée)', async ({ request }) => {
const res = await request.get('/api/vigilance');
expect(res.status()).toBe(200);
expect(res.headers()['access-control-allow-origin']).toBe('*');
const body = await res.json();
expect(body).toHaveProperty('fetchedAt');
expect(body).toHaveProperty('alerts');
expect(Array.isArray(body.alerts)).toBe(true);
expect(res.status()).toBe(404);
});
test('/api/vigilance/dept/13 retourne enrichi avec labels', async ({ request }) => {
const res = await request.get('/api/vigilance/dept/13');
expect(res.status()).toBe(200);
const body = await res.json();
expect(body.departement.code).toBe('13');
expect(body.departement.name).toBe('Bouches-du-Rhône');
expect(body).toHaveProperty('today');
expect(body).toHaveProperty('tomorrow');
});
test('/api/vigilance/dept/999 retourne 404', async ({ request }) => {
const res = await request.get('/api/vigilance/dept/999');
test('/api/vigilance/dept/75 retourne 404 (API publique retirée)', async ({ request }) => {
const res = await request.get('/api/vigilance/dept/75');
expect(res.status()).toBe(404);
});
});