apps/mobile (Expo SDK 57, TS strict, workspace pnpm) : connexion
e-mail/mdp + sélecteur démo ADR-002 (uniquement si l'API l'expose),
tabbar de la maquette validée (onglets futurs marqués R4.2/R4.3),
« Ma journée » triée priorité puis échéance (fonction pure testée),
urgence en tête, pastille de synchro.
D1 en actes (lecture) : cache TanStack persisté dans AsyncStorage
(7 jours), NetInfo → onlineManager + bandeau hors-ligne horodaté ;
jeton en SecureStore ; tokens light/dark répliqués et testés ; client
typé régénéré depuis docs/openapi.json (règle d'or).
API : CORS_ORIGINS opt-in (vide par défaut) — Expo web/debug seulement,
le web de prod reste derrière le proxy, les apps natives n'ont pas
d'Origin.
Vérifié 10/10 en Expo web piloté (connexion démo Ahmed → Ma journée
scopée → hors-ligne servie du cache → retour) ; 6 tests jest-expo ;
lint racine étendu (react-hooks) ; job CI mobile, deploy en dépend.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Design d'abord : aucune ligne de code Expo avant validation. Ma journée
(en ligne / hors-ligne côte à côte), fiche OT, clôture terrain (bilan
codé R2, garde visible, variante « en file »), scan QR des étiquettes
A6 (R1, hors-ligne inclus), fiche ascenseur, checklist du mois (coches
individuelles en file), synchro & conflits (verrou optimiste, l'humain
tranche). Tokens répliqués, bi-thème, données du parc seedé.
5 décisions soumises avec les écrans : offline-first en file, verrou
optimiste, périmètre fermé technicien, scan résolu en local, photos
compressées en file — ni audio ni géolocalisation en R4 (loi 09-08).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Arbitrage du référent sur la revue pixel : tout corriger, activer la
recherche.
- Stock : filtre fournisseur, sous-seuil en tête, « Entrée de stock »
depuis la liste ; fiche pièce : fournisseur → lien Tiers.
- Statistiques : période 3/6/12 mois (paramètre months au contrat).
- Tiers : rattachements syndic→site (migration r3_recette_fixes,
Location.partnerId gardé CLIENT), éditable sur la fiche site, seedé.
- Bibliothèque : filtre « Rattaché à » + glisser-déposer (modale
préremplie, rattachement toujours requis).
- Recherche globale : GET /search (73 opérations) — familles OT/
ascenseurs/sites filtrées par la matrice, « voir autre » respecté ;
topbar ⌘K, debounce, résultats groupés, navigation clavier.
74 tests API (8 nouveaux sur le scoping de la recherche), 14/14
Playwright dont un parcours « recette corrigée », 18/18 contrôles en
navigateur réel, zéro erreur console.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Retour de pré-recette : les fichiers téléversés n'avaient ni aperçu ni
ouverture. Les images affichent leur vraie vignette (blob authentifié →
URL objet révoquée au démontage — un <img src> nu ne porte pas le jeton) ;
« Ouvrir » (bouton + clic vignette) affiche PDF et images dans un nouvel
onglet, ouvert dans le geste utilisateur pour passer les bloqueurs de
pop-up. « Télécharger » inchangé.
Vérifié en navigateur réel : vignette chargée, onglets blob (PDF rendu
dans la visionneuse), download intact, zéro erreur console.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Stock : alertes sous seuil (strie ambre), « Préparer le BC » sur la ligne ;
fiche pièce où les mouvements SONT le stock (entrée / ajustement motivé)
- Bons de commande : liste + panneau (envoi, annulation, réception → entrées
de stock à PU figé) ; création préremplie depuis l'alerte de seuil
- Fiche OT : carte « Pièces & main-d'œuvre » réelle (consommation à prix figé
annoncé avant le clic, temps au taux figé) + carte Documents (upload/download) ;
même carte Documents sur la fiche ascenseur
- Statistiques : 4 KPI, pannes par organe (bilans codés), coûts par mois,
top équipements ; le tableau de bord allume « Pannes par organe »
- Tiers, bibliothèque (upload rattaché, filtre par type), taux horaire
éditable dans Personnes ; nav Ressources/Pilotage activée par la matrice
- Recette R3 Playwright (2 parcours autonomes) ; cleanup-e2e étendu aux
entités R3 ; le formulaire BC attend la fin du refetch (stock périmé en cache)
13/13 e2e verts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- FileStorage : putObject/getObjectStream/removeObject, bucket créé au
démarrage — MinIO confiné à son implémentation (règle ESLint intacte)
- documents : upload multipart (PDF/JPG/PNG, 20 Mo max, rattachement
appareil OU OT requis, permission d'édition sur la CIBLE), liste
filtrable, téléchargement STREAMÉ par l'API (MinIO jamais exposé),
suppression ; e2e : octets téléchargés identiques aux octets envoyés
- analytics : GET /analytics/summary dérivé du réel — coûts/mois
(mouvements + main-d'œuvre figés), pannes par organe (bilans codés),
taux de préventif, durée moyenne de résolution, top équipements
- générateur OpenAPI : query params, multipart, réponse binaire (71 ops)
- CI : service MinIO (bitnami) sur les jobs api et e2e
- test de régression du tri « Interventions récentes » rendu déterministe
(positions absolues instables sous 12 suites parallèles) ; 58 tests,
6 runs complets consécutifs verts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Le formulaire email/mot de passe s'affichait seul, sans explication, quand
l'API locale n'était pas démarrée (la liste démo était masquée comme si
DEMO_MODE était absent). Une erreur réseau affiche désormais « L'API ne
répond pas — démarrez-la avec pnpm dev » ; le 404 (pas de mode démo)
reste silencieux, c'est le comportement ADR-002.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- maquette-r3.html (moule validé) : stock DÉRIVÉ des mouvements (alertes
sous seuil → préparer le BC), fiche pièce (les mouvements sont le stock),
bons de commande (réception → entrées, PU figé), coûts sur OT (pièces à
prix figé, main-d'œuvre à taux figé), statistiques (pannes par organe
depuis les bilans codés, coûts, top équipements — palette CVD), tiers,
bibliothèque (documents typés rattachés, MinIO via FileStorage)
- 4 décisions soumises (stock jamais saisi, prix/taux figés, réception
créatrice de mouvements, types de documents fermés)
- rendu vérifié (7 écrans, bi-thème, zéro erreur)
- BLOQUANT : validation du référent avant tout code applicatif R3
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Anomalie de recette (référent) : OT assigné à Ahmed, traité, clôturé —
visible dans son tableau de bord mais pas dans celui de Salma ni de
l'admin. Cause : liste triée par statut (Terminés en queue) alors que le
tableau de bord prend les 5 premières lignes ; les listes scopées
(technicien) sont courtes, celles des rôles « voir autre » non.
- tri par dernière activité (updatedAt desc) : un OT fraîchement clôturé
remonte en tête pour tous
- urgences « personne bloquée » ACTIVES épinglées au sommet (une urgence
annulée ne squatte plus la tête — corrigé au passage)
- test de régression dans la recette e2e (position ≤ urgences actives)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- migration : Asset.underContract + WorkOrder.periodKey avec unicité
[assetId, periodKey] — l'idempotence de la génération est EN BASE
(deux appels concurrents ne doublent jamais une grille)
- génération : une grille par appareil sous contrat, périodicités ancrées
sur la mise en service (mensuelles toujours dues), premier contrôle
(toutes les tâches) pour un appareil sans historique, échéance fin de
mois, événement GENERATED ; déclenchement manuel (cron au durcissement)
- gabarits administrables (désactivé = exclu des générations suivantes) ;
GET /preventive/status (générées, terminées, en retard, premiers contrôles)
- compteurs : GET meters (2 compteurs, récents d'abord) ; relevé
strictement croissant, refus motivé sinon
- contrat +7 opérations (48) ; 50 tests verts (94,7 % / 78 %) ; smoke test
prod : juillet généré (9 grilles, 8 premiers contrôles), 2e appel à zéro
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- migration r2_exploitation (10 tables) : WorkOrder (référence séquentielle,
horodatages), WorkOrderEvent, Request (1-1, motif de rejet), ReferenceValue,
InterventionReport (6 FK), TaskTemplate/ChecklistItem, Meter/MeterReading
- contrat : 15 opérations (41 total) ; la table des transitions et les champs
requis du bilan vivent dans @siop/shared ; la fiche OT expose
allowedTransitions + closureBlockers (messages métier)
- API : machine à états stricte ; garde de clôture (bilan 3 champs requis +
checklist sans tâche en attente) ; approbation → OT lié 1-1 (409 si déjà
traitée) ; rejet à motif obligatoire ; scoping « voir autre » sur listes et
accès directs (404 sans fuite) ; validation des valeurs de bilan par champ ;
« personne bloquée » triée en tête côté API
- seed : 31 valeurs de référentiels, 8 gabarits (parachute réglementaire),
OT/demandes/compteurs de la maquette — idempotent
- 45 tests verts (95 % stmts / 79 % branches) dont la recette officielle
rejouée de bout en bout ; smoke test sur build de prod
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- R0 close : tag release/r0 (recette + production en ligne)
- maquette-r1.html dans le moule validé (CSS répliquée, tokens identiques) :
sites + carte PostGIS, fiche site (hiérarchie d'emplacements), liste
ascenseurs (statuts d'équipement distincts des statuts OT), création
(identité → rattachement → organes), étiquette QR imprimable A6,
personnes & équipes (invitation par lien d'activation), catégories
- rendu vérifié en Chrome headless (7 écrans, bi-thème, zéro erreur)
- BLOQUANT : validation du référent avant tout code applicatif R1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- job deploy : webhook Dokploy appelé sur push main uniquement si les
5 jobs CI sont verts ; skip explicite tant que DOKPLOY_WEBHOOK_URL
n'est pas configuré
- runbook : instance de démonstration ENSET, checklist de déploiement
manuel depuis GitHub (§3) et mise en place du CD (§4)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- ci-contract : régénère docs/openapi.json + schema.d.ts et échoue au
moindre diff — la règle d'or (ADR-001) devient bloquante
- api : services PostgreSQL 18 + Redis, prisma migrate deploy, typecheck,
Jest avec coverageThreshold global 70 % (mesuré : 97,5 % stmts / 90,7 % branches)
- web : typecheck + vitest + build de production
- test unitaire PermissionsGuard (23 tests au total) ; badge CI au README
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>