fix(0.32.2): résolution par requête des URL dracodev, base agent dérivée et CSP du panneau
CI / test (push) Successful in 2m21s

La dérivation 0.32.1 ne couvrait que les URL sœurs depuis
AGENT_EVENEMENTS_URL, jamais agent_url : sur la dev, le panneau
visait le défaut prod (agent injoignable, prod non installée),
console morte. Désormais, pour tout rendu à une requête (barre,
iframe du panneau, CSP frame-src) : explicite > hôte public au
motif fermé dracodev > dérivation élargie (événements ou base du
service) > défaut officiel. Contextes sans requête inchangés
sinon ; aucun SSO ajouté.
This commit is contained in:
Spark
2026-10-26 02:07:46 +00:00
parent 65c467bc90
commit d419fe3086
6 changed files with 441 additions and 41 deletions
+22 -8
View File
@@ -41,7 +41,7 @@ from fastapi.staticfiles import StaticFiles
from jinja2 import Environment, FileSystemLoader, select_autoescape
from starlette.middleware.base import BaseHTTPMiddleware
from app.config import APP_VERSION, get_settings
from app.config import APP_VERSION, get_settings, resoudre_urls_draco
from app.gitea_client import GiteaClient
from app import code_links as code_links_service
from app import digest as digest_service
@@ -2149,21 +2149,26 @@ def render(
# aucun nom public n'est codé en dur dans les gabarits ni dans le
# JS statique — tout vient de app.config (défauts = noms
# officiels/prod ; la dev déclare ses noms en ``-dev`` par .env).
# Résolution par requête (0.32.2) : les URL rendues suivent
# l'hôte public de la requête quand aucune variable explicite
# ne les fixe (voir resoudre_urls_draco) — barre, panneau et
# CSP de cette même réponse consomment la même résolution.
_pub = get_settings()
_urls = resoudre_urls_draco(request.headers.get("host"), base=_pub)
context.setdefault(
"draco_urls",
{
"obsigate": _pub.sso_url,
"flowdeck": _pub.flowdeck_url,
"tiktak": _pub.tiktak_url,
"kanbante": _pub.public_url,
"obsigate": _urls.sso_url,
"flowdeck": _urls.flowdeck_url,
"tiktak": _urls.tiktak_url,
"kanbante": _urls.public_url,
},
)
context.setdefault("agent_url", _pub.agent_url)
context.setdefault("agent_url", _urls.agent_url)
context.setdefault(
"sso_authorize_url",
f"{_pub.sso_url}/sso/authorize?return_to="
f"{quote(_pub.public_url + '/auth/draco', safe='')}",
f"{_urls.sso_url}/sso/authorize?return_to="
f"{quote(_urls.public_url + '/auth/draco', safe='')}",
)
# Fusion ACC-1 : initiale de l'opérateur pour la barre d'apps commune.
context.setdefault(
@@ -2194,6 +2199,15 @@ def render(
context.setdefault("user_workspaces", [])
html = _tpl_env.get_template(name).render(**context)
response = HTMLResponse(html, status_code=status_code)
# CSP du panneau (0.32.2) : la seule iframe de l'app est la
# console Spark, chargée depuis l'origine de l'agent résolue
# pour CETTE requête — la même que celle injectée au panneau
# (DRACO_PANNEAU_CONFIG), jamais une autre. Aucune CSP
# n'existait auparavant : l'origine de l'agent n'était énoncée
# nulle part.
response.headers["Content-Security-Policy"] = (
f"frame-src 'self' {_urls.agent_url}"
)
if generated:
response.set_cookie(CSRF_COOKIE, token, samesite="lax", httponly=True)
return response