CLAUDE.md — Projet API-KA
Vision du projet
API-KA est la plateforme centrale légendaire de l'écosystème KA. Elle collecte, sauvegarde et centralise chaque jour les données de tous les services KA (lou-ka, immo-ka, food-ka, auto-ka, fabri-ka, resto-ka, sorti-ka, crea-ka) dans une base de données unifiée, puis les expose via une API publique accessible sur www.api-ka.com (tunnel ngrok).
Tout le déploiement se fait sur le node m3u96b. Aucun service de production ne tourne ailleurs.
Auteur — OBLIGATOIRE dans chaque fichier
Chaque fichier de code (Python, JS, SQL, shell, config, etc.) DOIT commencer par un en-tête d'auteur. Règle non négociable — aucun fichier sans en-tête.
Python / Shell / SQL / YAML :
# ============================================
# Projet : API-KA
# Fichier : <nom_du_fichier>
# Node : m3u96b
# Author : Simon-Pierre Boucher
# Contact : contact@spboucher.ai
# Date : <date de création>
# ============================================JavaScript / TypeScript :
/**
* ============================================
* Projet : API-KA
* Fichier : <nom_du_fichier>
* Node : m3u96b
* Author : Simon-Pierre Boucher
* Contact : contact@spboucher.ai
* Date : <date de création>
* ============================================
*/Node de déploiement : m3u96b
- Node cible unique :
m3u96b. Tous les services (API, scheduler, base de données, tunnel ngrok) tournent sur ce node. - Répertoire de déploiement :
/opt/api-ka/sur m3u96b. - Données et backups :
/opt/api-ka/data/et/opt/api-ka/data/backups/. - Logs centralisés :
/opt/api-ka/logs/. - Les services sont gérés par systemd sur m3u96b (voir section "Services systemd").
- Toute commande de déploiement, cron ou service doit référencer explicitement m3u96b dans sa documentation et ses logs (
hostnamevérifié au démarrage : si le hostname n'est pasm3u96b, le service refuse de démarrer en mode production et log un avertissement).
Vérification du node au démarrage (obligatoire dans chaque service)
import socket, os
REQUIRED_NODE = "m3u96b"
def verify_node():
hostname = socket.gethostname()
if os.getenv("APP_ENV") == "production" and hostname != REQUIRED_NODE:
raise RuntimeError(f"API-KA doit tourner sur {REQUIRED_NODE}, node actuel : {hostname}")Sources de données (les 8 services KA)
| Service | Table | Variable source | Fréquence |
|---|---|---|---|
| lou-ka | louka_data |
LOUKA_SOURCE_URL |
Quotidienne |
| immo-ka | immoka_data |
IMMOKA_SOURCE_URL |
Quotidienne |
| food-ka | foodka_data |
FOODKA_SOURCE_URL |
Quotidienne |
| auto-ka | autoka_data |
AUTOKA_SOURCE_URL |
Quotidienne |
| fabri-ka | fabrika_data |
FABRIKA_SOURCE_URL |
Quotidienne |
| resto-ka | restoka_data |
RESTOKA_SOURCE_URL |
Quotidienne |
| sorti-ka | sortika_data |
SORTIKA_SOURCE_URL |
Quotidienne |
| crea-ka | creaka_data |
CREAKA_SOURCE_URL |
Quotidienne |
RÈGLE CRITIQUE : les données de chaque service DOIVENT être sauvegardées tous les jours, sans exception.
- Chaque exécution quotidienne est journalisée.
- Tout échec de collecte est détecté, loggé et relancé automatiquement (3 tentatives, backoff exponentiel : 30s → 2min → 10min).
- Si un service échoue après 3 tentatives, une entrée
status=failedest écrite danscollection_runset une alerte est ajoutée àlogs/alerts.log. Le lendemain, le job tente automatiquement un rattrapage (backfill) des dates manquées.
Architecture
/opt/api-ka/ # sur le node m3u96b
├── CLAUDE.md
├── README.md
├── .env # jamais commité
├── .env.example
├── requirements.txt
├── src/
│ ├── config.py # chargement .env + vérification node m3u96b
│ ├── collectors/
│ │ ├── base_collector.py # classe abstraite : fetch, validate, save, retry
│ │ ├── louka_collector.py
│ │ ├── immoka_collector.py
│ │ ├── foodka_collector.py
│ │ ├── autoka_collector.py
│ │ ├── fabrika_collector.py
│ │ ├── restoka_collector.py
│ │ ├── sortika_collector.py
│ │ └── creaka_collector.py
│ ├── database/
│ │ ├── models.py # SQLAlchemy : 8 tables données + collection_runs
│ │ ├── db.py # engine, session, init, healthcheck
│ │ └── migrations/ # Alembic
│ ├── api/
│ │ ├── main.py # FastAPI, monté derrière ngrok
│ │ ├── routes/
│ │ │ ├── services.py # /api/v1/{service}...
│ │ │ ├── runs.py # /api/v1/runs
│ │ │ └── health.py # /health (inclut node, dernière collecte, db)
│ │ └── middleware/
│ │ ├── logging.py # log de chaque requête
│ │ └── ratelimit.py # protection basique de l'API publique
│ ├── scheduler/
│ │ ├── daily_job.py # orchestre les 8 collecteurs
│ │ └── backfill.py # rattrapage des dates manquées
│ └── utils/
│ ├── logger.py # logs JSON structurés, rotation quotidienne
│ ├── retry.py # décorateur retry avec backoff
│ └── backup.py # dump quotidien horodaté
├── scripts/
│ ├── deploy_m3u96b.sh # déploiement complet sur le node
│ ├── run_daily_backup.sh
│ ├── start_ngrok.sh # tunnel www.api-ka.com avec auto-restart
│ └── healthcheck.sh # utilisé par systemd / monitoring
├── systemd/
│ ├── apika-api.service
│ ├── apika-scheduler.service
│ └── apika-ngrok.service
├── data/
│ └── backups/YYYY-MM-DD/ # dumps quotidiens par service
├── logs/
└── tests/Base de données
- Moteur : PostgreSQL 16 sur m3u96b (SQLite acceptable uniquement en dev local).
- Base :
apika, utilisateur dédiéapika_user, accès restreint à localhost sur m3u96b.
Schéma des tables de données (identique pour les 8 services)
| Colonne | Type | Détail |
|---|---|---|
id |
BIGSERIAL | Clé primaire |
payload |
JSONB | Données brutes du service |
source |
TEXT | Nom du service (ex. louka) |
collected_at |
TIMESTAMPTZ | Horodatage exact de la collecte |
date_key |
DATE | Date logique de la collecte (index) |
checksum |
TEXT | SHA-256 du payload (déduplication) |
Index : (date_key), (source, date_key), unique sur (source, date_key, checksum).
Table collection_runs
id, service, date_key, status (success / failed / retried), records_count, duration_seconds, error_message, node (toujours m3u96b), started_at, finished_at.
Règles
- Append-only : aucune suppression destructive, l'historique complet est conservé.
- Backup quotidien :
pg_dumphorodaté par service dansdata/backups/YYYY-MM-DD/, compressé (.sql.gz), conservé 90 jours minimum. - Vérification d'intégrité hebdomadaire : comparaison du nombre de
date_keydistincts vs jours écoulés — toute journée manquante déclenche un backfill.
Collecte quotidienne (scheduler)
- Job planifié tous les jours à 02:00 (heure du node m3u96b) via
apika-scheduler.service(APScheduler) — cron système en fallback. - Les 8 collecteurs s'exécutent en parallèle mais de façon indépendante : l'échec d'un service ne bloque jamais les autres.
- Pipeline par collecteur :
fetch → validate → checksum → insert → backup → log run. - À la fin du run global : résumé dans
collection_runs+logs/daily_YYYY-MM-DD.log+ mise à jour de/health. backfill.pys'exécute juste après le job quotidien et rattrape automatiquement toute date manquée des 7 derniers jours.
API publique (www.api-ka.com via ngrok)
- Framework : FastAPI (docs auto sur
/docs, OpenAPI sur/openapi.json). - Serveur :
uvicornsur127.0.0.1:8000(jamais exposé directement — seul ngrok est public). - Tunnel :
ngrok http --domain=www.api-ka.com 8000— le domaine doit être réservé dans le dashboard ngrok (compte payant requis pour un domaine personnalisé) et leNGROK_AUTHTOKENconfiguré sur m3u96b. apika-ngrok.serviceredémarre le tunnel automatiquement en cas de coupure (Restart=always).
Endpoints
| Méthode | Route | Description |
|---|---|---|
| GET | / |
Statut de la plateforme + version |
| GET | /health |
Node (m3u96b), état DB, dernière collecte par service |
| GET | /api/v1/{service} |
Données paginées d'un service |
| GET | /api/v1/{service}/latest |
Dernière collecte du service |
| GET | /api/v1/{service}/date/{YYYY-MM-DD} |
Données d'une date précise |
| GET | /api/v1/{service}/stats |
Nb d'enregistrements par jour, dernière réussite |
| GET | /api/v1/runs |
Historique des collectes (filtrable par service/statut) |
{service}∈louka,immoka,foodka,autoka,fabrika,restoka,sortika,creaka— toute autre valeur → 404.- Versionnement
/api/v1/, pagination?page=&limit=(limit max 500). - Format de réponse uniforme :
{ "success": true, "data": [...], "meta": { "page": 1, "limit": 100, "total": 4200, "node": "m3u96b" } }- Rate limiting basique (ex. 120 req/min/IP) car l'API est publique via ngrok.
Services systemd (sur m3u96b)
| Service | Rôle | Restart |
|---|---|---|
apika-api.service |
uvicorn FastAPI :8000 | always |
apika-scheduler.service |
Job quotidien 02:00 + backfill | always |
apika-ngrok.service |
Tunnel www.api-ka.com | always |
Commandes : sudo systemctl enable --now apika-api apika-scheduler apika-ngrok, statut via systemctl status apika-*.
Configuration (.env sur m3u96b)
APP_ENV=production
NODE_NAME=m3u96b
DATABASE_URL=postgresql://apika_user:***@localhost:5432/apika
NGROK_AUTHTOKEN=...
NGROK_DOMAIN=www.api-ka.com
API_PORT=8000
DAILY_RUN_HOUR=02
BACKUP_RETENTION_DAYS=90
LOUKA_SOURCE_URL=...
IMMOKA_SOURCE_URL=...
FOODKA_SOURCE_URL=...
AUTOKA_SOURCE_URL=...
FABRIKA_SOURCE_URL=...
RESTOKA_SOURCE_URL=...
SORTIKA_SOURCE_URL=...
CREAKA_SOURCE_URL=...Ne jamais commiter .env — seulement .env.example avec des valeurs vides.
Standards de code
- Python 3.11+, type hints partout,
black+ruff, docstrings sur toute fonction publique. - Logging structuré JSON via
utils/logger.pyavec rotation quotidienne — jamais deprint()en production. - Tests
pytestdanstests/: chaque collecteur, chaque route API, la logique de retry et de backfill. - Gestion d'erreurs explicite : jamais de
except: pass. - Commits descriptifs ; branche
main= état déployé sur m3u96b. - Rappel : en-tête d'auteur (Simon-Pierre Boucher / contact@spboucher.ai / Node m3u96b) dans CHAQUE fichier.
Commandes utiles
# Déploiement complet sur m3u96b
bash scripts/deploy_m3u96b.sh
# Initialiser la base
python -m src.database.db --init
# Collecte manuelle immédiate (tous les services)
python -m src.scheduler.daily_job --now
# Backfill d'une date manquée
python -m src.scheduler.backfill --date 2026-08-15
# API en local (dev)
uvicorn src.api.main:app --reload --port 8000
# Tunnel public
bash scripts/start_ngrok.sh
# Vérifier la santé
curl http://127.0.0.1:8000/healthPriorités absolues (dans l'ordre)
- Fiabilité de la sauvegarde quotidienne — aucune journée sans données pour aucun des 8 services.
- Intégrité de la base (append-only, checksums, backups horodatés, rétention 90 jours).
- Tout tourne sur le node m3u96b — vérification du hostname au démarrage.
- Disponibilité de l'API publique sur www.api-ka.com (auto-restart ngrok + uvicorn).
- En-tête d'auteur présent dans chaque fichier.
- Logs, alertes et traçabilité de chaque collecte et chaque requête.
Plateforme légendaire API-KA — Node m3u96b — créée par Simon-Pierre Boucher (contact@spboucher.ai)