feat: HUB-19 — rôles du Hub consommés par ObsiGate (registre D3(a)) #228
CI / lint (pull_request) Successful in 1m17s
CI / security (pull_request) Successful in 21s
CI / test (pull_request) Failing after 3m39s
CI / build (pull_request) Skipped
CI / e2e (pull_request) Skipped

This commit is contained in:
Spark
2026-11-06 16:30:30 +00:00
parent a3f76e9b0c
commit dcf847e2fd
15 changed files with 618 additions and 20 deletions
+33
View File
@@ -29,6 +29,17 @@
# (issued_sessions_for_user) et la révocation unitaire contrôlée par
# appartenance (revoke_one_for_user), exposées par l'API machine des
# sessions (backend/routers/comptes_machine.py).
#
# Rôles du Hub (HUB-19, #228) : à l'ouverture de session draco,
# `user_for_draco` consulte en plus le registre des rôles du Hub
# (`backend/hub_roles.py`, contrat D3(a) posé par le pilote ShaarIt) :
# niveau connu ``aucun`` → la session draco est refusée (l'authenti-
# fication native d'ObsiGate, émettrice, n'est jamais touchée) ;
# niveau connu → il est joint au dict utilisateur (``_hub_role``)
# pour que les routes d'administration du canal draco exigent
# ``administrateur`` ; rôle inconnu (Hub injoignable) → comportement
# actuel, aucun verrouillage nouveau. Aucun rôle dans le jeton :
# validation locale, émission et révocations sont inchangées.
from __future__ import annotations
@@ -334,6 +345,28 @@ def user_for_draco(request) -> dict | None:
user["_token_vaults"] = candidate.get("vaults", [])
user["_token_scope"] = "full"
user["_draco_sub"] = sub
# HUB-19 (#228) : rôle du registre du Hub pour ce porteur.
# Niveau connu « aucun » → pas de session établie par draco :
# le refus est consigné sur la requête pour que `require_auth`
# réponde un message explicite en français (et non un simple
# 401 générique). Rôle connu → joint au dict (`_hub_role`) ;
# rôle inconnu → `_hub_role` vaut None et le comportement
# actuel s'applique, sans verrouillage nouveau.
from backend import hub_roles
cookie = ""
try:
cookie = request.headers.get("cookie", "") or ""
except Exception: # un objet requête minimal (tests) ne casse rien
cookie = ""
role = hub_roles.role_pour(sub, cookie)
if role == "aucun":
try:
request.state.role_hub_refuse = "aucun"
except Exception: # pas d'état mutable : refus quand même
pass
return None
user["_hub_role"] = role
return user
return None