Commit Graph
4 Commits
Author SHA1 Message Date
bruno f1f6138eb9 feat(docs): documentation web des API (Swagger UI) liée depuis le menu
CI / build-and-test (push) Successful in 15m9s
Le lien « API » du menu ouvre /api/docs (et /proxy/api/docs) : Swagger UI
auto-hébergé (swagger-ui-dist, aucun CDN, thème sombre), spécification chargée
depuis `${base}/openapi.json`.

/openapi.json devient exhaustif :
- inventaire généré depuis l'arbre Express (collectApiRoutes) : `:param` →
  `{param}`, `*` → `{path}`, miroirs /proxy/* et métadonnées écartés, préfixe
  /api retiré (le document porte les serveurs /api et /proxy/api) ;
- `app.all()` réduit à GET — ses 35 méthodes HTTP (acl, propfind, m-search…)
  entraient dans le document et figaient Swagger au bout de 2 groupes ;
- authentification marquée automatiquement (middlewares de route ET de préfixe,
  ex. `r.use('/download', …)`), route publique laissée publique ;
- tags + descriptions de groupe, résumés FR pour les routes courantes ;
- 3 schémas d'auth : bearerAuth (JWT), apiKeyAuth (X-API-Key), cookieAuth ;
- description : méthodes d'auth avec exemples, codes d'erreur et seuils de
  débit, section « Serveur MCP » avec snippet `mcpServers` et la liste des
  outils LUE dans mcp/server.mjs au démarrage (aucune liste à maintenir).

Dockerfile : `mcp/` copié dans l'image (cette lecture doit exister en prod).
package.json → 1.0.61 (tag de cette livraison).

Tests : api_coverage +3 cas (page /docs + assets, exhaustivité/méthodes/tags/
sécurité, 3 schémas + outils MCP dans la description) → 51/51 verts.
Vérifs instance locale : lien menu = /proxy/api/docs, 114 opérations rendues
sur 12 groupes, bouton Authorize + section MCP visibles, zéro erreur console.
2026-10-03 00:33:46 -04:00
bruno 41a28dfccc feat(api): production-ready P0/P1 — secrets hors navigateur, clés d'API, métriques
CI / build-and-test (push) Successful in 14m57s
P0
- Aucun secret servi au navigateur : /assets/config.local.js est généré par le
  serveur AVANT les montages statiques (il l'emporte sur le fichier local) et
  ne contient plus YOUTUBE_API_KEY(S) ; le fichier local n'est plus copié dans
  l'image Docker ni embarqué dans dist (angular ignore config.local.js) ;
  youtube-api.service n'appelle plus googleapis directement (fetchYouTube =
  /api/yt -> /proxy/api/yt), gardes « pas de clé => écran vide », rotation et
  carte de bans côté client supprimées ; readiness YouTube via /healthz
  (youtube.keys.count) ; messages d'erreur orientés configuration serveur.
- CORS : origines pilotées par API_ALLOWED_ORIGINS (CSV), méthode PATCH
  ajoutée (requis par /user/preferences), header X-API-Key accepté.
- Clés d'API longue durée : table api_keys (empreinte SHA-256 + préfixe
  affichable), routes GET/POST /api/keys et DELETE /api/keys/:id, jeton
  ntk_… affiché une seule fois, last_used_at à chaque usage ; X-API-Key
  accepté par authMiddleware ET authMiddlewareCookieAware.

P1
- X-Request-Id renvoyé sur chaque réponse + journal JSON structuré en prod
  (ts, reqId, method, route, status, ms).
- GET /metrics : exposition Prometheus sans dépendance (http_requests_total
  par route/code, somme+nombre de durées, uptime/mémoire ; METRICS_TOKEN
  verrouille l'accès si défini).
- Rate-limit sur /api/details (DETAILS_RATE_LIMIT, 60/min, réponse JSON) —
  /transcript avait déjà le sien.
- Version unique package.json : menu du compte, info.version de l'OpenAPI
  (+ schéma apiKeyAuth et chemins /keys / /metrics documentés).

Tests : api_coverage +7 cas « production-ready » (sentinel de fuite de clé,
X-Request-Id, /metrics, CORS PATCH, contrat/version, cycle complet des clés
d'API), suggest, transcript, flags, filters, kind — verts. Build OK.
Vérifs instance locale : config servie sans secret, /api/yt 200 avec la clé
serveur, /metrics alimenté, menu 1.0.59 et 40 cartes rendues sans clé côté
client.
2026-10-02 23:24:50 -04:00
bruno 735255b7d8 feat(library): liste « À regarder plus tard » (watch later)
CI / build-and-test (push) Successful in 14m55s
Nouvelle liste dans la section Vous de la barre latérale, avec un bouton
horloge a cote du coeur sur toutes les cartes (accueil, themes, provider-
themes, recherche).

- db : les 4 fonctions de listes (like/unlike/isLiked/list) prennent un
  paramètre `tag` — la table `tags` sert déjà de mot-clés génériques, donc
  zéro migration.
- api : les 4 routes likes sont générées par registerVideoTagRoutes(prefix,
  tagName) ; /api/user/watch-later = même fabrique, même enrichissement
  yt-dlp, même middleware cookie-aware. Entrée OpenAPI ajoutée.
- front : LikesService prend un VideoTag, like-button un @Input() list
  (icône horloge, ambre quand enregistré, libellés a11y dédiés) — un seul
  composant pour les deux boutons, pas de copie.
- cartes de recherche : la grille partagée n'avait AUCUN bouton ; cœur +
  horloge ajoutés, masqués sur les lives et cartes chaîne (coin bas-gauche
  déjà occupé par le compteur de spectateurs / pas des vidéos).
- route /library/watch-later = LikedComponent via data.list (titre, icône,
  placeholder et état vide pilotés par la route), clés nav.watchLater FR/EN.

Tests : npm run test:api 41/41 (nouveau test watch-later : ajout, statut,
indépendance vis-à-vis des likes, liste, retrait, 400, 401) + 21 autres
suites vertes. Build OK, instance locale 4200 rebuildée. Sondage Playwright
desktop+mobile : 12/14 (2 faux positifs du sondage : accordéon replié sur
une route hors /library, 3×401 console pendant la phase déconnectée).
2026-10-01 14:13:43 -04:00
bruno 1812b86dd4 feat(mcp): serveur MCP stdio 7 outils + guide API/MCP + couverture tests
CI / build-and-test (push) Successful in 14m3s
- mcp/server.mjs : search, suggest, details, trending, transcript,
  transcript_text, health_check (client fin vers API REST)
- docs/API_MCP_GUIDE.md : reference complete REST + MCP + transcript
- tests : server/tests/api_coverage.test.mjs (17 cas HTTP),
  mcp/tools.test.mjs (7 outils sur stub), scripts test:mcp/test:api
- fix(db): DELETE playlist 500 FK -> metrique avant delete + cleanup
  enfants + recordPlaylistMetric tolerant (observabilite)
2026-09-27 18:39:26 -04:00