Flowdeck 7.85.2 — HUB-19 : propagation des rôles du Hub (registre D3(a)) #53

Merged
bruno merged 1 commits from hub19-roles-flowdeck into main 2026-11-06 11:32:11 -05:00
Owner

Périmètre — HUB-19, suite du pilote ShaarIt (0.7.0, en production) : Flowdeck consomme le registre des rôles du Hub (plan Hub v2, décision D3(a)) pour l'application flowdeck. Branche hub19-roles-flowdeck sur main (v7.85.1, commit distant 5203b62 — vérifié par l'API avant la PR, aucun écart), version 7.85.2 (VERSION + littéral app/main.py + entrée CHANGELOG). Aucune fusion : branche + PR seulement.

Contrat — À l'ouverture de session draco, consultation de GET {hub}/api/roles/flowdeck en relayant l'en-tête Cookie complet de la requête, Accept: application/json, délai 2 s → 200 {"app","sub","role","explicite","ttl_secondes":60}, rôle ∈ {aucun, utilisateur, administrateur}. Nouveau client app/services/hub_roles.py, portage Python du patron Rust du pilote (hub_roles.rs) : cache mémoire par sub, TTL 60 s, horodatage posé avant l'appel (échec = ancien cache conservé, pas de rafale). URL du Hub résolue comme la barre commune (draco_urls.hub_url() : explicite HUB_URL > hôte de la requête > dérivation par l'hôte sœur de l'agent > défaut officiel) — jamais d'URL dev figée.

Effets (sessions draco seulement)

  1. Rôle connu aucun → refus avant la création de la session locale, au point d'insertion unique où un cookie draco aboutit à une session : le pont GET /auth/draco, qui appelle désormais user_for_draco(..., refuser_aucun=True). Réponse 403 en français nommant le registre des rôles du Hub. Exemptions (patron du pilote) : session locale préexistante (accès de secours par mot de passe — le pont ne refuse pas), page de connexion, santé (/api/health) et statiques (jamais passées par le pont), contrats API propres (OAuth externe Gitea/GitHub et jetons Bearer/SCIM de Flowdeck ne sont pas draco, intacts), et recherche fédérée /api/search (repli draco sans création de session : défaut refuser_aucun=False, aucun refus nouveau).
  2. Surfaces d'administration de l'instance gardées par hub_roles.admin_hub_ok (session draco + rôle connu → administrateur exigé, en plus du drapeau local) : /api/admin/* (admin_required), configuration des fournisseurs de l'agent (agent._current_admin), journal d'audit unifié (branche session), administration SCIM/domaines (branche session), configuration SSO (branche session de _require_admin). Les voies Bearer de ces surfaces et l'administration d'espace de travail (rôles de membre) ne sont pas touchées.
  3. Ordre JIT/refus : RoleAucunRefuse est levée dans user_for_draco après validation du jeton et extraction du sub, avant la résolution de compte (_linked_user) et donc avant le provisionnement JIT de HUB-15 — aucun compte ni lien draco_links n'est créé pour un sub refusé (vérifié par test). Le provisionnement JIT lui-même est inchangé.

Repli — Toute erreur (401/404/réseau/JSON illisible/rôle hors ensemble) = rôle inconnu → comportement actuel intégralement conservé ; le registre ne crée jamais un verrouillage nouveau.

Tests lus — Nouveau tests/test_hub_roles.py : 28 réussis (contrat exact de l'appel Hub — URL, cookie complet, Accept, délai 2 s —, cache par sub, ancien cache après échec, erreurs → inconnu ; intégration : 403 français au pont, refus avant JIT avec compte et lien absents, rôle utilisateur avec JIT intact, repli rôle inconnu, session préexistante exemptée, garde /api/admin/* selon le rôle). Balayage de régression (hub_roles, fusion_draco, draco_urls, barre, SSO v67, API publique v2, recherche, PWA, agent, audit, permissions) : 266 réussis, 4 échecs — tous préexistants et reconfirmés identiques sur main vierge : les 3 du fonds HUB-15 (test_audit_p0_fixes : test_csp_no_cdn_and_vendor, test_http_client_shared_and_loop_scoped, test_og_metadata_rejects_private_host) et test_public_api_v2::test_v2_webhooks_crud (fonds connu depuis la 7.84.11).

**Périmètre** — HUB-19, suite du pilote ShaarIt (0.7.0, en production) : Flowdeck consomme le registre des rôles du Hub (plan Hub v2, décision D3(a)) pour l'application `flowdeck`. Branche `hub19-roles-flowdeck` sur `main` (v7.85.1, commit distant 5203b62 — vérifié par l'API avant la PR, aucun écart), version **7.85.2** (VERSION + littéral `app/main.py` + entrée CHANGELOG). **Aucune fusion** : branche + PR seulement. **Contrat** — À l'ouverture de session draco, consultation de `GET {hub}/api/roles/flowdeck` en relayant l'en-tête Cookie complet de la requête, `Accept: application/json`, délai 2 s → 200 `{"app","sub","role","explicite","ttl_secondes":60}`, rôle ∈ {`aucun`, `utilisateur`, `administrateur`}. Nouveau client `app/services/hub_roles.py`, portage Python du patron Rust du pilote (`hub_roles.rs`) : cache mémoire par `sub`, TTL 60 s, horodatage posé **avant** l'appel (échec = ancien cache conservé, pas de rafale). URL du Hub résolue comme la barre commune (`draco_urls.hub_url()` : explicite `HUB_URL` > hôte de la requête > dérivation par l'hôte sœur de l'agent > défaut officiel) — jamais d'URL dev figée. **Effets (sessions draco seulement)** 1. Rôle connu `aucun` → refus **avant** la création de la session locale, au point d'insertion unique où un cookie draco aboutit à une session : le pont `GET /auth/draco`, qui appelle désormais `user_for_draco(..., refuser_aucun=True)`. Réponse 403 en français nommant le registre des rôles du Hub. Exemptions (patron du pilote) : session locale préexistante (accès de secours par mot de passe — le pont ne refuse pas), page de connexion, santé (`/api/health`) et statiques (jamais passées par le pont), contrats API propres (OAuth externe Gitea/GitHub et jetons Bearer/SCIM de Flowdeck ne sont pas draco, intacts), et recherche fédérée `/api/search` (repli draco sans création de session : défaut `refuser_aucun=False`, aucun refus nouveau). 2. Surfaces d'administration de l'instance gardées par `hub_roles.admin_hub_ok` (session draco + rôle connu → `administrateur` exigé, en plus du drapeau local) : `/api/admin/*` (`admin_required`), configuration des fournisseurs de l'agent (`agent._current_admin`), journal d'audit unifié (branche session), administration SCIM/domaines (branche session), configuration SSO (branche session de `_require_admin`). Les voies Bearer de ces surfaces et l'administration d'espace de travail (rôles de membre) ne sont pas touchées. 3. **Ordre JIT/refus** : `RoleAucunRefuse` est levée dans `user_for_draco` après validation du jeton et extraction du `sub`, **avant** la résolution de compte (`_linked_user`) et donc avant le provisionnement JIT de HUB-15 — aucun compte ni lien `draco_links` n'est créé pour un `sub` refusé (vérifié par test). Le provisionnement JIT lui-même est inchangé. **Repli** — Toute erreur (401/404/réseau/JSON illisible/rôle hors ensemble) = rôle **inconnu** → comportement actuel intégralement conservé ; le registre ne crée jamais un verrouillage nouveau. **Tests lus** — Nouveau `tests/test_hub_roles.py` : **28 réussis** (contrat exact de l'appel Hub — URL, cookie complet, Accept, délai 2 s —, cache par `sub`, ancien cache après échec, erreurs → inconnu ; intégration : 403 français au pont, refus avant JIT avec compte et lien absents, rôle `utilisateur` avec JIT intact, repli rôle inconnu, session préexistante exemptée, garde `/api/admin/*` selon le rôle). Balayage de régression (hub_roles, fusion_draco, draco_urls, barre, SSO v67, API publique v2, recherche, PWA, agent, audit, permissions) : **266 réussis, 4 échecs — tous préexistants et reconfirmés identiques sur `main` vierge** : les 3 du fonds HUB-15 (`test_audit_p0_fixes` : `test_csp_no_cdn_and_vendor`, `test_http_client_shared_and_loop_scoped`, `test_og_metadata_rejects_private_host`) et `test_public_api_v2::test_v2_webhooks_crud` (fonds connu depuis la 7.84.11).
bruno added 1 commit 2026-11-06 10:37:23 -05:00
Flowdeck 7.85.2 — HUB-19 : propagation des rôles du Hub (registre D3(a))
FlowDeck CI / test (push) Failing after 1s
FlowDeck CI / docker (push) Skipped
FlowDeck CI / lint (push) Failing after 12s
FlowDeck CI / test (pull_request) Failing after 2s
FlowDeck CI / docker (pull_request) Skipped
FlowDeck CI / lint (pull_request) Failing after 14s
bd5357f589
bruno merged commit e6f5cff870 into main 2026-11-06 11:32:11 -05:00
Sign in to join this conversation.