8.8 KiB
Correspondance draco par utilisateur (HUB-16, 0.46.0)
Kanbante participe au SSO de la suite dracodev : ObsiGate émet le
cookie draco_session (JWS HS256, claims sub, name, iat,
exp, jti), Kanbante le valide localement (app/draco.py) et le
pont GET /auth/draco le convertit en session Kanbante native.
Depuis la 0.46.0, un jeton draco valide désigne le compte Kanbante de cette identité — et aucun autre. L'ancienne hypothèse mono-utilisateur (« un jeton valide = l'opérateur ») a disparu. C'est ce qui fait tenir le critère de la suite : « un compte créé fonctionne dans toutes les applications ».
Où vit la correspondance
Dans le modèle existant des comptes : la colonne
users.draco_sub (texte, UNIQUE, présente depuis la 0.24.0)
porte le sub draco lié à chaque compte Kanbante.
models.get_user_by_draco(sub) est la résolution canonique ; la
règle de décision complète vit dans
app.accounts.resolve_draco_user(), seul point d'entrée du pont
et du contrôle draco de /api/search. La correspondance est donc
biunivoque : un sub ↔ un compte, garanti par la contrainte
d'unicité.
Résolution d'une connexion draco (/auth/draco)
Dans l'ordre :
- Session native déjà ouverte : si le navigateur porte à la
fois une session Kanbante et un cookie draco dont le
subn'est lié à aucun compte, lesubest lié au compte de la session (première visite doublement connectée — mécanisme historique, inchangé, aussi appliqué à la connexion native danslogin_submit). - Correspondance existante : la session du compte lié est ouverte. Un compte désactivé n'ouvre aucune session et n'est jamais contourné (voir § Désactivation).
- Compte d'amorçage — adoption conditionnée (fusion #145,
0.46.5) : s'il n'existe qu'un seul compte et que c'est un
admin actif sans liaison, ce compte (celui créé à
l'installation depuis l'environnement
KANBANTE_AUTH_USER/KANBANTE_AUTH_PASSWORD, Bruno) n'est adopté que dans l'un de ces deux cas :- (a) le
subentrant est « administrateur » pour kanbante au registre des rôles du Hub (le pont consulte le registre avant la résolution et transmet le rôle àresolve_draco_user(); Hub muet ou rôle moindre = pas d'adoption, dans le doute on ne lie pas) ; - (b) l'adoption est initiée depuis une session native
déjà authentifiée (point 1 ci-dessus, ou connexion native
doublement connectée) : l'utilisateur connecté lie
explicitement son propre compte.
Tout autre
subinconnu reçoit le parcours ordinaire (création JIT d'un compte membre propre, point 4) — jamais l'amorçage. Avant la 0.46.5, le premiersubvalide de passage adoptait l'amorçage quel qu'il soit : sur une instance fraîche, un simple utilisateur de la suite devenait l'administrateur local (audit « compte partout » du 2026-11-06). Les autres accès de l'amorçage restent inchangés dans tous les cas : connexion native avec le mot de passe du compte, et repli d'urgence par les identifiants d'environnement (formulaire et Basic), qui ne dépendent pas de draco.
- (a) le
- Création JIT : sinon, un compte Kanbante est créé pour cette identité (détail ci-dessous) et sa session est ouverte.
Un sub inconnu n'ouvre jamais la session de l'opérateur
d'environnement ni celle d'un compte existant non lié — y compris
si le nom affiché draco ressemble au nom d'un compte local : le
JIT crée toujours un compte nouveau (nom suffixé -2, -3…
en cas de collision), jamais une adoption.
Création JIT (juste-à-temps)
À la première connexion draco d'une identité sans correspondance :
- nom d'utilisateur : nom affiché des claims slugifié
(
Alice Exemple→alice-exemple), libre ou suffixé ; replidraco-<sub>si le nom est inexploitable ; - nom d'affichage : le
namedes claims ; - rôle :
member(utilisateur standard) — jamais admin ; - mot de passe local : secret aléatoire, haché (PBKDF2 comme
tous les comptes), jamais divulgué — l'accès normal passe
par draco. Un administrateur peut ensuite poser un mot de
passe local depuis
/admin(bouton « Réinitialiser ») si un accès local est voulu ; - espace : le compte rejoint l'espace Principal comme membre, comme tout utilisateur créé par l'administration ;
- le geste est journalisé (
draco.jitdans le journal d'administration).
Liaison par l'administrateur (comptes préexistants)
Pour associer un compte Kanbante existant à une identité draco sans attendre un premier passage :
- Se connecter à Kanbante avec un compte admin.
- Ouvrir Administration (
/admin), section Utilisateurs. - Dans la colonne Draco (sub) du compte visé, saisir le
subdraco de l'identité (l'identifiant du compte de suite chez l'émettrice, ObsiGate) et cliquer Lier. - La liaison est immédiate et journalisée (
draco.link.admin). Le bouton Délier de la même colonne la retire (draco.unlink.admin).
Gardes : un sub déjà lié à un autre compte est refusé avec un
message d'erreur (délier l'autre compte d'abord). L'administrateur
peut lier son propre compte — c'est la voie manuelle pour le
compte d'amorçage si le premier passage ne l'a pas lié.
Chaque utilisateur peut aussi voir sa propre liaison dans Mon profil → Liaison draco (SSO) et la délier lui-même.
Le registre matriciel des rôles par application côté Hub (carte HUB-19) lit cette correspondance ; la 0.46.0 ne livrait que le côté Kanbante, qui reste la source de vérité locale. La consommation du registre par Kanbante est décrite à la section suivante (0.46.2).
Rôles du Hub (HUB-19, 0.46.2)
Le registre des rôles du Hub (matrice par application, contrat
D3(a)) est consulté par app/hub_roles.py — portage du pilote
ShaarIt 0.7.0 : GET {hub}/api/roles/kanbante, en-tête Cookie
complet de la requête relayé, délai 2 s, cache mémoire par
sub de 60 s avec horodatage posé avant l'appel (un échec
conserve l'ancien cache et ne déclenche pas de rafale). L'URL
du Hub est celle de la barre commune (resoudre_urls_draco).
Toute erreur rend un rôle inconnu, qui vaut toujours
« comportement actuel » — jamais un verrouillage nouveau.
Effets, pour les seules sessions établies par le pont draco :
- Pont
/auth/draco: la consultation précède la liaison, la résolution de la correspondance et la création JIT. Rôle connuaucun→ refus explicite (403, en français) : aucune session ouverte par draco pour cesub, aucun compte créé. La session que le pont ouvre porte un marqueur « draco » couvert par la signature du cookie (user.expiry.draco.hmac). /admin(et ses actions, même garde_require_admin) : session établie par draco + rôle du registre connu ⇒ il fautadministrateurdans le registre, en plus du rôle local. Rôle inconnu ou session native ⇒ règles locales, inchangées.
Les autres accès ne sont pas draco et ne sont pas touchés :
session native préexistante, connexion native (mot de
passe), Basic d'environnement, jetons kbt_. Ni les droits
internes ni la réconciliation par étiquettes ne changent.
Surfaces voisines
GET /api/search(« Rechercher partout ») : le cookie draco n'y est plus accepté « en tant qu'opérateur ». Il faut que lesubdésigne un compte (correspondance existante). Cette surface ne consulte pas le registre et n'initie aucune liaison : elle ne peut donc jamais adopter le compte d'amorçage (fusion #145) — l'adoption a lieu au pont, ou pas. Aucune création JIT sur cette surface : la création a lieu à la première vraie connexion, par le pont. Les autres modes d'accès à/api/search(session, Basic, jetonkbt_) sont inchangés.- Désactivation : désactiver un compte dans
/admincoupe tous ses accès — session native, pont draco (la correspondance résout à « refusé ») et jetonskbt_. Réactiver le compte rétablit la correspondance telle quelle.
Non-régressions garanties
- Jetons personnels
kbt_: création, usage sur/mcpet/api/, révocation — inchangés ; un jeton n'ouvre toujours pas l'interface web. - Sessions propres Kanbante et connexion native (formulaire, mot de passe de la base) : inchangées, y compris la liaison automatique à la première visite doublement connectée.
- Authentification Basic (identifiants d'environnement, pour les scripts) : inchangée.
- Pont inerte sans
DRACO_SESSION_SECRET: sans secret configuré,/auth/dracorenvoie au login, comme avant. - La réconciliation Kanbante/Gitea par étiquettes (adoption d'une
colonne seulement si exactement une étiquette
kanban:*est reconnue) n'est pas touchée par cette carte.