Aller au contenu

PD-298 — Rapport de confrontation (Étape 8 — Gate CLOSURE)

Ce rapport est produit par l'orchestrateur Claude avant la gate PMO de clôture. Il confronte les documents produits pour identifier convergences, divergences et zones d'ombre. Date : 2026-04-22.

1. Sources confrontées

  • PD-298-specification.md (spec de besoin, step 1) — 17 invariants, 15 CA, matrice d'états contractuelle.
  • PD-298-tests.md (tests contractuels, step 2) — 45 TC (17 NOM + 12 ERR + 8 NR + 8 NEG), matrice INV→TC.
  • PD-298-plan.md (plan d'implémentation, step 4) — 10 modules (C01…C10), mapping INV/CA/TC→mécanismes, hypothèses techniques HT-01 à HT-11.
  • PD-298-acceptability.md (acceptabilité, step 7) — reviews LLM (code, tests, sécurité), synthèse ACC-01 à ACC-06.
  • PD-298-review-step8.md (revue post-correction, step 8) — suivi append-only des écarts ACC-*, preuves fichiers/commits.

2. Convergences

Les quatre documents s'accordent explicitement sur :

  • CV-01 — Périmètre fonctionnel. Spec §2 (inclus/exclus), tests §1, plan §10 et acceptability §Prérequis confirment le périmètre strictement côté propriétaire, sans portail destinataire, sans push, sans offline, sans deep-link destinataire.
  • CV-02 — Machine d'états à 5 valeurs. {PENDING_ACTIVATION, ACTIVE, OTP_BLOCKED, REVOKED, EXPIRED} avec REVOKED et EXPIRED terminaux (spec §5.5 ; tests TC-NOM-16 ; plan §3 INV-298-08/11/14/15 + matrice ALLOWED_ACTIONS §F4).
  • CV-03 — Bornes TTL. [15, 43200] minutes, défaut 10080 (spec §5.2 ; tests TC-NOM-01 / TC-ERR-08 ; plan §3 INV-298-04 via TtlPicker + validateTtl).
  • CV-04 — Pagination contractuelle. offset/limit=20 fixe, tri created_at desc (spec §5.1/§5.4 ; tests TC-NOM-05 / TC-NEG-02 ; plan §F3 avec SHARE_PAGE_SIZE = 20).
  • CV-05 — No-cache persistant. Chaque ouverture déclenche un appel réseau frais (spec INV-298-05 ; tests TC-NOM-13 / TC-NR-01 ; plan §3 via cacheTime=0, staleTime=0).
  • CV-06 — Endpoints backend consommés. Les quatre endpoints PD-287 (POST /shares, GET /shares, POST /shares/:id/revoke, GET /shares/:id/events) sont référencés de manière cohérente par les quatre documents.
  • CV-07 — 17 invariants + 15 CA + 45 TC. La table de traçabilité tests §2 (matrice invariant→test) et plan §3/§5 couvrent l'intégralité des invariants et critères d'acceptation de la spec. Aucun invariant n'est orphelin de mécanisme au niveau contractuel.
  • CV-08 — i18n 100 %. Les quatre documents imposent l'externalisation complète des chaînes visibles (spec INV-298-10 ; tests TC-NOM-14 / TC-NR-02 ; plan §1.1 + ESLint no-literal-string).
  • CV-09 — Scope cross-module unique. La seule modification hors du module sharing est le CTA « Partager » sur l'écran détail preuve, strictement owner-only (spec §5.8 ; plan §9 « Mécanismes cross-module »).
  • CV-10 — Réserves documentaires reconnues. Spec §9/§10 (HT-298-/PC-298-), tests §9 (règles non testables), plan §8 (HT-01/HT-02/HT-03/HT-04/HT-05) et acceptability (review écart E-08) concordent sur les placeholders : regex D-287-03, textes ARB-7/ARB-8, copy RGPD rétention, borne maxViews, mapping eventType, masquage IPv6 canonique.

3. Divergences

⚠️ Les conflits ne sont pas lissés. Chaque divergence est rendue visible telle qu'observée dans les sources.

DIV-01 — Guard owner-only (INV-298-12 / CA-298-12)

  • Plan (§3, §F1, §Mécanismes cross-module) : le CTA « Partager » est conditionné par useOwnership(proofId) monté dans ProofDetailScreen ; sans propriété, le composant ShareCta retourne null. Le plan référence explicitement src/screens/proofs/ProofDetailScreen.tsx.
  • Acceptability (ACC-01, review step 8 §2) : le guard partiel est présent dans src/sharing/guards/index.ts:34, mais aucune preuve de câblage dans ProofDetailScreen.tsx n'est fournie ; l'écran preuve principal (src/screens/ProofScreen.tsx:1) reste générique. Statut : PARTIELLEMENT RÉSOLU.
  • Tests (TC-NOM-07, TC-ERR-07) : aucun résultat d'exécution PASS fourni.
  • Impact : INV-298-12 et CA-298-12 non démontrés. Risque fonctionnel direct : CTA partage visible sur preuve non possédée côté UI.

DIV-02 — Scrubbing PII télémétrie (INV-298-07 / CA-298-14)

  • Plan (§3 INV-298-07, §7 SEC-01) : C10 sharing-telemetry filtre strictement recipientEmail et eventRecipientEmail ; Sentry beforeSend scrub les breadcrumbs ; console.log banni via ESLint.
  • Acceptability (ACC-03, review step 8 §2) : metadata reste typé Record<string, string | number | boolean> dans src/sharing/telemetry/index.ts:23, sans allowlist anti-PII runtime. La sérialisation relaie metadata tel quel (telemetry/index.ts:45). Statut : NON RÉSOLU.
  • Tests (TC-NOM-15, TC-ERR-04) : aucun résultat d'exécution PASS fourni.
  • Impact : INV-298-07 (protection PII) n'est pas matériellement garanti ; risque RGPD direct si un appelant injecte un email via metadata.

DIV-03 — Masquage IP fallback (INV-298-09 / CA-298-09)

  • Plan (§3 INV-298-09) : le fallback de maskIp retourne le libellé i18n t('sharing.events.ip_masked_unavailable') si l'IP est non interprétable. Conformité annoncée avec TC-NEG-07.
  • Acceptability (ACC-04, review step 8 §2) : src/sharing/masking/index.ts:45-46 retourne encore la valeur brute/trimmée en fallback. Statut : NON RÉSOLU.
  • Tests (TC-NOM-12, TC-NEG-07) : aucun résultat d'exécution PASS fourni.
  • Impact : INV-298-09 non garanti ; risque d'affichage d'IP brute en UI sur entrée malformée.

DIV-04 — Détection offline (INV-298-17 / CA-298 via TC-NOM-17)

  • Plan (§3 INV-298-17, §6 ERR-298-12) : useNetInfoOnline() bloque toute action sharing offline ; bannière hors-ligne rendue ; actions désactivées.
  • Acceptability (ACC-05, review step 8 §2) : aucune détection NetInfo observée. Les écrans (ShareCreateScreen.tsx:22, MySharesScreen.tsx:18, ShareDetailScreen.tsx:46, ShareEventsScreen.tsx:17) appellent directement les hooks réseau sans garde. Statut : NON RÉSOLU.
  • Tests (TC-NOM-17, TC-ERR-12) : aucun résultat d'exécution PASS fourni.
  • Impact : INV-298-17 non matérialisé ; UX incohérente offline, risque de faux succès local contraire à ERR-298-12.

DIV-05 — Hook useProofShares mal utilisé

  • Plan (§F2) : ProofShareListSection monte useProofShares(proofId) avec un proofId garanti (contexte écran preuve).
  • Acceptability (ACC-02, review step 8 §2) : src/sharing/screens/ShareDetailScreen.tsx:46 appelle useProofShares(undefined) alors que src/sharing/hooks/index.ts:72-76 impose un proofId non vide. Statut : NON RÉSOLU.
  • Tests : TC concernés (détail/révocation) sans preuve d'exécution PASS.
  • Impact : comportement runtime indéterminé sur l'écran détail (erreur d'hypothèse, requête malformée, ou écran cassé selon l'implémentation du hook).

DIV-06 — Couverture tests / preuves d'exécution

  • Plan (§Périmètre de test) : « Couverture ≥ 80 % lignes / 80 % branches sur src/sharing/** ». 45 TC listés (§5) avec niveau unit / intégration / lint / contrat.
  • Tests (§10 Verdict QA) : « Testable partiellement (avec réserves listées) » — le document tests ne prétend pas que les TC sont exécutés, il les spécifie.
  • Acceptability (§Prérequis, ACC-06) : « Coverage : N/A — pas de tests Jest dans le module sharing ». Aucun fichier sharing/PD-298 sous src/__tests__ (review step 8). Aucune preuve d'exécution PASS pour l'un quelconque des 45 TC. Exécution locale Jest bloquée par environnement read-only (EPERM sur .jest-cache).
  • Impact : les 45 TC, 17 invariants, 15 CA restent non vérifiés par une exécution matérielle. Aucun des écarts ACC-01 à ACC-06 ne peut être classé RÉSOLU faute de preuve (review step 8 §3).

DIV-07 — Sonar : QG « OK » vs issues BLOCKER

  • Acceptability (§Analyse Sonar) : « Quality Gate : OK (API) » ET « Issues BLOCKER (projet entier) : 28 (pré-existantes, 0 dans src/sharing/) ». Scanner local non exécutable (token auth).
  • Spec / Plan : aucun critère quantitatif Sonar imposé au niveau story ; le plan (§Périmètre de test) liste uniquement ESLint / tsc.
  • Impact : apparence contradictoire (QG OK alors que 28 BLOCKER existent). La distinction « 0 dans src/sharing/ » est tenable contractuellement côté story PD-298, mais le scanner local non exécuté reste une réserve conforme à la procédure /gov-accept (Phase 1.5 Sonar bloquante).

DIV-08 — Stub d'authentification

  • Acceptability (§Prérequis) : getAuthToken() est un stub documenté, flaggé « intégration auth existante requise ».
  • Plan : ne mentionne pas ce stub ; présuppose que le client HTTP (C05) consomme un token existant.
  • Tests (TC-ERR-11) : « 401/session expirée → redirection flux auth existant » est spécifié mais ne peut être démontré tant que le stub est en place.
  • Impact : ERR-298-11 non vérifiable en l'état ; le stub constitue une dépendance d'intégration hors code sharing.

DIV-09 — Tests unitaires : spec neutre, plan exigeant, réalité absente

  • Spec : ne prescrit pas de test unitaire (artefact fonctionnel).
  • Plan (§Périmètre de test) : impose « unit + intégration + lint + contrat » avec couverture 80 %.
  • Acceptability : « N/A — pas de tests Jest dans le module (tests contractuels fonctionnels, pas unitaires) » + ACC-06 « Tests unitaires absents — Dette technique — story séparée ».
  • Impact : divergence de prescription entre plan (unitaire attendu) et acceptability (dette technique reportée sur story séparée). Aucune arbitration documentée entre les deux positions.

4. Zones d'ombre

ZO-01 — Regex email D-287-03 (HT-01 / PC-298-01)

Non fournie dans les artefacts accessibles. Plan (§8.1) prévoit extraction depuis le code backend (ProbatioVault-backend/src/sharing/dto/*.ts) en fin de Wave 1 ; aucune trace d'exécution de cette action. Fallback RFC 5322 simplifié en C02 annoncé mais version non tracée (pattern_version).

ZO-02 — Textes ARB-7 / ARB-8 exacts (HT-03 / PC-298 / NT-03)

Placeholders i18n conservés (« À définir — PD-287 ARB-7 », idem ARB-8). Plan §1.2 signale l'escalade PO requise avant Gate 8 ; aucune escalade documentée. INV-298-02 / INV-298-03 vérifiés sur placeholder, pas sur texte officiel.

ZO-03 — Copy RGPD rétention (HT-02 / PC-298-06)

Contenu normatif (finalité, base légale, rétention chiffrée, droits) non fourni. Plan §1.2 escalade Product/Legal non documentée. INV-298-06 / CA-287-27 vérifiés sur template, pas sur texte final.

ZO-04 — Borne maximale maxViews backend (HT-05 / PC-298-02)

Non définie dans les entrées accessibles. Plan §8 accepte explicitement de propager l'erreur backend 400 telle quelle ; tests classent la règle « non testable ». Aucune confirmation backend.

ZO-05 — Mapping eventType backend→UI (HT-04 / PC-298-03)

Valeurs backend définitives non figées. Plan prévoit fallback UNKNOWN_EVENT, tests TC-NEG-06 ciblent ce fallback ; le mapping nominal reste hypothétique.

ZO-06 — Masquage IPv6 canonique (HT-11 / PC-298-05)

Règle normative précise non jointe. Plan cite la lib ipaddr.js pour canonicalisation ; tests classent la règle « non testable » faute de norme de rendu. Deux cas (adresse canonique vs zero-compressed) non distingués dans la spec §5.1.

ZO-07 — Compatibilité endpoints PD-287 effective (HT-06 / HT-07 / HT-08)

Plan §8.1 prévoit vérification via Swagger PD-287 + tests d'intégration contre backend dev en fin de Wave 2 ; aucune trace de Swagger confronté. L'hypothèse offset/limit vs cursor-based, l'acceptation de ?state=, et la matrice de réponses 204/409 sur revoke ne sont pas démontrées à partir d'une source externe jointe.

ZO-08 — Backend 403 enumeration-free

Tests TC-ERR-07 prescrivent « message géré sans fuite », plan §SEC-08 mappe 403 → sharing.errors.generic_403. Le comportement backend effectif (contenu des réponses 403) n'est pas évidencé dans les artefacts de la story côté app.

ZO-09 — Stratégie de lift des placeholders post-Gate 8

Aucun document ne spécifie si la livraison MVP est conditionnée par le remplacement des placeholders ARB-7/ARB-8/RGPD, ni quel verdict est appliqué si ces textes restent en placeholder à production. Plan §8.1 dit « step 6b démarre sur placeholders mais Gate 8 NON_CONFORME » ; acceptability ne reprend pas ce principe.

ZO-10 — Déclenchement des vérifications CI attendues

Plan prévoit ESLint no-literal-string + i18n-unused + tsc --noEmit en CI. Acceptability mentionne « Lint / Format : Passé via lint-staged hooks sur chaque commit » sans preuve de run complet CI sur PR. Aucun rapport CI formel joint.

5. Recommandation

  • Procéder — convergence confirmée, aucun conflit bloquant
  • Rework nécessaire — divergences à résoudre avant de continuer
  • Escalade — décision humaine requise sur un point structurant

Constat factuel (pas de prise de position) :

  1. Cinq invariants non négociables (INV-298-07, INV-298-09, INV-298-12, INV-298-17, INV-298-11 via DIV-05) sont spécifiés, tracés au plan, mais contredits par l'implémentation constatée (DIV-01 à DIV-05).
  2. Aucun des 45 TC n'a de preuve d'exécution PASS jointe (DIV-06), ce qui laisse impossible la classification RÉSOLU des écarts ACC-01 à ACC-06 (review step 8 §3).
  3. Trois placeholders contractuels (ARB-7, ARB-8, RGPD rétention) n'ont pas été levés malgré l'engagement plan §8.1 (ZO-02, ZO-03).

Ces éléments sont soumis en état au dossier de conformité PMO pour verdict Gate 8. L'orchestrateur ne tranche ni ne corrige.