Gérer des candidatures locatives chiffrées de bout en bout #135

Open
opened 2026-08-22 13:37:29 +02:00 by nessar · 26 comments
nessar commented 2026-08-22 13:37:29 +02:00 (Migrated from 172.24.0.1:8928)

Parent

#1

Objectif

Livrer un parcours complet de Candidature pour centraliser, sans compte candidat, les données personnelles et les justificatifs d'une personne qui postule pour un Appartement. Les contenus sont chiffrés dans le navigateur avant tout envoi et le serveur ne possède aucun moyen de les déchiffrer.

Une Candidature correspond exactement à un Candidat et à un Appartement. Plusieurs candidatures individuelles sélectionnées peuvent ensuite fournir plusieurs Locataires à un même Bail sans fusionner leurs dossiers sensibles.

Le vocabulaire autoritatif se trouve dans CONTEXT.md, la décision cryptographique dans docs/adr/0034-encrypt-candidate-applications-outside-the-server.md, la conservation dans l'ADR-0006 et le schéma descriptif dans le README.md.

Parcours retenu

Activation par le Bailleur

  • Les fonctions sans Candidature continuent de demander uniquement l'authentification OIDC.
  • Lorsqu'un Bailleur sans Passkey de candidature crée son premier Lien public de candidature, une boîte de dialogue explique la chaîne complète : réception de données sensibles, chiffrement hors serveur, passkey nécessaire à la lecture et impossibilité de récupération si toutes les passkeys sont perdues.
  • L'annulation, l'échec WebAuthn ou l'absence de support PRF laisse le lien non créé et affiche une aide de compatibilité. Aucun PIN, secret de récupération ou mécanisme à clé serveur n'est proposé.
  • Une passkey suffit ; un avertissement non bloquant recommande d'en ajouter une deuxième sur un autre appareil ou gestionnaire.

Liens public et privé

  • Un Appartement possède au plus un lien public actif. Le Bailleur peut le copier, afficher son QR code ou préparer un message mailto: ; l'application n'envoie ni ne suit les e-mails.
  • Le GET public charge seulement l'application et la notice d'information. Le client exécuté demande immédiatement la création par POST, sans clic supplémentaire, afin qu'une prévisualisation sans JavaScript ne crée rien.
  • Chaque création produit un nouveau brouillon puis redirige vers son lien privé. Fermer le lien public interdit seulement les nouvelles créations et n'invalide pas les liens privés existants ; une remise en location ultérieure reçoit un nouveau lien public.
  • La création est limitée par lien public et IP avec une politique configurable et testée. Un dépassement retourne 429, sans CAPTCHA ; l'IP ne devient jamais une métadonnée du dossier et n'est gardée que pendant la fenêtre anti-abus.
  • Le lien privé porte un identifiant technique non secret et, dans son fragment #, deux secrets aléatoires indépendants à forte entropie : la capacité d'accès et la clé de la Candidature. Le client transmet la capacité dans un en-tête d'autorisation, le serveur n'en conserve qu'une empreinte et ne reçoit jamais la clé de chiffrement.
  • Perdre le lien privé impose de recommencer depuis le lien public. Ni le serveur ni le Bailleur ne peuvent le reconstituer. Une issue terminale invalide la capacité mais ne peut pas effacer une copie déjà récupérée par son détenteur.

Saisie et cycle de vie

  • Le Candidat n'a ni compte, ni session OIDC, ni accès au portefeuille du Bailleur.
  • La saisie progresse par étapes explicites « Enregistrer et continuer ». Chaque étape chiffre puis enregistre atomiquement ses champs ; chaque fichier expose sa propre progression. Un état confirme la réussite, une sortie avec changements locaux avertit et une révision optimiste refuse tout écrasement par un autre appareil ou onglet périmé.
  • Les états sont DRAFT, SUBMITTED, SELECTED, REJECTED, WITHDRAWN et EXPIRED.
  • DRAFT -> SUBMITTED est demandé par le Candidat lorsque prénom, nom et au moins e-mail ou téléphone sont présents. Toute autre donnée ou pièce peut manquer : la complétude est informative et ne bloque jamais.
  • SUBMITTED -> DRAFT est demandé par le Bailleur après un échange privé externe. Le Candidat peut alors corriger avec le même lien ; le Bailleur perd l'accès serveur aux contenus jusqu'à la nouvelle soumission.
  • Seul SUBMITTED peut devenir SELECTED ou REJECTED. Le Candidat peut retirer un brouillon ou un dossier soumis ; le système peut faire expirer ces deux états. Toute issue terminale est irréversible.
  • Seuls un enregistrement réussi, une soumission ou un retour en brouillon actualisent l'activité. Ouvrir, lire, télécharger ou déchiffrer ne repousse jamais l'échéance.

Données et examen

  • Le formulaire applique un catalogue national, typé, fermé et versionné, limité aux pièces que la liste légale courante permet pour le Candidat et ses éventuelles Garanties proposées : identité, domicile, activité professionnelle et ressources. Les pièces génériques sont refusées.
  • Une Candidature peut proposer zéro à plusieurs garants personnes physiques ou organismes et, simultanément ou non, Visale. Cela ne crée ni un second Candidat ni une Garantie locative déjà contractuelle et ne bloque pas la soumission.
  • Un brouillon vide reste invisible au Bailleur. Après le premier enregistrement et avant la soumission, il ne voit que l'existence, la création et la dernière activité, jamais l'identité ni le contenu.
  • Après déverrouillage, la liste des dossiers soumis montre localement prénom, nom, date de soumission, situation professionnelle et total mensuel des ressources. Elle se trie localement par date ou ressources, sans score ni classement automatique et sans précharger les justificatifs.
  • Le Bailleur peut rejeter manuellement depuis cette liste sans ouvrir les pièces. Aucun motif n'est conservé ; une réponse générique est seulement copiable ou préparée par mailto:.
  • L'application ne fournit aucune messagerie. Les échanges privés restent externes.

Chiffrement et clés

  • La première activation génère dans le navigateur une paire RSA-OAEP 3072 / SHA-256 propre au Bailleur. Le serveur reçoit la clé publique et une enveloppe chiffrée de la clé privée, jamais la clé privée en clair.
  • Chaque Candidature reçoit une clé aléatoire de 256 bits. Chaque objet structuré ou binaire est chiffré par AES-256-GCM avec un nouveau nonce aléatoire de 96 bits et un tag de 128 bits. RSA-OAEP chiffre la clé de Candidature sous la clé publique du Bailleur.
  • Les données authentifiées associées lient la version de suite, le Bailleur, la Candidature, l'objet et sa révision. Les nonces ne sont jamais réutilisés. Les valeurs aléatoires applicatives proviennent de crypto.getRandomValues.
  • Pour chaque credential WebAuthn, HKDF-SHA-256 dérive depuis le résultat PRF une clé AES-256-GCM qui produit une enveloppe séparée du même matériel privé. Sel, nonce et formats sont versionnés. Aucun résultat PRF, clé dérivée ou matériel privé en clair ne quitte le navigateur.
  • Seules les API Web Crypto et WebAuthn natives sont utilisées ; aucune cryptographie maison ni nouvelle dépendance n'est introduite.
  • Le support PRF est vérifié à l'exécution. Si l'inscription ne fournit pas immédiatement le résultat, une assertion WebAuthn complète l'enrôlement avant la création du lien.

Gestion et usage des passkeys

  • Le Bailleur peut ajouter plusieurs credentials, notamment sur Windows, Android et macOS, après OIDC et déverrouillage par une passkey existante. OIDC seul ne donne jamais accès aux anciens dossiers.
  • L'ajout exécute une cérémonie avec la passkey existante pour ouvrir les octets de clé privée uniquement le temps de produire la nouvelle enveloppe, puis importe la clé d'usage comme CryptoKey non exportable et abandonne ces octets.
  • Chaque credential possède un libellé choisi, une date de création et une date de dernière utilisation. L'application ne prétend pas déterminer si deux credentials dépendent du même gestionnaire synchronisé.
  • La révocation exige OIDC et une autre passkey déjà enregistrée. La dernière passkey ne peut pas être retirée tant qu'un lien public est actif ou que des données ne sont pas purgées.
  • Une réinitialisation explicitement confirmée reste possible : elle ferme tous les liens, révoque les credentials et rend tous les dossiers restants immédiatement éligibles à la purge de #39. Elle ne récupère aucun contenu.
  • Après déverrouillage, la clé privée importée comme CryptoKey non exportable reste seulement référencée en mémoire. BroadcastChannel la clone entre les onglets LMNP Organizer de la même origine et du même profil navigateur après vérification de la session OIDC.
  • La déconnexion ou l'expiration OIDC ordonne à tous les onglets coopérants de supprimer leur référence. Fermer tous les onglets ou redémarrer le navigateur impose une nouvelle passkey. Aucun secret déverrouillé n'est placé dans localStorage, sessionStorage ou IndexedDB.

Fichiers, métadonnées et sécurité HTTP

  • Les octets, noms, types métier et éventuelles miniatures des justificatifs sont chiffrés. Le serveur ne voit que les chiffrés.
  • Seuls PDF, JPEG et PNG sont acceptés. Le navigateur vérifie leur signature binaire avant chiffrement et après déchiffrement. Archives, Office, SVG, HTML et exécutables sont refusés.
  • Un fichier source est limité à 25 Mo et une Candidature à 250 Mo de chiffrés stockés. Le client contrôle la source ; le serveur contrôle la taille de chaque chiffré avec sa marge versionnée et le total atomiquement, y compris en concurrence.
  • Le serveur ne peut pas analyser les chiffrés avec un antivirus ; cette limite est visible au Bailleur et aucun contenu actif n'est rendu.
  • Tant qu'elles appartiennent à la Candidature, la liste fermée des données en clair contient seulement : identifiants techniques de la Candidature, de l'Appartement et du Bailleur ; état, révision et dates du cycle de vie ; échéance de purge ; nombre et tailles des chiffrés ; version cryptographique ; empreinte de capacité ; clés publiques et enveloppes chiffrées ; métadonnées de gestion des passkeys. La sélection seule crée ensuite une nouvelle copie en clair des prénom, nom et contact confirmés dans le modèle Locataire actuel, jusqu'au chiffrement prévu par #146.
  • Les routes sensibles utilisent Cache-Control: no-store et Referrer-Policy: no-referrer. Fragments, capacités, en-têtes d'autorisation, données personnelles, contenus déchiffrés et payloads sensibles ne sont jamais journalisés ou envoyés à une télémétrie.
  • Toutes les opérations Bailleur exigent OIDC et contrôlent côté backend la propriété du portefeuille. Une capacité candidat n'autorise que son dossier et ne donne jamais accès à une autre Candidature, un Appartement ou un portefeuille.

Confidentialité, sélection et conservation

  • Les pages publiques et privées rendent accessible une notice complète et affichent un résumé avant le premier enregistrement. Elle identifie le Bailleur responsable, les finalités, catégories, destinataires, durées, droits, secret et irrécupérabilité du lien privé, absence d'antivirus et limites du chiffrement/révocation. Aucune case de consentement n'est exigée pour la démarche précontractuelle.
  • Une Candidature sélectionnée, rejetée ou retirée devient éligible à la purge 90 jours après son issue. Un brouillon ou dossier soumis expire après 90 jours sans mutation admissible et devient immédiatement éligible, sans 90 jours supplémentaires.
  • #135 persiste l'issue et l'échéance et fournit les opérations de cycle de vie ; #39 exécute et réconcilie la suppression des documents, fichiers, métadonnées et matériels de clé propres au dossier.
  • La sélection confirme puis crée atomiquement un Locataire avec prénom, nom et au moins e-mail ou téléphone ; l'adresse peut être complétée avant que la préparation du Bail exige un profil contractuel complet. Plusieurs sélections restent des Locataires distincts réunissables sur un Bail.
  • Aucun justificatif n'est copié automatiquement dans les pièces jointes actuelles du Locataire. Les copies de candidature restent chiffrées et suivent les 90 jours. La conservation sélective sans duplication et le chiffrement des Locataires/Baux sont reportés à #146.

Limites de menace explicites

  • Un intrus qui obtient tous les droits sur l'hôte ne peut pas déchiffrer les contenus déjà stockés avec les seuls fichiers, MongoDB, configurations et sauvegardes du serveur.
  • Dès que le Bailleur ou un futur Candidat utilise un client web servi par cet hôte compromis, l'intrus peut modifier JavaScript pour capturer résultat PRF, clé, données déchiffrées ou futures soumissions, ou substituer la clé publique. Il peut aussi supprimer ou restaurer d'anciens chiffrés et métadonnées. Une application signée indépendante ou du matériel dédié reste hors périmètre.
  • L'invalidation d'un lien, la révocation d'une passkey et l'effacement coopératif multi-onglets empêchent les futurs accès normaux mais ne révoquent pas cryptographiquement une clé ou copie déjà extraite.

Critères d'acceptation et vérification

  • Le domaine applique exactement les états, transitions, minimum de soumission, activité, échéances et révisions ci-dessus, avec erreurs structurées et tests de toutes les transitions interdites.
  • Les API publiques, à capacité et OIDC restent distinctes, valident leurs frontières de confiance et couvrent l'isolation entre Bailleur, Appartement, Candidature et credentials.
  • Le parcours public GET -> POST -> lien privé, la fermeture/réouverture, les aperçus sans effet, le 429 et la perte du lien sont couverts.
  • Les primitives cryptographiques sont encapsulées dans un module frontend étroit et testées par vecteurs/aller-retour : bon déchiffrement, mauvais credential, mauvais AAD, altération de tag, permutation d'objet, révision périmée et formats/version inconnus.
  • L'enrôlement, l'ajout, l'usage, le partage multi-onglets, la révocation, la perte totale et la réinitialisation des passkeys couvrent succès, annulation, PRF absent et erreurs sans mode dégradé.
  • Les API et stockages de Candidature ne reçoivent jamais les champs et fichiers en clair ; les tests vérifient la liste fermée de métadonnées, limitent le contrat de sélection aux prénom, nom et contact confirmés du nouveau Locataire, et excluent les secrets des erreurs et journaux.
  • Les limites PDF/JPEG/PNG, signatures, 25 Mo/250 Mo, concurrence et absence d'antivirus possèdent des états de chargement, progression et erreurs actionnables.
  • Le parcours candidat couvre première sauvegarde, reprise, conflit, soumission incomplète autorisée, lecture seule, correction après retour en brouillon, retrait et expiration.
  • Le parcours Bailleur couvre brouillons masqués, déverrouillage, liste/tri locaux, chargement des pièces à la demande, rejet sans ouverture, réponse générique, sélection et création atomique du Locataire.
  • Les interfaces publiques et authentifiées sont accessibles, responsives et exposent des états véridiques de chargement, succès, absence et erreur sans fuite de données.
  • Les tests frontend, backend et intégration pertinents, formatter, lint, typecheck, analyses statiques et builds passent ; le diff ne contient ni secret, donnée personnelle de test réaliste, log de débogage ni artefact généré.
  • Un test humain documente au minimum un credential Windows, Android et macOS compatible PRF ainsi qu'un parcours inter-appareil par QR lorsque le navigateur le propose. Une combinaison incompatible vérifie le message sans repli.

Hors périmètre

  • candidature groupée ou plusieurs Candidats dans une Candidature ;
  • compte ou authentification du Candidat ;
  • messagerie, envoi automatique d'e-mail, suivi de lecture ou conservation des échanges privés ;
  • score, classement automatique, décision ou rejet automatique ;
  • récupération par OIDC seul, PIN, secret serveur ou séquestre de clé ;
  • chiffrement de bout en bout des Locataires, Baux et pièces durablement promues, traité par #146 ;
  • client signé indépendant, extension navigateur ou matériel cryptographique dédié ;
  • moteur de purge coordonnée, traité par #39.

Dépendances

  • #39 dépend de ce ticket pour les états et échéances de Candidature.
  • #146 est bloqué par ce ticket pour réutiliser le coffre multi-passkey.
## Parent #1 ## Objectif Livrer un parcours complet de Candidature pour centraliser, sans compte candidat, les données personnelles et les justificatifs d'une personne qui postule pour un Appartement. Les contenus sont chiffrés dans le navigateur avant tout envoi et le serveur ne possède aucun moyen de les déchiffrer. Une Candidature correspond exactement à un Candidat et à un Appartement. Plusieurs candidatures individuelles sélectionnées peuvent ensuite fournir plusieurs Locataires à un même Bail sans fusionner leurs dossiers sensibles. Le vocabulaire autoritatif se trouve dans `CONTEXT.md`, la décision cryptographique dans `docs/adr/0034-encrypt-candidate-applications-outside-the-server.md`, la conservation dans l'ADR-0006 et le schéma descriptif dans le `README.md`. ## Parcours retenu ### Activation par le Bailleur - Les fonctions sans Candidature continuent de demander uniquement l'authentification OIDC. - Lorsqu'un Bailleur sans Passkey de candidature crée son premier Lien public de candidature, une boîte de dialogue explique la chaîne complète : réception de données sensibles, chiffrement hors serveur, passkey nécessaire à la lecture et impossibilité de récupération si toutes les passkeys sont perdues. - L'annulation, l'échec WebAuthn ou l'absence de support PRF laisse le lien non créé et affiche une aide de compatibilité. Aucun PIN, secret de récupération ou mécanisme à clé serveur n'est proposé. - Une passkey suffit ; un avertissement non bloquant recommande d'en ajouter une deuxième sur un autre appareil ou gestionnaire. ### Liens public et privé - Un Appartement possède au plus un lien public actif. Le Bailleur peut le copier, afficher son QR code ou préparer un message `mailto:` ; l'application n'envoie ni ne suit les e-mails. - Le `GET` public charge seulement l'application et la notice d'information. Le client exécuté demande immédiatement la création par `POST`, sans clic supplémentaire, afin qu'une prévisualisation sans JavaScript ne crée rien. - Chaque création produit un nouveau brouillon puis redirige vers son lien privé. Fermer le lien public interdit seulement les nouvelles créations et n'invalide pas les liens privés existants ; une remise en location ultérieure reçoit un nouveau lien public. - La création est limitée par lien public et IP avec une politique configurable et testée. Un dépassement retourne `429`, sans CAPTCHA ; l'IP ne devient jamais une métadonnée du dossier et n'est gardée que pendant la fenêtre anti-abus. - Le lien privé porte un identifiant technique non secret et, dans son fragment `#`, deux secrets aléatoires indépendants à forte entropie : la capacité d'accès et la clé de la Candidature. Le client transmet la capacité dans un en-tête d'autorisation, le serveur n'en conserve qu'une empreinte et ne reçoit jamais la clé de chiffrement. - Perdre le lien privé impose de recommencer depuis le lien public. Ni le serveur ni le Bailleur ne peuvent le reconstituer. Une issue terminale invalide la capacité mais ne peut pas effacer une copie déjà récupérée par son détenteur. ### Saisie et cycle de vie - Le Candidat n'a ni compte, ni session OIDC, ni accès au portefeuille du Bailleur. - La saisie progresse par étapes explicites « Enregistrer et continuer ». Chaque étape chiffre puis enregistre atomiquement ses champs ; chaque fichier expose sa propre progression. Un état confirme la réussite, une sortie avec changements locaux avertit et une révision optimiste refuse tout écrasement par un autre appareil ou onglet périmé. - Les états sont `DRAFT`, `SUBMITTED`, `SELECTED`, `REJECTED`, `WITHDRAWN` et `EXPIRED`. - `DRAFT -> SUBMITTED` est demandé par le Candidat lorsque prénom, nom et au moins e-mail ou téléphone sont présents. Toute autre donnée ou pièce peut manquer : la complétude est informative et ne bloque jamais. - `SUBMITTED -> DRAFT` est demandé par le Bailleur après un échange privé externe. Le Candidat peut alors corriger avec le même lien ; le Bailleur perd l'accès serveur aux contenus jusqu'à la nouvelle soumission. - Seul `SUBMITTED` peut devenir `SELECTED` ou `REJECTED`. Le Candidat peut retirer un brouillon ou un dossier soumis ; le système peut faire expirer ces deux états. Toute issue terminale est irréversible. - Seuls un enregistrement réussi, une soumission ou un retour en brouillon actualisent l'activité. Ouvrir, lire, télécharger ou déchiffrer ne repousse jamais l'échéance. ### Données et examen - Le formulaire applique un catalogue national, typé, fermé et versionné, limité aux pièces que la liste légale courante permet pour le Candidat et ses éventuelles Garanties proposées : identité, domicile, activité professionnelle et ressources. Les pièces génériques sont refusées. - Une Candidature peut proposer zéro à plusieurs garants personnes physiques ou organismes et, simultanément ou non, Visale. Cela ne crée ni un second Candidat ni une Garantie locative déjà contractuelle et ne bloque pas la soumission. - Un brouillon vide reste invisible au Bailleur. Après le premier enregistrement et avant la soumission, il ne voit que l'existence, la création et la dernière activité, jamais l'identité ni le contenu. - Après déverrouillage, la liste des dossiers soumis montre localement prénom, nom, date de soumission, situation professionnelle et total mensuel des ressources. Elle se trie localement par date ou ressources, sans score ni classement automatique et sans précharger les justificatifs. - Le Bailleur peut rejeter manuellement depuis cette liste sans ouvrir les pièces. Aucun motif n'est conservé ; une réponse générique est seulement copiable ou préparée par `mailto:`. - L'application ne fournit aucune messagerie. Les échanges privés restent externes. ## Chiffrement et clés - La première activation génère dans le navigateur une paire RSA-OAEP 3072 / SHA-256 propre au Bailleur. Le serveur reçoit la clé publique et une enveloppe chiffrée de la clé privée, jamais la clé privée en clair. - Chaque Candidature reçoit une clé aléatoire de 256 bits. Chaque objet structuré ou binaire est chiffré par AES-256-GCM avec un nouveau nonce aléatoire de 96 bits et un tag de 128 bits. RSA-OAEP chiffre la clé de Candidature sous la clé publique du Bailleur. - Les données authentifiées associées lient la version de suite, le Bailleur, la Candidature, l'objet et sa révision. Les nonces ne sont jamais réutilisés. Les valeurs aléatoires applicatives proviennent de `crypto.getRandomValues`. - Pour chaque credential WebAuthn, HKDF-SHA-256 dérive depuis le résultat PRF une clé AES-256-GCM qui produit une enveloppe séparée du même matériel privé. Sel, nonce et formats sont versionnés. Aucun résultat PRF, clé dérivée ou matériel privé en clair ne quitte le navigateur. - Seules les API Web Crypto et WebAuthn natives sont utilisées ; aucune cryptographie maison ni nouvelle dépendance n'est introduite. - Le support PRF est vérifié à l'exécution. Si l'inscription ne fournit pas immédiatement le résultat, une assertion WebAuthn complète l'enrôlement avant la création du lien. ## Gestion et usage des passkeys - Le Bailleur peut ajouter plusieurs credentials, notamment sur Windows, Android et macOS, après OIDC et déverrouillage par une passkey existante. OIDC seul ne donne jamais accès aux anciens dossiers. - L'ajout exécute une cérémonie avec la passkey existante pour ouvrir les octets de clé privée uniquement le temps de produire la nouvelle enveloppe, puis importe la clé d'usage comme `CryptoKey` non exportable et abandonne ces octets. - Chaque credential possède un libellé choisi, une date de création et une date de dernière utilisation. L'application ne prétend pas déterminer si deux credentials dépendent du même gestionnaire synchronisé. - La révocation exige OIDC et une autre passkey déjà enregistrée. La dernière passkey ne peut pas être retirée tant qu'un lien public est actif ou que des données ne sont pas purgées. - Une réinitialisation explicitement confirmée reste possible : elle ferme tous les liens, révoque les credentials et rend tous les dossiers restants immédiatement éligibles à la purge de #39. Elle ne récupère aucun contenu. - Après déverrouillage, la clé privée importée comme `CryptoKey` non exportable reste seulement référencée en mémoire. `BroadcastChannel` la clone entre les onglets LMNP Organizer de la même origine et du même profil navigateur après vérification de la session OIDC. - La déconnexion ou l'expiration OIDC ordonne à tous les onglets coopérants de supprimer leur référence. Fermer tous les onglets ou redémarrer le navigateur impose une nouvelle passkey. Aucun secret déverrouillé n'est placé dans `localStorage`, `sessionStorage` ou IndexedDB. ## Fichiers, métadonnées et sécurité HTTP - Les octets, noms, types métier et éventuelles miniatures des justificatifs sont chiffrés. Le serveur ne voit que les chiffrés. - Seuls PDF, JPEG et PNG sont acceptés. Le navigateur vérifie leur signature binaire avant chiffrement et après déchiffrement. Archives, Office, SVG, HTML et exécutables sont refusés. - Un fichier source est limité à 25 Mo et une Candidature à 250 Mo de chiffrés stockés. Le client contrôle la source ; le serveur contrôle la taille de chaque chiffré avec sa marge versionnée et le total atomiquement, y compris en concurrence. - Le serveur ne peut pas analyser les chiffrés avec un antivirus ; cette limite est visible au Bailleur et aucun contenu actif n'est rendu. - Tant qu'elles appartiennent à la Candidature, la liste fermée des données en clair contient seulement : identifiants techniques de la Candidature, de l'Appartement et du Bailleur ; état, révision et dates du cycle de vie ; échéance de purge ; nombre et tailles des chiffrés ; version cryptographique ; empreinte de capacité ; clés publiques et enveloppes chiffrées ; métadonnées de gestion des passkeys. La sélection seule crée ensuite une nouvelle copie en clair des prénom, nom et contact confirmés dans le modèle `Locataire` actuel, jusqu'au chiffrement prévu par #146. - Les routes sensibles utilisent `Cache-Control: no-store` et `Referrer-Policy: no-referrer`. Fragments, capacités, en-têtes d'autorisation, données personnelles, contenus déchiffrés et payloads sensibles ne sont jamais journalisés ou envoyés à une télémétrie. - Toutes les opérations Bailleur exigent OIDC et contrôlent côté backend la propriété du portefeuille. Une capacité candidat n'autorise que son dossier et ne donne jamais accès à une autre Candidature, un Appartement ou un portefeuille. ## Confidentialité, sélection et conservation - Les pages publiques et privées rendent accessible une notice complète et affichent un résumé avant le premier enregistrement. Elle identifie le Bailleur responsable, les finalités, catégories, destinataires, durées, droits, secret et irrécupérabilité du lien privé, absence d'antivirus et limites du chiffrement/révocation. Aucune case de consentement n'est exigée pour la démarche précontractuelle. - Une Candidature sélectionnée, rejetée ou retirée devient éligible à la purge 90 jours après son issue. Un brouillon ou dossier soumis expire après 90 jours sans mutation admissible et devient immédiatement éligible, sans 90 jours supplémentaires. - #135 persiste l'issue et l'échéance et fournit les opérations de cycle de vie ; #39 exécute et réconcilie la suppression des documents, fichiers, métadonnées et matériels de clé propres au dossier. - La sélection confirme puis crée atomiquement un Locataire avec prénom, nom et au moins e-mail ou téléphone ; l'adresse peut être complétée avant que la préparation du Bail exige un profil contractuel complet. Plusieurs sélections restent des Locataires distincts réunissables sur un Bail. - Aucun justificatif n'est copié automatiquement dans les pièces jointes actuelles du Locataire. Les copies de candidature restent chiffrées et suivent les 90 jours. La conservation sélective sans duplication et le chiffrement des Locataires/Baux sont reportés à #146. ## Limites de menace explicites - Un intrus qui obtient tous les droits sur l'hôte ne peut pas déchiffrer les contenus déjà stockés avec les seuls fichiers, MongoDB, configurations et sauvegardes du serveur. - Dès que le Bailleur ou un futur Candidat utilise un client web servi par cet hôte compromis, l'intrus peut modifier JavaScript pour capturer résultat PRF, clé, données déchiffrées ou futures soumissions, ou substituer la clé publique. Il peut aussi supprimer ou restaurer d'anciens chiffrés et métadonnées. Une application signée indépendante ou du matériel dédié reste hors périmètre. - L'invalidation d'un lien, la révocation d'une passkey et l'effacement coopératif multi-onglets empêchent les futurs accès normaux mais ne révoquent pas cryptographiquement une clé ou copie déjà extraite. ## Critères d'acceptation et vérification - [ ] Le domaine applique exactement les états, transitions, minimum de soumission, activité, échéances et révisions ci-dessus, avec erreurs structurées et tests de toutes les transitions interdites. - [ ] Les API publiques, à capacité et OIDC restent distinctes, valident leurs frontières de confiance et couvrent l'isolation entre Bailleur, Appartement, Candidature et credentials. - [ ] Le parcours public `GET -> POST -> lien privé`, la fermeture/réouverture, les aperçus sans effet, le `429` et la perte du lien sont couverts. - [ ] Les primitives cryptographiques sont encapsulées dans un module frontend étroit et testées par vecteurs/aller-retour : bon déchiffrement, mauvais credential, mauvais AAD, altération de tag, permutation d'objet, révision périmée et formats/version inconnus. - [ ] L'enrôlement, l'ajout, l'usage, le partage multi-onglets, la révocation, la perte totale et la réinitialisation des passkeys couvrent succès, annulation, PRF absent et erreurs sans mode dégradé. - [ ] Les API et stockages de Candidature ne reçoivent jamais les champs et fichiers en clair ; les tests vérifient la liste fermée de métadonnées, limitent le contrat de sélection aux prénom, nom et contact confirmés du nouveau Locataire, et excluent les secrets des erreurs et journaux. - [ ] Les limites PDF/JPEG/PNG, signatures, 25 Mo/250 Mo, concurrence et absence d'antivirus possèdent des états de chargement, progression et erreurs actionnables. - [ ] Le parcours candidat couvre première sauvegarde, reprise, conflit, soumission incomplète autorisée, lecture seule, correction après retour en brouillon, retrait et expiration. - [ ] Le parcours Bailleur couvre brouillons masqués, déverrouillage, liste/tri locaux, chargement des pièces à la demande, rejet sans ouverture, réponse générique, sélection et création atomique du Locataire. - [ ] Les interfaces publiques et authentifiées sont accessibles, responsives et exposent des états véridiques de chargement, succès, absence et erreur sans fuite de données. - [ ] Les tests frontend, backend et intégration pertinents, formatter, lint, typecheck, analyses statiques et builds passent ; le diff ne contient ni secret, donnée personnelle de test réaliste, log de débogage ni artefact généré. - [ ] Un test humain documente au minimum un credential Windows, Android et macOS compatible PRF ainsi qu'un parcours inter-appareil par QR lorsque le navigateur le propose. Une combinaison incompatible vérifie le message sans repli. ## Hors périmètre - candidature groupée ou plusieurs Candidats dans une Candidature ; - compte ou authentification du Candidat ; - messagerie, envoi automatique d'e-mail, suivi de lecture ou conservation des échanges privés ; - score, classement automatique, décision ou rejet automatique ; - récupération par OIDC seul, PIN, secret serveur ou séquestre de clé ; - chiffrement de bout en bout des Locataires, Baux et pièces durablement promues, traité par #146 ; - client signé indépendant, extension navigateur ou matériel cryptographique dédié ; - moteur de purge coordonnée, traité par #39. ## Dépendances - #39 dépend de ce ticket pour les états et échéances de Candidature. - #146 est bloqué par ce ticket pour réutiliser le coffre multi-passkey.
nessar commented 2026-08-22 13:37:34 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #39

mentioned in issue #39
nessar commented 2026-08-22 17:44:32 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #146

mentioned in issue #146
nessar commented 2026-08-22 18:16:47 +02:00 (Migrated from 172.24.0.1:8928)

changed title from Modéliser le cycle de vie des candidatures to Gérer des candidatures locatives chiffrées de bout en bout

<p>changed title from <code class="idiff"><span class="idiff left right deletion">Modéliser le cycle de vie des candidatures</span></code> to <code class="idiff"><span class="idiff left right addition">Gérer des candidatures locatives chiffrées de bout en bout</span></code></p>
nessar commented 2026-08-22 18:16:47 +02:00 (Migrated from 172.24.0.1:8928)

changed the description

changed the description
nessar commented 2026-08-22 18:18:32 +02:00 (Migrated from 172.24.0.1:8928)

changed the description

changed the description
nessar commented 2026-08-22 18:19:59 +02:00 (Migrated from 172.24.0.1:8928)

changed the description

changed the description
nessar commented 2026-08-22 18:22:09 +02:00 (Migrated from 172.24.0.1:8928)

changed the description

changed the description
nessar commented 2026-08-22 18:34:11 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #147

mentioned in issue #147
nessar commented 2026-08-22 18:34:12 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #148

mentioned in issue #148
nessar commented 2026-08-22 18:34:12 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #149

mentioned in issue #149
nessar commented 2026-08-22 18:34:13 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #150

mentioned in issue #150
nessar commented 2026-08-22 18:34:14 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #151

mentioned in issue #151
nessar commented 2026-08-22 18:34:14 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #152

mentioned in issue #152
nessar commented 2026-08-22 18:34:15 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #153

mentioned in issue #153
nessar commented 2026-08-22 18:34:16 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #154

mentioned in issue #154
nessar commented 2026-08-22 18:34:17 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #155

mentioned in issue #155
nessar commented 2026-08-22 18:34:17 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #156

mentioned in issue #156
nessar commented 2026-08-22 18:34:18 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #157

mentioned in issue #157
nessar commented 2026-08-22 18:34:19 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #158

mentioned in issue #158
nessar commented 2026-08-22 18:34:20 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #159

mentioned in issue #159
nessar commented 2026-09-05 04:09:57 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #183

mentioned in issue #183
nessar commented 2026-09-05 04:09:57 +02:00 (Migrated from 172.24.0.1:8928)

marked as related to #183

marked as related to #183
nessar commented 2026-09-05 04:40:05 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in issue #190

mentioned in issue #190
nessar commented 2026-09-26 18:14:39 +02:00 (Migrated from 172.24.0.1:8928)

mentioned in commit 79cfb2d26e

mentioned in commit 79cfb2d26ea390e03a8ec7782eab8e78d0819d71

Preserved GitLab #135 history: source attribution, exact timestamps, discussion grouping and review positions. Historical diff snapshots: 5; visible source notes: 24.

gitlab-47-issue-135.md (SHA-256 0ba1382a657a37e75837a26f258ed855bc3a71882855d2ae16c0c76180601923)

gitlab-47-issue-135.json (SHA-256 959560788811f25776a0fc4f7dc79fb77f87e2c6f82ca85afce4fdd276b944f1)

Old CI job execution and reports are omitted. Original source files and rollback backups remain protected.

<!-- gitlab-to-gitea-history:47:Issue:135 --> Preserved GitLab #135 history: source attribution, exact timestamps, discussion grouping and review positions. Historical diff snapshots: 5; visible source notes: 24. [gitlab-47-issue-135.md](https://gitea.nessar.fr/attachments/a152c97b-9e13-44ca-b11a-585f5f5fff82) (SHA-256 `0ba1382a657a37e75837a26f258ed855bc3a71882855d2ae16c0c76180601923`) [gitlab-47-issue-135.json](https://gitea.nessar.fr/attachments/ee837f7a-7209-46eb-83c1-1c0481ce12e3) (SHA-256 `959560788811f25776a0fc4f7dc79fb77f87e2c6f82ca85afce4fdd276b944f1`) Old CI job execution and reports are omitted. Original source files and rollback backups remain protected.

Source GitLab relationships: relates to (symmetric; no blocker dependency).

<!-- gitlab-to-gitea-related-links:47:135 --> Source GitLab relationships: **relates to** (symmetric; no blocker dependency). - [#183: Assouplir les candidatures et assurer leur continuité chiffrée vers les locataires](https://gitea.nessar.fr/nessar/lmnp-organizer/issues/183) — source link 1, created 2026-09-05T02:09:57.046358 UTC.
gitea-emergency added this to the Development project 2026-10-11 22:14:35 +02:00
gitea-emergency moved this to need-human-test in Development on 2026-10-11 22:14:35 +02:00
gitea-emergency added this to the Development — Parents project 2026-10-11 22:14:40 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: nessar/lmnp-organizer#135