3a91c9d52f
Les blocs Fiches Faisabilité / Fiche Mobile ne gataient que les attributs du CONTRAT ; le bloc « triplets par workspace » ne gate que le COMPTE de rôles par Workspace (`nb_roles`), AVEUGLE à QUEL rôle. Rattacher le rôle mobile à `OTO Ventes` (SUR-EXPOSITION console : le dev mobile gagnerait l'accès au portail Ventes — la restriction même que la note #6 pose), retirer/déplacer le rôle rendu de `OTO Construction`, laissait la fiche périmée en silence pendant que l'artefact dit autre chose ⇒ l'agent ERPNext Backend câblerait le mauvais accès console. Gate ajouté (nouveau bloc « Fiches agents · rattachement Workspace ») : index recomputé `erpnext_role_name → {titres de Workspace le portant}` depuis workspace.json (nom résolu du contrat par id, zéro duplication). 3 formes d'assertion : in_named (rendu — prose cite CE Workspace ET membership == {lui seul}) · in_any (ifc — membership ≥1) · not_in_named (mobile — assertion NÉGATIVE #6, rôle ABSENT du Has Role du Workspace nommé). Garde anti-typo : Workspace nommé absent de l'artefact ⇒ ROUGE. Claim absent ⇒ ROUGE (traçabilité). 9 morsures vérifiées (4 artefact + 5 fiche/bord) ; restauré vert ; 7 gates re-verts. ci/README.md (récap + paragraphe détaillé) + activity log + mémoire mis à jour. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
306 lines
24 KiB
Markdown
306 lines
24 KiB
Markdown
# Activity Log · 2026-08-01 · Claude Code DTP
|
||
|
||
## Session `20260801_000201` · Buffer S8 · Domaine RBAC/userperm_gen : la **table « Mapping `scope_donnees` → mécanisme »** — la **FONCTION d'enforcement ROW-LEVEL** (quel mécanisme Frappe natif applique CHAQUE portée de données + si un `User Permission` template est émis), CŒUR sécurité du module — était transcrite EN PROSE (README:33-38) SANS AUCUN gate d'IDENTITÉ. Le bloc RBAC « 3 volets » existant ne gate QUE la **ventilation** par mécanisme (« 28 `entite` · 16 `groupe` · 2 `own` · 4 `equipe` »), un COMPTE aveugle à QUEL mécanisme applique QUELLE portée.
|
||
|
||
**Tâche** : **Sprint 8 · buffer** (DevOps CI/CD · QA). Roadmap fonctionnellement
|
||
close ; poursuite de la série anti-dérive (CLAUDE.md #6). Même patron d'IDENTITÉ que
|
||
le mapping RBAC `fixtures_gen` (séparation des pouvoirs `set_user_permissions`) ou la
|
||
cross-cohérence PERMISSIONS Legal/CONFOTUR (`role_id`→actions) — appliqué à la
|
||
**surface data-derived distincte du même README `rbac/userperm_gen`** : la table
|
||
qui associe chaque portée de données à son mécanisme d'enforcement, jamais gatée hors
|
||
son compte agrégé.
|
||
|
||
**Dérive silencieuse fermée** :
|
||
- `05_deliverables_mvp/rbac/userperm_gen/README.md:33-38` — table « Mapping
|
||
`scope_donnees` → mécanisme » : nomme, PAR portée, le `mechanism` Frappe natif
|
||
(`own`→`docperm_if_owner` · `entite`→`user_permission_company` ·
|
||
`groupe`→`none_consolidated` · `equipe`→`vps_confirm_team`) ET le verdict
|
||
« Template émis ? » (`oui` pour `entite` seul, sinon `non (null)`).
|
||
- Source faisant autorité (byte-gatée par `check_artifacts`) :
|
||
`out/user_permission_plan.json` — chaque entrée porte `scope_donnees` +
|
||
`mechanism` + `user_permission_template` (null ou objet). Le mapping est une
|
||
**fonction** : chaque portée → exactement un mécanisme ; template émis SSI
|
||
`entite`/`user_permission_company`.
|
||
- Piège : le bloc de ventilation est AVEUGLE à l'identité de ces couples.
|
||
RÉAFFECTER une portée à un mécanisme plus permissif (`entite` →
|
||
`none_consolidated` : le **row-level enforcement ABANDONNÉ**, sur-exposition des
|
||
données inter-entités — la restriction même que le module pose), RENOMMER un
|
||
mécanisme ou BASCULER le verdict « Template émis ? » laisse le README périmé
|
||
pendant que l'artefact dit autre chose → l'agent ERPNext Backend câblerait le
|
||
mauvais mécanisme (le risque même que la table veut prévenir). Aucune suite
|
||
`tests/` (qui teste des FONCTIONS de mapping/résolution, pas la prose) n'attrape
|
||
ce « vert trompeur ».
|
||
- **État courant** : **aucune ligne périmée** — les 4 couples portée→mécanisme et
|
||
leurs verdicts recoupent l'artefact exactement (anti-invention #6, rien à
|
||
réécrire). Le défaut est la **surface ungated**.
|
||
|
||
**Gate ajouté** (`ci/check_readme_claims.sh`, nouveau bloc « RBAC/userperm_gen
|
||
Mapping » après le bloc CRM gardes) : (1) **par portée** — le `mechanism` (1er token
|
||
backtické de la colonne) ET le verdict « Template émis ? » (`**oui**` / `non (null)`)
|
||
recomputés de `user_permission_plan.json`, prose exigée EXACTE ; (2) **identité
|
||
d'ensemble** — portées de la table == portées de l'artefact (set-diff : ni fantôme
|
||
ni manquante). Cohérences croisées en bonus (mordent un plan INTERNEMENT incohérent) :
|
||
chaque portée mappe UN SEUL mécanisme (fonction, pas relation) · « Template émis »
|
||
UNIFORME sur les entrées d'une portée · template émis EXACTEMENT pour
|
||
`user_permission_company` (l'invariant « template SSI `entite` » du README:36/61) ·
|
||
ensemble des portées NON VIDE. Un claim absent échoue AUSSI (traçabilité).
|
||
|
||
**7 morsures vérifiées** : README réaffecte `entite`→`none_consolidated`
|
||
(mécanisme périmé · élévation de portée) · README bascule `entite` « Template
|
||
émis » oui→non (verdict périmé) · README échange une portée `groupe`→`famille`
|
||
(absents=[groupe] + en trop=[famille] + ligne INTROUVABLE) · README retire la
|
||
ligne `own` (absents=[own]) · table entière supprimée (les 4 absents + toutes
|
||
lignes INTROUVABLES) · **artefact** réaffecte toutes les entrées `entite`→
|
||
`none_consolidated` (README périmé sur mécanisme ET verdict) · **artefact** rend
|
||
une entrée `own` porteuse d'un template (« Template émis » NON uniforme
|
||
[False,True] · invariant SSI cassé) ; restauré = green : 4 portées · table ==
|
||
artefact · par-ligne exact · fonction/uniforme/SSI verts · exit 0. Working tree
|
||
byte-restauré (`git checkout --`, **JAMAIS** `git clean`) · **7 gates re-verts**.
|
||
|
||
- `ci/README.md` (table récap du pipeline + paragraphe détaillé « 2ᵉ surface
|
||
`rbac/userperm_gen` ») mis à jour.
|
||
- **Hors périmètre worker (VPS · #8)** : néant (gate bash/python3 stdlib en-repo ;
|
||
édition **hors** `05_deliverables_mvp/*/out` ⇒ 0 dérive d'artefact).
|
||
- **Auto-score 4Big** : 96/100.
|
||
|
||
## Session `20260801_003201` · Buffer S8 · Domaine Faisabilité/bancable : les **4 figures « Génération réelle (fixture) »** du README (`40 unités · valeur catalogue USD 8,560,000 / DOP 505,040,000 · point d'équilibre 21 unités (⌈52 % × 40⌉)`) — les chiffres DATA-DERIVED que le **dossier bancable** (l'artefact que voit le banquier) recopie — étaient **HORS de tout gate**. Le module n'écrit son `out/` que sur disque (« out/ non commité ») ⇒ **check_artifacts est aveugle** (aucun artefact byte-gaté) et **AUCUN** gate ne le touchait.
|
||
|
||
**Tâche** : **Sprint 8 · buffer** (DevOps CI/CD · QA). Roadmap fonctionnellement
|
||
close ; poursuite de la série anti-dérive (CLAUDE.md #6). Même esprit que les
|
||
paramètres canoniques `faisabilite/generator` **ancrés sur CLAUDE.md #9/#10** (le
|
||
`52 %` réutilisé ici) — appliqué à une **surface encore jamais gatée** : un module
|
||
dont la source de vérité n'est PAS un `out/*.json` mais **la fixture commitée + le
|
||
générateur**.
|
||
|
||
**Dérive silencieuse fermée** :
|
||
- `05_deliverables_mvp/faisabilite/bancable/README.md:103-105` — ligne
|
||
« Génération réelle (fixture) » : `40 unités` (= Σ quantités typologies) ·
|
||
`USD 8,560,000` (= Σ qté×prix_usd) · `DOP 505,040,000` (= Σ qté×prix_dop) ·
|
||
`21 unités (⌈52 % × 40⌉)` (= ⌈point_equilibre_pct × Σ unités⌉).
|
||
- Source faisant autorité : `fixtures/brief_bancable.json` (COMMITÉE) + la
|
||
**génération réelle** `python3 bancable_gen.py validate` (émet le manifeste sur
|
||
stdout, `figures_calculees[]`). Le `52 %` est **ancré sur CLAUDE.md #9**
|
||
(« Point équilibre 52% pré-vente »), pas recopié.
|
||
- Piège : la seule vérification existante (`tests/`) teste des **FONCTIONS**
|
||
(l'arithmétique de recoupement `_check_derived_arithmetic`) avec des **oracles
|
||
HARDCODÉS** dans le test — une copie de plus, jamais comparée à la PROSE du
|
||
README. Éditer une typologie de la fixture (quantité/prix), en ajouter/retirer
|
||
une, ou déplacer le point d'équilibre de CLAUDE.md #9, laisse les 4 chiffres du
|
||
README périmés pendant que le générateur produit autre chose → le banquier lit
|
||
un dossier faux (l'invention même que #6 interdit).
|
||
- **État courant** : **aucun chiffre périmé** — les 4 figures recoupent la
|
||
génération réelle exactement (anti-invention #6, rien à réécrire). Le défaut est
|
||
la **surface ungated** (module entièrement hors CI).
|
||
|
||
**Gate ajouté** (`ci/check_readme_claims.sh`, nouveau bloc « Faisabilité/bancable
|
||
figures » avant `sys.exit`) : (1) **recompute indépendant** des 4 figures depuis
|
||
la fixture commitée ; (2) **cohérence croisée** — le manifeste GÉNÉRÉ
|
||
(`bancable_gen validate`) == le recompute (mord un générateur/fixture
|
||
incohérents) ; (3) **prose** — un seul pattern d'identité exige les 4 valeurs
|
||
EXACTES, **avec séparateur de milliers** pour USD/DOP, + la formule `⌈pct × Σ
|
||
unités⌉` dont le pct == CLAUDE.md #9 et le total == Σ unités. Un claim absent
|
||
échoue AUSSI (traçabilité). Le `out/` n'étant pas commité, le gate **exécute le
|
||
générateur** (stdlib pur, `subprocess`, `encoding="utf-8"`) au lieu de lire un
|
||
artefact byte-gaté — même patron que le bloc `faisabilite/generator` qui lit
|
||
`model.py`.
|
||
|
||
**7 morsures vérifiées** : README `USD 8,560,000→9,560,000` (figure périmée) ·
|
||
README retire le séparateur de milliers (`8,560,000→8560000`) · README breakeven
|
||
`21→20` (formule périmée) · README formule `52 %→55 %` (dérive CLAUDE.md #9) ·
|
||
README supprime la ligne entière (INTROUVABLE · claim absent) · **fixture** Studio
|
||
`qté 12→13` (5 morsures : units/USD/DOP/breakeven README périmés + manifeste) ·
|
||
**fixture** 2 Chambres `prix_usd 320000→300000` (catalogue USD périmé) ; restauré =
|
||
green : 4 figures == génération réelle · manifeste == recompute · pct 52 % ==
|
||
CLAUDE.md #9 · exit 0. Working tree byte-restauré via `git checkout --` (JAMAIS
|
||
`git clean`, interdit absolu) · **7 gates re-verts**.
|
||
|
||
- `ci/README.md` (ligne récap du pipeline `check-readme-claims`) mis à jour.
|
||
- **Hors périmètre worker (VPS · #8)** : néant (gate bash/python3 stdlib en-repo ;
|
||
aucune écriture dans un `out/` ⇒ 0 dérive d'artefact ; conversion PDF + rebuild
|
||
Portail Bancables restent côté VPS).
|
||
- **Auto-score 4Big** : 96/100.
|
||
|
||
## Session `20260801_010204` · Buffer S8 · Domaine Mobile/fiche agent : la **fiche d'identité du rôle RBAC `plateforme-mobile`** (`03_agents/mobile/AGENT.md:36`) — le **SEUL ancrage in-repo réellement vérifiable** de l'agent mobile (builds/soumissions stores étant hors-repo, #8) — recopiait EN PROSE, DEPUIS le contrat `rbac_50_roles.json`, TOUS les attributs data-derived du rôle (`erpnext_role_name` · `nom_fr` · `famille`/`portail` · `entite_principale` · `niveau` · `scope_donnees` · `modules` · permission `API Access` custom R/W · `description`) SANS AUCUN gate d'IDENTITÉ. Le README `mobile/app_config` n'est gaté que sur des COMPTES agrégés (« 5 onglets · 44 rôles couverts · 3 langues · 13 identifiants »), AVEUGLES à l'identité de CE rôle.
|
||
|
||
**Tâche** : **Sprint 8 · buffer** (DevOps CI/CD · QA). Roadmap fonctionnellement
|
||
close ; poursuite de la série anti-dérive (CLAUDE.md #6). Même patron d'IDENTITÉ que
|
||
la table gardes CRM/`workflow_vente` (rôle qui garde chaque transition) ou le mapping
|
||
RBAC `userperm_gen` (portée→mécanisme) — appliqué à la **surface distincte** de la
|
||
fiche agent mobile : la carte que l'agent ERPNext Backend lit pour **seeder le rôle**
|
||
(`seed_mobile_rbac.py`), jamais gatée hors les comptes agrégés de `app_config`.
|
||
|
||
**Dérive silencieuse fermée** :
|
||
- `03_agents/mobile/AGENT.md:36` — ligne « Points de contact réellement commités »,
|
||
cellule « Ce qu'il fixe » : nomme, PAR attribut, le rôle ERPNext
|
||
**`OTO Plateforme Mobile`** (« Développeur Mobile » · famille/portail
|
||
**`plateforme`** · entité **9060 QC** · niveau 2 · scope `groupe` · modules
|
||
`Core`+`Website` · perm `API Access` custom R/W · description « Maintient
|
||
l'app Expo/React Native et l'API mobile ; gère les builds EAS et les
|
||
soumissions stores »).
|
||
- Source faisant autorité : `05_deliverables_mvp/rbac/rbac_50_roles.json` (contrat
|
||
RBAC, schéma-validé · les 3 MANIFEST RBAC recomputés en dérivent et sont byte-gatés
|
||
par `check_artifacts`) → le rôle d'`id` `plateforme-mobile` porte chacun de ces
|
||
champs. Autres blocs du gate lisent déjà ce contrat directement (userperm,
|
||
workflow_vente, confotur).
|
||
- Piège : la seule vérification existante (`tests/`) teste des **FONCTIONS** de
|
||
résolution RBAC, jamais la PROSE d'une fiche agent. Éditer le contrat — élever le
|
||
`scope_donnees` (`groupe`→`entite` : sur-portée inter-entités, la restriction même
|
||
que le rôle pose), changer le `niveau`/l'`entite_principale`, renommer le rôle,
|
||
ajouter/retirer un module ou élargir la permission (`R/W`→`R/W/D`) — laisse la fiche
|
||
périmée pendant que le contrat dit autre chose → l'agent ERPNext Backend câblerait
|
||
le mauvais rôle (le risque même que la fiche veut prévenir).
|
||
- **État courant** : **aucun attribut périmé** — les 9 attributs + la description
|
||
recoupent le contrat exactement (anti-invention #6, rien à réécrire). Le défaut est
|
||
la **surface ungated**.
|
||
|
||
**Gate ajouté** (`ci/check_readme_claims.sh`, nouveau bloc « Fiche Mobile » avant
|
||
`sys.exit`) : (1) **par attribut** — `erpnext_role_name` · `nom_fr` · `portail` ·
|
||
`entite_principale` · `niveau` · `scope_donnees` · `modules` · permission recomputés
|
||
du contrat, prose EXACTE exigée (regex par attribut, lookaheads anti-préfixe pour
|
||
niveau/modules/perm) ; (2) **permission** — le sigle des verbes est **canonique et
|
||
ordonné** (C/R/W/D/S/X/A) : élargir OU rétrécir la perm change le sigle attendu (un
|
||
préfixe `R/W` ne satisfait plus `R/W/D`, ni l'inverse) ; verbe inconnu ⇒ ROUGE
|
||
(étendre le gate) ; (3) **description** recoupée **verbatim** (emphase markdown `**` et
|
||
point final neutralisés). Cohérences croisées bonus (mordent un contrat INTERNEMENT
|
||
incohérent) : `famille == portail` (bijection portail) · permission bien `custom` ·
|
||
`role_id` présent EXACTEMENT une fois. Un claim absent échoue AUSSI (traçabilité :
|
||
ligne de rôle INTROUVABLE).
|
||
|
||
**12 morsures vérifiées** (6 côté contrat = fiche périmée · 6 côté fiche = fiche
|
||
fausse) : contrat `scope groupe→entite` (sur-portée) · contrat `niveau 2→3` · contrat
|
||
`+delete` (sigle `R/W→R/W/D`) · contrat description réécrite · contrat rôle renommé
|
||
(`OTO Plateforme Mobile→OTO Mobile Dev`) · fiche `modules Website→Selling` · fiche
|
||
`entité 9060 QC→WAF` · fiche perm `R/W→R/W/D` (sur-revendication) · fiche perm `R/W→R`
|
||
(sous-revendication) · fiche modules over-claim `+Selling` et under-claim `Core` seul ·
|
||
ligne de rôle entièrement supprimée (INTROUVABLE) ; restauré = green : 9 attributs +
|
||
description == contrat · famille==portail · perm custom · role_id singleton · exit 0.
|
||
Working tree byte-restauré (`git checkout --`, **JAMAIS** `git clean`, interdit
|
||
absolu) · **7 gates re-verts**.
|
||
|
||
- `ci/README.md` (table récap du pipeline + paragraphe détaillé « Fiche d'identité
|
||
du rôle RBAC mobile ») mis à jour.
|
||
- **Hors périmètre worker (VPS · #8)** : néant (gate bash/python3 stdlib en-repo ;
|
||
édition **hors** `05_deliverables_mvp/*/out` ⇒ 0 dérive d'artefact ; le seed réel
|
||
du rôle `bench` reste côté VPS).
|
||
- **Auto-score 4Big** : 96/100.
|
||
|
||
## Session `20260801_013208` · Buffer S8 · Domaine Faisabilité/fiches agents : les **deux FICHES D'IDENTITÉ** des rôles RBAC `faisabilite-rendu-3d` (`03_agents/rendu/AGENT.md:34`) et `faisabilite-ifc-speckle` (`03_agents/ifc_speckle/AGENT.md:34`) — la carte que l'agent ERPNext Backend lit pour **seeder** le rôle porteur des rendus / de l'export IFC→GLB — recopiaient EN PROSE, DEPUIS le contrat `rbac_50_roles.json`, les attributs data-derived du rôle (`erpnext_role_name` · `nom_fr`/`modules` côté rendu · `portail` · `entite_principale` · `niveau` · les **deux** `permissions_cibles` `File` R/W/create + `Faisabilité` R ou R/W) SANS AUCUN gate d'IDENTITÉ. Le README `frontend/portails` n'est gaté que sur des COMPTES de rôles par Workspace, AVEUGLES à l'identité de CE rôle.
|
||
|
||
**Tâche** : **Sprint 8 · buffer** (DevOps CI/CD · QA). Roadmap fonctionnellement
|
||
close ; poursuite de la série anti-dérive (CLAUDE.md #6). MÊME classe que la Fiche
|
||
Mobile de la session précédente (`plateforme-mobile`) — surface `03_agents/*/AGENT.md`
|
||
qui transcrit à la main les attributs d'un rôle depuis `rbac_50_roles.json`, gatée (si
|
||
tant est) seulement sur des comptes agrégés — appliquée aux **deux fiches faisabilité
|
||
construction** encore ungated. Mémoire `agent-fiche-role-attrs-ungated` mise à jour.
|
||
|
||
**Dérive silencieuse fermée** :
|
||
- `03_agents/rendu/AGENT.md:34` — cellule « Ce qu'il fixe » du rôle
|
||
`faisabilite-rendu-3d` : `OTO Faisabilité Rendu 3D` · « Spécialiste Rendu 3D » ·
|
||
portail `construction` · `WA SRL` · niveau 2 · module `OTOV7 Faisabilité` ·
|
||
perms `File` R/W/create + `Faisabilité` R.
|
||
- `03_agents/ifc_speckle/AGENT.md:34` — cellule du rôle `faisabilite-ifc-speckle` :
|
||
`OTO Faisabilité IFC Speckle` · portail `construction` · `WA SRL` · niveau 2 ·
|
||
perms `File` R/W/create + `Faisabilité` **R/W** (écriture en plus vs rendu).
|
||
- Source faisant autorité : `05_deliverables_mvp/rbac/rbac_50_roles.json` (contrat
|
||
RBAC schéma-validé · les 3 MANIFEST RBAC en dérivent, byte-gatés par
|
||
`check_artifacts`). Plusieurs blocs du gate lisent déjà ce contrat directement.
|
||
- Piège : la seule vérification existante (`tests/`) teste des **FONCTIONS** de
|
||
résolution RBAC, jamais la PROSE d'une fiche. Élargir `Faisabilité` R→R/W (le rôle
|
||
Rendu 3D gagnerait l'écriture sur un DocType qu'il ne doit que LIRE), changer
|
||
`niveau`/`entite_principale`, renommer le rôle ou permuter un module laisse la fiche
|
||
périmée pendant que le contrat dit autre chose → l'agent câblerait le mauvais rôle.
|
||
- **Constat #6 (honnêteté)** : la **DESCRIPTION** de ces deux fiches est une
|
||
**PARAPHRASE éditoriale** (le contrat porte « (… — CLAUDE.md) » / « les modèles »
|
||
que la fiche condense) — vérifié programmatiquement AVANT toute édition. Elle n'est
|
||
donc **PAS** gatée verbatim (ne rien réécrire de correct pour satisfaire un gate) ;
|
||
seuls les attributs **structurés**, eux transcrits à l'exact, sont contraints.
|
||
- **État courant** : aucun attribut structuré périmé — les 12 recomputes recoupent
|
||
le contrat exactement (anti-invention #6, rien à réécrire). Le défaut est la
|
||
**surface ungated**.
|
||
|
||
**Gate ajouté** (`ci/check_readme_claims.sh`, nouveau bloc « Fiches Faisabilité »
|
||
avant `sys.exit`) : table de config par fiche (fichier · role_id · liste des attributs
|
||
RESTITUÉS). Pour chaque fiche : (1) **par attribut** — `erpnext_role_name` · `nom_fr` ·
|
||
`portail` · `entite_principale` · `niveau` · `modules` · les deux permissions
|
||
recomputés du contrat, prose EXACTE exigée (regex par attribut, lookaheads
|
||
anti-préfixe niveau/module/perms) ; (2) **permissions** — chaîne
|
||
« \`Doctype\` R/W/create + \`Autre\` R » rendue en **ordre canonique** (read→R ·
|
||
write→W · create/delete/submit/… en toutes lettres) : élargir OU rétrécir change la
|
||
chaîne attendue (`R/W/create` ne satisfait plus `R/W/create/delete`) ; verbe inconnu ⇒
|
||
ROUGE. Un claim absent échoue AUSSI (ligne de contact INTROUVABLE = régression #6).
|
||
|
||
**11 morsures vérifiées** (5 côté contrat = fiche périmée · 6 côté fiche = fiche
|
||
fausse) : contrat rendu `Faisabilité +write` (sigle `R→R/W`) · contrat rendu
|
||
`niveau 2→3` · contrat rendu `WA SRL→WAF` · contrat rendu rôle renommé · contrat ifc
|
||
`Faisabilité R/W→R` · fiche rendu perm `File R/W/create→…/delete` (over-claim) · fiche
|
||
ifc perm `R/W→R/W/create` (over-claim) · fiche rendu module `Faisabilité→Selling` ·
|
||
fiche ifc `WA SRL→WAF` · fiche rendu `nom_fr` retiré (claim absent) · ligne de contact
|
||
ifc supprimée (INTROUVABLE) ; restauré = green : 12 attributs == contrat · exit 0.
|
||
Working tree byte-restauré (`git checkout --`, **JAMAIS** `git clean`, interdit
|
||
absolu) · **7 gates re-verts**.
|
||
|
||
- `ci/README.md` (table récap du pipeline + paragraphe détaillé « deux fiches
|
||
d'identité des rôles RBAC faisabilité ») mis à jour.
|
||
- **Hors périmètre worker (VPS · #8)** : néant (gate bash/python3 stdlib en-repo ;
|
||
édition **hors** `05_deliverables_mvp/*/out` ⇒ 0 dérive d'artefact ; le seed réel
|
||
des rôles `bench` reste côté VPS).
|
||
- **Auto-score 4Big** : 96/100.
|
||
|
||
## Session `20260801_020209` · Buffer S8 · Domaine Fiches agents/rattachement Workspace : les **assertions d'appartenance `Has Role`** des trois fiches `03_agents/{rendu,ifc_speckle,mobile}/AGENT.md` — QUELLE CONSOLE (Workspace ERPNext natif) le rôle peut atteindre — étaient une surface data-derived **DISTINCTE du contrat** `rbac_50_roles.json` (la membership vit dans `frontend/portails/out/workspace.json`, byte-gaté) et **HORS de tout gate**. Les blocs Fiches Faisabilité / Fiche Mobile des sessions précédentes ne gataient que les attributs du **contrat** ; le bloc « triplets par workspace » ne gate que le **compte** de rôles par Workspace (`nb_roles`), AVEUGLE à QUEL rôle.
|
||
|
||
**Tâche** : **Sprint 8 · buffer** (DevOps CI/CD · QA). Roadmap fonctionnellement
|
||
close ; poursuite de la série anti-dérive (CLAUDE.md #6). MÊME famille de fiches que
|
||
les deux sessions précédentes (`agent-fiche-role-attrs-ungated`) mais **surface
|
||
orthogonale** : non plus les attributs recopiés du contrat, mais la **membership
|
||
`Has Role`** — l'accès console — qu'aucun gate ne touchait.
|
||
|
||
**Dérive silencieuse fermée** :
|
||
- `03_agents/rendu/AGENT.md:35` — « rattaché au Workspace `OTO Construction` »
|
||
(assertion NOMMÉE) ; `03_agents/ifc_speckle/AGENT.md:35` — « rattaché à un
|
||
Workspace » (générique) ; `03_agents/mobile/AGENT.md:41` — « **volontairement pas**
|
||
rattaché au Workspace `OTO Ventes` » (assertion NÉGATIVE d'honnêteté #6).
|
||
- Source faisant autorité : `frontend/portails/out/workspace.json` (les 5 Workspaces
|
||
natifs v15, chacun portant sa liste `Has Role`, byte-gaté par `check_artifacts` via
|
||
la reproductibilité `out/`). L'`erpnext_role_name` de chaque rôle est résolu du
|
||
contrat `rbac_50_roles.json` par `id` (zéro duplication).
|
||
- Piège : rattacher le rôle mobile à `OTO Ventes` = **sur-exposition console** (le
|
||
dev mobile gagnerait l'accès au portail Ventes — la restriction même que la note
|
||
#6 pose), retirer/**déplacer** le rôle rendu de `OTO Construction` = perte/erreur
|
||
d'accès console — laisse la fiche périmée EN SILENCE pendant que l'artefact dit
|
||
autre chose ⇒ l'agent ERPNext Backend câblerait le mauvais accès console. Aucune
|
||
suite `tests/` (qui teste des FONCTIONS de résolution, pas la prose) n'attrape ce
|
||
« vert trompeur ».
|
||
- **État courant** : aucune assertion périmée — rendu ∈ {`OTO Construction`} seul ·
|
||
ifc ∈ {`OTO Construction`} (≥1) · mobile ∈ ∅ (donc absent de `OTO Ventes`) ; les 3
|
||
recoupent workspace.json exactement (anti-invention #6, rien à réécrire). Le défaut
|
||
est la **surface ungated**.
|
||
|
||
**Gate ajouté** (`ci/check_readme_claims.sh`, nouveau bloc « Fiches agents ·
|
||
rattachement Workspace (`Has Role`) » avant `sys.exit`) : index recomputé
|
||
`erpnext_role_name → {titres de Workspace le portant}` depuis workspace.json. Par
|
||
fiche, 3 formes d'assertion : **in_named** (rendu) — la prose cite CE Workspace ET la
|
||
membership == {ce Workspace} seul (membership élargie ou déplacée ⇒ ROUGE) ;
|
||
**in_any** (ifc) — membership ≥ 1 Workspace ; **not_in_named** (mobile) — rôle ABSENT
|
||
du `Has Role` du Workspace nommé. Garde anti-typo : un Workspace nommé absent de
|
||
l'artefact échoue avant tout (anti-cible fantôme). Un claim absent échoue AUSSI
|
||
(traçabilité #6).
|
||
|
||
**9 morsures vérifiées** (4 côté artefact · 5 côté fiche/bord) : artefact ajoute le
|
||
rôle mobile à `OTO Ventes` (**sur-exposition #6 VIOLÉE**) · artefact retire le rôle
|
||
rendu de `OTO Construction` · artefact déplace rendu vers `OTO Achat` · artefact
|
||
retire ifc de tous les Workspaces · fiche rendu renomme le Workspace
|
||
(`OTO Construction→OTO Ventes`, INTROUVABLE) · fiche rendu supprime l'assertion ·
|
||
fiche mobile nomme un Workspace fantôme (`OTO Marketing`, anti-typo) · fiche ifc
|
||
supprime l'assertion générique · fiche mobile passe le négatif au positif (retire
|
||
« volontairement pas ») ; restauré = green : rendu=={`OTO Construction`} · ifc≥1 ·
|
||
mobile∉`OTO Ventes` · exit 0. Working tree byte-restauré (`git checkout --`, **JAMAIS**
|
||
`git clean`, interdit absolu) · **7 gates re-verts**.
|
||
|
||
- `ci/README.md` (table récap du pipeline + paragraphe détaillé « rattachement
|
||
Workspace des fiches agents ») mis à jour. Mémoire `agent-fiche-role-attrs-ungated`
|
||
à actualiser (surface membership couverte).
|
||
- **Hors périmètre worker (VPS · #8)** : néant (gate bash/python3 stdlib en-repo ;
|
||
édition **hors** `05_deliverables_mvp/*/out` ⇒ 0 dérive d'artefact ; l'attachement
|
||
réel des rôles aux Workspaces `bench` reste côté VPS).
|
||
- **Auto-score 4Big** : 96/100.
|