La migration r5_ia exige pgvector, absent de postgis/postgis — la
bascule annoncée en R1 (« pgvector arrivera en R5 ») est faite : les
jobs api et e2e construisent infra/postgres et le démarrent par étape
(les services GitHub ne savent pas builder). La migration crée aussi
l'extension elle-même (idempotent, même patron que PostGIS en r1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ADR-004 : embeddings locaux sur CPU (fastembed ONNX,
paraphrase-multilingual-MiniLM-L12-v2, 384 dims — les textes du client
ne quittent jamais le serveur), pgvector dans le Postgres existant
(RagChunk possédé par Prisma, migration r5_ia + état de corpus sur
Document), génération opt-in (mode extractif par défaut : la recette
passe sans clé API), service siop2-ai jamais exposé — joint par l'API
NestJS seule (X-Service-Token).
apps/ai (FastAPI + uv) : pipeline PDF MinIO → texte paginé (pypdf) →
anonymisation D4 (e-mails, téléphones marocains, noms connus de la
base, insensible casse/accents — fonction pure testée) → découpage
avec chevauchement (testé) → embeddings → RagChunk localisé (« p. 42 »,
« bilan du 17/07 »). Bilans codés clôturés ingérés. Exclusion de
corpus (D3) appliquée à l'ingestion ET à la lecture.
14 pytest + ruff, embeddeur déterministe en CI (aucun téléchargement),
job CI ai (uv), deploy en dépend. Vérifié en réel avec le vrai modèle :
corpus seedé réindexé en 7 s (PDF réel → 31 extraits paginés + 3
bilans), recherche sémantique concluante, e-mails → ⟨contact⟩,
0 identité dans les chunks (contrôle SQL).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Jest reçoit tout ce qui suit « -- » comme pattern positionnel ; sur
GitHub Actions CI=true suffit, Jest le détecte seul.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
- 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>
- 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>