docs: refonte du README (pastilles + captures d écran à jour)
3 changed files +86 −98
modified
README.md
+86 −98
@@ -1,132 +1,120 @@ | |||||
| 1 | −# API-Ka — L'API de données du Groupe Ka | 1 | +<!-- Auteur : Simon-Pierre Boucher — contact@spboucher.ai --> | ||
| 2 | 2 | ||||
| 3 | −**API-Ka** collecte, sauvegarde et centralise **chaque jour** les données des **8 plateformes** de l'écosystème **Groupe Ka** dans une base **PostgreSQL** unifiée, puis les expose via une API publique sur **www.api-ka.com** — avec en prime le **KA Agent** (assistant IA de l'écosystème) et le **hub SSO KA ID**. | 3 | +# API·Ka | ||
| 4 | 4 | ||||
| 5 | − | 5 | +**L'API centrale du Groupe KA : collecte quotidienne des données des plateformes de l'écosystème, base PostgreSQL unifiée, API publique et KA Agent (IA).** | ||
| 6 | 6 | ||||
| 7 | −## Description | 7 | +[](https://www.api-ka.com) | ||
| 8 | + | ||||
| 9 | + | ||||
| 10 | + | ||||
| 8 | 11 | ||||
| 9 | −**API-Ka** est la **plateforme centrale** de l'écosystème **Groupe Ka** : | 12 | + | ||
| 13 | + | ||||
| 14 | + | ||||
| 15 | + | ||||
| 16 | + | ||||
| 10 | 17 | ||||
| 11 | −- **8 collecteurs** quotidiens (**lou-ka, immo-ka, food-ka, auto-ka, fabri-ka, resto-ka, sorti-ka, crea-ka**) : fetch → validation → **checksum** → insertion → **backup** → journal de run, avec **retry 3×** (backoff **30 s → 2 min → 10 min**). | 18 | +**API·Ka** ([www.api-ka.com](https://www.api-ka.com)) est la **plateforme de données centrale de l'écosystème Groupe KA**. Chaque jour, **8 collecteurs** (lou-ka, immo-ka, food-ka, auto-ka, fabri-ka, resto-ka, sorti-ka, crea-ka) sauvegardent les données des plateformes dans une base **PostgreSQL** unifiée (fetch → validation → checksum → insertion → backup → journal de run, retry 3× avec backoff 30 s → 2 min → 10 min), puis les exposent via une **API FastAPI publique** : données paginées, historiques par date, statistiques, rapports PDF. | ||
| 12 | −- Un **scheduler** (**APScheduler**) qui lance le job quotidien à **02:00**, collecteurs **en parallèle** et indépendants, plus un **backfill automatique** des dates manquées (**7 derniers jours**). | ||||
| 13 | −- Une **API FastAPI** publique (données paginées, historiques, stats, rapports **PDF**). | ||||
| 14 | −- Le **KA Agent** — assistant IA central du Groupe Ka (**Claude Haiku 4.5**) en **SSE**, avec une boucle de **12 outils** branchés sur les API publiques des plateformes (logements, propriétés, véhicules, emplois, épicerie, produits, restos, sorties, créateurs, web QC, stats live, état des services) et **CORS** ouvert aux **13 domaines** de l'écosystème. | ||||
| 15 | −- Le **hub SSO KA ID** (login **ka_id** partagé) + l'échange de jetons pour l'**app iOS native KA**. | ||||
| 16 | −- Des **backups quotidiens** horodatés par service (`data/backups/YYYY-MM-DD/`, rétention **90 jours**). | ||||
| 17 | 19 | ||||
| 18 | −## Endpoints | 20 | +Elle héberge aussi le **KA Agent** — l'assistant IA central du groupe (Claude Haiku, SSE, boucle d'outils branchés sur les API publiques des plateformes) servi en widget (`/ka-agent.js`) aux 13 domaines de l'écosystème — et sert de **superviseur des connecteurs** (historique des collectes `/api/v1/runs`, santé par service, alertes). L'accès à l'API produit exige une authentification : session **KA ID** ou **jeton personnel** (`kapi_`, généré sur groupe-ka.com/compte). | ||
| 19 | 21 | ||||
| 20 | −### Données des plateformes | 22 | +## Captures d'écran | ||
| 21 | 23 | ||||
| 22 | −- `GET /` — **statut** de la plateforme + version | 24 | +<p align="center"> | ||
| 23 | −- `GET /health` — nœud (**m3u96b**), état **DB**, dernière collecte par service | 25 | + <img src="docs/screenshots/api-ka-desktop.png" width="640" alt="Accueil — desktop"> | ||
| 24 | −- `GET /api/v1/{service}` — données **paginées** (`?page=&limit=`, limit max **500**) | 26 | + <img src="docs/screenshots/api-ka-mobile.png" width="200" alt="Accueil — mobile"> | ||
| 25 | −- `GET /api/v1/{service}/latest` — **dernière collecte** | 27 | +</p> | ||
| 26 | −- `GET /api/v1/{service}/date/{YYYY-MM-DD}` — données d'une **date précise** | ||||
| 27 | −- `GET /api/v1/{service}/stats` — enregistrements par jour, dernière réussite | ||||
| 28 | −- `GET /api/v1/runs` — **historique des collectes** (filtrable par service/statut) | ||||
| 29 | 28 | ||||
| 30 | −`{service}` ∈ **`louka`**, **`immoka`**, **`foodka`**, **`autoka`**, **`fabrika`**, **`restoka`**, **`sortika`**, **`creaka`**. | 29 | +## Fonctionnalités | ||
| 31 | 30 | ||||
| 32 | −### Stats & rapports | 31 | +- **8 collecteurs quotidiens** — un par plateforme Ka, avec validation, checksum, retry 3× (backoff exponentiel) et journal de run ; tout échec après 3 tentatives est loggé (`collection_runs`, `logs/alerts.log`). | ||
| 32 | +- **Scheduler APScheduler** — job quotidien à 02:00 (collecteurs en parallèle et indépendants) + **backfill automatique** des dates manquées (7 derniers jours). | ||||
| 33 | +- **API publique de données** — `GET /api/v1/{service}` (pagination, limit max 500), `/latest`, `/date/{YYYY-MM-DD}`, `/stats`, `/api/v1/runs` (historique des collectes), pour `{service}` ∈ louka, immoka, foodka, autoka, fabrika, restoka, sortika, creaka. | ||||
| 34 | +- **Authentification obligatoire sur l'API produit** — session KA ID ou jeton Bearer `kapi_` ; monitoring, stats et agent restent ouverts. | ||||
| 35 | +- **KA Agent (IA)** — `POST /api/agent/chat` en SSE (Claude Haiku, boucle d'outils sur les données live des plateformes : logements, propriétés, véhicules, emplois, épicerie, produits, restos, sorties, créateurs, stats, état des services) + widget embarquable `GET /ka-agent.js`, CORS ouvert aux 13 domaines. | ||||
| 36 | +- **SSO KA ID** — `GET /api/auth/ka/{login,callback}`, session `/api/auth/me`, et échange de jeton pour l'app iOS native (`POST /api/ios/auth/exchange`, vérification HS256 `aud=ka-ios`). | ||||
| 37 | +- **Stats & rapports** — tableau de bord `/stats`, `GET /api/stats/report` (PDF de la plateforme) et `GET /api/stats/ecosystem-report` (rapport PDF consolidé de l'écosystème, liste dynamique via `ecosystem.json`) + rapports PDF personnalisés (catalogue + constructeur). | ||||
| 38 | +- **Backups quotidiens** horodatés par service (`data/backups/YYYY-MM-DD/`, rétention 90 jours). | ||||
| 39 | +- **Santé & supervision** — `GET /health` (nœud, état DB, dernière collecte par service) ; chaque service vérifie le hostname au démarrage et refuse de tourner en production ailleurs que sur `m3u96b`. | ||||
| 40 | +- **SEO du site de doc** — robots.txt, sitemap.xml, canonical/hreflang/JSON-LD. | ||||
| 33 | 41 | ||||
| 34 | −- `GET /stats` — **tableau de bord analytique** de la plateforme (page web) | 42 | +## Architecture | ||
| 35 | −- `GET /api/stats/dashboard` — stats live de la plateforme | ||||
| 36 | −- `GET /api/stats/report` — rapport **PDF** de la plateforme | ||||
| 37 | −- `GET /api/stats/ecosystem-report` — **rapport PDF consolidé** des **12 plateformes** du Groupe Ka (nombre de plateformes **dynamique** via `ecosystem.json`) | ||||
| 38 | 43 | ||||
| 39 | −### KA Agent (IA) | 44 | +- **FastAPI + Uvicorn** (`src/api/`) : routes health, services, runs, stats, agent, auth, iosauth + pages web et PDF (fpdf2). | ||
| 45 | +- **PostgreSQL** via **SQLAlchemy 2** (+ **Alembic** pour les migrations, `psycopg2`) : une table de données par service + journal `collection_runs`. | ||||
| 46 | +- **Collecteurs** (`src/collectors/`) : classe abstraite `base_collector` (fetch, validate, save, retry) + 8 collecteurs concrets, httpx. | ||||
| 47 | +- **Scheduler** (`src/scheduler/`) : `daily_job.py` (02:00) + `backfill.py`. | ||||
| 48 | +- **Utils** (`src/utils/`) : backups quotidiens, rétention 90 jours ; `src/monitoring/` pour la supervision. | ||||
| 49 | +- **anthropic** SDK pour le KA Agent. | ||||
| 40 | 50 | ||||
| 41 | −- `POST /api/agent/chat` — chat en **SSE** avec le **KA Agent** (boucle d'outils, prompt par site, cache système) | 51 | +Processus PM2 sur le nœud : | ||
| 42 | −- `GET /ka-agent.js` — **widget de chat** embarquable sur les sites du Groupe Ka | ||||
| 43 | 52 | ||||
| 44 | −### Auth (KA ID / iOS) | 53 | +| Processus | Rôle | | ||
| 54 | +|---|---| | ||||
| 55 | +| `apika-api` | l'API FastAPI/Uvicorn sur le port **8000** (liée à 127.0.0.1) | | ||||
| 56 | +| `apika-scheduler` | le job quotidien 02:00 + backfill | | ||||
| 57 | +| `apika-ngrok` | tunnel ngrok vers **www.api-ka.com** | | ||||
| 45 | 58 | ||||
| 46 | −- `GET /api/auth/ka/login` + `GET /api/auth/ka/callback` — **SSO KA ID** (hub groupe-ka.com) | 59 | +## Structure du repo | ||
| 47 | −- `GET /api/auth/me`, `POST /api/auth/logout` — session | ||||
| 48 | −- `POST /api/ios/auth/exchange` — échange du **ka_token** (vérification **HS256**, `aud=ka-ios`) contre un **profil hub signé** pour l'**app iOS KA** | ||||
| 49 | − | ||||
| 50 | −Assets de partage servis à la racine : **`og.png`**, **`favicon.svg`**, **`apple-touch-icon.png`**, page **`/contact`**. | ||||
| 51 | − | ||||
| 52 | −## Stack | ||||
| 53 | − | ||||
| 54 | −- **Python 3** — **FastAPI** + **Uvicorn** | ||||
| 55 | −- **PostgreSQL** — **SQLAlchemy 2** + **Alembic** (migrations), `psycopg2` | ||||
| 56 | −- **APScheduler** — job quotidien + backfill | ||||
| 57 | −- **httpx** — collecteurs et outils de l'agent | ||||
| 58 | −- **fpdf2** — rapports PDF | ||||
| 59 | −- **PM2** + **ngrok** — exécution résiliente et exposition publique | ||||
| 60 | −- **pytest** — tests (`tests/`) | ||||
| 61 | − | ||||
| 62 | −## Structure | ||||
| 63 | 60 | ||||
| 64 | ``` | 61 | ``` | ||
| 65 | /opt/api-ka | 62 | /opt/api-ka | ||
| 66 | −├── src/ | 63 | +├── src/ # api/ (routes, web, PDF), collectors/ (8), scheduler/, database/, monitoring/, utils/, config.py | ||
| 67 | −│ ├── api/ # FastAPI : main, routes/ (health, services, runs, stats, agent, auth, iosauth), web/, PDF | 64 | +├── scripts/ # deploy_m3u96b.sh, start_ngrok.sh… | ||
| 68 | −│ ├── collectors/ # 8 collecteurs quotidiens (un par plateforme Ka) | 65 | +├── systemd/ # unités historiques (le déploiement actuel utilise PM2) | ||
| 69 | −│ ├── scheduler/ # daily_job.py (02:00) + backfill.py | 66 | +├── tests/ # pytest | ||
| 70 | −│ ├── database/ # modèles + init DB | 67 | +├── data/ # backups/YYYY-MM-DD/ (rétention 90 jours) | ||
| 71 | −│ ├── utils/ # backup.py (dumps quotidiens, rétention 90 j) | 68 | +├── logs/ # logs centralisés + alerts.log | ||
| 72 | −│ └── config.py | 69 | +├── docs/ # captures d'écran | ||
| 73 | −├── scripts/ # deploy_m3u96b.sh, start_ngrok.sh… | 70 | +└── alembic.ini · pyproject.toml · requirements.txt · CLAUDE.md | ||
| 74 | −├── systemd/ # unités historiques (le déploiement actuel utilise PM2) | ||||
| 75 | −├── tests/ # pytest | ||||
| 76 | −├── data/ # backups/YYYY-MM-DD/ | ||||
| 77 | −├── logs/ | ||||
| 78 | −├── alembic.ini · pyproject.toml · requirements.txt | ||||
| 79 | −└── docs/screenshot.png | ||||
| 80 | ``` | 71 | ``` | ||
| 81 | 72 | ||||
| 82 | −## Démarrage local | 73 | +## Développement (remote-first) | ||
| 74 | + | ||||
| 75 | +**La source de vérité est le repo git sur le nœud M3U96b** (`/opt/api-ka`) — on n'édite jamais les copies laptop. Toute modification se fait sur le nœud via SSH : édition, tests, `pm2 restart`, puis commit/push depuis le nœud. | ||||
| 76 | + | ||||
| 77 | +- Remote `origin` = **spbgit** (git perso [git.spboucher.ai](https://git.spboucher.ai), bare repos sur M3U96a). **Pas GitHub.** | ||||
| 78 | +- L'agent forwarding SSH est actif : le `git push origin main` fonctionne pendant une session SSH depuis le laptop. | ||||
| 79 | +- Chaque fichier du dépôt porte l'en-tête d'auteur obligatoire (voir `CLAUDE.md`). | ||||
| 83 | 80 | ||||
| 84 | ```bash | 81 | ```bash | ||
| 85 | python3 -m venv venv && source venv/bin/activate | 82 | python3 -m venv venv && source venv/bin/activate | ||
| 86 | pip install -r requirements.txt | 83 | pip install -r requirements.txt | ||
| 87 | 84 | ||||
| 88 | −# Initialiser la base | 85 | +python -m src.database.db --init # initialiser la base | ||
| 89 | −python -m src.database.db --init | 86 | +uvicorn src.api.main:app --reload --port 8000 # API en dev | ||
| 90 | − | 87 | +python -m src.scheduler.daily_job --now # collecte manuelle immédiate | ||
| 91 | −# API en dev | ||||
| 92 | −uvicorn src.api.main:app --reload --port 8000 | ||||
| 93 | − | ||||
| 94 | −# Collecte manuelle immédiate (tous les services) | ||||
| 95 | −python -m src.scheduler.daily_job --now | ||||
| 96 | − | ||||
| 97 | −# Backfill d'une date manquée | ||||
| 98 | python -m src.scheduler.backfill --date 2026-08-15 | 88 | python -m src.scheduler.backfill --date 2026-08-15 | ||
| 99 | − | ||||
| 100 | −# Vérifier la santé | ||||
| 101 | −curl http://127.0.0.1:8000/health | ||||
| 102 | − | ||||
| 103 | −# Tests | ||||
| 104 | pytest tests/ -v | 89 | pytest tests/ -v | ||
| 105 | −``` | ||||
| 106 | − | ||||
| 107 | −## Déploiement | ||||
| 108 | 90 | ||||
| 109 | −- **Nœud** : **M3U96b** (Mac Studio, cluster MacLustr) — répertoire **`/opt/api-ka`**. Chaque service **vérifie le hostname** au démarrage et refuse de tourner ailleurs en production. | 91 | +pm2 restart apika-api # après un changement en production | ||
| 110 | −- **Port** : **8000** (API liée à `127.0.0.1`, exposée uniquement via le tunnel). | ||||
| 111 | −- **Domaine** : **https://www.api-ka.com** (tunnel **ngrok**). | ||||
| 112 | −- **PM2** (3 process, auto-restart) : | ||||
| 113 | − - **`apika-api`** — l'API FastAPI/Uvicorn sur le port **8000** | ||||
| 114 | − - **`apika-scheduler`** — le job quotidien **02:00** + backfill | ||||
| 115 | − - **`apika-ngrok`** — le tunnel **www.api-ka.com** | ||||
| 116 | − | ||||
| 117 | −```bash | ||||
| 118 | −pm2 ls | grep apika # état des 3 process | ||||
| 119 | −pm2 restart apika-api # après un changement de code | ||||
| 120 | −pm2 logs apika-scheduler # suivre les collectes | ||||
| 121 | ``` | 92 | ``` | ||
| 122 | 93 | ||||
| 123 | −## Développement remote-first (IMPORTANT) | 94 | +## Déploiement | ||
| 124 | − | ||||
| 125 | −La **source de vérité** est le **repo git sur le nœud M3U96b** (`/opt/api-ka`), **pas** une copie sur le laptop. Toute modification se fait **via SSH sur le nœud** : édition, test, `pm2 restart`, puis commit/push **depuis le nœud**. | ||||
| 126 | 95 | ||||
| 127 | −- Remote **`origin`** = **spbgit** (git perso **git.spboucher.ai**, bare repos sur M3U96a) — **pas GitHub**. | 96 | +- **Nœud** : M3U96b (Mac Studio, cluster MacLustr) — répertoire `/opt/api-ka` (hostname vérifié au démarrage) | ||
| 128 | −- **Agent forwarding** actif : le `git push origin main` fonctionne pendant une session SSH depuis le laptop. | 97 | +- **Port** : **8000** (API liée à 127.0.0.1, exposée uniquement via le tunnel) | ||
| 98 | +- **Processus PM2** : `apika-api` (API) + `apika-scheduler` (collectes) + `apika-ngrok` (tunnel) | ||||
| 99 | +- **Domaine** : **https://www.api-ka.com** (tunnel ngrok) | ||||
| 100 | + | ||||
| 101 | +## Écosystème Groupe KA | ||||
| 102 | + | ||||
| 103 | +- [groupe-ka.com](https://www.groupe-ka.com) — portail du groupe et compte unique KA ID | ||||
| 104 | +- [lou-ka.com](https://www.lou-ka.com) — logements à louer | ||||
| 105 | +- [immo-ka.com](https://www.immo-ka.com) — propriétés à vendre | ||||
| 106 | +- [vrai-prix.com](https://www.vrai-prix.com) — estimation immobilière | ||||
| 107 | +- [auto-ka.com](https://www.auto-ka.com) — véhicules | ||||
| 108 | +- [fabri-ka.com](https://www.fabri-ka.com) — produits québécois | ||||
| 109 | +- [food-ka.com](https://www.food-ka.com) — épicerie et alimentation | ||||
| 110 | +- [resto-ka.com](https://www.resto-ka.com) — restaurants | ||||
| 111 | +- [sorti-ka.com](https://www.sorti-ka.com) — sorties et événements | ||||
| 112 | +- [job-ka.com](https://www.job-ka.com) — emplois | ||||
| 113 | +- [crea-ka.com](https://www.crea-ka.com) — créateurs de contenu | ||||
| 114 | +- [trouve-ka.com](https://www.trouve-ka.com) — petites annonces | ||||
| 115 | +- [api-ka.com](https://www.api-ka.com) — API de données *(ce repo)* | ||||
| 129 | 116 | ||||
| 130 | --- | 117 | --- | ||
| 131 | 118 | ||||
| 132 | −Un service **Groupe Ka** — créé par **Simon-Pierre Boucher** (contact@spboucher.ai) | 119 | +© Groupe KA — Simon-Pierre Boucher · contact@spboucher.ai | ||
| 120 | +Ce repo vit sur **spbgit** ([git.spboucher.ai](https://git.spboucher.ai)). | ||||
added
docs/screenshots/api-ka-desktop.png
+0 −0
Binary file not shown.
added
docs/screenshots/api-ka-mobile.png
+0 −0
Binary file not shown.