- New api_v1/routes/admin.py: admin client management blueprint
- admin_users table for admin role (no ALTER TABLE needed)
- require_admin decorator for endpoint protection
- GET/PUT/DELETE /api/v1/admin/clients/<id>
- POST /api/v1/admin/setup (first-time admin init)
- POST /api/v1/admin/clients/<id>/suspend|activate
- GET /api/v1/admin/stats (client counts by plan)
- Registered in api_v1/__init__: auto-wired into portal_server.py
- No new service, no merge tables, no ALTER TABLE
Bug #2: portal_server.py importait api_v1_bp depuis saas_api_v1 au lieu
de api_v1/__init__.py. Tous les sous-blueprints api_v1/routes/* (health,
courses, predictions, valuebets, backtest, export, metrics, ml_feedback)
n'etaient jamais enregistres -> 404.
Fix: utiliser register_api_v1(app) depuis api_v1/__init__.py.
Bug #3: Conflit de nom de blueprint entre saas_api_v1 et api_v1 (tous
deux nommes api_v1). Renomme le blueprint de saas_api_v1 en saas_api_v1_bp.
Supprime les record_once handlers de saas_api_v1 qui dupliquaient
l'enregistrement de sous-blueprints (billing, org, user, history) -
desormais geres par register_api_v1(app).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Crée ml_feedback_saas.py (adaptation de ml_feedback.py pour turf_saas.db)
- DB_PATH = /home/h3r7/turf_saas/turf_saas.db
- Stratégies : xgboost_sg, xgboost_value, xgboost_sp, xgboost_2sur4
- Idempotent (ne duplique pas les paris existants)
- Tested : 188 paris insérés en 1ère exécution, 0 en 2ème (idempotence OK)
- Crée api_v1/routes/ml_feedback.py
- POST /api/v1/ml/feedback/run (admin only via X-Admin-Token ou plan pro)
- GET /api/v1/ml/feedback/stats (premium+)
- Enregistre ml_feedback_bp dans api_v1/__init__.py
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Création POD/Intelligence/ML_Predictions_SaaS.md : architecture ML complète,
flow ml_predictions_cache → ml_feedback_saas → paris → ROI dashboard,
schéma données/jointures, décision duplication vs modification turf_scraper,
documentation des 4 stratégies XGBoost, idempotence, usage CLI
- Mise à jour DOCUMENTATION.md : ajout section Turf SaaS API v1 complète
avec tous les endpoints documentés dont /api/v1/roi/* et /api/v1/ml/feedback/*
(HRT-92 ROI backend + HRT-93 ML feedback loop)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Pro = 365j (historique le plus long), Premium = 90j, Free = 7j
Corrigé suite au point d'attention CTO dans revue de code.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Ajout sections: Value Bets, Alertes Telegram, API Token, Webhook, Historique, Multi-compte
- Gating plan strict: Free < Premium < Pro (jamais de données réelles derrière plan inférieur)
- Value Bets: raccordé sur endpoint réel /api/v1/valuebets (premium+)
- Historique: raccordé sur endpoint réel /api/v1/history (HRT-81)
- Telegram / API Token / Webhook: mocks structurés avec contrats d'interface
(TODO: replace mock — HRT-79 pour Telegram, HRT-80 pour API Token/Webhook)
- Multi-compte: gating UI Pro uniquement, endpoint non défini
- Navigation par section avec chargement lazy
- Design cohérent dark theme avec badges, lock icons et CTA upgrade par plan
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Bug 1: Replace area["name"="..."] query with direct bounding box (50.4,2.8,50.8,3.3)
— area resolution fails silently on public Overpass API depending on server version.
— Direct bbox is deterministic and reliable for MEL coverage.
— Also simplify website filter to use [!"website"] tag negation syntax.
Bug 2: Add explicit Content-Type: application/x-www-form-urlencoded header
— Some network configs/proxies strip the implicit header set by requests.post(data={}).
— Explicit header is best practice per Overpass API docs.
Bug 3 (discovered during test): Add User-Agent header
— overpass-api.de returns 406 Not Acceptable for User-Agent: python-requests/*.
— Fix: send H3R7Tech-LeadHunter/1.0 as custom User-Agent.
— Tested: 5 OSM leads returned from Lille center bounding box.
Backup: leadhunter_scraper.py.backup_20260427_221429
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Port 8769 était occupé par /home/h3r7/depenses_trello/app.py (pid=2287989).
Mise à jour du port dans :
- leadhunter_api.py (docstring, healthcheck, app.run)
- infra/turf-saas-leadhunter.service (description)
Ref: HRT-66
Co-Authored-By: Paperclip <noreply@paperclip.ing>
abc12345 n'est pas dans WEAK_PASSWORDS de saas_auth.py et satisfait
les règles de complexité → test échouait (attendait 400, obtenait 201).
abc1234 est explicitement dans la blacklist (ligne 84 de saas_auth.py).
Correction demandée par CTO en review PR #7 (HRT-63).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add WEAK_PASSWORDS set (50+ common passwords) in saas_auth.py
- Add validate_password_strength() function: checks min length, blacklist, digits, letters
- Replace raw len() checks in /register and /change-password with validate_password_strength()
- Add TestWeakPasswordRejection class in test_security.py: parametrized weak pwd test, strong pwd 201 test, no-digit, no-letter tests
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Ajout tests/test_ml_cache_integrity.py : 7 tests integration vérifiant
que hippodrome, race_label et heure ne sont pas NULL pour la date courante
- Ajout marqueur 'integration' dans pytest.ini
- Connexion DB en lecture seule (mode=ro) pour protection prod
- Support variable d'env TEST_DATE et TURF_DB_PATH
- Tests skippés proprement si job 19h30 n'a pas encore tourné
- Validé sur les données 2026-04-26 : 7/7 PASSED (1005 lignes, 0 NULL)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The api_v1 Blueprint includes billing routes (POST/GET /api/v1/billing/*),
which import from billing_db. This module lives in feature/billing-stripe
(HRT-31) but is needed here for tests to pass. Added the file so all
42 integration tests pass without modification.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Blueprint Flask api_v1 avec prefix /api/v1/
- GET /api/v1/health — healthcheck public
- GET /api/v1/courses/today — courses du jour (paginé, filtré)
- GET /api/v1/courses/{id}/predictions — prédictions ML pour une course
- GET /api/v1/predictions/top3 — top 3 global (free tier)
- GET /api/v1/predictions/all — toutes prédictions (premium+)
- GET /api/v1/valuebets — value bets du jour (premium+)
- GET /api/v1/backtest — résultats backtest historiques (pro)
- GET /api/v1/export/csv — export CSV prédictions/paris (pro)
- GET /api/v1/metrics — métriques perf ML (premium+)
- Swagger/OpenAPI via flasgger à /api/v1/docs
- Erreurs uniformes {status, message, code}
- Pagination limit/offset sur toutes les listes
- 42 tests d'intégration passants
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Docker compose healthchecks target /health on combined-api, dashboard-api
and portal, but these endpoints did not exist (returned 404). This caused
all dependent services (condition: service_healthy) to fail startup.
- combined_api.py: GET /health + /turf/health with DB connectivity check
- dashboard_api.py: GET /health + /turf/health with DB connectivity check
- portal_server.py: GET /health (lightweight, no DB)
QA Finding 1 from HRT-34 review of HRT-33 branch feature/devops-cicd.
Co-Authored-By: Paperclip <noreply@paperclip.ing>