Simpl-Resultat/docs/adr/0011-providers-best-effort-yahoo.md
le king fu ddb0cb257b
All checks were successful
PR Check / rust (push) Successful in 25m39s
PR Check / frontend (push) Successful in 2m42s
PR Check / rust (pull_request) Successful in 26m45s
PR Check / frontend (pull_request) Successful in 2m58s
docs(prices): commit /v1/prices contract + ADR 0011
- 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
2026-04-27 08:06:03 -04:00

6.5 KiB
Raw Blame History

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 :

  1. Yahoo Finance n'a pas d'API publique officielle. Les endpoints query1/query2.finance.yahoo.com sont 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.
  2. 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

  1. 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.
  2. Circuit breaker côté maximus-api : seuil 5 erreurs Yahoo / 60 sec → breaker ouvert pour 15 min. Notification automatique Telegram/email à maxime2tremblay@protonmail.com.
  3. Quota baissé : 200 req/jour/licence (vs 2000 initialement). Suffit pour ~50 actifs × snapshot mensuel. Réduit l'incitation à abuser.
  4. Saisie manuelle toujours active : aucun chemin d'erreur ne bloque la saisie d'un snapshot.
  5. Headers stripping rigoureux : tous les headers entrants supprimés avant call sortant. Vers Yahoo : UA browser-like (Mozilla/5.0 ...). Vers exchanges : UA maximus-api/<version>.
  6. Logs séparés : pas de log conjoint (license_id, symbol). Implémentation via wrapper logger injectable (src/logger.ts pino).

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_degraded sur 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.ts parallèle à providers/yahoo.ts. Switch via env var STOCKS_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 nock ne 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 ops dans maximus-api pour le monitoring continu une fois deployé.

References