Aller au contenu

Lot 1 — Plan d'exécution avec Claude Code

Version 1, 30 septembre 2026. S’appuie sur le découpage (Lot 1), les décisions d’écarts (EC-010, EC-012, EC-014, EC-021, EC-023 à EC-028, EC-031, AV1-01, AV1-02, GPS-03, GPS-04) et les cinq livrables du Lot 0.

  • Le Lot 1 livre les données de référence dont dépendent les flux (Lot 2) et le terrain (Lot 3) : campagnes, produits, numérotation, acteurs, foncier, certification, contrats, capacité.
  • Il avance sur deux pistes parallèles :
    • Piste A — données et API : migrations, fonctions SQL, packages/domain, points d’entrée de l’API, règles PowerSync ;
    • Piste B — back-office : socle d’interface, galerie de composants, puis écrans des référentiels.
  • La piste B est un ajout au découpage, qui ne prévoit aucun écran avant le Lot 2. Sans elle, rien n’est visible avant la mi-octobre, alors que la réponse Naturland est due le 15/10/2026. Voir la section 4.
  • Sortie du Lot 1 : le contrat d’API et les tables synchronisées sont gelés. C’est ce qui débloque les Lots 2 et 3 en parallèle.
# Prérequis Pourquoi Vérification
P1 Critères de fin du Lot 0 passés : SB-01 à SB-14, vecteurs VT, KC-xx, SP-01 à SP-15 Le Lot 1 réutilise installer_table, validation, sync.controle et le module numerotation Intégration continue verte sur main
P2 Cahier v1.3 gelé, au moins pour les règles du Lot 1 Risque « spécification instable » du découpage Pages fonctionnel/regles/ du Lot 1 au statut v1.2, corrigée v1.3 ou nouvelle
P3 EC-021 appliqué : chaque fonctionnalité des référentiels porte lot: 1 Sinon Claude Code ne sait pas ce qui est dans le périmètre Liste générée depuis le front-matter
P4 CLAUDE.md complété d’une section « Lot 1 » (section 7) Claude Code relit ce fichier à chaque session Relu par vous
P5 Ce plan déposé dans apps/docs/src/content/docs/technique/lot-1/ Même principe que pour le Lot 0 –

Si P2 n’est pas tenu, démarrez quand même les séquences A1 à A3 (campagnes, produits, numérotation), qui dépendent peu du cahier, et gelez le reste en parallèle.

Domaine Contenu Décisions et règles
Organisation Sites, emplacements –
Campagnes Code unique, AA = année d’ouverture, deux campagnes possibles par an, version de pack et de modèle de numérotation figées EC-023, EC-031
Produits Produits, unités, attributs typés par filière, recettes de transformation (données seulement, l’exécution est au Lot 2) EC-030, paramètres contextuels (facteur produit)
Numérotation Modèle par segments, séquence sur 4 chiffres, préfixe entreprise facultatif, nature « vente » retirée EC-010, EC-023
Acteurs Producteurs (pièce d’identité), groupements, affectation des agents, fournisseurs, clients ; éligibilité au groupe AV1-02, EC-031, EC-014, EC-028
Foncier Parcelles, versions de polygone, zones de cueillette, écart de surface avec incertitude AV1-01, GPS-03, GPS-04, EC-030, facteurs region, mode_culture, type_sol
Certification Statut de conformité par unité et par référentiel (six états), certificats, source interne ou externe, « expiré » calculé EC-024, EC-025, EC-026, EC-027
Contrats Achat, vente, prestation ; prix et devise ; primes ; formule de réfaction ; tolérances EC-016 (préparation), EC-028, module pesee
Capacité Par campagne, sur surface mesurée, double validation direction + RSCI, solde précalculé EC-012, AV1-01, protocole §7.3

Hors périmètre : collectes, lots, transformations (Lot 2) ; écrans mobiles, relevé GPS, synchronisation montante (Lot 3) ; formulaires d’inspection (Lot 4).

Une migration dbmate par séquence, dans cet ordre. Chaque table passe par app.installer_table et porte COMMENT ON sur chaque colonne.

A1 site, emplacement, campagne
A2 facteur, facteur_valeur (globales), unite, produit, attribut, recette
+ clé étrangère mouvement_ligne.produit_id
A3 modele_numerotation (ajout seul), sequence_numero, fonction attribuer_numero()
A4 groupement, producteur, affectation_agent, fournisseur, client
+ cible producteur dans sync.controle (le motif doublon_identite existe dans le socle)
A5 parcelle, parcelle_version (geometry + geojson), zone_cueillette,
vue parcelle_version_en_vigueur, fonctions de validité et de chevauchement
A6 referentiel, statut_conformite, certificat, fonction peut_revendiquer()
A7 contrat, contrat_ligne, prime
A8 capacite_version, solde_capacite, cible capacite_version_id dans validation

Dépendances : A1 → A2 → A3. A4 dépend de A1. A5 dépend de A4. A6 dépend de A4 et A5. A7 dépend de A2 et A4. A8 dépend de A5, A6 et A7.

Contraintes à ne pas oublier pour le Lot 3 (protocole §7.3) : organisation_id et groupement_id directement sur producteur, parcelle, version de polygone et solde ; colonne GeoJSON tenue par déclencheur ; solde de capacité précalculé.

4. Aurez-vous une interface pour tester des rendus ?

Section intitulée « 4. Aurez-vous une interface pour tester des rendus ? »

Pas automatiquement. Le Lot 0 a produit un squelette apps/backoffice vide et un prototype terrain pour PowerSync. Le découpage ne programme aucun écran au Lot 1 : c’est un trou à combler.

Proposition : la piste B démarre dès le premier jour, en parallèle de la piste A.

Étape Ce que vous pouvez voir Données Disponible après
B1 Galerie de composants « Registre » : tampons de qualité, références, jauge de capacité, états vides, formulaire généré Données fictives dans le code B1, environ un jour
B2 Coquille du back-office : connexion Keycloak, navigation du design system, sélecteur de campagne Organisation de démonstration B2 et A1
B3 Écrans des référentiels, un par séquence A Jeu de démonstration « ananas Togo » Chaque séquence A correspondante

Galerie sans nouvelle dépendance. Une route /_galerie, active seulement en développement, suffit. Storybook serait une dépendance du socle, donc une ADR. Il n’apporte pas assez au pilote pour la justifier.

Le prototype Lovable sert de maquette de parcours. On reprend ses écrans comme référence, pas son code (décision du découpage).

Jeu de démonstration. Un jeu testdata/demo/togo-ananas/ alimente les écrans et la démonstration Naturland : 1 organisation, 2 campagnes, 3 groupements, 60 producteurs (dont 2 doublons de pièce d’identité), 90 parcelles avec polygones réels ou plausibles (dont 1 invalide et 1 chevauchement), certificats dont 1 expiré, 2 contrats d’achat, capacités validées et en attente. Chargé par pnpm demo:charger, jamais en production.

Chaque séquence correspond à une session Claude Code et à une demande de fusion. Même méthode qu’au Lot 0 : mode plan d’abord, relecture, exécution, fin définie par les tests.

Objectif. Écrire les tests avant le code.

  • Section « Lot 1 » de CLAUDE.md.
  • Scénarios de recette du lot SR-L1-01 et suivants, dans apps/docs/.../fonctionnel/scenarios/, un par règle du Lot 1 sans scénario (EC-019).
  • Squelette du jeu de démonstration (structure des fichiers, sans les polygones).
  • Liste des informations manquantes ajoutée à ecarts.md (voir section 8).

Fin. Scénarios relus par vous, et par une personne qui connaît les audits bio pour ceux de certification et de capacité.

  • Tables site, emplacement, campagne : code unique par organisation, année d’ouverture, dates prévues, pack_version_id et modele_numerotation_version figés à l’ouverture, statut (préparation, ouverte, clôturée).
  • Points d’entrée de l’API, schémas TypeBox, client régénéré.

Tests. Unicité du code (EC-031) ; AA calculé depuis l’année d’ouverture (EC-023) ; la version de pack d’une campagne ouverte ne change plus.

A2 · Produits, unités, attributs, facteurs (1 jour)

Section intitulée « A2 · Produits, unités, attributs, facteurs (1 jour) »
  • Tables globales facteur et facteur_valeur, chargées avec les packs.
  • unite, produit (code utilisé par la numérotation), attributs typés par filière décrits en JSON Schema dans le pack, recettes de transformation paramétrables (entrées, sorties, coproduits, rendement de référence lu dans le pack).
  • Clé étrangère mouvement_ligne.produit_id.
  • Chargement du pack fruits minimal (produits et attributs de l’ananas), sans les rendements calibrés.

Tests. Un attribut hors schéma est refusé par Ajv, côté client et côté serveur ; un facteur absent du catalogue est refusé à la publication du pack ; vecteurs de tests du pack.

  • modele_numerotation en ajout seul, versionné par organisation ; format de l’avenant par défaut ; préfixe entreprise désactivé.
  • sequence_numero par (organisation, campagne, nature, produit) ; fonction SQL attribuer_numero() qui verrouille la ligne de séquence dans la transaction.
  • Liste des natures sans « vente ».
  • L’API appelle numeroOfficiel de packages/domain pour le format. La base garantit l’unicité et l’absence de trou.
  • Mise en œuvre : attribuer_numero() renvoie le rang, pas la chaîne ; l’API compose le numéro. Voir la page de la séquence.

Tests.

  • Critère de fin n° 1 : deux campagnes du même produit la même année donnent des numéros distincts.
  • Cent attributions concurrentes : aucun doublon, aucun trou.
  • Au-delà de 9 999 : erreur sequence_hors_capacite, aucun numéro attribué.
  • Une campagne garde son modèle quand une nouvelle version est publiée.
  • groupement, producteur (pièce d’identité, photo en fichier, chiffre_affaires_annuel avec devise), affectation_agent, fournisseur, client.
  • Doublon de pièce d’identité signalé, pas bloquant : contrôle doublon_identite ouvert ; tant qu’il n’est pas levé, ni capacité ni paiement pour la nouvelle fiche.
  • Fusion de deux fiches : action du back-office, tracée, qui ne supprime rien (la fiche absorbée passe en statut « fusionnée » avec un lien vers la fiche retenue).
  • Éligibilité au groupe (EC-014) : fonction pure dans packages/domain, critères alternatifs, seuils en paramètres versionnés en m² et en EUR.

Tests. AV1-02 ; levée du contrôle par l’auteur refusée (SB-12) ; vecteurs de l’éligibilité sur chaque critère et sur leur combinaison ; comparaison EUR/XOF par taux daté.

A5 · Foncier (2 jours, séquence la plus risquée)

Section intitulée « A5 · Foncier (2 jours, séquence la plus risquée) »
  • parcelle : code unique par organisation, groupement_id, region, mode_culture, type_sol en clés étrangères vers facteur_valeur, surface déclarée.
  • parcelle_version en ajout seul : geometry(Polygon, 4326), colonne GeoJSON par déclencheur, surface via ST_Area(geography), métadonnées GPS-03, lien vers la trace brute dans fichier.
  • Vue parcelle_version_en_vigueur.
  • ST_IsValid obligatoire, jamais de ST_MakeValid silencieux ; chevauchement détecté par ST_Intersects avec une tolérance d’aire en paramètre.
  • Écart de surface avec incertitude (evaluerEcartSurface) calculé et exposé par l’API.
  • Au Lot 1, les polygones arrivent par import GeoJSON dans le back-office (méthode « import » dans GPS-03). Le relevé terrain est au Lot 3.
  • zone_cueillette sur le même modèle.

Tests.

  • Polygone invalide : contrôle polygone_invalide, parcelle non éligible à une capacité.
  • Surface PostGIS comparée à surfaceM2 avec une tolérance de 0,1 %.
  • Un écart dans la marge d’incertitude n’est pas une anomalie (GPS-04).
  • Une ancienne version reste lisible à une date passée.

Point levé. La méthode « import » est ajoutée aux valeurs de la métadonnée « méthode » (EC-048). Mise en œuvre : page de la séquence A5.

  • referentiel (UE, NOP…), statut_conformite : six états (conversion A1, conversion A2+, bio, conventionnel, suspendu, retiré), cible unique parmi producteur, parcelle et zone de cueillette, source interne ou externe, période de validité.
  • certificat : cible opérateur ou groupement, organisme et code propres, sans contrôle de format, fichier PDF en fichier.
  • « Expiré » calculé à la date de l’opération.
  • Fonction pure peutRevendiquer(referentiel, unite, date), qui servira aux ventes (AV1-03, Lot 2). Mise en œuvre : pas de fonction SQL du même nom (une seule implémentation du verdict, dans le domaine) ; la base fournit les faits. Voir la page de la séquence.

Tests.

  • Critère de fin n° 3 : un certificat expiré bloque la revendication du référentiel correspondant.
  • « Retiré » et « conventionnel » restent distincts dans l’API et à l’affichage.
  • CHECK « exactement une cible renseignée ».
  • contrat : achat, vente, prestation ; contrepartie (producteur, groupement, fournisseur ou client) ; campagne ; période ; statut.
  • contrat_ligne : produit, quantité engagée en grammes, prix en unité mineure avec devise, tolérances.
  • prime : type, montant ou taux, devise.
  • Formule de réfaction en JSON, validée par le schéma de FormuleRefaction, lue par calculerPesee au Lot 2.

Tests. Une formule invalide est refusée ; vecteurs de calculerPesee avec la formule d’un contrat de démonstration ; aucun montant sans devise.

Point levé. Le mode d’arrondi est un champ de la formule portée par la ligne, plus_proche par défaut (EC-051), à confirmer sur un premier contrat type. Mise en œuvre : page de la séquence A7, précédée de la correction d’EC-070 (taux de change).

  • capacite_version par campagne et par parcelle, calculée sur la surface mesurée en vigueur ; nouvelle version à chaque modification.
  • Refus de saisie si la parcelle n’a pas de polygone valide, ou si le producteur a un contrôle doublon_identite ouvert.
  • Extension de app.validation : cible capacite_version_id, unicité (version, rôle), deux rôles requis (direction et RSCI), auteur exclu.
  • solde_capacite précalculé, avec groupement_id, consommé à zéro jusqu’au Lot 2.
  • Mise en œuvre : la capacité est une colonne générée de la base (une seule formule), le rendement est historisé avec motif et sans valeur par défaut (EC-074). Voir la page de la séquence.

Tests.

  • Critère de fin n° 2 : une parcelle sans polygone valide ne peut pas recevoir de capacité.
  • Validation par l’auteur refusée (SB-11) ; même personne sous deux rôles refusée ; capacité applicable seulement après les deux validations.
  • Vecteurs de evaluerCollecte sur un solde issu de la base.

A9 · Règles de synchronisation et gel du contrat (1 jour)

Section intitulée « A9 · Règles de synchronisation et gel du contrat (1 jour) »
  • Compartiments PowerSync organisation et perimetre_agent sur les vraies tables du Lot 1.

  • Mesure du volume synchronisé sur le jeu de démonstration étendu à 2 000 producteurs (cible : moins de 20 Mo).

  • Gel du contrat d’API : OpenAPI publié dans la documentation, version marquée, client régénéré.

  • Mise en œuvre : règles bucket_definitions (EC-076), colonnes générées calculées sur le téléphone (EC-077), volume 4,62 Mo (11,48 Mo au pire), contrat 1.0.0 gelé. Voir la page de la séquence.

Fin. Un téléphone de test reçoit le périmètre d’un agent, et seulement celui-là.

B1 · Socle d’interface et galerie (piste B, 1 jour)

Section intitulée « B1 · Socle d’interface et galerie (piste B, 1 jour) »
  • Jetons « Registre » dans packages/ui : variables CSS, correspondance Tailwind et shadcn, densités Bureau et Terrain, polices IBM Plex.
  • Composants : tampon de qualité, référence (provisoire et officielle), jauge de capacité, état vide, bandeau « À traiter », état de cycle de vie.
  • Thème react-jsonschema-form « Registre » (libellé au-dessus, unité à droite, erreur en clair).
  • Route /_galerie en développement.

Tests. Contraste des jetons vérifié par un test ; aucune couleur de statut mappée sur --destructive ou --success (test sur la feuille de style) ; tampon lisible sans couleur (symbole et bordure présents).

  • Connexion Keycloak (code d’autorisation + PKCE), second facteur imposé aux rôles sensibles.

  • Navigation du design system, sections non livrées grisées.

  • Sélecteur de campagne, formatage fr (espace insécable, JJ/MM/AAAA).

  • Écran « À traiter » branché sur sync.controle.

  • Mise en œuvre : connexion code + PKCE sans dépendance, jetons en mémoire, navigation du §7 avec sections non livrées grisées, sélecteur de campagne dans l’URL, écran « À traiter » avec levée motivée, contrat d’API 1.1.0 (bloquant, EC-079). Voir la page de la séquence.

B3 · Écrans des référentiels (au fil des séquences A)

Section intitulée « B3 · Écrans des référentiels (au fil des séquences A) »
Écran Après Points d’attention
Campagnes A1 Code, année, version de pack affichée
Produits et attributs A2 Formulaire généré depuis le pack
Numérotation A3 Aperçu du prochain numéro, lecture seule
Producteurs, groupements A4 Fiche avec doublon signalé et action de fusion
Parcelles A5 Carte MapLibre en lecture, import GeoJSON, écart de surface avec incertitude
Certificats et statuts A6 Tampons par référentiel, « Expiré » calculé
Contrats A7 Lignes, primes, formule de réfaction lisible
Capacités A8 Jauge, circuit de double validation, motif obligatoire
  • Mise en œuvre : les huit écrans, une route de lecture par besoin (contrat d’API 1.2.0 à 1.9.0), trois actions (fusion, import de polygone, validation de capacité), carte MapLibre (ADR 0041) et formulaires générés (ADR 0042). Voir la page de la séquence.

Fin de la piste B. La démonstration du Lot 1 se fait depuis le back-office sur le jeu « ananas Togo », sans passer par l’API en direct.

Avec deux sessions Claude Code en parallèle (une par piste, sur deux arbres de travail git distincts) :

Jour Piste A Piste B
J1 A0, A1 B1
J2 A2 B2
J3 A3, A4 (début) B3 : campagnes, produits
J4 A4 B3 : numérotation, producteurs
J5 A5 B3 : parcelles (début)
J6 A5, A6 B3 : parcelles
J7 A6, A7 B3 : certificats, contrats
J8 A8 B3 : capacités
J9 A9, recette Recette, jeu de démonstration

Neuf jours ouvrés, soit plus que la S2 du découpage. Le découpage suppose des équipes parallèles, pas un seul pilote avec Claude Code. À arbitrer : soit vous acceptez ce décalage, soit A7 (contrats) passe en tête du Lot 2, qui en a besoin en premier.

## Lot 1 — référentiels du noyau
Plan : apps/docs/src/content/docs/technique/lot-1/lot1-plan-execution.md
Séquence en cours : indiquée dans la demande.
- Une migration dbmate par séquence, toujours via app.installer_table.
- COMMENT ON en français sur chaque table et colonne.
- Toute table descendue sur le téléphone porte organisation_id ET groupement_id.
- Aucun ST_MakeValid silencieux.
- « Expiré » se calcule, il ne se stocke pas.
- Doublon de pièce d'identité : contrôle, jamais refus.
- Toute valeur métier (seuil, taux, tolérance) est un paramètre versionné.
- Chaque règle testée porte son identifiant : describe("AV1-01 – …").
- Toute information manquante va dans ecarts.md, jamais inventée.

Modèle de demande pour chaque séquence :

Séquence A5 du plan du Lot 1 (foncier).
1. Lis le plan, le schéma du socle et les décisions GPS-03, GPS-04, AV1-01.
2. Propose un plan : migration, fonctions SQL, fonctions de packages/domain,
points d'entrée, tests. Liste ce qui te semble ambigu. Attends ma validation.
3. Après validation : écris d'abord les tests, puis le code.
4. Fin : pnpm build, tests d'intégration et vecteurs au vert, types Kysely
régénérés, pages de documentation mises à jour, commit en français.

À verser dans ecarts.md dès la séquence A0.

Sujet Question Bloque
Méthode « import » des polygones L’ajouter aux méthodes GPS-03 ? A5
Tolérance de chevauchement Surface minimale d’intersection qui déclenche le contrôle A5
Capacité des zones de cueillette Même mécanisme que les parcelles, ou estimation par zone ? A8
Arrondi de la réfaction Mode par défaut, à caler sur un contrat type A7
Contrat de prestation Contenu minimal : unité facturée, service A7
Fournisseurs et clients Champs obligatoires ; certificat d’un fournisseur selon RG-013 corrigée A4, A6
Recettes de transformation Niveau de détail attendu au Lot 1 (structure seule ou avec coproduits) A2
Critère Couvert par
Deux campagnes du même produit la même année produisent des numéros distincts A3
Une parcelle sans polygone valide ne peut pas recevoir de capacité A5, A8
Un certificat expiré bloque la revendication du référentiel correspondant A6
Scénarios SR-L1 du lot passés A0 à A8
Contrat d’API gelé, tables synchronisées publiées, budget de volume mesuré A9
Démonstration sur le jeu « ananas Togo » depuis le back-office B3