[DTP-Worker 20260802_133549] Sprint 8 · buffer · roles_couverts (« 44 ») : enquête anti-dérive → NON-surface prouvée (3 manifestes importent la même fonction roles_by_portail sur l'unique contrat rbac_50_roles.json → transitivement mono-sourcé, un cross-gate serait redondant #5, contra le cross-check RBAC-50 qui re-dérive) + documentation du garde-fou dans ci/README.md pour prévenir un gate N+1 redondant

This commit is contained in:
Claude Code DTP Worker
2026-08-02 13:45:38 +00:00
parent 8dcedb092c
commit 576e78b6a9
2 changed files with 58 additions and 0 deletions
+20
View File
@@ -491,6 +491,26 @@ Marketing), un **retrait** (Compta absent — l'énumération tombe à 4 tandis
est aveugle. Cohérence croisée : `len(role_navigation) == counts.onglets ==
counts.portails` — mord un compteur du manifeste désynchronisé de sa navigation.
**Non-surface documentée — `roles_couverts` (« 44 ») N'EST PAS cross-gaté, à dessein.**
Le total « 44 rôles couverts par les 5 portails » apparaît, identique, dans **trois**
manifestes (`frontend/portails`, `frontend/chat_otoia`, `mobile/app_config` ·
`counts.roles_couverts=44`). On pourrait croire à trois rendus indépendants réclamant
un cross-check façon RBAC « 50 » (où `rbac/apply_plan/rbac_apply_plan.py:149` exige
`fixtures==userperm==roleprofile`, car chacun **re-dérive** son décompte avec sa propre
logique). Ce n'est **pas** le cas ici : les trois modules **importent la même** fonction
de partition — `mobilelib/deps.py:77` et `chatlib/deps.py:84` font tous deux
`roles_by_portail = portails_builder.roles_by_portail` (l'unique définition,
`frontend/portails/wslib/builder.py:36`) — appliquée à l'**unique** contrat
`rbac/rbac_50_roles.json`. `roles_couverts` est donc **transitivement mono-sourcé**
(code partagé + donnée partagée) : les trois totaux ne peuvent diverger que si cette
fonction ou ce contrat change, auquel cas les trois changent ensemble et
`check_artifacts` (reproductibilité byte-à-byte) vérifie chaque rebuild. Un gate
« 44==44==44 » serait **redondant** (#5) — cf. mémoire *fix-vs-gate-transitively-
protected-constant*. Chaque « 44 » vif reste néanmoins ancré à SON manifeste
(mobile README ci-dessus · `demo/scenarios/out/run_sheet.md` sourcé à
`portails/…/roles_couverts`), ce qui suffit : la valeur ne peut mentir que si son
manifeste ment, et le manifeste est byte-gaté.
Même classe enfin sur le **DocType CONFOTUR Application** (livrable `legal/confotur`) :
la ligne de synthèse du README du module (« **18 champs** (14 de donnée) · **4
sections** · **3 rôles** · … · **2 évènements de dépôt** ») **et** la cellule de la