Aller au contenu

ADR-0034 — Propriété du modèle IAM et localisation du Policy Decision Point

Date : 2026-08-30 Catégorie : A (modèle d'autorisation transverse) Décideur : Lead architecte DYNORS Statut : Acceptée — validée architecte le 2026-08-30 ; validation CTO à programmer Tranche : la réserve « spec policy point ABAC dans 60 j » de ADR-2026-05-15-iam-rbac-abac-trust-layer (échéance dépassée depuis le 2026-08-20) Clarifie : [[0003-entitlements-source-agnostique-events]], docs/adr/ADR-2026-05-15-bounded-contexts-ecosysteme-dynors, dynors-docs/docs/05-architecture-si/dynors-auth.md Complétée par : [[0031-habilitation-projet-affectation-projection-locale]], [[0032-resolution-habilitation-user-group]], [[0033-capacites-contextualisees-politique-declarative]]


Contexte

En câblant l'habilitation projet de SIRRAT (ADR-0031 → 0033), un audit de l'existant a mis au jour une contradiction documentaire antérieure de trois mois, entre des textes tous adoptés :

Source Ce qu'elle dit de la propriété des rôles et permissions
ADR-2026-05-15-bounded-contexts (ADOPTÉ 2026-06-21) Le contexte Identité & Accès (dynors-auth + dynors-security + Trust Layer) est propriétaire de « Utilisateur, rôle, permission, délégation, session »
dynors-auth.md §chapeau « Périmètre strictement limité à l'identité. Les rôles, permissions et droits d'accès aux produits sont résolus par dynors-entitlements »
dynors-auth.md §Références « dynors-entitlements — moteur d'autorisation runtime (rôles, droits, produits) »
ADR-2026-05-15-iam-rbac-abac-trust-layer §1 Réduit entitlements à l'étage 3 : « le produit/feature est-il souscrit/activé ? » — alors que son propre document de référence distingue quatre subject_type, dont USER : « l'utilisateur a-t-il un rôle dans une app ? »

ADR-0033 a tranché implicitement en plaçant la politique de traduction dans dynors-entitlements, sans citer aucun de ces textes. Elle a rendu la contradiction visible sans la nommer.

Ce que la contradiction cache réellement

Les textes ne se contredisent pas sur les faits. Ils confondent deux questions différentes :

QUI POSSÈDE LE CONCEPT          ≠          QUEL SERVICE EXÉCUTE LA DÉCISION

« Les rôles sont résolus par entitlements » est une phrase sur le runtime. La table des bounded contexts est une phrase sur la gouvernance. Lues comme si elles répondaient à la même question, elles s'excluent ; lues chacune à sa place, elles sont toutes deux vraies.


Décision

1. La formulation de référence

Le contexte Identité & Accès gouverne le modèle d'autorisation ; dynors-entitlements en constitue le moteur d'évaluation et de projection des droits effectifs.

Cette phrase est normative. Elle doit être reprise telle quelle dans dynors-auth.md, dynors-entitlements.md et toute documentation qui aborde la propriété des rôles.

2. Répartition — qui possède quoi

IDENTITÉ & ACCÈS  (gouvernance)
    définit et gouverne :  rôles métier · capacités/permissions · règles d'autorisation
                           délégation · modèle de session
    ne calcule rien.

TAKKU  (Delivery & Staffing)
    possède le FAIT :      personne/groupe × projet × rôle métier × période
    ne définit ni rôle ni capacité.

dynors-entitlements  (PDP / PEP runtime)
    ÉVALUE :               faits + politique déclarée + attributs
    PRODUIT :              droits effectifs, projetés vers les consommateurs
    n'est PAS propriétaire métier de la politique.

dynors-auth
    identité, authentification, session, émission du token d'élévation.
    Ne porte ni rôle ni permission — « périmètre strictement limité à l'identité ».

CONSOMMATEURS  (SIRRAT, GitLab, …)
    ENFORCENT :            require(subject, capability, contexte)
    ne définissent rien, n'interprètent rien, ne complètent rien.

3. Pourquoi entitlements et pas ailleurs

Le choix n'est pas de convenance ; quatre contraintes déjà adoptées l'imposent.

Contrainte Source Ce qu'elle exclut
Le JWT reste minimal ; les attributs ABAC sont résolus côté service, jamais empilés dans le token ADR IAM §1 + amendement B Exclut dynors-auth : l'émetteur ne porte pas les attributs
« Périmètre strictement limité à l'identité » dynors-auth.md Exclut dynors-auth une seconde fois
« Interdiction de recoder une brique existante » pragmatisme-preuves Exclut la création d'un sixième composant « policy service »
DecisionLog, /check, cache 60 s, client fail-closed code dynors-platform/entitlements + ADR-0003 L'ossature d'un PDP y est déjà construite ; la dupliquer serait un gaspillage doublé d'un risque

4. Ce qui change pour ADR-0003

ADR-0003 §1 dit : « Il ne décide rien par lui-même ». ADR-0033 §0 l'a amendée en « ne prend aucune décision discrétionnaire ». Cet amendement est confirmé, et précisé ici :

  • entitlements n'invente aucune règle — il applique une politique déclarée, versionnée, auditée ;
  • entitlements n'est pas l'auteur de cette politique — l'auteur est la gouvernance IAM ;
  • entitlements est le seul point où la règle rencontre les faits.

Le reste d'ADR-0003 — projection source-agnostique, multi-producteurs, UPSERT idempotent par event_id, fraîcheur 60 s, audit — est inchangé.

5. Autorité d'administration — capacités, pas identités

Le pouvoir d'administrer l'IAM est lui-même exprimé en capacités portées par le modèle, avec un scope. Il n'y a pas de personne privilégiée dans le code.

POLICY_ADMIN        définir/modifier la politique (rôle → capacités)
ROLE_ADMIN          créer/modifier un rôle métier au catalogue
ASSIGNMENT_ADMIN    affecter une personne/un groupe à un projet
GRANT_ADMIN         accorder une capacité en octroi direct
AUDIT_READ          consulter l'historique des décisions et des changements

scope :  global  |  application=<code>  |  project=<code>

(Noms indicatifs, susceptibles d'évoluer ; ce qui est décidé est le modèle, pas le vocabulaire.)

Phase bootstrap — aujourd'hui

DYNORS compte deux à trois personnes. Le CTO / admin groupe reçoit les cinq capacités en scope global. C'est suffisant, et créer aujourd'hui un IAM Security Officer, un Entitlement Manager et un comité d'approbation pour trois personnes serait la sur-structuration que operating-model §3 interdit explicitement.

Interdiction formelle : ne jamais écrire if (user == CTO), ni aucun équivalent. Le CTO reçoit ces capacités par le même modèle IAM que tout le monde. Une exception codée pour une personne est un chemin d'autorisation que le modèle ne connaît pas, donc que la revue ne verra pas et que la révocation n'atteindra pas.

Croissance — la même mécanique, d'autres scopes

owner produit SIRRAT      →  POLICY_ADMIN application=sirrat
chef de projet DAWALALE   →  ASSIGNMENT_ADMIN project=dawalale
RH / staffing             →  ASSIGNMENT_ADMIN scope=organisation
security officer          →  GRANT_ADMIN global + AUDIT_READ global

Aucune refonte n'est nécessaire pour y arriver : ce sont les mêmes capacités, dans un scope plus étroit. Les rôles P2/P3 de operating-model §3 et le registre d'ownership produit (§2 du même ADR) fournissent déjà les titulaires — il n'y a pas de rôle d'entreprise à inventer.

L'invariant qui structure tout

Attribuer un rôle et définir ce que permet ce rôle sont deux pouvoirs différents.

chef de projet DAWALALE
  ✅ peut attribuer DEVELOPER sur DAWALALE          (ASSIGNMENT_ADMIN project=dawalale)
  ❌ ne peut pas décider que DEVELOPER obtient FORGE_CONFIGURE   (POLICY_ADMIN)

Confondre les deux est le défaut classique des IAM maison : celui qui distribue les rôles finit par pouvoir redéfinir ce qu'ils valent, et la séparation des pouvoirs disparaît sans que personne n'ait décidé de la supprimer.

Ce qui n'est pas construit maintenant : les rôles P2/P3, le workflow d'approbation, les écrans d'administration. Seuls les scopes de délégation sont préparés.

6. Frontière Tenant IAM / Internal Workforce IAM

Deux modèles portent des noms voisins et ne doivent jamais être confondus.

TENANT IAM                                  INTERNAL WORKFORCE IAM
RoleDefinition / PermissionDefinition       BusinessRole / Capability / Assignment
dynors-security.models                      TAKKU + entitlements + consommateurs

portée   : tenantCode                       portée   : personne × projet × cercle
grammaire: resource × action (CRUD)         grammaire: capacité contextualisée
usage    : sécurité d'un tenant CLIENT      usage    : habilitation d'un COLLABORATEUR
durée    : configuration, pas d'expiration  durée    : projection expirable, provenance obligatoire

RoleDefinition et PermissionDefinition sont la configuration de sécurité d'un tenant produit/client — pas les habilitations internes DYNORS. Leur javadoc actuel (« Définie par TAKKU ») est exact dans ce périmètre et trompeur hors de lui.

Décision : documenter la frontière dans les deux sens, immédiatement. Un renommage (TenantRoleDefinition, TenantPermissionDefinition) reste possible ultérieurement — il touche un module publié et se décide à froid.

7. Attributs d'organisation — reportés, pas oubliés

L'étage ABAC de l'ADR IAM prévoit entité, BU, division, centre de coût, équipe, résolus depuis le contexte Organisation (ADR-05) — qui n'existe pas encore.

Ce contexte ne bloque pas les chantiers en cours. Pour P1, le contexte d'autorisation est :

subject × project × circle × capability

C'est une instance restreinte et suffisante de l'étage ABAC. Les attributs d'organisation seront ajoutés quand un cas d'usage réel les demandera, conformément au principe déjà adopté : « activation progressive, pas de hiérarchie complète avant le besoin réel ».

Construire aujourd'hui un contexte Organisation pour rendre le modèle théoriquement complet transformerait un chantier de sécurisation en programme IAM de groupe — et laisserait entre-temps les trous d'autorisation ouverts.


Conséquences

Positif. La contradiction documentaire est levée par une distinction, pas par un arbitrage arbitraire entre deux textes adoptés. SIRRAT devient un consommateur du modèle IAM DYNORS au lieu d'en être un second exemplaire. L'administration se distribue par scope sans refonte. Le faux ami RoleDefinition est neutralisé par la documentation avant d'avoir fait un dégât.

Coût / vigilance. La politique doit être gouvernée explicitement — elle ne se maintient pas seule. Le jour où un consommateur ajoutera « juste ce cas-là » en dur, la frontière retombe : des tests doivent la tenir, pas seulement des documents. Et tant que le contexte Organisation n'existe pas, l'étage ABAC reste restreint à project × circle : c'est assumé, pas oublié.

Ne change pas. Le JWT minimal. La centralisation dynors-auth. SLY et la signature de transit. Les cookies host-only. La délégation par token d'élévation. Le moteur d'approbation dynors-workflow.


Alternatives écartées

  • Faire d'entitlements le propriétaire métier des rôles. Contredit la table des bounded contexts, adoptée, et confond propriété et exécution. Écartée.
  • Faire de dynors-auth le PDP. Contredit son propre périmètre (« strictement limité à l'identité ») et l'interdiction d'empiler les attributs ABAC dans le token. Écartée.
  • Créer un composant « policy service » dédié. Frontière propre en théorie, brique prématurée en pratique : TAKKU → Policy Service → Entitlements → SIRRAT pour un besoin qui tient dans une table déclarative. Contraire à pragmatisme-preuves. Écartée.
  • Réutiliser RoleDefinition pour l'IAM interne. Mauvaise portée (tenant), mauvaise grammaire (CRUD), pas d'expiration ni de provenance. Écartée — c'est le faux ami de §6.
  • Attendre le contexte Organisation avant de terminer l'autorisation SIRRAT. Reporterait la fermeture de trous d'autorisation réels derrière un programme de plusieurs mois. Écartée (§7).

Références

  • docs/adr/ADR-2026-05-15-iam-rbac-abac-trust-layer.md (réserve tranchée ici)
  • docs/adr/ADR-2026-05-15-bounded-contexts-ecosysteme-dynors.md
  • docs/adr/ADR-2026-05-15-pattern-delegation.md · ADR-2026-05-15-moteur-workflow-approbation-transverse.md
  • docs/adr/ADR-2026-05-15-operating-model-modele-economique.md §2 et §3 (ownership, paliers P1/P2/P3)
  • docs/adr/DECISION_ADOPTION_LOT_2026-06-21.md amendement B
  • dynors-docs/docs/05-architecture-si/dynors-auth.md · dynors-entitlements.md
  • dynors-internal/applications/sirrat/docs/AUDIT_EXISTANT_GOUVERNANCE_ROLES_HABILITATIONS.md
  • dynors-internal/applications/sirrat/docs/RECONCILIATION_IAM_ADR_STRATEGIQUES_VS_0031_0032_0033.md