SPB Git forge

spb/api-ka

Public

API-KA — plateforme centrale : collecte quotidienne des 8 services KA, historisation append-only et API publique sur www.api-ka.com

48commits 1branches 0releases
5.9 MBsize
maindefault branch
19 days agolast push
Python 60.9% HTML 21% TypeScript 7.3% JavaScript 5.2% CSS 4.8% Shell 0.8%
13.0 KB · 276 lines markdown
Rendered Raw Blame History
1# CLAUDE.md — Projet API-KA23## Vision du projet45**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).67**Tout le déploiement se fait sur le node `m3u96b`.** Aucun service de production ne tourne ailleurs.89## Auteur — OBLIGATOIRE dans chaque fichier1011Chaque 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.1213**Python / Shell / SQL / YAML :**14```15# ============================================16# Projet   : API-KA17# Fichier  : <nom_du_fichier>18# Node     : m3u96b19# Author   : Simon-Pierre Boucher20# Contact  : contact@spboucher.ai21# Date     : <date de création>22# ============================================23```2425**JavaScript / TypeScript :**26```javascript27/**28 * ============================================29 * Projet   : API-KA30 * Fichier  : <nom_du_fichier>31 * Node     : m3u96b32 * Author   : Simon-Pierre Boucher33 * Contact  : contact@spboucher.ai34 * Date     : <date de création>35 * ============================================36 */37```3839## Node de déploiement : m3u96b4041- **Node cible unique** : `m3u96b`. Tous les services (API, scheduler, base de données, tunnel ngrok) tournent sur ce node.42- Répertoire de déploiement : `/opt/api-ka/` sur m3u96b.43- Données et backups : `/opt/api-ka/data/` et `/opt/api-ka/data/backups/`.44- Logs centralisés : `/opt/api-ka/logs/`.45- Les services sont gérés par **systemd** sur m3u96b (voir section "Services systemd").46- Toute commande de déploiement, cron ou service doit référencer explicitement m3u96b dans sa documentation et ses logs (`hostname` vérifié au démarrage : si le hostname n'est pas `m3u96b`, le service refuse de démarrer en mode production et log un avertissement).4748### Vérification du node au démarrage (obligatoire dans chaque service)4950```python51import socket, os5253REQUIRED_NODE = "m3u96b"5455def verify_node():56    hostname = socket.gethostname()57    if os.getenv("APP_ENV") == "production" and hostname != REQUIRED_NODE:58        raise RuntimeError(f"API-KA doit tourner sur {REQUIRED_NODE}, node actuel : {hostname}")59```6061## Sources de données (les 8 services KA)6263| Service   | Table            | Variable source      | Fréquence   |64|-----------|------------------|----------------------|-------------|65| lou-ka    | `louka_data`     | `LOUKA_SOURCE_URL`   | Quotidienne |66| immo-ka   | `immoka_data`    | `IMMOKA_SOURCE_URL`  | Quotidienne |67| food-ka   | `foodka_data`    | `FOODKA_SOURCE_URL`  | Quotidienne |68| auto-ka   | `autoka_data`    | `AUTOKA_SOURCE_URL`  | Quotidienne |69| fabri-ka  | `fabrika_data`   | `FABRIKA_SOURCE_URL` | Quotidienne |70| resto-ka  | `restoka_data`   | `RESTOKA_SOURCE_URL` | Quotidienne |71| sorti-ka  | `sortika_data`   | `SORTIKA_SOURCE_URL` | Quotidienne |72| crea-ka   | `creaka_data`    | `CREAKA_SOURCE_URL`  | Quotidienne |7374**RÈGLE CRITIQUE : les données de chaque service DOIVENT être sauvegardées tous les jours, sans exception.**75- Chaque exécution quotidienne est journalisée.76- Tout échec de collecte est détecté, loggé et relancé automatiquement (3 tentatives, backoff exponentiel : 30s → 2min → 10min).77- Si un service échoue après 3 tentatives, une entrée `status=failed` est écrite dans `collection_runs` et une alerte est ajoutée à `logs/alerts.log`. Le lendemain, le job tente automatiquement un rattrapage (backfill) des dates manquées.7879## Architecture8081```82/opt/api-ka/                      # sur le node m3u96b83├── CLAUDE.md84├── README.md85├── .env                          # jamais commité86├── .env.example87├── requirements.txt88├── src/89│   ├── config.py                 # chargement .env + vérification node m3u96b90│   ├── collectors/91│   │   ├── base_collector.py     # classe abstraite : fetch, validate, save, retry92│   │   ├── louka_collector.py93│   │   ├── immoka_collector.py94│   │   ├── foodka_collector.py95│   │   ├── autoka_collector.py96│   │   ├── fabrika_collector.py97│   │   ├── restoka_collector.py98│   │   ├── sortika_collector.py99│   │   └── creaka_collector.py100│   ├── database/101│   │   ├── models.py             # SQLAlchemy : 8 tables données + collection_runs102│   │   ├── db.py                 # engine, session, init, healthcheck103│   │   └── migrations/           # Alembic104│   ├── api/105│   │   ├── main.py               # FastAPI, monté derrière ngrok106│   │   ├── routes/107│   │   │   ├── services.py       # /api/v1/{service}...108│   │   │   ├── runs.py           # /api/v1/runs109│   │   │   └── health.py         # /health (inclut node, dernière collecte, db)110│   │   └── middleware/111│   │       ├── logging.py        # log de chaque requête112│   │       └── ratelimit.py      # protection basique de l'API publique113│   ├── scheduler/114│   │   ├── daily_job.py          # orchestre les 8 collecteurs115│   │   └── backfill.py           # rattrapage des dates manquées116│   └── utils/117│       ├── logger.py             # logs JSON structurés, rotation quotidienne118│       ├── retry.py              # décorateur retry avec backoff119│       └── backup.py             # dump quotidien horodaté120├── scripts/121│   ├── deploy_m3u96b.sh          # déploiement complet sur le node122│   ├── run_daily_backup.sh123│   ├── start_ngrok.sh            # tunnel www.api-ka.com avec auto-restart124│   └── healthcheck.sh            # utilisé par systemd / monitoring125├── systemd/126│   ├── apika-api.service127│   ├── apika-scheduler.service128│   └── apika-ngrok.service129├── data/130│   └── backups/YYYY-MM-DD/       # dumps quotidiens par service131├── logs/132└── tests/133```134135## Base de données136137- **Moteur** : PostgreSQL 16 sur m3u96b (SQLite acceptable uniquement en dev local).138- Base : `apika`, utilisateur dédié `apika_user`, accès restreint à localhost sur m3u96b.139140### Schéma des tables de données (identique pour les 8 services)141142| Colonne        | Type        | Détail                                  |143|----------------|-------------|------------------------------------------|144| `id`           | BIGSERIAL   | Clé primaire                             |145| `payload`      | JSONB       | Données brutes du service                |146| `source`       | TEXT        | Nom du service (ex. `louka`)             |147| `collected_at` | TIMESTAMPTZ | Horodatage exact de la collecte          |148| `date_key`     | DATE        | Date logique de la collecte (index)      |149| `checksum`     | TEXT        | SHA-256 du payload (déduplication)       |150151Index : `(date_key)`, `(source, date_key)`, unique sur `(source, date_key, checksum)`.152153### Table `collection_runs`154155`id`, `service`, `date_key`, `status` (`success` / `failed` / `retried`), `records_count`, `duration_seconds`, `error_message`, `node` (toujours `m3u96b`), `started_at`, `finished_at`.156157### Règles158- **Append-only** : aucune suppression destructive, l'historique complet est conservé.159- **Backup quotidien** : `pg_dump` horodaté par service dans `data/backups/YYYY-MM-DD/`, compressé (`.sql.gz`), conservé 90 jours minimum.160- Vérification d'intégrité hebdomadaire : comparaison du nombre de `date_key` distincts vs jours écoulés — toute journée manquante déclenche un backfill.161162## Collecte quotidienne (scheduler)163164- Job planifié **tous les jours à 02:00 (heure du node m3u96b)** via `apika-scheduler.service` (APScheduler) — cron système en fallback.165- 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.166- Pipeline par collecteur : `fetch → validate → checksum → insert → backup → log run`.167- À la fin du run global : résumé dans `collection_runs` + `logs/daily_YYYY-MM-DD.log` + mise à jour de `/health`.168- `backfill.py` s'exécute juste après le job quotidien et rattrape automatiquement toute date manquée des 7 derniers jours.169170## API publique (www.api-ka.com via ngrok)171172- Framework : **FastAPI** (docs auto sur `/docs`, OpenAPI sur `/openapi.json`).173- Serveur : `uvicorn` sur `127.0.0.1:8000` (jamais exposé directement — seul ngrok est public).174- 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 le `NGROK_AUTHTOKEN` configuré sur m3u96b.175- `apika-ngrok.service` redémarre le tunnel automatiquement en cas de coupure (`Restart=always`).176177### Endpoints178179| Méthode | Route                                   | Description                                        |180|---------|-----------------------------------------|----------------------------------------------------|181| GET     | `/`                                     | Statut de la plateforme + version                   |182| GET     | `/health`                               | Node (m3u96b), état DB, dernière collecte par service |183| GET     | `/api/v1/{service}`                     | Données paginées d'un service                       |184| GET     | `/api/v1/{service}/latest`              | Dernière collecte du service                        |185| GET     | `/api/v1/{service}/date/{YYYY-MM-DD}`   | Données d'une date précise                          |186| GET     | `/api/v1/{service}/stats`               | Nb d'enregistrements par jour, dernière réussite    |187| GET     | `/api/v1/runs`                          | Historique des collectes (filtrable par service/statut) |188189- `{service}` ∈ `louka`, `immoka`, `foodka`, `autoka`, `fabrika`, `restoka`, `sortika`, `creaka` — toute autre valeur → 404.190- Versionnement `/api/v1/`, pagination `?page=&limit=` (limit max 500).191- Format de réponse uniforme :192```json193{ "success": true, "data": [...], "meta": { "page": 1, "limit": 100, "total": 4200, "node": "m3u96b" } }194```195- Rate limiting basique (ex. 120 req/min/IP) car l'API est publique via ngrok.196197## Services systemd (sur m3u96b)198199| Service                  | Rôle                              | Restart  |200|--------------------------|-----------------------------------|----------|201| `apika-api.service`      | uvicorn FastAPI :8000             | always   |202| `apika-scheduler.service`| Job quotidien 02:00 + backfill    | always   |203| `apika-ngrok.service`    | Tunnel www.api-ka.com             | always   |204205Commandes : `sudo systemctl enable --now apika-api apika-scheduler apika-ngrok`, statut via `systemctl status apika-*`.206207## Configuration (.env sur m3u96b)208209```210APP_ENV=production211NODE_NAME=m3u96b212DATABASE_URL=postgresql://apika_user:***@localhost:5432/apika213NGROK_AUTHTOKEN=...214NGROK_DOMAIN=www.api-ka.com215API_PORT=8000216DAILY_RUN_HOUR=02217BACKUP_RETENTION_DAYS=90218LOUKA_SOURCE_URL=...219IMMOKA_SOURCE_URL=...220FOODKA_SOURCE_URL=...221AUTOKA_SOURCE_URL=...222FABRIKA_SOURCE_URL=...223RESTOKA_SOURCE_URL=...224SORTIKA_SOURCE_URL=...225CREAKA_SOURCE_URL=...226```227228Ne jamais commiter `.env` — seulement `.env.example` avec des valeurs vides.229230## Standards de code231232- Python 3.11+, type hints partout, `black` + `ruff`, docstrings sur toute fonction publique.233- Logging structuré JSON via `utils/logger.py` avec rotation quotidienne — jamais de `print()` en production.234- Tests `pytest` dans `tests/` : chaque collecteur, chaque route API, la logique de retry et de backfill.235- Gestion d'erreurs explicite : jamais de `except: pass`.236- Commits descriptifs ; branche `main` = état déployé sur m3u96b.237- **Rappel : en-tête d'auteur (Simon-Pierre Boucher / contact@spboucher.ai / Node m3u96b) dans CHAQUE fichier.**238239## Commandes utiles240241```bash242# Déploiement complet sur m3u96b243bash scripts/deploy_m3u96b.sh244245# Initialiser la base246python -m src.database.db --init247248# Collecte manuelle immédiate (tous les services)249python -m src.scheduler.daily_job --now250251# Backfill d'une date manquée252python -m src.scheduler.backfill --date 2026-08-15253254# API en local (dev)255uvicorn src.api.main:app --reload --port 8000256257# Tunnel public258bash scripts/start_ngrok.sh259260# Vérifier la santé261curl http://127.0.0.1:8000/health262```263264## Priorités absolues (dans l'ordre)2652661. **Fiabilité de la sauvegarde quotidienne** — aucune journée sans données pour aucun des 8 services.2672. Intégrité de la base (append-only, checksums, backups horodatés, rétention 90 jours).2683. Tout tourne sur le node **m3u96b** — vérification du hostname au démarrage.2694. Disponibilité de l'API publique sur www.api-ka.com (auto-restart ngrok + uvicorn).2705. En-tête d'auteur présent dans chaque fichier.2716. Logs, alertes et traçabilité de chaque collecte et chaque requête.272273---274275*Plateforme légendaire API-KA — Node m3u96b — créée par Simon-Pierre Boucher (contact@spboucher.ai)*276