- Add frozen v2 /v1/prices API contract (docs/api-contract-prices.md) - Add ADR 0011: providers best-effort Yahoo (docs/adr/0011-providers-best-effort-yahoo.md) - Add dedicated ADR table section to docs/architecture.md (rows 0001-0011) Closes #154
6.5 KiB
ADR 0011 — Providers de prix : exchanges directs (crypto) + Yahoo Finance best-effort (stocks)
- Status: Accepted
- Date: 2026-04-26
- Successor of: ADR 0009 (architecture proxy) — précise les providers concrets
- Milestone:
spec-price-fetching+prices-proxy(maximus-api)
Context
ADR 0009 a établi qu'un proxy maximus-api mutualisé sert le price-fetching premium pour préserver la privacy (IP cachée, headers strippés). La revue spec du contrat /v1/prices (2026-04-26) a soulevé deux risques critiques :
- Yahoo Finance n'a pas d'API publique officielle. Les endpoints
query1/query2.finance.yahoo.comsont non documentés, leur ToS interdit l'usage commercial et la redistribution. Un IP-ban du VPS coupe le feature pour 100% des premium en même temps. - CoinGecko free tier interdit le proxy commercial. Seul le plan Demo/Pro payant (~129 $/mo Analyst) le permet contractuellement.
Quatre options ont été considérées (cf. revue inline docs/api-contract-prices.md §0) :
| Option | Coût/mois | Légalité commercial | Stabilité | Couverture |
|---|---|---|---|---|
| Polygon.io Starter | 29 $ | ✅ contractuelle | ✅ haute | Stocks NYSE/NASDAQ + crypto |
| Tiingo Power + exchanges directs (crypto) | 10 $ | ✅ Tiingo, ✅ exchanges (public market data OSS-légal) | ✅ haute | Stocks + crypto |
| Exchanges directs (crypto) + Yahoo best-effort (stocks) | 0 $ | ⚠️ Yahoo ToS risqué (data publique mais redistribution interdite) ; ✅ exchanges | ⚠️ Yahoo fragile, exchanges stables | Stocks + crypto |
| Polygon Stocks + CoinGecko Pro | 158 $ | ✅ | ✅ | Best-of-both |
Decision
Adopter l'option « tout-OSS / best-effort » pour le MVP :
- Crypto : interrogation directe des exchanges majeurs via la lib
ccxt(MIT). Les données de marché publiques (ticker, OHLC) sont gratuites et explicitement autorisées en commercial par les ToS de Kraken, Coinbase, Binance, etc. Implémentation initiale : Kraken d'abord, Coinbase en fallback si Kraken 404. - Stocks : interrogation de Yahoo Finance via
query1.finance.yahoo.com/v7/finance/quote(et v8 chart pour historique) avec un User-Agent navigateur. Best-effort assumé : peut échouer ou changer sans préavis.
Le client paie pour l'infrastructure d'anonymisation, pas pour la donnée. Cette distinction est centrale au modèle économique : la valeur premium = privacy (proxy mutualisé) + commodité (auto-fill), pas la donnée elle-même.
Garde-fous obligatoires
- Label UX explicite : sur les catégories de bilan en stocks, le bouton fetch affiche un badge « best-effort » + warning au premier usage. Sur crypto : pas de warning.
- Circuit breaker côté maximus-api : seuil
5 erreurs Yahoo / 60 sec → breaker ouvert pour 15 min. Notification automatique Telegram/email àmaxime2tremblay@protonmail.com. - Quota baissé : 200 req/jour/licence (vs 2000 initialement). Suffit pour ~50 actifs × snapshot mensuel. Réduit l'incitation à abuser.
- Saisie manuelle toujours active : aucun chemin d'erreur ne bloque la saisie d'un snapshot.
- Headers stripping rigoureux : tous les headers entrants supprimés avant call sortant. Vers Yahoo : UA browser-like (
Mozilla/5.0 ...). Vers exchanges : UAmaximus-api/<version>. - Logs séparés : pas de log conjoint
(license_id, symbol). Implémentation via wrapper logger injectable (src/logger.tspino).
Plan de migration si Yahoo devient inutilisable
Triggers de migration vers un provider payant :
- Plus de 1 incident IP-ban / mois pendant 2 mois consécutifs, OU
- Plus de 30% des requêtes stocks tombent en circuit-breaker
service_degradedsur 7 jours, OU - Plainte légale formelle de Yahoo / Verizon Media.
Provider de bascule prioritaire : Tiingo plan Power (~10 $/mo, 1000 req/jour, ToS-clean).
- Implémentation : ajouter un module
providers/tiingo.tsparallèle àproviders/yahoo.ts. Switch via env varSTOCKS_PROVIDER=yahoo|tiingo. - Délai de bascule : ≤ 30 jours après déclenchement d'un trigger.
- Communication : entrée CHANGELOG explicite + email aux licences premium actives.
Si l'audience grandit (>500 licences premium actives), bascule vers Polygon Starter (~29 $/mo) considérée.
Consequences
Positives
- 0 $ de coût récurrent au MVP — pas de cash burn avant que le produit ait validé son marché.
- Crypto 100% OSS-légal — voie pérenne, ne nécessitera jamais de migration.
- Justification premium cohérente — privacy comme valeur, pas la donnée. Aligne avec les principes du projet.
- Plan de bascule pré-engagé — pas pris au dépourvu si Yahoo devient hostile.
Négatives / Risques actés
- ToS Yahoo en zone grise — le proxy commercial de leur data publique n'est pas formellement autorisé. Yahoo a déjà émis des cease-and-desist contre yfinance (lib Python). Risque légal théorique mais peu probable à petite échelle.
- IP-ban probable à un moment ou l'autre — Yahoo bloque les UA non browser et les patterns de requête trop réguliers. Le circuit breaker absorbe l'événement, mais le feature devient temporairement HS pour tous les premium.
- Pas de garantie de stabilité de schéma — Yahoo peut renommer un champ JSON sans préavis. Tests d'intégration
nockne capturent pas ça (mock = donnée figée). - Charge ops accrue — il faudra surveiller le taux d'erreur Yahoo et réagir vite si dégradation.
Neutre
- Première implémentation un peu plus complexe côté serveur (deux providers + circuit breaker), mais le code reste contained dans
src/providers/et est testable.
Suivi
- ADR à reviewer dans 6 mois (2026-10-26) ou plus tôt si trigger de migration déclenché.
- Métriques à tracker dans le log applicatif maximus-api :
yahoo_success_rate_7d,yahoo_breaker_open_count_30d,crypto_provider_distribution. - Issue de suivi : créer une issue
opsdansmaximus-apipour le monitoring continu une fois deployé.
References
- Yahoo Finance ToS — sec. 7-8 sur l'usage commercial
- CoinGecko API ToS — restrictions free tier
- Kraken API public market data — explicite : free public tier, commercial OK pour data publique
- CCXT (MIT) — abstraction multi-exchange, lib OSS
- ADR 0009 — Architecture du proxy
docs/api-contract-prices.md— Contrat figé/v1/prices