From 576e78b6a99922a22e5cd1b6eeccc507ccbfc53d Mon Sep 17 00:00:00 2001 From: Claude Code DTP Worker Date: Sun, 2 Aug 2026 13:45:38 +0000 Subject: [PATCH] =?UTF-8?q?[DTP-Worker=2020260802=5F133549]=20Sprint=208?= =?UTF-8?q?=20=C2=B7=20buffer=20=C2=B7=20roles=5Fcouverts=20(=C2=AB=2044?= =?UTF-8?q?=20=C2=BB)=20:=20enqu=C3=AAte=20anti-d=C3=A9rive=20=E2=86=92=20?= =?UTF-8?q?NON-surface=20prouv=C3=A9e=20(3=20manifestes=20importent=20la?= =?UTF-8?q?=20m=C3=AAme=20fonction=20roles=5Fby=5Fportail=20sur=20l'unique?= =?UTF-8?q?=20contrat=20rbac=5F50=5Froles.json=20=E2=86=92=20transitivemen?= =?UTF-8?q?t=20mono-sourc=C3=A9,=20un=20cross-gate=20serait=20redondant=20?= =?UTF-8?q?#5,=20contra=20le=20cross-check=20RBAC-50=20qui=20re-d=C3=A9riv?= =?UTF-8?q?e)=20+=20documentation=20du=20garde-fou=20dans=20ci/README.md?= =?UTF-8?q?=20pour=20pr=C3=A9venir=20un=20gate=20N+1=20redondant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 05_activity_log/2026-08-02.md | 38 +++++++++++++++++++++++++++++++++++ ci/README.md | 20 ++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/05_activity_log/2026-08-02.md b/05_activity_log/2026-08-02.md index b24b32f..0c38a64 100644 --- a/05_activity_log/2026-08-02.md +++ b/05_activity_log/2026-08-02.md @@ -1371,3 +1371,41 @@ figés à 13 ⇒ les **5 surfaces head-docs+GAP mordent** « dit 13 MAIS 03_agen (preuve que l'autorité est le git-index, pas la cohérence interne). Arbre restauré. **7 gates re-joués → exit 0** : check_ci_integrity · check_artifacts · check_docs · check_readme_claims · check_regression · guard_constraints · validate_json. Aucune commande touchant au VPS. + +## Sprint 8 · buffer · `roles_couverts` (« 44 ») — enquête anti-dérive → **non-surface prouvée** + documentation du garde-fou mono-source (évite un gate N+1 redondant #5) + +**Contexte** — Série anti-dérive Sprint 8. Un balayage des comptes numériques a +exhumé un candidat de **cohérence croisée** : le total « **44 rôles couverts par les +5 portails** » apparaît, identique, dans **trois** manifestes byte-gatés +(`frontend/portails`, `frontend/chat_otoia`, `mobile/app_config` · +`counts.roles_couverts=44`). Chaque « 44 » vif n'est ancré qu'à SON propre manifeste +(mobile README · `demo/scenarios/out/run_sheet.md`). Aucun `ci/*.sh` ne compare les +trois entre eux. Hypothèse initiale : surface non couverte, analogue au cross-check +RBAC « 50 » (`rbac/apply_plan/rbac_apply_plan.py:149` exige +`fixtures==userperm==roleprofile`). + +**Enquête — l'analogie RBAC-50 ne tient PAS** (mémoire *fix-vs-gate-transitively- +protected-constant*). Le « 50 » EST cross-gaté car ses trois rendus **re-dérivent** +chacun leur décompte avec leur **propre** logique. Ici, au contraire, 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` +(unique définition `frontend/portails/wslib/builder.py:36`), appliquée à l'**unique** +contrat `rbac/rbac_50_roles.json` (une seule copie de chaque dans `git ls-files`). +`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)** et masquerait la vraie garantie (le partage de code), pas une +surface à protéger. + +**Livraison — DOCUMENTATION du garde-fou, pas un gate.** Ajout d'un bloc sourcé +« **Non-surface documentée — `roles_couverts` N'EST PAS cross-gaté, à dessein** » dans +`ci/README.md` (entre le bloc mobile Expo et le bloc CONFOTUR) : cite les 3 imports +partagés + le contrat unique + contraste explicite avec le cross-check RBAC-50, pour +qu'une session future ne rajoute PAS le gate redondant. Chemins en backticks (non +link-checkés, cf. mémoire *backtick-path-escapes-check-docs*). + +**Vérif** — 4 citations de lignes vérifiées exactes (`deps.py:77`, `deps.py:84`, +`wslib/builder.py:36`, `rbac_apply_plan.py:149`). **7 gates re-joués → exit 0** : +guard_constraints · validate_json · check_docs · check_artifacts · check_regression · +check_ci_integrity · check_readme_claims. Aucune commande touchant au VPS. diff --git a/ci/README.md b/ci/README.md index a0dd797..c2c3e16 100644 --- a/ci/README.md +++ b/ci/README.md @@ -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