fix(draco): résolution dev/prod par l'hôte de la requête (7.82.4)
Le mode console du panneau restait une page morte sur flowdeck-dev : CSP frame-src/connect-src et DRACO_PANNEAU_CONFIG.agent_url pointaient l'agent prod (pas encore installée). Deux trous de la 7.82.3 : agent_url() sans aucune dérivation, et aucune résolution lisant l'hôte de la requête. Pour tout ce qui est rendu à une requête (barre/DRACO_URLS, iframe du panneau, CSP, boutons et redirections SSO) : explicite > hôte public de la requête (motif fermé ^(og|flowdeck|tiktak|kanbante|agent)(SUFFIXE).dracodev.net$, suffixe appliqué aux sœurs et à l'agent) > dérivation par les adresses de l'agent connues en config (élargie : agent_url() se dérive de l'URL d'événements explicite) > défaut officiel. L'hôte est posé par le middleware CSP dans un ContextVar (patron du nonce CSP) : iframe et CSP de la même réponse consomment la même origine résolue. Contextes sans requête inchangés sinon. Tests : +12 dans test_draco_urls_devprod.py (25/25) — Host dev sans aucun env → tout en -dev ; Host prod → officiels ; Host LAN → repli config/défauts ; explicite gagne sur l'hôte ; motif fermé. Suite complète : 4 failed / 26 errors identiques sur arbre propre (familles préexistantes MCP/realtime/my_tasks/gallery/sync).
This commit is contained in:
@@ -134,8 +134,9 @@ class ContentSecurityPolicyMiddleware(BaseHTTPMiddleware):
|
||||
# service d'agents commun (premier parti, même programme) —
|
||||
# seul hôte externe nommé, rien d'autre ne s'ouvre.
|
||||
# v7.82.0 (dev/prod) : cet hôte n'est plus figé — {agent} est
|
||||
# l'origine résolue par la config (DRACO_AGENT_URL ; défaut =
|
||||
# nom officiel, un dev déclare son agent-dev dans le .env).
|
||||
# l'origine résolue par draco_urls (DRACO_AGENT_URL explicite,
|
||||
# sinon hôte de la requête — v7.82.4 —, sinon dérivation par
|
||||
# l'agent connu en config ; défaut = nom officiel).
|
||||
# Même origine pour frame-src : la console du service est
|
||||
# encadrée en iframe par le panneau (surimpression v3).
|
||||
"connect-src 'self' {agent} ws://{host} wss://{host}; "
|
||||
@@ -152,6 +153,17 @@ class ContentSecurityPolicyMiddleware(BaseHTTPMiddleware):
|
||||
# tâche créée maintenant → le contexte (donc le nonce) y est copié,
|
||||
# exactement ce que les templates liront via `csp_nonce()`.
|
||||
CSP_NONCE.set(nonce)
|
||||
# v7.82.4 : même patron pour l'hôte public de la requête —
|
||||
# `draco_urls` le lit pour résoudre l'environnement (dev/prod)
|
||||
# de tout ce qui est rendu à cette requête (barre, iframe du
|
||||
# panneau, SSO), et la CSP ci-dessous consomme la MÊME origine
|
||||
# agent résolue. X-Forwarded-Host prime, comme
|
||||
# `get_redirect_uri()` (app/routers/auth.py).
|
||||
from app.services import draco_urls
|
||||
|
||||
draco_urls.definir_hote_requete(
|
||||
request.headers.get("x-forwarded-host", "")
|
||||
or request.headers.get("host", ""))
|
||||
response = await call_next(request)
|
||||
# Only set CSP on HTML responses
|
||||
content_type = response.headers.get("content-type", "")
|
||||
@@ -160,8 +172,6 @@ class ContentSecurityPolicyMiddleware(BaseHTTPMiddleware):
|
||||
# on retire quand même tout caractère hors base URL par sécurité.
|
||||
host = re.sub(r"[^0-9A-Za-z.\-:\[\]]", "",
|
||||
request.headers.get("host", ""))
|
||||
from app.services import draco_urls
|
||||
|
||||
agent = re.sub(r"[^0-9A-Za-z.\-:/]", "",
|
||||
draco_urls.origine(draco_urls.agent_url()))
|
||||
response.headers[self.CSP_HEADER] = self.CSP_VALUE.format(
|
||||
|
||||
Reference in New Issue
Block a user