Aller au contenu

PD-298 — UI propriétaire de création et gestion des liens de partage sans compte

1. Objectif

La User Story PD-298 DOIT permettre au propriétaire authentifié d’une preuve, depuis l’application mobile ProbatioVault, de :

  • créer un lien de partage sans compte (email destinataire, TTL, options),
  • visualiser ses liens de partage (par preuve et globalement),
  • révoquer un lien avec confirmation contractuelle,
  • consulter le journal des accès d’un lien,
  • voir les avertissements contractuels DRM/RGPD avant action.

La story est strictement côté propriétaire. Aucune capacité destinataire native n’est incluse.

2. Périmètre / Hors périmètre

Inclus

  • Création d’un lien via POST /shares depuis la fiche d’une preuve possédée.
  • Liste des liens associés à une preuve.
  • Écran global “Mes partages” avec tri décroissant de création, filtre par état, pagination offset/limit.
  • Détail d’un lien et révocation via POST /shares/:id/revoke.
  • Consultation du journal via GET /shares/:id/events.
  • Affichage contractuel :
  • avertissement révocation (texte ARB-7 exact),
  • avertissement absence de DRM (première création + reconsultation),
  • encart RGPD visible avant soumission.
  • Validation client des entrées (email, TTL).
  • i18n FR (chaînes externalisées), multilingue-ready.

Exclu

  • Portail destinataire dans l’app.
  • Modification des endpoints backend PD-287.
  • Push notifications côté app.
  • Deep linking vers un partage.
  • Mode hors-ligne / queue offline.
  • Partage multi-preuves.
  • RGAA complet (hors périmètre MVP).

3. Définitions

Terme Définition
Propriétaire Utilisateur authentifié détenteur de la preuve (owner_user_id).
Lien de partage Autorisation d’accès sans compte gérée côté backend PD-287.
États du lien PENDING_ACTIVATION, ACTIVE, OTP_BLOCKED, REVOKED, EXPIRED.
TTL Durée de validité du lien avant expiration automatique.
Journal d’accès Historique append-only des événements d’accès du lien.
ARB-7 Texte contractuel d’avertissement de révocation (PD-287).
ARB-8 Avertissement contractuel d’absence de DRM (PD-287).
CA-287-27 Obligation d’information RGPD avant création.

Règle non testable marquée hors périmètre : - Validité juridique de la base légale RGPD (qualification légale) : hors périmètre de validation fonctionnelle UI.

4. Invariants (non négociables)

ID Règle Justification
INV-298-01 Le formulaire DOIT valider l’email avant tout appel réseau ; un email invalide NE DOIT PAS être soumis. Évite erreurs évitables et fuite de qualité vers backend.
INV-298-02 Toute révocation DOIT afficher le texte ARB-7 exact avant confirmation. Réduction du risque d’action irréversible non comprise.
INV-298-03 À la première ouverture de création (par compte), l’avertissement DRM DOIT être affiché puis mémorisé localement. Information explicite sur l’absence de DRM.
INV-298-04 Le TTL DOIT rester dans [15 min, 30 j] ; valeur par défaut 7 j. Cohérence avec PD-287 et contrôle abus.
INV-298-05 Les données de partage (listes, détail, events) NE DOIVENT PAS être mises en cache local ; chaque affichage DOIT être frais réseau. Évite incohérences d’état sensibles.
INV-298-06 L’encart RGPD DOIT être visible avant le bouton de soumission du formulaire. Conformité CA-287-27.
INV-298-07 Les emails destinataires NE DOIVENT JAMAIS être loggés ; seul shareId est loggable. Protection PII / RGPD.
INV-298-08 Le badge d’état affiché DOIT refléter strictement l’état backend parmi 5 états contractuels. Source de vérité unique backend.
INV-298-09 L’IP affichée dans le journal DOIT être partiellement masquée côté UI. Minimisation exposition données réseau.
INV-298-10 100% des chaînes visibles DOIVENT être externalisées i18n (aucune chaîne en dur). Maintenabilité locale + conformité linguistique.
INV-298-11 Les actions disponibles DOIVENT dépendre de l’état du lien (matrice contractuelle §5.5). Prévention actions invalides.
INV-298-12 L’action “Partager” NE DOIT être visible que sur preuve possédée par l’utilisateur connecté. Empêche tentative de partage hors propriété.
INV-298-13 L’écran global DOIT paginer en offset/limit, limit=20 fixe MVP, tri created_at desc. Scalabilité fonctionnelle MVP.
INV-298-14 Toute transition d’état non listée en §5.5 est INTERDITE contractuellement. Fermeture explicite de la machine à états.
INV-298-15 REVOKED et EXPIRED sont terminaux : -> * : INTERDITE (état terminal, résolution manuelle uniquement). Irréversibilité métier explicite.
INV-298-16 Le client NE DOIT PAS effectuer d’appels exploratoires pour inférer des partages non autorisés. Préservation anti-enumeration.
INV-298-17 Le module de gestion des partages requiert réseau disponible ; aucune exécution offline n’est autorisée. Cohérence sécurité/fraîcheur.

5. Flux nominaux

5.1 Modèle de données contractuel (source unique formats)

Donnée Format / Encodage Taille Jeu de caractères Case-sensitivity Regex / Validation Comportement si invalide
shareId UUID v4 texte 36 chars [0-9a-f-] case-insensitive /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/ Rejet UI de la navigation détail, erreur bloquante.
proofId UUID v4 texte 36 chars [0-9a-f-] case-insensitive même regex UUID v4 Action “Partager” masquée si absent/invalide.
ownerUserId UUID v4 texte 36 chars [0-9a-f-] case-insensitive même regex UUID v4 Partage interdit côté UI.
recipientEmail Email RFC 5322 simplifié (référence PD-287 D-287-03) 3..254 chars ASCII printable sans espace terminal comparaison case-insensitive Regex exacte D-287-03 requise (non fournie ici) Blocage soumission + message validation.
shareState Enum texte 1 valeur A-Z_ case-sensitive {PENDING_ACTIVATION, ACTIVE, OTP_BLOCKED, REVOKED, EXPIRED} État inconnu => erreur bloquante + non-actionnable.
ttlMinutes Entier signé base10 1..5 digits [0-9] n/a 15 <= ttlMinutes <= 43200 Rejet client (pas d’appel API).
maxViews (optionnel) Entier base10 ou null null ou 1..10 digits [0-9] n/a null ou entier >=1 ; borne max backend à clarifier Valeur <=0 rejet client ; > max backend => erreur backend propagée.
notificationsEnabled Booléen 1 bit logique true/false n/a bool strict Valeur non-bool = rejet client.
createdAt, expiresAt, eventAt ISO 8601 UTC 20..35 chars ASCII case-sensitive Date parseable ISO8601 Affichage “date indisponible” + pas de crash UI.
eventType Enum texte 1 valeur A-Z_ case-sensitive {CREATION, ACTIVATION, CONSULTATION, EXPORT, ECHEC_OTP, REVOCATION} (mapping backend à figer) Valeur inconnue => libellé UNKNOWN_EVENT, journal conservé.
eventRecipientEmail Même contrat que recipientEmail 3..254 chars ASCII printable cf. email cf. D-287-03 Si invalide, masquer valeur, garder événement.
eventIpRaw IPv4 ou IPv6 texte 7..45 chars [0-9a-fA-F:.] case-insensitive IPv4/IPv6 valide Affichage “IP masquée indisponible”.
eventIpMasked IP masquée texte v4: x.x.*.* ; v6: 4 hextets + *:*:*:* [0-9a-fA-F*:.] case-insensitive Transformation déterministe de eventIpRaw Si masquage impossible: fallback “IP masquée indisponible”.
deviceType Enum texte 1 valeur A-Z_ case-sensitive {MOBILE, DESKTOP} Valeur inconnue => UNKNOWN_DEVICE.
drmWarningSeen Booléen persistant local par compte 1 bit logique true/false n/a bool strict Si absent => considéré false (premier affichage obligatoire).

5.2 Bornes numériques contractuelles

Paramètre Valeur par défaut Min Max Unité Contexte / Percentile Comportement hors bornes
ttlMinutes 10080 (7j) 15 43200 (30j) minutes n/a (pas d’objectif perf chiffré) Rejet client bloquant.
Presets TTL {15,60,1440,10080,43200} 15 43200 minutes n/a Preset hors liste impossible en UI.
pagination.limit 20 20 20 éléments/page n/a Valeur différente interdite en MVP.
pagination.offset 0 0 2147483620 éléments n/a Valeur hors bornes => clamp [0,max].
maxViews (optionnel) null (illimité) 1 Non défini dans besoin/PD-287 accessible consultations n/a <=0: rejet client ; >max backend: erreur backend, non masquée.

Note contractuelle : - Aucun objectif de performance chiffré (latence P95/P99, mémoire) n’est fourni pour cette story ; ces SLA de performance sont hors périmètre.

5.3 SLA temporels (transitions)

SLA Valeur par défaut Borne min Borne max Configurabilité Comportement à expiration
Validité lien (share_ttl) 7j 15min 30j Configurable par propriétaire (preset/custom) État backend -> EXPIRED, accès futur révoqué, UI en lecture seule (journal consultable).

Aucune autre transition temporelle identifiée côté UI propriétaire.

5.4 Flux nominaux contractuels

F-298-01 — Création d’un lien depuis une preuve

  1. Le propriétaire ouvre la fiche d’une preuve.
  2. Le système vérifie la propriété (ownerUserId == user connecté).
  3. Le propriétaire ouvre le formulaire de partage.
  4. Le système vérifie l’indicateur drmWarningSeen :
  5. false => affiche avertissement DRM avant saisie effective.
  6. true => pas de réaffichage automatique.
  7. Le formulaire expose : email destinataire, TTL (presets/custom), maxViews optionnel, notifications, encart RGPD visible avant CTA.
  8. À soumission, validations client obligatoires (email, TTL, types).
  9. Si valide, appel POST /shares.
  10. En succès, affichage du lien créé avec état PENDING_ACTIVATION.
  11. Rafraîchissement de la liste des liens.

F-298-02 — Liste des liens d’une preuve

  1. Depuis une preuve possédée, le propriétaire ouvre la section partages.
  2. Le système récupère les partages du propriétaire et affiche uniquement ceux liés à la preuve.
  3. Chaque ligne affiche au minimum : statut (badge), date création, email (non loggé), actions contextuelles.
  4. Pull-to-refresh force un rechargement réseau.

F-298-03 — Écran global “Mes partages”

  1. Le propriétaire ouvre l’écran via navigation principale.
  2. Le système appelle GET /shares avec offset/limit.
  3. Résultats triés par création décroissante, filtrables par état.
  4. Infinite scroll par incrément d’offset de 20.
  5. Aucun cache local des données de partage.

F-298-04 — Détail et révocation

  1. Le propriétaire ouvre le détail d’un shareId.
  2. Le système affiche données du lien + actions autorisées selon état.
  3. Sur action “Révoquer”, affichage obligatoire de la modale ARB-7.
  4. Si confirmation explicite, appel POST /shares/:id/revoke.
  5. En succès, rafraîchissement état et verrouillage des actions non autorisées.

F-298-05 — Journal des accès

  1. Le propriétaire ouvre le journal d’un lien.
  2. Le système appelle GET /shares/:id/events.
  3. Chaque entrée affiche : date/heure, type, email, IP masquée, device.
  4. Si journal vide, un message contextuel explicite est affiché (pas de vide silencieux).

F-298-06 — Consultation répétée des avertissements

  1. Le propriétaire peut reconsulter l’avertissement DRM depuis paramètres ou formulaire.
  2. L’encart RGPD est affiché à chaque création, avant soumission.

5.5 Machine d’états, transitions retour et états terminaux

Matrice des transitions

État source -> PENDING_ACTIVATION -> ACTIVE -> OTP_BLOCKED -> REVOKED -> EXPIRED
PENDING_ACTIVATION INTERDITE AUTORISÉE (activation OTP) AUTORISÉE (blocage OTP) AUTORISÉE (révocation propriétaire) AUTORISÉE (TTL atteint)
ACTIVE INTERDITE INTERDITE INTERDITE AUTORISÉE (révocation propriétaire) AUTORISÉE (TTL atteint)
OTP_BLOCKED INTERDITE INTERDITE INTERDITE AUTORISÉE (révocation propriétaire) AUTORISÉE (TTL atteint)
REVOKED INTERDITE (terminal) INTERDITE (terminal) INTERDITE (terminal) INTERDITE (terminal) INTERDITE (terminal)
EXPIRED INTERDITE (terminal) INTERDITE (terminal) INTERDITE (terminal) INTERDITE (terminal) INTERDITE (terminal)

Transitions retour (obligatoire)

  • ACTIVE -> PENDING_ACTIVATION : INTERDITE (pas de rollback activation).
  • OTP_BLOCKED -> PENDING_ACTIVATION : INTERDITE (pas de déblocage manuel en MVP).
  • REVOKED -> ACTIVE : INTERDITE (révocation irréversible).
  • EXPIRED -> ACTIVE : INTERDITE (expiration irréversible).
  • REVOKED -> * : INTERDITE (état terminal, résolution manuelle uniquement).
  • EXPIRED -> * : INTERDITE (état terminal, résolution manuelle uniquement).

Comportement downgrade/retour

  • Données historiques (journal, métadonnées) : conservées en lecture seule.
  • Quotas/limites : réappliqués immédiatement par état backend.
  • Fonctionnalités : re-verrouillées immédiatement en REVOKED/EXPIRED.
  • Aucune transition bidirectionnelle autorisée : Aucune transition retour applicable au sens A↔B autorisé.

Checklist machine à états

  • Chaque état liste ses transitions sortantes autorisées/interdites.
  • Chaque état terminal mentionne explicitement -> * : INTERDITE.
  • Modèle d’états couvert par invariant dédié (INV-298-14, INV-298-15).

5.6 Mécanismes de protection distribuée

Aucun mécanisme de protection distribuée applicable (module synchrone mono-instance).

5.7 Atomicité multi-composant

Aucune atomicité multi-composant applicable côté PD-298 (pas de transaction DB/queue côté app).

5.8 Contraintes inter-modules

Élément Contrat
Routes/écrans d’un autre module à protéger Écran détail preuve (module preuves) : action “Partager” visible uniquement pour preuve possédée.
Mécanisme de protection Garde UI de propriété (ownerUserId de la preuve vs utilisateur connecté).
Données nécessaires de l’autre schéma/module proof.id, proof.owner_user_id, auth.user.id.
Résolution FK cross-module share.proof_id référence logique proof.id (contrat API).
Scope d’enregistrement du guard Scope local à la feature partage dans l’écran preuve, non global app-wide.
Exceptions d’accès Aucune exception rôle spécifiée dans le besoin.

5.9 Stratégie de migration DDL

Aucune migration DDL applicable (story UI mobile, aucune modification de colonne/base).

5bis. Diagrammes (obligatoires)

Diagramme d’état

stateDiagram-v2
    [*] --> PENDING_ACTIVATION : creation share (POST /shares)

    PENDING_ACTIVATION --> ACTIVE : OTP valide (backend)
    PENDING_ACTIVATION --> OTP_BLOCKED : seuil OTP atteint (backend)
    PENDING_ACTIVATION --> REVOKED : revoke owner
    PENDING_ACTIVATION --> EXPIRED : ttl atteint
    PENDING_ACTIVATION --> PENDING_ACTIVATION : INTERDITE

    ACTIVE --> REVOKED : revoke owner
    ACTIVE --> EXPIRED : ttl atteint
    ACTIVE --> PENDING_ACTIVATION : INTERDITE
    ACTIVE --> OTP_BLOCKED : INTERDITE
    ACTIVE --> ACTIVE : INTERDITE

    OTP_BLOCKED --> REVOKED : revoke owner
    OTP_BLOCKED --> EXPIRED : ttl atteint
    OTP_BLOCKED --> PENDING_ACTIVATION : INTERDITE
    OTP_BLOCKED --> ACTIVE : INTERDITE
    OTP_BLOCKED --> OTP_BLOCKED : INTERDITE

    REVOKED --> PENDING_ACTIVATION : INTERDITE (terminal)
    REVOKED --> ACTIVE : INTERDITE (terminal)
    REVOKED --> OTP_BLOCKED : INTERDITE (terminal)
    REVOKED --> EXPIRED : INTERDITE (terminal)
    REVOKED --> REVOKED : INTERDITE (terminal)

    EXPIRED --> PENDING_ACTIVATION : INTERDITE (terminal)
    EXPIRED --> ACTIVE : INTERDITE (terminal)
    EXPIRED --> OTP_BLOCKED : INTERDITE (terminal)
    EXPIRED --> REVOKED : INTERDITE (terminal)
    EXPIRED --> EXPIRED : INTERDITE (terminal)

Diagramme de séquence

sequenceDiagram
    participant U as Propriétaire
    participant APP as App ProbatioVault
    participant LS as Stockage local
    participant API as API Sharing (PD-287)

    U->>APP: Ouvre formulaire création
    APP->>LS: Lire drmWarningSeen(userId)
    LS-->>APP: true/false
    alt drmWarningSeen == false
        APP-->>U: Afficher avertissement DRM (ARB-8)
        U->>APP: Accepte avertissement
        APP->>LS: Ecrire drmWarningSeen(userId)=true
    end

    APP-->>U: Afficher encart RGPD avant CTA
    U->>APP: Saisit email + TTL + options
    APP->>APP: normaliser(email), valider(regex D-287-03), valider TTL [15..43200]
    APP->>API: POST /shares {proofId, recipientEmail, ttlMinutes, maxViews?, notificationsEnabled}
    API-->>APP: 201 {shareId, state=PENDING_ACTIVATION, expiresAt}
    APP-->>U: Afficher résultat + état

    U->>APP: Ouvre journal du lien
    APP->>API: GET /shares/:id/events
    API-->>APP: events[{eventAt, eventType, recipientEmail, ip, deviceType}]
    APP->>APP: transformer ip -> ipMasked
    APP-->>U: Afficher events (IP masquée)

6. Cas d’erreur

Code erreur Condition Comportement attendu
ERR-298-01 Email invalide en création Blocage local, aucun appel réseau, message de validation.
ERR-298-02 Tentative révocation sans confirmation Action annulée, aucun appel POST /revoke.
ERR-298-03 État UI obsolète vs backend Rechargement réseau immédiat, état backend prioritaire.
ERR-298-04 Email présent dans logs Non-conformité sécurité (échec test invariant).
ERR-298-05 Avertissement DRM non affiché à première création Blocage de la soumission tant que non affiché.
ERR-298-06 Journal vide sans contexte Afficher message contextualisé (jamais activé / pas d’événement / erreur réseau).
ERR-298-07 Preuve non possédée (action partage) Action non affichée ; si contournement, backend 403 géré sans fuite.
ERR-298-08 TTL hors bornes Rejet local avant appel API.
ERR-298-09 État OTP_BLOCKED sans action Afficher explication + action recommandée “Révoquer”.
ERR-298-10 Encart RGPD absent avant soumission Soumission interdite tant que non visible.
ERR-298-11 401/session expirée sur endpoint share Afficher erreur d’auth, redirection flux auth existant.
ERR-298-12 Échec réseau (timeout/offline) Afficher erreur réseau explicite, pas de faux succès local.

7. Critères d’acceptation (testables)

ID Critère Observable
CA-298-01 Création valide appelle POST /shares et retourne un état initial affiché. Requête observée + badge PENDING_ACTIVATION.
CA-298-02 Email invalide n’atteint jamais le backend. Aucune requête réseau quand format invalide.
CA-298-03 TTL hors [15min,30j] est bloqué côté client. Bouton submit inopérant + message d’erreur.
CA-298-04 Révocation affiche le texte ARB-7 exact avant appel API. Modal avec texte strict + appel seulement après confirmation.
CA-298-05 Écran global liste les partages triés desc et paginés offset/limit=20. Ordre vérifié + chargement page suivante.
CA-298-06 Filtres par état appliquent la matrice des 5 états. Résultats filtrés cohérents à l’état sélectionné.
CA-298-07 Aucune donnée de partage n’est lue depuis cache local persistant. Chaque entrée d’écran déclenche appel réseau frais.
CA-298-08 Journal affiche date/type/email/IP masquée/device. Colonnes visibles et remplies selon payload.
CA-298-09 IP affichée est masquée, jamais brute. Pattern x.x.*.* (v4) / masquage v6.
CA-298-10 Avertissement DRM est affiché à la première ouverture uniquement. Première ouverture: visible ; seconde ouverture: non automatique.
CA-298-11 Encart RGPD est visible avant CTA de création. Encart visible à l’écran au moment de soumission.
CA-298-12 Action “Partager” absente sur preuve non possédée. Aucun CTA partage si ownerUserId différent.
CA-298-13 Toutes les chaînes UI de la feature sont externalisées i18n. Audit statique sans chaînes littérales hardcodées.
CA-298-14 Emails destinataires absents des logs applicatifs. Inspection logs/tests: aucun email brut.
CA-298-15 Actions disponibles respectent la matrice par état. Boutons visibles/invisibles selon shareState.

8. Scénarios de test (Given / When / Then)

Scénario 1 — Création nominale

  • GIVEN propriétaire authentifié sur preuve possédée
  • WHEN il soumet email valide + TTL 7j
  • THEN POST /shares réussit
  • AND le lien apparaît avec état PENDING_ACTIVATION

Scénario 2 — Email invalide

  • GIVEN formulaire de création ouvert
  • WHEN email invalide est saisi
  • THEN la soumission est bloquée localement
  • AND aucune requête backend n’est envoyée

Scénario 3 — TTL hors borne haute

  • GIVEN formulaire ouvert
  • WHEN TTL custom > 30j
  • THEN la soumission est refusée côté client
  • AND un message de borne est affiché

Scénario 4 — Révocation confirmée

  • GIVEN un lien ACTIVE
  • WHEN propriétaire clique “Révoquer” puis confirme
  • THEN modal ARB-7 exacte est visible avant appel
  • AND POST /shares/:id/revoke est envoyé après confirmation
  • AND l’état devient REVOKED

Scénario 5 — Révocation annulée

  • GIVEN un lien ACTIVE
  • WHEN propriétaire ferme la modal sans confirmer
  • THEN aucun appel revoke n’est effectué
  • AND l’état reste inchangé

Scénario 6 — Première création et avertissement DRM

  • GIVEN drmWarningSeen=false
  • WHEN formulaire création est ouvert
  • THEN l’avertissement DRM est affiché avant soumission
  • AND le flag est mémorisé après acquittement

Scénario 7 — Journal d’accès

  • GIVEN un lien ayant des événements
  • WHEN propriétaire ouvre “Voir journal”
  • THEN GET /shares/:id/events est appelé
  • AND chaque ligne affiche IP masquée, pas IP brute

Scénario 8 — Journal vide contextualisé

  • GIVEN un lien sans événement retourné
  • WHEN écran journal est affiché
  • THEN un message explicatif contextuel est visible
  • AND l’écran n’est pas silencieusement vide

Scénario 9 — Preuve non possédée

  • GIVEN preuve dont ownerUserId != user connecté
  • WHEN utilisateur ouvre le détail de preuve
  • THEN action “Partager” est absente
  • AND aucun endpoint de création n’est appelé

Scénario 10 — Pas de cache local

  • GIVEN un lien révoqué depuis un autre terminal
  • WHEN propriétaire rouvre la liste partages
  • THEN un appel réseau frais est effectué
  • AND l’état affiché est REVOKED

9. Hypothèses explicites

ID Hypothèse Impact si faux
H-298-01 La regex email contractuelle D-287-03 est disponible côté référence backend. Validation client non alignée backend, écarts UX/API.
H-298-02 GET /shares expose pagination offset/limit utilisable en app. Infinite scroll non réalisable tel que spécifié.
H-298-03 Le backend accepte limit=20 constant pour le MVP. Liste globale inopérante ou tronquée.
H-298-04 Le payload events contient bien eventAt, eventType, recipientEmail, ip, deviceType. Journal incomplet vs objectif métier.
H-298-05 La borne maximale backend pour maxViews existe mais n’est pas fournie ici. Validation client incomplète, risque de 400 backend.
H-298-06 Les transitions backend réelles sont compatibles avec la matrice §5.5. Divergence machine d’états UI/backend (écart majeur).
H-298-07 La durée de rétention RGPD à afficher est fournie par source juridique produit. Encart RGPD incomplet/non conforme.
H-298-08 Validation juridique de la base légale RGPD n’est pas un test fonctionnel UI. À traiter en conformité légale (hors périmètre tests fonctionnels).

10. Points à clarifier

10.1 Contraintes techniques contractuelles (stack réelle)

Élément Valeur contractuelle
Projet cible ProbatioVault-app
Stack mobile React Native + Expo SDK 54 + TypeScript
Contrainte Safe Area react-native-safe-area-context (obligatoire)
Picker TTL custom @react-native-community/datetimepicker (décision PO du 2026-04-22)
Backend consommé ProbatioVault-backend (NestJS + TypeORM + PostgreSQL) via endpoints PD-287 uniquement
Interdictions explicites Aucun Swift/SwiftUI, aucun framework backend alternatif dans cette spec

10.2 Données manquantes / arbitrages restants

ID Point à clarifier Donnée manquante
PC-298-01 Regex email D-287-03 exacte Motif regex normatif backend non fourni dans l’expression de besoin.
PC-298-02 Borne max maxViews côté backend Valeur max contractuelle absente.
PC-298-03 Codes exacts eventType backend Mapping backend->UI à figer (labels FR vs enums API).
PC-298-04 Comportement exact transitions non listées (ex: ACTIVE -> OTP_BLOCKED) Matrice backend PD-287 détaillée non jointe.
PC-298-05 Gestion normative IPv6 masquée Règle UI v6 à valider produit/sécurité.
PC-298-06 Texte exact “durée de rétention” RGPD Valeur juridique à afficher non fournie.
PC-298-07 Message contextuel journal vide par état Copywriting final non fourni (i18n clés à valider).

Références

  • Epic : Référence épique non fournie dans l’expression de besoin.
  • JIRA : PD-298.
  • Repos concernés : ProbatioVault-app (principal), ProbatioVault-backend (dépendance API PD-287).
  • Documents associés :
  • Expression de besoin PD-298 (date 2026-04-22),
  • PD-287 (backend, DONE, date 2026-04-19),
  • ARB-7 / ARB-8 PD-287,
  • CA-287-27 (encart RGPD).