"""Tests de la recherche fédérée ObsiGate (fusion #68). Fonctions pures de backend/recherche_cors.py uniquement : aucune base, aucun serveur. """ from backend.recherche_cors import ( cors_headers_for, is_dev_host, is_prod_host, origin_of, preflight_headers, sister_origins, ) RESOLVED_DEV = { "obsigate": "https://og-dev.dracodev.net", "flowdeck": "https://flowdeck-dev.dracodev.net", "tiktak": "https://tiktak-dev.dracodev.net", "kanbante": "https://kanbante-dev.dracodev.net", "agent": "https://agent-dev.dracodev.net", "gitea": "https://git.dracodev.net", } def test_is_dev_host(): assert is_dev_host("og-dev.dracodev.net") is True assert is_dev_host("og.dracodev.net") is False assert is_dev_host("x-dev.dracodev.net.evil") is False assert is_prod_host("og.dracodev.net") is True assert is_prod_host("og-dev.dracodev.net") is False def test_origin_of(): assert origin_of("https://og-dev.dracodev.net") == "https://og-dev.dracodev.net" assert origin_of("https://og-dev.dracodev.net/chemin") == "https://og-dev.dracodev.net" assert origin_of("{{URL_OBSIGATE}}") is None def test_sister_origins_dev(): # Correctif 2026-10-28 : 10 origines officielles (8 sœurs + 2 agent), prod ET dev, # quelle que soit la résolution. assert sister_origins(RESOLVED_DEV) == { "https://og.dracodev.net", "https://flowdeck.dracodev.net", "https://tiktak.dracodev.net", "https://kanbante.dracodev.net", "https://og-dev.dracodev.net", "https://flowdeck-dev.dracodev.net", "https://tiktak-dev.dracodev.net", "https://kanbante-dev.dracodev.net", "https://agent.dracodev.net", "https://agent-dev.dracodev.net", } def test_cors_headers_agent_console_autorise(): # Fédération depuis la console (2026-10-28) : les origines agent # prod ET dev passent, avec credentials ; un tiers reste refusé. for origine in ("https://agent.dracodev.net", "https://agent-dev.dracodev.net"): headers = cors_headers_for(origine, RESOLVED_DEV) assert headers is not None assert headers["Access-Control-Allow-Origin"] == origine assert headers["Access-Control-Allow-Credentials"] == "true" assert cors_headers_for("https://agent.dracodev.net.evil.example", RESOLVED_DEV) is None def test_sister_origins_ajoute_env_de_la_requete(): # Correctif 2026-10-28 : configuration muette, quel que soit # l'hôte de la requête, prod ET dev passent — l'hôte ne # restreint plus l'allowlist. assert "https://og-dev.dracodev.net" in sister_origins( {}, request_host="og-dev.dracodev.net" ) assert "https://og-dev.dracodev.net" in sister_origins( {}, request_host="og.dracodev.net" ) assert "https://og.dracodev.net" in sister_origins( {}, request_host="og-dev.dracodev.net" ) def test_cors_headers(): headers = cors_headers_for("https://tiktak-dev.dracodev.net", RESOLVED_DEV) assert headers["Access-Control-Allow-Origin"] == "https://tiktak-dev.dracodev.net" assert headers["Access-Control-Allow-Credentials"] == "true" assert cors_headers_for("https://evil.example", RESOLVED_DEV) is None assert cors_headers_for("https://og-dev.dracodev.net.evil.example", RESOLVED_DEV) is None # Autre environnement autorisé (correctif 2026-10-28). assert cors_headers_for("https://og.dracodev.net", RESOLVED_DEV) is not None def test_preflight_headers(): headers = preflight_headers("https://flowdeck-dev.dracodev.net", RESOLVED_DEV) assert headers["Access-Control-Allow-Methods"] == "GET, OPTIONS" assert preflight_headers("https://evil.example", RESOLVED_DEV) is None