e8b30d7147
Ces 4 figures sont Σ quantités · Σ(qté×prix_usd) · Σ(qté×prix_dop) · ⌈point_equilibre_pct × Σ unités⌉ calculées sur la fixture COMMITÉE fixtures/brief_bancable.json, le 52 % ancré sur CLAUDE.md #9 (« Point équilibre 52% pré-vente »). 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) — « vert trompeur » qu'aucune suite tests/ n'attrape. Nouveau bloc « Faisabilité/bancable figures » dans ci/check_readme_claims.sh (avant sys.exit), même esprit que le bloc faisabilite/generator ancré sur CLAUDE.md #9/#10 mais appliqué à une surface dont la source de vérité n'est PAS un out/*.json : (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, exécuté via subprocess stdlib pur, encoding utf-8) == 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é). État courant : aucun chiffre périmé (anti-invention #6, rien à réécrire) — le défaut est la surface ungated (module entièrement hors CI). 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) · 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) · 7 gates re-verts. ci/README.md (ligne récap check-readme-claims) mis à jour · log 05_activity_log/2026-08-01.md. Auto-score 4Big 96/100. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
122 lines
9.0 KiB
Markdown
122 lines
9.0 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.
|