Périmètre — Propagation des rôles du Hub à Kanbante (HUB-19, suite du pilote ShaarIt 0.7.0 en production), hôte Projets/kanbante, clé d'app kanbante, version 0.46.2. Branche portée sur le main distant actuel (v0.46.1, barre v0.5.0 incluse — arbre comparé fichier par fichier via l'API avant la PR, aucune différence non voulue). Aucune fusion : cette PR attend la revue de Bruno.
Contrat (D3(a)) — Nouveau client app/hub_roles.py (portage Python de hub_roles.rs du pilote) : à l'ouverture de session draco, GET {hub}/api/roles/kanbante en relayant l'en-tête Cookie complet de la requête, Accept: application/json, délai 2 s → rôle ∈ {aucun, utilisateur, administrateur}. 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 (resoudre_urls_draco : DRACO_HUB_URL explicite > hôte public de la requête > dérivation par l'hôte sœur de l'agent > défaut officiel) — jamais d'URL dev figée. Toute erreur = rôle inconnu → comportement actuel.
Effets (sessions établies par le pont draco seulement)
Rôle connu aucun → le pont refuse (403, message explicite en français) : aucune session Kanbante ouverte par draco pour ce sub.
/admin (et ses actions, même garde _require_admin) : session établie par draco + rôle du registre connu ⇒ administrateur du registre exigé en plus du rôle local admin. Rôle inconnu ou session native → règles locales inchangées.
Ordre consultation/création — Dans draco_bridge, la consultation du Hub précède tout : la liaison à une session native préexistante, resolve_draco_user() (le point d'insertion HUB-16, inchangé) et donc toute création JIT. Un sub refusé ne reçoit aucun compte et aucune liaison. La session ouverte par le pont porte un marqueur « établie par draco » couvert par la signature du cookie (user.expiry.draco.hmac ; le format natif historique reste lu tel quel) — c'est lui qui soumet /admin au registre, pas la simple présence d'un cookie draco.
Non touchés — session native préexistante, connexion native (mot de passe), Basic d'environnement, jetons kbt_, /api/search, droits internes, réconciliation Gitea par étiquettes (le piège « exactement une étiquette reconnue » n'est pas le sujet).
Repli — Hub injoignable, en erreur ou réponse illisible ⇒ rôle inconnu ⇒ comportement d'avant la 0.46.2, partout. Le registre ne crée jamais un verrouillage nouveau.
Tests (chiffres lus dans cet environnement) — tests/test_hub_roles.py nouveau (14 tests : contrat d'appel et cookie relayé, cache/TTL, échec sans rafale avec ancien cache conservé, réponses illisibles, résolution d'URL par hôte dev et variable explicite, marqueur signé infalsifiable, refus aucun sans création ni liaison, JIT utilisateur, repli inconnu, /admin gardé pour session draco — refusé en utilisateur malgré le rôle local admin, accepté en administrateur, repli local si inconnu, session native non soumise). Suite complète : 409 réussis / 5 échecs / 1 sauté, contre 395 / 5 / 1 sur le main vierge 0.46.1 dans le même environnement — les 5 échecs sont strictement identiques au fond vierge (préexistants, sans rapport) : test_palier18.py::test_snapshot_write_through_and_hydration, test_palier21.py::test_gitea_download_follows_browser_download_url, test_palier5.py::test_mcp_list_tools, test_palier5.py::test_mcp_call_tool, test_mobile.py::test_menu_compte_draco_fonctionnel (celui relevé en vague B, reconfirmé sur main vierge).
Documentation : section « Rôles du Hub (HUB-19) » dans docs/correspondance-draco.md, entrée de changelog 0.46.2.
**Périmètre** — Propagation des rôles du Hub à Kanbante (HUB-19, suite du pilote ShaarIt 0.7.0 en production), hôte `Projets/kanbante`, clé d'app `kanbante`, version **0.46.2**. Branche portée sur le `main` distant actuel (v0.46.1, barre v0.5.0 incluse — arbre comparé fichier par fichier via l'API avant la PR, aucune différence non voulue). **Aucune fusion** : cette PR attend la revue de Bruno.
**Contrat (D3(a))** — Nouveau client `app/hub_roles.py` (portage Python de `hub_roles.rs` du pilote) : à l'ouverture de session draco, `GET {hub}/api/roles/kanbante` en relayant l'en-tête Cookie complet de la requête, `Accept: application/json`, délai 2 s → rôle ∈ {`aucun`, `utilisateur`, `administrateur`}. 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 (`resoudre_urls_draco` : `DRACO_HUB_URL` explicite > hôte public de la requête > dérivation par l'hôte sœur de l'agent > défaut officiel) — jamais d'URL dev figée. **Toute erreur = rôle inconnu → comportement actuel.**
**Effets (sessions établies par le pont draco seulement)**
1. Rôle connu `aucun` → le pont refuse (403, message explicite en français) : aucune session Kanbante ouverte par draco pour ce `sub`.
2. `/admin` (et ses actions, même garde `_require_admin`) : session établie par draco + rôle du registre connu ⇒ `administrateur` du registre exigé **en plus** du rôle local admin. Rôle inconnu ou session native → règles locales inchangées.
**Ordre consultation/création** — Dans `draco_bridge`, la consultation du Hub précède tout : la liaison à une session native préexistante, `resolve_draco_user()` (le point d'insertion HUB-16, inchangé) et donc toute création JIT. Un `sub` refusé ne reçoit **aucun compte** et aucune liaison. La session ouverte par le pont porte un marqueur « établie par draco » **couvert par la signature** du cookie (`user.expiry.draco.hmac` ; le format natif historique reste lu tel quel) — c'est lui qui soumet `/admin` au registre, pas la simple présence d'un cookie draco.
**Non touchés** — session native préexistante, connexion native (mot de passe), Basic d'environnement, jetons `kbt_`, `/api/search`, droits internes, réconciliation Gitea par étiquettes (le piège « exactement une étiquette reconnue » n'est pas le sujet).
**Repli** — Hub injoignable, en erreur ou réponse illisible ⇒ rôle inconnu ⇒ comportement d'avant la 0.46.2, partout. Le registre ne crée jamais un verrouillage nouveau.
**Tests (chiffres lus dans cet environnement)** — `tests/test_hub_roles.py` nouveau (14 tests : contrat d'appel et cookie relayé, cache/TTL, échec sans rafale avec ancien cache conservé, réponses illisibles, résolution d'URL par hôte dev et variable explicite, marqueur signé infalsifiable, refus `aucun` sans création ni liaison, JIT `utilisateur`, repli inconnu, `/admin` gardé pour session draco — refusé en `utilisateur` malgré le rôle local admin, accepté en `administrateur`, repli local si inconnu, session native non soumise). Suite complète : **409 réussis / 5 échecs / 1 sauté**, contre **395 / 5 / 1** sur le `main` vierge 0.46.1 dans le même environnement — les 5 échecs sont **strictement identiques** au fond vierge (préexistants, sans rapport) : `test_palier18.py::test_snapshot_write_through_and_hydration`, `test_palier21.py::test_gitea_download_follows_browser_download_url`, `test_palier5.py::test_mcp_list_tools`, `test_palier5.py::test_mcp_call_tool`, `test_mobile.py::test_menu_compte_draco_fonctionnel` (celui relevé en vague B, reconfirmé sur main vierge).
Documentation : section « Rôles du Hub (HUB-19) » dans `docs/correspondance-draco.md`, entrée de changelog 0.46.2.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Périmètre — Propagation des rôles du Hub à Kanbante (HUB-19, suite du pilote ShaarIt 0.7.0 en production), hôte
Projets/kanbante, clé d'appkanbante, version 0.46.2. Branche portée sur lemaindistant actuel (v0.46.1, barre v0.5.0 incluse — arbre comparé fichier par fichier via l'API avant la PR, aucune différence non voulue). Aucune fusion : cette PR attend la revue de Bruno.Contrat (D3(a)) — Nouveau client
app/hub_roles.py(portage Python dehub_roles.rsdu pilote) : à l'ouverture de session draco,GET {hub}/api/roles/kanbanteen relayant l'en-tête Cookie complet de la requête,Accept: application/json, délai 2 s → rôle ∈ {aucun,utilisateur,administrateur}. Cache mémoire parsub, TTL 60 s, horodatage posé avant l'appel (échec = ancien cache conservé, pas de rafale). URL du Hub résolue comme la barre commune (resoudre_urls_draco:DRACO_HUB_URLexplicite > hôte public de la requête > dérivation par l'hôte sœur de l'agent > défaut officiel) — jamais d'URL dev figée. Toute erreur = rôle inconnu → comportement actuel.Effets (sessions établies par le pont draco seulement)
aucun→ le pont refuse (403, message explicite en français) : aucune session Kanbante ouverte par draco pour cesub./admin(et ses actions, même garde_require_admin) : session établie par draco + rôle du registre connu ⇒administrateurdu registre exigé en plus du rôle local admin. Rôle inconnu ou session native → règles locales inchangées.Ordre consultation/création — Dans
draco_bridge, la consultation du Hub précède tout : la liaison à une session native préexistante,resolve_draco_user()(le point d'insertion HUB-16, inchangé) et donc toute création JIT. Unsubrefusé ne reçoit aucun compte et aucune liaison. La session ouverte par le pont porte un marqueur « établie par draco » couvert par la signature du cookie (user.expiry.draco.hmac; le format natif historique reste lu tel quel) — c'est lui qui soumet/adminau registre, pas la simple présence d'un cookie draco.Non touchés — session native préexistante, connexion native (mot de passe), Basic d'environnement, jetons
kbt_,/api/search, droits internes, réconciliation Gitea par étiquettes (le piège « exactement une étiquette reconnue » n'est pas le sujet).Repli — Hub injoignable, en erreur ou réponse illisible ⇒ rôle inconnu ⇒ comportement d'avant la 0.46.2, partout. Le registre ne crée jamais un verrouillage nouveau.
Tests (chiffres lus dans cet environnement) —
tests/test_hub_roles.pynouveau (14 tests : contrat d'appel et cookie relayé, cache/TTL, échec sans rafale avec ancien cache conservé, réponses illisibles, résolution d'URL par hôte dev et variable explicite, marqueur signé infalsifiable, refusaucunsans création ni liaison, JITutilisateur, repli inconnu,/admingardé pour session draco — refusé enutilisateurmalgré le rôle local admin, accepté enadministrateur, repli local si inconnu, session native non soumise). Suite complète : 409 réussis / 5 échecs / 1 sauté, contre 395 / 5 / 1 sur lemainvierge 0.46.1 dans le même environnement — les 5 échecs sont strictement identiques au fond vierge (préexistants, sans rapport) :test_palier18.py::test_snapshot_write_through_and_hydration,test_palier21.py::test_gitea_download_follows_browser_download_url,test_palier5.py::test_mcp_list_tools,test_palier5.py::test_mcp_call_tool,test_mobile.py::test_menu_compte_draco_fonctionnel(celui relevé en vague B, reconfirmé sur main vierge).Documentation : section « Rôles du Hub (HUB-19) » dans
docs/correspondance-draco.md, entrée de changelog 0.46.2.