ObsiGate 2.85.0 — HUB-22 : API machine des sessions draco (liste et révocation, #227) #68

Merged
bruno merged 14 commits from hub22-sessions-machine into main 2026-11-06 11:25:27 -05:00
Owner

HUB-22 (partie ObsiGate, vague C du plan Hub v2.1) — #227. Le Hub (0.17.0) doit lister les sessions actives d'un utilisateur et les révoquer une à une ou toutes, via le canal « jti » livré en HUB-13 (#226). Aucune route machine « sessions » n'existait : cette PR la crée. Aucune fusion — branche + PR seulement.

Routes livrées (garde require_machine_admin, en-têtes X-Draco-Machine-Key / X-Draco-Actor, erreurs detail FastAPI comme l'existant)

  • GET /api/admin/machine/comptes/{username}/sessions → 200 {"username", "sessions": [{"jti", "exp", "expire_le" (ISO 8601 UTC), "revoquee"}]} ; 404 compte inconnu ou API non configurée.
  • POST /api/admin/machine/comptes/{username}/sessions/{jti}/revoquer → 200 {"jti", "revoquee": true} ; 404 si le jti n'est pas dans l'ensemble actif de cet utilisateur (jamais de révocation cross-utilisateur).
  • POST /api/admin/machine/comptes/{username}/sessions/revoquer-toutes → 200 {"revoquees": n} — réutilise revoke_all_for_user, sans désactiver le compte (déconnexion globale distincte de la désactivation).

Backend

  • backend/draco_session.py : issued_sessions_for_user(sub) (sessions actives triées par exp croissant, purge des expirés au passage) et revoke_one_for_user(sub, jti) (révoque via revoke() seulement si le jti appartient à l'ensemble émis du sub et n'est pas expiré ; booléen).
  • backend/routers/comptes_machine.py : les trois routes + clé d'identité factorisée _identifiant_sessions (le même sub que _revoquer_sessions : id, à défaut username) ; écritures journalisées (session_revoquee, sessions_revoquees) via log_compte_admin.

Version et docs

  • 2.85.0 via scripts/bump_version.py --set 2.85.0 (dérivés synchronisés) ; base = main distant 2.84.1 (HUB-18) — le diff ne contient que cette livraison (vérifié fichier par fichier par hachages).
  • CHANGELOG.md [2.85.0], Roadmap #227 (nouvel ID stable), fiche docs/features/hub-sessions-machine-227.md. Aucun impact frontend (pas d'i18n).

Tests (lus)

  • Ciblés : tests/test_draco_session.py + tests/test_comptes_machine.py + tests/test_version.py = 102/102 (dont TestSessions : liste, révocation unitaire succès + 404 cross-utilisateur, tout-révoquer sans désactivation, garde 401/404, journalisation ; et les unitaires du registre : tri, purge des expirés, refus cross-utilisateur/expiré).
  • ruff check backend/ : 0 erreur. mypy backend/ --ignore-missing-imports : 0 erreur (127 fichiers).
  • Suite complète : non obtenue — l'environnement d'exécution a gelé les écritures disque par intermittence pendant la fenêtre (premier run bloqué ~19 min, relances mortes sur tempfile) ; le périmètre ciblé ci-dessus couvre l'intégralité du code touché. À confirmer par le CI de la PR.

Note de livraison (transparence)

Le git push local étant bloqué par ce même gel d'écritures, la branche a été poussée via l'API Contents de Gitea (14 commits, un par fichier, même message). Un premier PUT a brièvement commité backend/draco_session.py sur main (champ new_branch_name ignoré par l'API) : revert immédiat (commit 51275105), contenu de main vérifié revenu à l'état 2.84.1 ; il en reste deux commits (erreur + revert) dans l'historique de main, sans aucun écart de contenu. Redéploiement Docker requis après fusion.

**HUB-22 (partie ObsiGate, vague C du plan Hub v2.1) — #227.** Le Hub (0.17.0) doit lister les sessions actives d'un utilisateur et les révoquer une à une ou toutes, via le canal « jti » livré en HUB-13 (#226). Aucune route machine « sessions » n'existait : cette PR la crée. **Aucune fusion** — branche + PR seulement. ## Routes livrées (garde require_machine_admin, en-têtes X-Draco-Machine-Key / X-Draco-Actor, erreurs detail FastAPI comme l'existant) - `GET /api/admin/machine/comptes/{username}/sessions` → 200 `{"username", "sessions": [{"jti", "exp", "expire_le" (ISO 8601 UTC), "revoquee"}]}` ; 404 compte inconnu ou API non configurée. - `POST /api/admin/machine/comptes/{username}/sessions/{jti}/revoquer` → 200 `{"jti", "revoquee": true}` ; **404** si le jti n'est pas dans l'ensemble actif de cet utilisateur (jamais de révocation cross-utilisateur). - `POST /api/admin/machine/comptes/{username}/sessions/revoquer-toutes` → 200 `{"revoquees": n}` — réutilise `revoke_all_for_user`, **sans désactiver le compte** (déconnexion globale distincte de la désactivation). ## Backend - `backend/draco_session.py` : `issued_sessions_for_user(sub)` (sessions actives triées par exp croissant, purge des expirés au passage) et `revoke_one_for_user(sub, jti)` (révoque via `revoke()` seulement si le jti appartient à l'ensemble émis du sub et n'est pas expiré ; booléen). - `backend/routers/comptes_machine.py` : les trois routes + clé d'identité factorisée `_identifiant_sessions` (le même sub que `_revoquer_sessions` : id, à défaut username) ; écritures journalisées (`session_revoquee`, `sessions_revoquees`) via `log_compte_admin`. ## Version et docs - **2.85.0** via `scripts/bump_version.py --set 2.85.0` (dérivés synchronisés) ; base = main distant **2.84.1** (HUB-18) — le diff ne contient que cette livraison (vérifié fichier par fichier par hachages). - `CHANGELOG.md` [2.85.0], Roadmap **#227** (nouvel ID stable), fiche `docs/features/hub-sessions-machine-227.md`. Aucun impact frontend (pas d'i18n). ## Tests (lus) - Ciblés : `tests/test_draco_session.py` + `tests/test_comptes_machine.py` + `tests/test_version.py` = **102/102** (dont `TestSessions` : liste, révocation unitaire succès + 404 cross-utilisateur, tout-révoquer sans désactivation, garde 401/404, journalisation ; et les unitaires du registre : tri, purge des expirés, refus cross-utilisateur/expiré). - `ruff check backend/` : **0 erreur**. `mypy backend/ --ignore-missing-imports` : **0 erreur** (127 fichiers). - Suite complète : **non obtenue** — l'environnement d'exécution a gelé les écritures disque par intermittence pendant la fenêtre (premier run bloqué ~19 min, relances mortes sur tempfile) ; le périmètre ciblé ci-dessus couvre l'intégralité du code touché. À confirmer par le CI de la PR. ## Note de livraison (transparence) Le `git push` local étant bloqué par ce même gel d'écritures, la branche a été poussée via l'API Contents de Gitea (14 commits, un par fichier, même message). Un premier PUT a brièvement commité `backend/draco_session.py` sur `main` (champ `new_branch_name` ignoré par l'API) : **revert immédiat** (commit `51275105`), contenu de `main` vérifié revenu à l'état 2.84.1 ; il en reste deux commits (erreur + revert) dans l'historique de `main`, sans aucun écart de contenu. Redéploiement Docker requis après fusion.
bruno added 14 commits 2026-11-06 11:09:03 -05:00
feat: HUB-22 — API machine des sessions draco : liste et révocation des sessions (2.85.0, #227)
CI / lint (pull_request) Successful in 1m17s
CI / security (pull_request) Successful in 17s
CI / test (pull_request) Successful in 3m34s
CI / build (pull_request) Successful in 17s
CI / e2e (pull_request) Failing after 16m29s
c157a22668
bruno merged commit a3f76e9b0c into main 2026-11-06 11:25:27 -05:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Projets/ObsiGate#68