Apparence
12. Modèle de données
👔 En clair
La liste des informations gérées par l'application (projets, modules, tests, étapes, campagnes, anomalies, preuves, CRIMs…) et leurs liens. Le diagramme ci-dessous en donne la vue d'ensemble ; les tableaux détaillés qui suivent sont techniques.
v2 — Convex. Le modèle est défini dans
packages/backend/convex/schema.ts(defineSchema) : des collections de documents typés (TypeScript + validateurs Zod partagés via@recette/validators), reliées par références indexées (v.id("table")) plutôt que par clés étrangères SQL. L'isolation multi-tenant passe par un champorganizationIdsur chaque document, filtré par la couche ABAC / RLS applicative. Environ 14 collections métier (héritées du périmètre v1 : PostgreSQL/Supabase, ~14 tables).
📌 Correspondances de typage v1 → v2 :
UUID/UUID FK→_idConvex /v.id("table")·JSONB→ objet imbriqué validé par Zod ·TEXT … CHECK→ union de littéraux (v.union(v.literal(...))) ·UNIQUE/ index SQL → index Convex (.index("by_...", [...])) · migrations SQL → composant migrations Convex.
12.1 Diagramme entité-relation (macro)
Représentation conceptuelle. En Convex, chaque « table » est une collection de documents et chaque relation un champ
Id<...>résolu par index (voir les relationship helpersconvex-helpers).
En v2, l'identité et l'authentification (
organizations/profilesde la v1) sont portées par Better Auth (@convex-dev/better-auth) : l'utilisateur et sonorganizationIdviennent deauthComponent.getAuthUser(ctx), pas d'une table métier gérée à la main.
12.2 Dictionnaire des entités principales
tests (Flux / cas de test) — cœur du plan de test.
| Champ | Type (Convex) | Description métier |
|---|---|---|
_id | Id<"tests"> | Identifiant du document |
testCode | string | Code lisible (T1, T2…), unique par projet (index) |
nom | string | Nom du flux |
metier, fonctId, fonctNom, scId, scNom | string | Dénormalisations de la hiérarchie (synchronisées par triggers) |
scenarioId | Id<"scenarios"> | null | Scénario parent (optionnel) |
crims | string[] | Cache des codes CRIM (union des étapes) |
statut | union littérale | Cycle de vie : Draft / À rédiger / Validé / Obsolète |
isRefTest | boolean | true = référentiel maître ; false = snapshot/campagne-only |
campaignIdSnapshot | Id<"campaigns"> | null | null = maître ; sinon appartient à la campagne |
sourceRefId | Id<"tests"> | null | Ligne maître d'origine (traçabilité) |
position | number | Ordre d'affichage |
testeur, qualite | objet imbriqué | Blocs d'infos (validés par Zod) |
organizationId | string | Tenant — filtré par la couche ABAC |
etapes — étape d'un flux (définition + résultat).
| Champ | Type (Convex) | Description |
|---|---|---|
testId | Id<"tests"> | Flux parent |
campaignId | Id<"campaigns"> | null | null = maître ; sinon snapshot |
position | number | Ordre (unicité (testId, position) par index) |
nom, description, jeu, attendu, crimCode | string | Définition (copiée au snapshot) |
resultat | union littérale | OK / KO / Non testé — résultat, par campagne |
gravite, commentaire | string | Résultat |
evidenceFileId | Id<"evidence_files"> | null | Preuve d'étape |
anomalies — défaut sur une étape.
| Champ | Type (Convex) | Description |
|---|---|---|
etapeId | Id<"etapes"> | Étape (unique — 1 anomalie max, garanti par index) |
campaignId, testId | Id<...> | Scope + flux parent |
description | string | Obligatoire |
gravite | union littérale | Bloquant / Majeur / Gênant |
statut, assigneA, responsable, jiraLink, declarePar, dateCreation | — | Triage |
| dénormalisations (metier, codes/noms, crimCodes) | — | Liste sans jointures |
campaigns, crims, test_runs, evidence_files, modules, functionalities, scenarios, projects : mêmes entités qu'en v1, portées par des collections Convex typées. schema.ts (+ @recette/validators) est la source unique du modèle en v2 (le docs/db-schema.json de v1 n'a plus cours).
12.3 Dénormalisations & dette assumée
En v1, ces points étaient une dette fragile ; en v2 ils deviennent des choix outillés :
testsporte des champs texte dupliqués depuis la hiérarchie → en v2, synchronisés atomiquement par triggers (convex-helpers/server/triggers) au lieu d'une boucle fire-and-forget.crimssurtests: cache de codes → recalculé par trigger à chaque changement d'étape.testeur,qualite,executant: objets imbriqués (validés par Zod) — normalisation vers des références utilisateur Better Auth possible via migration.campaign_tests(M2M campagne↔test) de la v1 : abandonnée (le flux snapshot utilisecampaignIdSnapshot) — non reprise en v2, voir Fonctionnalités inaccessibles.