fix(draco): URLs sœurs dérivées de l'environnement de l'agent (7.82.3)
FlowDeck CI / test (push) Successful in 29m39s
FlowDeck CI / lint (push) Successful in 2m18s
FlowDeck CI / docker (push) Successful in 1m41s

Résolution uniforme des quatre sœurs (ObsiGate, Flowdeck, TikTak,
Kanbante) dans app/services/draco_urls.py : explicite prioritaire
(contrat inchangé), sinon dérivation depuis l'hôte de l'agent connu
via AGENT_EVENEMENTS_URL (agent<SUFFIXE>.dracodev.net →
<slug><SUFFIXE>.dracodev.net), sinon défaut officiel. Hors motif
(autre domaine, LAN, IP) : aucune dérivation. Gitea inchangé.
Tests +4 dans test_draco_urls_devprod.py.
This commit is contained in:
Spark
2026-10-26 00:46:21 +00:00
parent 53ba3d1124
commit 283e226adf
5 changed files with 179 additions and 5 deletions
+82 -3
View File
@@ -18,11 +18,26 @@ Priorité de résolution, à chaque appel (les tests et les modules qui
lisaient déjà ``os.environ`` au moment de l'appel gardent ce
comportement) : variable d'environnement > ``app.config.settings`` >
défaut officiel. Aucun défaut ne contient ``-dev``.
**Dérivation d'environnement (v7.82.3)** — pour les quatre URL
sœurs (ObsiGate, Flowdeck, TikTak, Kanbante), entre la configuration
explicite et le défaut officiel : si l'origine de l'agent telle que
l'app la connaît déjà (``AGENT_EVENEMENTS_URL``, via
``agent_evenements_url()``) a un hôte de la forme
``agent<SUFFIXE>.dracodev.net`` (SUFFIXE éventuellement vide,
typiquement ``-dev``), l'URL sœur est dérivée :
``https://<slug><SUFFIXE>.dracodev.net`` (slugs : ``og``,
``flowdeck``, ``tiktak``, ``kanbante``). Ainsi une installation dev
qui ne déclare que l'agent pointe ses liens inter-apps en ``-dev``
sans quatre variables de plus. Si l'hôte de l'agent ne correspond
pas au motif (autre domaine, LAN, IP), **aucune dérivation** : on
ne fabrique jamais un lien deviné. L'URL Gitea ne change pas.
"""
from __future__ import annotations
import os
import re
from urllib.parse import urlparse
from app.config import settings
@@ -51,9 +66,70 @@ def _resoudre(env_name: str, settings_attr: str, app: str) -> str:
return OFFICIELLES[app]
# Slugs d'hôte des applications sœurs (dérivation d'environnement).
_SLUGS_SOEURS = {
"obsigate": "og",
"flowdeck": "flowdeck",
"tiktak": "tiktak",
"kanbante": "kanbante",
}
# Hôte de l'agent : agent<SUFFIXE>.dracodev.net (SUFFIXE = ``-dev``…).
_MOTIF_HOTE_AGENT = re.compile(r"^agent(-[a-z0-9-]+)?\.dracodev\.net$")
def _suffixe_environnement() -> str | None:
"""Suffixe d'environnement porté par l'hôte de l'agent, ou None.
Source : l'origine de l'agent telle que l'app la connaît déjà —
``agent_evenements_url()`` (``AGENT_EVENEMENTS_URL`` explicite,
sinon dérivée de la base de l'agent). Retourne ``""`` pour
l'hôte officiel, ``"-dev"`` pour ``agent-dev.dracodev.net``, et
None si l'hôte ne correspond pas au motif (aucune dérivation).
"""
hote_agent = (urlparse(agent_evenements_url()).hostname or "").lower()
m = _MOTIF_HOTE_AGENT.match(hote_agent)
if not m:
return None
return m.group(1) or ""
def _url_derivee(app: str) -> str:
"""URL sœur dérivée de l'environnement de l'agent ("" si aucune)."""
slug = _SLUGS_SOEURS.get(app)
if not slug:
return ""
suffixe = _suffixe_environnement()
if suffixe is None:
return ""
return f"https://{slug}{suffixe}.dracodev.net"
def _resoudre_soeur(env_name: str, settings_attr: str, app: str) -> str:
"""Résolution d'une URL sœur : explicite > dérivation > officiel.
La valeur ``settings`` égale au nom officiel est le *défaut* de
``app/config.py``, pas un choix explicite : elle ne doit pas
bloquer la dérivation d'environnement. Une valeur settings
différente (dev, LAN, domaine propre) reste prioritaire.
"""
env = _nettoyer(os.environ.get(env_name, ""))
if env:
return env
cfg = _nettoyer(getattr(settings, settings_attr, "") or "")
if cfg and cfg != OFFICIELLES[app]:
return cfg
derivee = _url_derivee(app)
if derivee:
return derivee
if cfg:
return cfg
return OFFICIELLES[app]
def obsigate_url() -> str:
"""ObsiGate — aussi l'émettrice SSO (DRACO_SSO_URL, déjà en service)."""
return _resoudre("DRACO_SSO_URL", "draco_sso_url", "obsigate")
return _resoudre_soeur("DRACO_SSO_URL", "draco_sso_url", "obsigate")
def agent_url() -> str:
@@ -62,11 +138,11 @@ def agent_url() -> str:
def tiktak_url() -> str:
return _resoudre("TIKTAK_URL", "tiktak_url", "tiktak")
return _resoudre_soeur("TIKTAK_URL", "tiktak_url", "tiktak")
def kanbante_url() -> str:
return _resoudre("KANBANTE_URL", "kanbante_url", "kanbante")
return _resoudre_soeur("KANBANTE_URL", "kanbante_url", "kanbante")
def gitea_url() -> str:
@@ -98,6 +174,9 @@ def flowdeck_url() -> str:
base = _nettoyer(getattr(settings, "app_base_url", "") or "")
if base and "localhost" not in base and "127.0.0.1" not in base:
return base
derivee = _url_derivee("flowdeck")
if derivee:
return derivee
return OFFICIELLES["flowdeck"]