mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-06-28 01:53:40 +02:00
capitalisation: triage 95_a_capitaliser + création domaine infra
Triage des 27 propositions du buffer de capitalisation (skill capitalisation-triage), avec vérification des doublons contre la base. Intégré dans knowledge/ (23 entrées): - backend: redis (compensation incrBy non-atomique), nestjs (injection cassée sous tsx watch; guard write mode dégradé), async (test rollback pipeline multi-fichiers), contracts (idempotence POST), auth (disclosure comptes soft-deleted), prisma (index partial soft-delete), llm-providers (nouveau: OAuth vs API key, prompt caching). - frontend: tests (garde-fous parking Later), navigation (fichiers non-route sous src/app Expo Router), general (type client vs payload backend), state (fallback catch-all mapping DB→UI). - workflow: story-tracking (statut BMAD vs narratif obsolète). - product: general (nouveau: doc feature store sans UI). - infra: NOUVEAU DOMAINE (traefik, tailscale, docker, docker-networking, reverse-proxy-paths, sidecar tailscale) + 00_INDEX.md. Autres: - 90_debug_et_postmortem.md: post-mortem réseau Docker partagé hors compose. - Rejeté 3 doublons (types enum contracts, getter PrismaService, $transaction). - Buffer 95_a_capitaliser.md purgé et restauré à son état initial. - _projects.conf: MAJ statuts epics + ajout app-rl799.
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
---
|
||||
title: Infra — Risques & vigilance : Traefik
|
||||
domain: infra
|
||||
bucket: risques
|
||||
tags: [traefik, docker, reverse-proxy, bun, websocket, basic-auth, ios]
|
||||
applies_to: [implementation, review, debug, architecture]
|
||||
severity: high
|
||||
validated_on: 2026-06-25
|
||||
source_projects: [_Assistant_Cuisine]
|
||||
---
|
||||
|
||||
# Infra — Risques & vigilance : Traefik
|
||||
|
||||
> Extrait de la base de connaissance Lead_tech. Voir `knowledge/infra/risques/README.md` pour l'index complet.
|
||||
|
||||
---
|
||||
|
||||
<a id="risque-traefik-v3-docker29-api"></a>
|
||||
## Pièges Traefik v3 + Docker Engine 29
|
||||
|
||||
### Risques
|
||||
|
||||
- **Incompatibilité d'API Docker** : Docker 29 a élevé la minimum API version. Traefik < 3.6 utilise un client Docker SDK figé en `1.24` ; le daemon refuse la connexion et aucune route ne fonctionne.
|
||||
- **`PathPrefix(/api)` trop large** : un routeur `Host(...) && PathPrefix(/api)` vole les routes `/api/*` de toutes les autres apps du même domaine (Homepage `/api/services`, Next.js `/api/...`, n'importe quel SPA) → 401/404 silencieux.
|
||||
- **Bun `new Response(body, {status: 3xx})` perd le header `Location`** : un proxy HTTP en Bun qui forward un upstream 302/303 retransmet le status mais le client reçoit un 200 vide (ou un status sans `Location`). Le navigateur ne suit pas la redirection.
|
||||
|
||||
### Symptômes
|
||||
|
||||
- Container Traefik qui tourne mais aucune route active, logs en boucle :
|
||||
|
||||
```
|
||||
ERR Failed to retrieve information of the docker client and server host
|
||||
error="Error response from daemon: client version 1.24 is too old.
|
||||
Minimum supported API version is 1.40, please upgrade your client to a newer version"
|
||||
```
|
||||
|
||||
- Une app exposée sur le même domaine que le dashboard Traefik se met à retourner 401/404 sur ses propres `/api/*`.
|
||||
- Un proxy Bun qui forward une redirection : le client reçoit un 200 vide ou un `Location` nul.
|
||||
|
||||
### Bonnes pratiques / mitigations
|
||||
|
||||
**Incompatibilité API Docker**
|
||||
|
||||
- Utiliser **Traefik 3.6.1+** (client Docker avec négociation auto de version). Les tags `:v3.5` / `:v3.2` ne marchent pas, même avec `DOCKER_API_VERSION=1.44` en env (le client n'honore pas cette variable dans Traefik).
|
||||
- Pinner explicitement la version (ex. `traefik:v3.6.15`), jamais le tag mouvant `:v3.6`.
|
||||
- Vérifier la compatibilité Traefik ↔ Docker Engine **avant** un upgrade Docker.
|
||||
|
||||
**`PathPrefix(/api)` trop large**
|
||||
|
||||
```yaml
|
||||
# ❌ trop large — capture tous les /api/* du domaine
|
||||
- "traefik.http.routers.dashboard-api.rule=Host(`example.com`) && PathPrefix(`/api`)"
|
||||
|
||||
# ✅ ne capture que les endpoints natifs Traefik
|
||||
- "traefik.http.routers.dashboard-api.rule=Host(`example.com`) && PathRegexp(`^/api/(overview|version|rawdata|support-dump|entrypoints|http|tcp|udp)(/|$$)`)"
|
||||
```
|
||||
|
||||
Les endpoints natifs Traefik sont fixés : `overview`, `version`, `rawdata`, `support-dump`, `entrypoints`, `http/*`, `tcp/*`, `udp/*`. Sur un domaine partagé entre plusieurs apps : **jamais** de `PathPrefix(/api)` générique, toujours une regex explicite.
|
||||
|
||||
**Bun `new Response` perd le `Location`**
|
||||
|
||||
```ts
|
||||
// ❌ perd le Location dans Bun (~1.1.x)
|
||||
return new Response(upstream.body, {
|
||||
status: upstream.status, // 303
|
||||
headers: upstream.headers, // contient Location, ignoré au final
|
||||
});
|
||||
|
||||
// ✅ Hono c.redirect() ou équivalent
|
||||
if (upstream.status >= 300 && upstream.status < 400) {
|
||||
const loc = upstream.headers.get("location");
|
||||
if (loc) return c.redirect(loc, upstream.status as 301 | 302 | 303 | 307 | 308);
|
||||
}
|
||||
```
|
||||
|
||||
**Règle** : tout proxy HTTP qui forward des redirects upstream doit traiter explicitement la branche 3xx avant la branche "body normal".
|
||||
|
||||
- Contexte technique : Traefik v3 / Docker 29 / Bun + Hono — _Assistant_Cuisine 04-05-2026
|
||||
|
||||
---
|
||||
|
||||
<a id="risque-basic-auth-websocket-webkit-ios"></a>
|
||||
## Basic auth + WebSocket : re-prompts répétés (surtout WebKit/iOS)
|
||||
|
||||
### Risques
|
||||
|
||||
- Une app derrière une basic auth (Traefik, nginx) qui utilise des WebSockets (code-server, Jupyter, ttyd, et beaucoup d'apps "live") déclenche **plusieurs prompts d'authentification** à l'ouverture, même quand les credentials viennent d'être saisis.
|
||||
|
||||
### Symptômes
|
||||
|
||||
- 3 prompts d'authentification successifs à chaque ouverture de l'app, observés notamment sur tablette iOS / iPadOS.
|
||||
- Persiste sur Chrome iOS et Firefox iOS (tous contraints d'utiliser WebKit sur iOS). Sporadique sur macOS, rare sur desktop Linux/Windows.
|
||||
|
||||
### Cause
|
||||
|
||||
Safari (et tous les navigateurs iOS, contraints à WebKit) ne **propage pas systématiquement les credentials basic auth aux requêtes WebSocket** d'une page déjà authentifiée. Chaque WS qui échoue redéclenche un prompt.
|
||||
|
||||
### Bonnes pratiques / mitigations
|
||||
|
||||
Remplacer la basic auth par une auth à **cookie de session** :
|
||||
|
||||
- Soit l'auth native de l'app si elle existe (code-server `HASHED_PASSWORD`, JupyterHub login form, etc.).
|
||||
- Soit un système central type Authelia / Authentik / traefik-forward-auth qui pose un cookie partagé entre apps.
|
||||
|
||||
Le cookie passe automatiquement avec les requêtes WebSocket (même origine) → plus de re-prompt.
|
||||
|
||||
**Règle** : pour toute app qui utilise des WebSockets ET qui doit être protégée, ne **pas** utiliser la basic auth. Toujours cookie-based. La basic auth reste OK pour des UI sans WS (dashboards en pull, API REST simples).
|
||||
|
||||
- Contexte technique : Traefik / basic auth / WebKit iOS — _Assistant_Cuisine 04-05-2026
|
||||
Reference in New Issue
Block a user