[{"data":1,"prerenderedAt":3851},["ShallowReactive",2],{"transparence-2026-07-21-audit-pq-akarup-mobile":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"source":10,"date":11,"body":12,"_type":3845,"_id":3846,"_source":3847,"_file":3848,"_stem":3849,"_extension":3850},"/transparence/2026-07-21-audit-pq-akarup-mobile","transparence",false,"","Audit du code source — application mobile pq-akarup-mobile","Date : 21 juillet 2026\nVersion : v2 (ajout section 3 — protocole post-quantique et conformité NIST)\nPérimètre : archive pq-akarup-mobile_copie.zip (copie de travail, HEAD e3a4483 sur develop)\nMéthode : restauration depuis le .git embarqué des dossiers exclus du zip (modules/, __mocks__/, docs/), exécution du workflow CSPN complet (npm ci, tsc --noEmit, vitest run, eslint), greps ciblés sur les pièges connus du projet, et lecture ligne à ligne des primitives cryptographiques ainsi que du code source de @noble/post-quantum 0.5.4 tel qu'installé dans node_modules.","Claude (Anthropic)","2026-07-21",{"type":13,"children":14,"toc":3815},"root",[15,24,158,162,169,174,262,283,290,613,616,622,628,636,641,759,764,882,921,966,980,988,997,1032,1056,1070,1078,1196,1221,1283,1289,1297,1359,1390,1430,1436,1444,1449,1511,1569,1581,1589,1624,1648,1654,1662,1764,1770,1778,1838,1843,1876,1879,1885,1904,1910,2250,2305,2311,2324,2412,2453,2502,2508,2531,2539,2551,2567,2575,2595,2642,2666,2672,2691,2699,2712,2827,2885,2891,2896,2913,2944,3002,3007,3066,3078,3095,3112,3118,3386,3396,3399,3405,3697,3715,3718,3724],{"type":16,"tag":17,"props":18,"children":20},"element","h1",{"id":19},"audit-du-code-source-pq-akarup-mobile",[21],{"type":22,"value":23},"text","Audit du code source — pq-akarup-mobile",{"type":16,"tag":25,"props":26,"children":27},"p",{},[28,34,36,41,43,48,50,57,59,65,67,73,75,80,82,88,90,96,98,104,105,111,113,119,120,126,127,133,134,140,142,148,150,156],{"type":16,"tag":29,"props":30,"children":31},"strong",{},[32],{"type":22,"value":33},"Date",{"type":22,"value":35}," : 21 juillet 2026\n",{"type":16,"tag":29,"props":37,"children":38},{},[39],{"type":22,"value":40},"Version",{"type":22,"value":42}," : v2 (ajout section 3 — protocole post-quantique et conformité NIST)\n",{"type":16,"tag":29,"props":44,"children":45},{},[46],{"type":22,"value":47},"Périmètre",{"type":22,"value":49}," : archive ",{"type":16,"tag":51,"props":52,"children":54},"code",{"className":53},[],[55],{"type":22,"value":56},"pq-akarup-mobile_copie.zip",{"type":22,"value":58}," (copie de travail, HEAD ",{"type":16,"tag":51,"props":60,"children":62},{"className":61},[],[63],{"type":22,"value":64},"e3a4483",{"type":22,"value":66}," sur ",{"type":16,"tag":51,"props":68,"children":70},{"className":69},[],[71],{"type":22,"value":72},"develop",{"type":22,"value":74},")\n",{"type":16,"tag":29,"props":76,"children":77},{},[78],{"type":22,"value":79},"Méthode",{"type":22,"value":81}," : restauration depuis le ",{"type":16,"tag":51,"props":83,"children":85},{"className":84},[],[86],{"type":22,"value":87},".git",{"type":22,"value":89}," embarqué des dossiers exclus du zip (",{"type":16,"tag":51,"props":91,"children":93},{"className":92},[],[94],{"type":22,"value":95},"modules/",{"type":22,"value":97},", ",{"type":16,"tag":51,"props":99,"children":101},{"className":100},[],[102],{"type":22,"value":103},"__mocks__/",{"type":22,"value":97},{"type":16,"tag":51,"props":106,"children":108},{"className":107},[],[109],{"type":22,"value":110},"docs/",{"type":22,"value":112},"), exécution du workflow CSPN complet (",{"type":16,"tag":51,"props":114,"children":116},{"className":115},[],[117],{"type":22,"value":118},"npm ci",{"type":22,"value":97},{"type":16,"tag":51,"props":121,"children":123},{"className":122},[],[124],{"type":22,"value":125},"tsc --noEmit",{"type":22,"value":97},{"type":16,"tag":51,"props":128,"children":130},{"className":129},[],[131],{"type":22,"value":132},"vitest run",{"type":22,"value":97},{"type":16,"tag":51,"props":135,"children":137},{"className":136},[],[138],{"type":22,"value":139},"eslint",{"type":22,"value":141},"), greps ciblés sur les pièges connus du projet, et lecture ligne à ligne des primitives cryptographiques ainsi que du code source de ",{"type":16,"tag":51,"props":143,"children":145},{"className":144},[],[146],{"type":22,"value":147},"@noble/post-quantum",{"type":22,"value":149}," 0.5.4 tel qu'installé dans ",{"type":16,"tag":51,"props":151,"children":153},{"className":152},[],[154],{"type":22,"value":155},"node_modules",{"type":22,"value":157},".",{"type":16,"tag":159,"props":160,"children":161},"hr",{},[],{"type":16,"tag":163,"props":164,"children":166},"h2",{"id":165},"_1-verdict-global-sain",[167],{"type":22,"value":168},"1. Verdict global : sain",{"type":16,"tag":25,"props":170,"children":171},{},[172],{"type":22,"value":173},"Le workflow CSPN passe intégralement sur cette copie :",{"type":16,"tag":175,"props":176,"children":177},"table",{},[178,197],{"type":16,"tag":179,"props":180,"children":181},"thead",{},[182],{"type":16,"tag":183,"props":184,"children":185},"tr",{},[186,192],{"type":16,"tag":187,"props":188,"children":189},"th",{},[190],{"type":22,"value":191},"Vérification",{"type":16,"tag":187,"props":193,"children":194},{},[195],{"type":22,"value":196},"Résultat",{"type":16,"tag":198,"props":199,"children":200},"tbody",{},[201,219,236,249],{"type":16,"tag":183,"props":202,"children":203},{},[204,214],{"type":16,"tag":205,"props":206,"children":207},"td",{},[208],{"type":16,"tag":51,"props":209,"children":211},{"className":210},[],[212],{"type":22,"value":213},"npx tsc --noEmit",{"type":16,"tag":205,"props":215,"children":216},{},[217],{"type":22,"value":218},"0 erreur",{"type":16,"tag":183,"props":220,"children":221},{},[222,231],{"type":16,"tag":205,"props":223,"children":224},{},[225],{"type":16,"tag":51,"props":226,"children":228},{"className":227},[],[229],{"type":22,"value":230},"npx vitest run",{"type":16,"tag":205,"props":232,"children":233},{},[234],{"type":22,"value":235},"888 tests verts, 1 skipped, 62 fichiers",{"type":16,"tag":183,"props":237,"children":238},{},[239,244],{"type":16,"tag":205,"props":240,"children":241},{},[242],{"type":22,"value":243},"Parité i18n fr/en",{"type":16,"tag":205,"props":245,"children":246},{},[247],{"type":22,"value":248},"708 clés = 708 clés, zéro manquante dans les deux sens",{"type":16,"tag":183,"props":250,"children":251},{},[252,257],{"type":16,"tag":205,"props":253,"children":254},{},[255],{"type":22,"value":256},"ESLint",{"type":16,"tag":205,"props":258,"children":259},{},[260],{"type":22,"value":261},"5 erreurs (cosmétiques), 123 warnings",{"type":16,"tag":25,"props":263,"children":264},{},[265,267,273,275,281],{"type":22,"value":266},"Le seul fichier de test en échec est ",{"type":16,"tag":51,"props":268,"children":270},{"className":269},[],[271],{"type":22,"value":272},"lib/crypto/__tests__/test-vectors-interop.test.ts",{"type":22,"value":274},", uniquement parce qu'il lit ",{"type":16,"tag":51,"props":276,"children":278},{"className":277},[],[279],{"type":22,"value":280},"../documentation/strategie et doc tech/test-vectors-archi006.json",{"type":22,"value":282}," hors du repo. Dépendance d'environnement, pas un bug (voir constat C4).",{"type":16,"tag":284,"props":285,"children":287},"h3",{"id":286},"pièges-historiques-du-projet-tous-propres",[288],{"type":22,"value":289},"Pièges historiques du projet : tous propres",{"type":16,"tag":291,"props":292,"children":293},"ul",{},[294,317,358,384,423,457,491,523,548,566],{"type":16,"tag":295,"props":296,"children":297},"li",{},[298,307,309,315],{"type":16,"tag":29,"props":299,"children":300},{},[301],{"type":16,"tag":51,"props":302,"children":304},{"className":303},[],[305],{"type":22,"value":306},"expo-file-system",{"type":22,"value":308}," : tous les imports actifs passent par le subpath ",{"type":16,"tag":51,"props":310,"children":312},{"className":311},[],[313],{"type":22,"value":314},"/legacy",{"type":22,"value":316}," (piège SDK 54). Aucun import direct détecté.",{"type":16,"tag":295,"props":318,"children":319},{},[320,325,327,333,335,341,343,349,350,356],{"type":16,"tag":29,"props":321,"children":322},{},[323],{"type":22,"value":324},"Argon2id",{"type":22,"value":326}," : toutes les dérivations passent par ",{"type":16,"tag":51,"props":328,"children":330},{"className":329},[],[331],{"type":22,"value":332},"buildEffectiveSalt",{"type":22,"value":334}," avec le préfixe de domaine ",{"type":16,"tag":51,"props":336,"children":338},{"className":337},[],[339],{"type":22,"value":340},"AKARUP/kdf/argon2id/v2/",{"type":22,"value":342}," (",{"type":16,"tag":51,"props":344,"children":346},{"className":345},[],[347],{"type":22,"value":348},"PasswordManager.ts:208",{"type":22,"value":97},{"type":16,"tag":51,"props":351,"children":353},{"className":352},[],[354],{"type":22,"value":355},"password-wrap.ts:96",{"type":22,"value":357},"). Aucun appel avec le salt base64 brut.",{"type":16,"tag":295,"props":359,"children":360},{},[361,374,376,382],{"type":16,"tag":29,"props":362,"children":363},{},[364,366,372],{"type":22,"value":365},"Plafond ",{"type":16,"tag":51,"props":367,"children":369},{"className":368},[],[370],{"type":22,"value":371},"crypto.getRandomValues",{"type":22,"value":373}," (65 536 octets)",{"type":22,"value":375}," : tous les buffers aléatoires audités sont de petites clés. Le seul point de dépassement possible (padding par buckets du bus, tranche ~50–95 Ko) est correctement traité par chunking de 65 536 octets dans ",{"type":16,"tag":51,"props":377,"children":379},{"className":378},[],[380],{"type":22,"value":381},"payload-encrypt.ts",{"type":22,"value":383}," (fix M-MEDIA-V1 PAQUET 3).",{"type":16,"tag":295,"props":385,"children":386},{},[387,398,400,406,408,414,416,422],{"type":16,"tag":29,"props":388,"children":389},{},[390,392],{"type":22,"value":391},"Singleton ",{"type":16,"tag":51,"props":393,"children":395},{"className":394},[],[396],{"type":22,"value":397},"IdentityService",{"type":22,"value":399}," : ",{"type":16,"tag":51,"props":401,"children":403},{"className":402},[],[404],{"type":22,"value":405},"clearIdentity()",{"type":22,"value":407}," (logout léger multi-utilisateur) et ",{"type":16,"tag":51,"props":409,"children":411},{"className":410},[],[412],{"type":22,"value":413},"resetIdentity()",{"type":22,"value":415}," remettent bien ",{"type":16,"tag":51,"props":417,"children":419},{"className":418},[],[420],{"type":22,"value":421},"isInitialized = false",{"type":22,"value":157},{"type":16,"tag":295,"props":424,"children":425},{},[426,431,433,439,441,447,449,455],{"type":16,"tag":29,"props":427,"children":428},{},[429],{"type":22,"value":430},"Fuites de secrets dans les logs",{"type":22,"value":432}," : aucune. Les ",{"type":16,"tag":51,"props":434,"children":436},{"className":435},[],[437],{"type":22,"value":438},"console.log",{"type":22,"value":440}," d'",{"type":16,"tag":51,"props":442,"children":444},{"className":443},[],[445],{"type":22,"value":446},"AuthFactory",{"type":22,"value":448}," et ",{"type":16,"tag":51,"props":450,"children":452},{"className":451},[],[453],{"type":22,"value":454},"CompleteRegisterServiceV2",{"type":22,"value":456}," décrivent les étapes (« Mnemonic generated », « MasterKey unwrapped ») sans jamais interpoler la valeur d'un mnemonic, seed, MasterKey, KEK ou clé privée.",{"type":16,"tag":295,"props":458,"children":459},{},[460,465,467,473,475,481,483,489],{"type":16,"tag":29,"props":461,"children":462},{},[463],{"type":22,"value":464},"Endpoints en dur",{"type":22,"value":466}," : aucun ",{"type":16,"tag":51,"props":468,"children":470},{"className":469},[],[471],{"type":22,"value":472},"http://",{"type":22,"value":474}," hors adresses LAN de développement. La config passe par ",{"type":16,"tag":51,"props":476,"children":478},{"className":477},[],[479],{"type":22,"value":480},"lib/config.ts",{"type":22,"value":482}," avec priorité ",{"type":16,"tag":51,"props":484,"children":486},{"className":485},[],[487],{"type":22,"value":488},".env.local",{"type":22,"value":490}," > défauts par environnement.",{"type":16,"tag":295,"props":492,"children":493},{},[494,499,501,507,508,514,515,521],{"type":16,"tag":29,"props":495,"children":496},{},[497],{"type":22,"value":498},"Hooks React après early return",{"type":22,"value":500}," : spot-check sur les écrans récents (",{"type":16,"tag":51,"props":502,"children":504},{"className":503},[],[505],{"type":22,"value":506},"automations.tsx",{"type":22,"value":97},{"type":16,"tag":51,"props":509,"children":511},{"className":510},[],[512],{"type":22,"value":513},"AutomationsEditor.tsx",{"type":22,"value":97},{"type":16,"tag":51,"props":516,"children":518},{"className":517},[],[519],{"type":22,"value":520},"DrivePicker.tsx",{"type":22,"value":522},") : tous les hooks sont déclarés avant les returns conditionnels.",{"type":16,"tag":295,"props":524,"children":525},{},[526,531,532,538,540,546],{"type":16,"tag":29,"props":527,"children":528},{},[529],{"type":22,"value":530},"Hooks git",{"type":22,"value":399},{"type":16,"tag":51,"props":533,"children":535},{"className":534},[],[536],{"type":22,"value":537},".githooks/",{"type":22,"value":539}," versionné et ",{"type":16,"tag":51,"props":541,"children":543},{"className":542},[],[544],{"type":22,"value":545},"core.hooksPath",{"type":22,"value":547}," configuré (recommandation antérieure appliquée).",{"type":16,"tag":295,"props":549,"children":550},{},[551,556,558,564],{"type":16,"tag":29,"props":552,"children":553},{},[554],{"type":22,"value":555},"Stockage",{"type":22,"value":557}," : JWT en mémoire (zustand), pas de persistance AsyncStorage ; secrets via SecureStore/EncryptedStore ; ",{"type":16,"tag":51,"props":559,"children":561},{"className":560},[],[562],{"type":22,"value":563},"useSignupFlowStore",{"type":22,"value":565}," explicitement RAM-only.",{"type":16,"tag":295,"props":567,"children":568},{},[569,580,582,588,590,596,598,604,605,611],{"type":16,"tag":29,"props":570,"children":571},{},[572,578],{"type":16,"tag":51,"props":573,"children":575},{"className":574},[],[576],{"type":22,"value":577},"Math.random",{"type":22,"value":579}," restants",{"type":22,"value":581}," : tous légitimes — identifiants locaux non cryptographiques (ids d'événements/notifs de sync), positions de vérification BIP39 (documenté non-sensible dans ",{"type":16,"tag":51,"props":583,"children":585},{"className":584},[],[586],{"type":22,"value":587},"Bip39Service.ts:303",{"type":22,"value":589},"), ou code mort (C1). Le ",{"type":16,"tag":51,"props":591,"children":593},{"className":592},[],[594],{"type":22,"value":595},"deviceIdOpaque",{"type":22,"value":597}," du bus passe bien par ",{"type":16,"tag":51,"props":599,"children":601},{"className":600},[],[602],{"type":22,"value":603},"getRandomValues",{"type":22,"value":342},{"type":16,"tag":51,"props":606,"children":608},{"className":607},[],[609],{"type":22,"value":610},"hash-destinataire.ts:82",{"type":22,"value":612},").",{"type":16,"tag":159,"props":614,"children":615},{},[],{"type":16,"tag":163,"props":617,"children":619},{"id":618},"_2-constats-à-traiter",[620],{"type":22,"value":621},"2. Constats à traiter",{"type":16,"tag":284,"props":623,"children":625},{"id":624},"c1-cluster-de-code-mort-legacy-v1-embarquant-crypto-js",[626],{"type":22,"value":627},"C1 — Cluster de code mort legacy V1 embarquant crypto-js",{"type":16,"tag":25,"props":629,"children":630},{},[631],{"type":16,"tag":29,"props":632,"children":633},{},[634],{"type":22,"value":635},"Priorité : haute (surface CSPN)",{"type":16,"tag":25,"props":637,"children":638},{},[639],{"type":22,"value":640},"Les fichiers suivants ne sont référencés par aucun écran ni service actif (chaînes d'import vérifiées une à une, elles bouclent entre elles) :",{"type":16,"tag":291,"props":642,"children":643},{},[644,670,687,705,714,723,732,741,750],{"type":16,"tag":295,"props":645,"children":646},{},[647,653,655,661,663,668],{"type":16,"tag":51,"props":648,"children":650},{"className":649},[],[651],{"type":22,"value":652},"src/services/RegisterService.ts",{"type":22,"value":654}," (V1, remplacé par ",{"type":16,"tag":51,"props":656,"children":658},{"className":657},[],[659],{"type":22,"value":660},"PreRegisterServiceV2",{"type":22,"value":662},"/",{"type":16,"tag":51,"props":664,"children":666},{"className":665},[],[667],{"type":22,"value":454},{"type":22,"value":669},")",{"type":16,"tag":295,"props":671,"children":672},{},[673,679,680,686],{"type":16,"tag":51,"props":674,"children":676},{"className":675},[],[677],{"type":22,"value":678},"src/services/LoginService.ts",{"type":22,"value":654},{"type":16,"tag":51,"props":681,"children":683},{"className":682},[],[684],{"type":22,"value":685},"LoginServiceV2",{"type":22,"value":669},{"type":16,"tag":295,"props":688,"children":689},{},[690,696,698,704],{"type":16,"tag":51,"props":691,"children":693},{"className":692},[],[694],{"type":22,"value":695},"lib/services/cryptoService.ts",{"type":22,"value":697}," (importé uniquement par les V1 morts et le barrel ",{"type":16,"tag":51,"props":699,"children":701},{"className":700},[],[702],{"type":22,"value":703},"lib/services/index.ts",{"type":22,"value":669},{"type":16,"tag":295,"props":706,"children":707},{},[708],{"type":16,"tag":51,"props":709,"children":711},{"className":710},[],[712],{"type":22,"value":713},"src/services/BlobCryptoService.ts",{"type":16,"tag":295,"props":715,"children":716},{},[717],{"type":16,"tag":51,"props":718,"children":720},{"className":719},[],[721],{"type":22,"value":722},"src/services/ChunkedUploadService.ts",{"type":16,"tag":295,"props":724,"children":725},{},[726],{"type":16,"tag":51,"props":727,"children":729},{"className":728},[],[730],{"type":22,"value":731},"src/managers/sync/BlobSyncManager.ts",{"type":16,"tag":295,"props":733,"children":734},{},[735],{"type":16,"tag":51,"props":736,"children":738},{"className":737},[],[739],{"type":22,"value":740},"src/services/MultiDeviceSyncService.ts",{"type":16,"tag":295,"props":742,"children":743},{},[744],{"type":16,"tag":51,"props":745,"children":747},{"className":746},[],[748],{"type":22,"value":749},"src/hooks/useBlobUpload.ts",{"type":16,"tag":295,"props":751,"children":752},{},[753],{"type":16,"tag":51,"props":754,"children":756},{"className":755},[],[757],{"type":22,"value":758},"src/hooks/useBlobDownload.ts",{"type":16,"tag":25,"props":760,"children":761},{},[762],{"type":22,"value":763},"Ce cluster pose trois problèmes pour l'évaluation ANSSI :",{"type":16,"tag":765,"props":766,"children":767},"ol",{},[768,792,833],{"type":16,"tag":295,"props":769,"children":770},{},[771,782,784,790],{"type":16,"tag":29,"props":772,"children":773},{},[774,776],{"type":22,"value":775},"Dépendance ",{"type":16,"tag":51,"props":777,"children":779},{"className":778},[],[780],{"type":22,"value":781},"crypto-js",{"type":22,"value":783}," : bibliothèque non auditée, redondante avec ",{"type":16,"tag":51,"props":785,"children":787},{"className":786},[],[788],{"type":22,"value":789},"@noble/hashes",{"type":22,"value":791}," déjà présent et utilisé partout ailleurs. Un évaluateur la relèvera même si elle est morte.",{"type":16,"tag":295,"props":793,"children":794},{},[795,800,801,807,809,815,817,823,825,831],{"type":16,"tag":29,"props":796,"children":797},{},[798],{"type":22,"value":799},"Hash non-standard",{"type":22,"value":399},{"type":16,"tag":51,"props":802,"children":804},{"className":803},[],[805],{"type":22,"value":806},"BlobCryptoService._hashBlobData",{"type":22,"value":808}," (ligne 606) fait ",{"type":16,"tag":51,"props":810,"children":812},{"className":811},[],[813],{"type":22,"value":814},"CryptoJS.SHA256(bytesToHex(data))",{"type":22,"value":816}," — un SHA-256 de la ",{"type":16,"tag":818,"props":819,"children":820},"em",{},[821],{"type":22,"value":822},"chaîne hexadécimale ASCII",{"type":22,"value":824},", pas des octets. Ce hash n'interopérerait jamais avec un ",{"type":16,"tag":51,"props":826,"children":828},{"className":827},[],[829],{"type":22,"value":830},"sha256.Sum256(data)",{"type":22,"value":832}," Go. Aucun bug en production puisque le code est mort, mais c'est un piège de réutilisation accidentelle.",{"type":16,"tag":295,"props":834,"children":835},{},[836,841,843,849,851,857,859,864,866,872,874,880],{"type":16,"tag":29,"props":837,"children":838},{},[839],{"type":22,"value":840},"Ordre d'arguments ML-DSA inversé",{"type":22,"value":842}," (découvert lors de l'analyse crypto, section 3) : ",{"type":16,"tag":51,"props":844,"children":846},{"className":845},[],[847],{"type":22,"value":848},"cryptoService.ts:202",{"type":22,"value":850}," appelle ",{"type":16,"tag":51,"props":852,"children":854},{"className":853},[],[855],{"type":22,"value":856},"ml_dsa65.sign(privateKey, messageBytes)",{"type":22,"value":858}," — l'ordre de l'",{"type":16,"tag":29,"props":860,"children":861},{},[862],{"type":22,"value":863},"ancienne",{"type":22,"value":865}," API noble. L'API 0.5.4 installée est ",{"type":16,"tag":51,"props":867,"children":869},{"className":868},[],[870],{"type":22,"value":871},"sign(msg, secretKey, opts?)",{"type":22,"value":873},". Les deux arguments étant des ",{"type":16,"tag":51,"props":875,"children":877},{"className":876},[],[878],{"type":22,"value":879},"Uint8Array",{"type":22,"value":881},", TypeScript ne détecte rien : si ce code mort était rappelé un jour, il signerait le mauvais contenu avec le mauvais matériau sans erreur de compilation. Argument supplémentaire décisif pour la purge.",{"type":16,"tag":25,"props":883,"children":884},{},[885,890,892,897,899,905,907,913,915,920],{"type":16,"tag":29,"props":886,"children":887},{},[888],{"type":22,"value":889},"Recommandation",{"type":22,"value":891}," : sprint de purge — supprimer les 9 fichiers (et leurs tests associés le cas échéant), retirer ",{"type":16,"tag":51,"props":893,"children":895},{"className":894},[],[896],{"type":22,"value":781},{"type":22,"value":898}," (dependencies) et ",{"type":16,"tag":51,"props":900,"children":902},{"className":901},[],[903],{"type":22,"value":904},"@types/crypto-js",{"type":22,"value":906}," (devDependencies) du ",{"type":16,"tag":51,"props":908,"children":910},{"className":909},[],[911],{"type":22,"value":912},"package.json",{"type":22,"value":914},", nettoyer le barrel ",{"type":16,"tag":51,"props":916,"children":918},{"className":917},[],[919],{"type":22,"value":703},{"type":22,"value":157},{"type":16,"tag":25,"props":922,"children":923},{},[924,929,930,936,938,943,944,950,951,957,958,964],{"type":16,"tag":29,"props":925,"children":926},{},[927],{"type":22,"value":928},"Attention",{"type":22,"value":399},{"type":16,"tag":51,"props":931,"children":933},{"className":932},[],[934],{"type":22,"value":935},"@noble/curves",{"type":22,"value":937}," est ",{"type":16,"tag":29,"props":939,"children":940},{},[941],{"type":22,"value":942},"actif",{"type":22,"value":342},{"type":16,"tag":51,"props":945,"children":947},{"className":946},[],[948],{"type":22,"value":949},"lib/crypto/primitives/ed25519.ts",{"type":22,"value":97},{"type":16,"tag":51,"props":952,"children":954},{"className":953},[],[955],{"type":22,"value":956},"x25519.ts",{"type":22,"value":97},{"type":16,"tag":51,"props":959,"children":961},{"className":960},[],[962],{"type":22,"value":963},"lib/crypto/bip39/IdentityDerivationService.ts",{"type":22,"value":965},") — à conserver.",{"type":16,"tag":284,"props":967,"children":969},{"id":968},"c2-quatre-fichiers-bak-versionnés-dans-git",[970,972,978],{"type":22,"value":971},"C2 — Quatre fichiers ",{"type":16,"tag":51,"props":973,"children":975},{"className":974},[],[976],{"type":22,"value":977},".bak",{"type":22,"value":979}," versionnés dans git",{"type":16,"tag":25,"props":981,"children":982},{},[983],{"type":16,"tag":29,"props":984,"children":985},{},[986],{"type":22,"value":987},"Priorité : moyenne (hygiène / convention)",{"type":16,"tag":989,"props":990,"children":992},"pre",{"code":991},"lib/services/DeviceService.ts.before-passe-4.bak\nlib/services/MessageStore.ts.before-dev-007.bak\nsrc/managers/AuthFactory.ts.before-passe-3.bak\nsrc/services/DeviceSetupService.ts.before-passe-4.bak\n",[993],{"type":16,"tag":51,"props":994,"children":995},{"__ignoreMap":7},[996],{"type":22,"value":991},{"type":16,"tag":25,"props":998,"children":999},{},[1000,1002,1008,1010,1016,1018,1023,1025,1031],{"type":22,"value":1001},"Contraire à la convention du projet (backups dans ",{"type":16,"tag":51,"props":1003,"children":1005},{"className":1004},[],[1006],{"type":22,"value":1007},"/tmp/",{"type":22,"value":1009}," uniquement). L'historique git suffit pour tout rollback — le commentaire de ",{"type":16,"tag":51,"props":1011,"children":1013},{"className":1012},[],[1014],{"type":22,"value":1015},"MessageStore.ts",{"type":22,"value":1017}," qui justifie le ",{"type":16,"tag":51,"props":1019,"children":1021},{"className":1020},[],[1022],{"type":22,"value":977},{"type":22,"value":1024}," « conservé pour rollback » est redondant avec ",{"type":16,"tag":51,"props":1026,"children":1028},{"className":1027},[],[1029],{"type":22,"value":1030},"git log",{"type":22,"value":157},{"type":16,"tag":25,"props":1033,"children":1034},{},[1035,1039,1041,1047,1049,1055],{"type":16,"tag":29,"props":1036,"children":1037},{},[1038],{"type":22,"value":889},{"type":22,"value":1040}," : supprimer les 4 fichiers, ajouter ",{"type":16,"tag":51,"props":1042,"children":1044},{"className":1043},[],[1045],{"type":22,"value":1046},"*.bak",{"type":22,"value":1048}," au ",{"type":16,"tag":51,"props":1050,"children":1052},{"className":1051},[],[1053],{"type":22,"value":1054},".gitignore",{"type":22,"value":157},{"type":16,"tag":284,"props":1057,"children":1059},{"id":1058},"c3-polyfill-react-native-get-random-values-non-hoisté",[1060,1062,1068],{"type":22,"value":1061},"C3 — Polyfill ",{"type":16,"tag":51,"props":1063,"children":1065},{"className":1064},[],[1066],{"type":22,"value":1067},"react-native-get-random-values",{"type":22,"value":1069}," non hoisté",{"type":16,"tag":25,"props":1071,"children":1072},{},[1073],{"type":16,"tag":29,"props":1074,"children":1075},{},[1076],{"type":22,"value":1077},"Priorité : moyenne → haute après l'analyse crypto (robustesse du CSPRNG)",{"type":16,"tag":25,"props":1079,"children":1080},{},[1081,1083,1089,1091,1097,1099,1104,1106,1112,1113,1119,1120,1126,1127,1133,1134,1140,1141,1147,1148,1154,1155,1161,1162,1168,1169,1175,1176,1182,1183,1188,1190,1195],{"type":22,"value":1082},"Le polyfill n'est importé (side-effect) que dans ",{"type":16,"tag":51,"props":1084,"children":1086},{"className":1085},[],[1087],{"type":22,"value":1088},"lib/services/FileCryptoServiceV2.ts:33",{"type":22,"value":1090}," — et dans le ",{"type":16,"tag":51,"props":1092,"children":1094},{"className":1093},[],[1095],{"type":22,"value":1096},"cryptoService",{"type":22,"value":1098}," mort (C1). Or une douzaine de modules actifs appellent ",{"type":16,"tag":51,"props":1100,"children":1102},{"className":1101},[],[1103],{"type":22,"value":371},{"type":22,"value":1105}," directement : ",{"type":16,"tag":51,"props":1107,"children":1109},{"className":1108},[],[1110],{"type":22,"value":1111},"GroupConversationService",{"type":22,"value":97},{"type":16,"tag":51,"props":1114,"children":1116},{"className":1115},[],[1117],{"type":22,"value":1118},"KdfMetadata",{"type":22,"value":97},{"type":16,"tag":51,"props":1121,"children":1123},{"className":1122},[],[1124],{"type":22,"value":1125},"ContactService",{"type":22,"value":97},{"type":16,"tag":51,"props":1128,"children":1130},{"className":1129},[],[1131],{"type":22,"value":1132},"DeviceService",{"type":22,"value":97},{"type":16,"tag":51,"props":1135,"children":1137},{"className":1136},[],[1138],{"type":22,"value":1139},"SPKRotationManager",{"type":22,"value":97},{"type":16,"tag":51,"props":1142,"children":1144},{"className":1143},[],[1145],{"type":22,"value":1146},"BlobService",{"type":22,"value":97},{"type":16,"tag":51,"props":1149,"children":1151},{"className":1150},[],[1152],{"type":22,"value":1153},"apiServiceV2",{"type":22,"value":97},{"type":16,"tag":51,"props":1156,"children":1158},{"className":1157},[],[1159],{"type":22,"value":1160},"hash-destinataire",{"type":22,"value":97},{"type":16,"tag":51,"props":1163,"children":1165},{"className":1164},[],[1166],{"type":22,"value":1167},"capability",{"type":22,"value":97},{"type":16,"tag":51,"props":1170,"children":1172},{"className":1171},[],[1173],{"type":22,"value":1174},"k-blob",{"type":22,"value":97},{"type":16,"tag":51,"props":1177,"children":1179},{"className":1178},[],[1180],{"type":22,"value":1181},"k-media",{"type":22,"value":97},{"type":16,"tag":51,"props":1184,"children":1186},{"className":1185},[],[1187],{"type":22,"value":454},{"type":22,"value":1189}," — auxquels s'ajoutent, vus en section 3, ",{"type":16,"tag":29,"props":1191,"children":1192},{},[1193],{"type":22,"value":1194},"tous les keygens ML-KEM/ML-DSA, l'entropie BIP39, les nonces AEAD et les seeds hedgées des signatures",{"type":22,"value":157},{"type":16,"tag":25,"props":1197,"children":1198},{},[1199,1204,1206,1211,1213,1219],{"type":16,"tag":51,"props":1200,"children":1202},{"className":1201},[],[1203],{"type":22,"value":371},{"type":22,"value":1205}," est donc l'unique racine d'entropie de toute la cryptographie de l'application, et son existence dans le runtime repose sur un effet de bord de l'ordre de chargement des modules. Si un futur chemin de code appelle ",{"type":16,"tag":51,"props":1207,"children":1209},{"className":1208},[],[1210],{"type":22,"value":603},{"type":22,"value":1212}," avant que ",{"type":16,"tag":51,"props":1214,"children":1216},{"className":1215},[],[1217],{"type":22,"value":1218},"FileCryptoServiceV2",{"type":22,"value":1220}," ne soit chargé, l'appel échoue.",{"type":16,"tag":25,"props":1222,"children":1223},{},[1224,1228,1229,1235,1237,1242,1244,1250,1252,1258,1260,1265,1267,1273,1275,1281],{"type":16,"tag":29,"props":1225,"children":1226},{},[1227],{"type":22,"value":889},{"type":22,"value":399},{"type":16,"tag":51,"props":1230,"children":1232},{"className":1231},[],[1233],{"type":22,"value":1234},"import 'react-native-get-random-values'",{"type":22,"value":1236}," en ",{"type":16,"tag":29,"props":1238,"children":1239},{},[1240],{"type":22,"value":1241},"première ligne",{"type":22,"value":1243}," de ",{"type":16,"tag":51,"props":1245,"children":1247},{"className":1246},[],[1248],{"type":22,"value":1249},"lib/polyfills.ts",{"type":22,"value":1251}," (déjà importé tôt dans ",{"type":16,"tag":51,"props":1253,"children":1255},{"className":1254},[],[1256],{"type":22,"value":1257},"app/_layout.tsx",{"type":22,"value":1259},"), et retirer l'import éparpillé de ",{"type":16,"tag":51,"props":1261,"children":1263},{"className":1262},[],[1264],{"type":22,"value":1218},{"type":22,"value":1266}," une fois le hoist en place. Documenter dans la cible de sécurité CSPN que le polyfill délègue à ",{"type":16,"tag":51,"props":1268,"children":1270},{"className":1269},[],[1271],{"type":22,"value":1272},"SecRandomCopyBytes",{"type":22,"value":1274}," (iOS) et ",{"type":16,"tag":51,"props":1276,"children":1278},{"className":1277},[],[1279],{"type":22,"value":1280},"SecureRandom",{"type":22,"value":1282}," (Android), soit les CSPRNG de l'OS.",{"type":16,"tag":284,"props":1284,"children":1286},{"id":1285},"c4-la-ci-gitlab-nexécute-aucun-test",[1287],{"type":22,"value":1288},"C4 — La CI GitLab n'exécute aucun test",{"type":16,"tag":25,"props":1290,"children":1291},{},[1292],{"type":16,"tag":29,"props":1293,"children":1294},{},[1295],{"type":22,"value":1296},"Priorité : moyenne (traçabilité CSPN)",{"type":16,"tag":25,"props":1298,"children":1299},{},[1300,1306,1308,1314,1315,1321,1323,1328,1330,1335,1336,1341,1343,1349,1351,1357],{"type":16,"tag":51,"props":1301,"children":1303},{"className":1302},[],[1304],{"type":22,"value":1305},".gitlab-ci.yml",{"type":22,"value":1307}," ne contient que deux stages ",{"type":16,"tag":51,"props":1309,"children":1311},{"className":1310},[],[1312],{"type":22,"value":1313},"build",{"type":22,"value":448},{"type":16,"tag":51,"props":1316,"children":1318},{"className":1317},[],[1319],{"type":22,"value":1320},"deploy",{"type":22,"value":1322}," (image Docker webapp). Ni ",{"type":16,"tag":51,"props":1324,"children":1326},{"className":1325},[],[1327],{"type":22,"value":125},{"type":22,"value":1329},", ni ",{"type":16,"tag":51,"props":1331,"children":1333},{"className":1332},[],[1334],{"type":22,"value":132},{"type":22,"value":1329},{"type":16,"tag":51,"props":1337,"children":1339},{"className":1338},[],[1340],{"type":22,"value":139},{"type":22,"value":1342}," n'y figurent. Le workflow CSPN repose donc entièrement sur la discipline locale — et le hook ",{"type":16,"tag":51,"props":1344,"children":1346},{"className":1345},[],[1347],{"type":22,"value":1348},"pre-commit",{"type":22,"value":1350}," versionné ne fait que le bump de version (",{"type":16,"tag":51,"props":1352,"children":1354},{"className":1353},[],[1355],{"type":22,"value":1356},"app.json",{"type":22,"value":1358},"), aucune vérification.",{"type":16,"tag":25,"props":1360,"children":1361},{},[1362,1366,1368,1374,1375,1381,1383,1388],{"type":16,"tag":29,"props":1363,"children":1364},{},[1365],{"type":22,"value":889},{"type":22,"value":1367}," : ajouter un stage ",{"type":16,"tag":51,"props":1369,"children":1371},{"className":1370},[],[1372],{"type":22,"value":1373},"test",{"type":22,"value":342},{"type":16,"tag":51,"props":1376,"children":1378},{"className":1377},[],[1379],{"type":22,"value":1380},"npm ci && npx tsc --noEmit && npx vitest run",{"type":22,"value":1382},") exécuté sur ",{"type":16,"tag":51,"props":1384,"children":1386},{"className":1385},[],[1387],{"type":22,"value":72},{"type":22,"value":1389},". Bénéfice direct pour le dossier CSPN (F-006) : trace opposable de l'exécution des vérifications à chaque push.",{"type":16,"tag":25,"props":1391,"children":1392},{},[1393,1398,1399,1405,1407,1413,1415,1421,1423,1428],{"type":16,"tag":29,"props":1394,"children":1395},{},[1396],{"type":22,"value":1397},"Point de vigilance lié",{"type":22,"value":399},{"type":16,"tag":51,"props":1400,"children":1402},{"className":1401},[],[1403],{"type":22,"value":1404},"test-vectors-interop.test.ts",{"type":22,"value":1406}," lit les vecteurs dans le repo ",{"type":16,"tag":51,"props":1408,"children":1410},{"className":1409},[],[1411],{"type":22,"value":1412},"documentation",{"type":22,"value":1414}," frère (",{"type":16,"tag":51,"props":1416,"children":1418},{"className":1417},[],[1419],{"type":22,"value":1420},"resolve(repoMobile, '..', 'documentation', ...)",{"type":22,"value":1422},"). En CI, il faudra soit rendre ce chemin configurable (variable d'environnement avec fallback), soit checkout le repo ",{"type":16,"tag":51,"props":1424,"children":1426},{"className":1425},[],[1427],{"type":22,"value":1412},{"type":22,"value":1429}," dans le job, soit vendorer une copie du JSON de vecteurs dans le repo mobile (option la plus simple et la plus robuste — le fichier est un artefact de référence figé).",{"type":16,"tag":284,"props":1431,"children":1433},{"id":1432},"c5-eslint-5-erreurs-123-warnings",[1434],{"type":22,"value":1435},"C5 — ESLint : 5 erreurs, 123 warnings",{"type":16,"tag":25,"props":1437,"children":1438},{},[1439],{"type":16,"tag":29,"props":1440,"children":1441},{},[1442],{"type":22,"value":1443},"Priorité : basse (cosmétique)",{"type":16,"tag":25,"props":1445,"children":1446},{},[1447],{"type":22,"value":1448},"Les 5 erreurs :",{"type":16,"tag":291,"props":1450,"children":1451},{},[1452,1484],{"type":16,"tag":295,"props":1453,"children":1454},{},[1455,1461,1463,1469,1470,1476,1478],{"type":16,"tag":51,"props":1456,"children":1458},{"className":1457},[],[1459],{"type":22,"value":1460},"react/no-unescaped-entities",{"type":22,"value":1462}," (apostrophes non échappées) : ",{"type":16,"tag":51,"props":1464,"children":1466},{"className":1465},[],[1467],{"type":22,"value":1468},"DeviceRegisterScreen.tsx:18",{"type":22,"value":97},{"type":16,"tag":51,"props":1471,"children":1473},{"className":1472},[],[1474],{"type":22,"value":1475},"ErrorScreen.tsx:17",{"type":22,"value":1477}," (×2), ",{"type":16,"tag":51,"props":1479,"children":1481},{"className":1480},[],[1482],{"type":22,"value":1483},"SuccessScreen.tsx:17",{"type":16,"tag":295,"props":1485,"children":1486},{},[1487,1493,1495,1501,1503,1509],{"type":16,"tag":51,"props":1488,"children":1490},{"className":1489},[],[1491],{"type":22,"value":1492},"import/namespace",{"type":22,"value":1494}," sur la référence calculée ",{"type":16,"tag":51,"props":1496,"children":1498},{"className":1497},[],[1499],{"type":22,"value":1500},"Lucide[name]",{"type":22,"value":1502}," dans ",{"type":16,"tag":51,"props":1504,"children":1506},{"className":1505},[],[1507],{"type":22,"value":1508},"src/design/atoms/Icon.tsx:166",{"type":22,"value":1510}," — faux positif classique de la règle sur les accès dynamiques à un namespace ; peut être désactivé localement avec un commentaire eslint-disable ciblé.",{"type":16,"tag":25,"props":1512,"children":1513},{},[1514,1516,1522,1524,1530,1532,1538,1540,1546,1547,1552,1554,1560,1562,1568],{"type":22,"value":1515},"Les 123 warnings sont quasi exclusivement des ",{"type":16,"tag":51,"props":1517,"children":1519},{"className":1518},[],[1520],{"type":22,"value":1521},"@typescript-eslint/no-unused-vars",{"type":22,"value":1523}," sur des ",{"type":16,"tag":51,"props":1525,"children":1527},{"className":1526},[],[1528],{"type":22,"value":1529},"catch (error)",{"type":22,"value":1531}," où l'erreur n'est pas utilisée (remplaçables par ",{"type":16,"tag":51,"props":1533,"children":1535},{"className":1534},[],[1536],{"type":22,"value":1537},"catch {}",{"type":22,"value":1539},"), plus un ",{"type":16,"tag":51,"props":1541,"children":1543},{"className":1542},[],[1544],{"type":22,"value":1545},"import/no-duplicates",{"type":22,"value":1502},{"type":16,"tag":51,"props":1548,"children":1550},{"className":1549},[],[1551],{"type":22,"value":1111},{"type":22,"value":1553}," (double import de ",{"type":16,"tag":51,"props":1555,"children":1557},{"className":1556},[],[1558],{"type":22,"value":1559},"bus-action.ts",{"type":22,"value":1561},"). 43 sont auto-corrigeables avec ",{"type":16,"tag":51,"props":1563,"children":1565},{"className":1564},[],[1566],{"type":22,"value":1567},"--fix",{"type":22,"value":157},{"type":16,"tag":284,"props":1570,"children":1572},{"id":1571},"c6-écriture-transitoire-en-clair-dans-automationsdrivesavestringtodrive",[1573,1575],{"type":22,"value":1574},"C6 — Écriture transitoire en clair dans ",{"type":16,"tag":51,"props":1576,"children":1578},{"className":1577},[],[1579],{"type":22,"value":1580},"automationsDrive.saveStringToDrive",{"type":16,"tag":25,"props":1582,"children":1583},{},[1584],{"type":16,"tag":29,"props":1585,"children":1586},{},[1587],{"type":22,"value":1588},"Priorité : basse (résiduel INV-015-10)",{"type":16,"tag":25,"props":1590,"children":1591},{},[1592,1598,1600,1606,1608,1614,1616,1622],{"type":16,"tag":51,"props":1593,"children":1595},{"className":1594},[],[1596],{"type":22,"value":1597},"src/components/automations/automationsDrive.ts:40-41",{"type":22,"value":1599}," écrit le contenu en clair dans un fichier temporaire (",{"type":16,"tag":51,"props":1601,"children":1603},{"className":1602},[],[1604],{"type":22,"value":1605},"cacheDirectory/akarup-automations-\u003Cts>.tmp",{"type":22,"value":1607},") avant ",{"type":16,"tag":51,"props":1609,"children":1611},{"className":1610},[],[1612],{"type":22,"value":1613},"driveServiceV2.addFile",{"type":22,"value":1615},", supprimé en ",{"type":16,"tag":51,"props":1617,"children":1619},{"className":1618},[],[1620],{"type":22,"value":1621},"finally",{"type":22,"value":1623},". Le pattern est documenté et assumé (pont T2, piège SDK 54), mais un crash entre l'écriture et la suppression laisse un résidu en clair dans le cache sandbox de l'app.",{"type":16,"tag":25,"props":1625,"children":1626},{},[1627,1631,1633,1639,1641,1647],{"type":16,"tag":29,"props":1628,"children":1629},{},[1630],{"type":22,"value":889},{"type":22,"value":1632}," (mitigation peu coûteuse) : purge au démarrage de l'app des fichiers ",{"type":16,"tag":51,"props":1634,"children":1636},{"className":1635},[],[1637],{"type":22,"value":1638},"akarup-automations-*.tmp",{"type":22,"value":1640}," orphelins dans ",{"type":16,"tag":51,"props":1642,"children":1644},{"className":1643},[],[1645],{"type":22,"value":1646},"cacheDirectory",{"type":22,"value":157},{"type":16,"tag":284,"props":1649,"children":1651},{"id":1650},"c7-observations-sur-larchive-elle-même",[1652],{"type":22,"value":1653},"C7 — Observations sur l'archive elle-même",{"type":16,"tag":25,"props":1655,"children":1656},{},[1657],{"type":16,"tag":29,"props":1658,"children":1659},{},[1660],{"type":22,"value":1661},"Priorité : informative",{"type":16,"tag":291,"props":1663,"children":1664},{},[1665,1682],{"type":16,"tag":295,"props":1666,"children":1667},{},[1668,1673,1675,1680],{"type":16,"tag":51,"props":1669,"children":1671},{"className":1670},[],[1672],{"type":22,"value":488},{"type":22,"value":1674}," est présent dans le zip. Contenu inspecté : uniquement des adresses LAN de développement (192.168.x.x), ",{"type":16,"tag":29,"props":1676,"children":1677},{},[1678],{"type":22,"value":1679},"aucun secret",{"type":22,"value":1681},". Pas de fuite, mais à garder en tête pour de futures archives partagées.",{"type":16,"tag":295,"props":1683,"children":1684},{},[1685,1687,1692,1694,1700,1701,1707,1709,1714,1716,1721,1723,1729,1731,1736,1737,1742,1744,1749,1750,1755,1757,1763],{"type":22,"value":1686},"La copie excluait ",{"type":16,"tag":51,"props":1688,"children":1690},{"className":1689},[],[1691],{"type":22,"value":95},{"type":22,"value":1693}," (dont ",{"type":16,"tag":51,"props":1695,"children":1697},{"className":1696},[],[1698],{"type":22,"value":1699},"expo-akarup-argon2",{"type":22,"value":448},{"type":16,"tag":51,"props":1702,"children":1704},{"className":1703},[],[1705],{"type":22,"value":1706},"expo-akarup-quickjs",{"type":22,"value":1708},") et ",{"type":16,"tag":51,"props":1710,"children":1712},{"className":1711},[],[1713],{"type":22,"value":103},{"type":22,"value":1715},", alors que le ",{"type":16,"tag":51,"props":1717,"children":1719},{"className":1718},[],[1720],{"type":22,"value":912},{"type":22,"value":1722}," référence ",{"type":16,"tag":51,"props":1724,"children":1726},{"className":1725},[],[1727],{"type":22,"value":1728},"file:./modules/expo-akarup-argon2",{"type":22,"value":1730},". Sur une copie brute sans ",{"type":16,"tag":51,"props":1732,"children":1734},{"className":1733},[],[1735],{"type":22,"value":87},{"type":22,"value":97},{"type":16,"tag":51,"props":1738,"children":1740},{"className":1739},[],[1741],{"type":22,"value":118},{"type":22,"value":1743}," échouerait et l'audit tsc/vitest serait impossible. Pour de futures archives d'audit : inclure ",{"type":16,"tag":51,"props":1745,"children":1747},{"className":1746},[],[1748],{"type":22,"value":95},{"type":22,"value":448},{"type":16,"tag":51,"props":1751,"children":1753},{"className":1752},[],[1754],{"type":22,"value":103},{"type":22,"value":1756},", ou fournir un ",{"type":16,"tag":51,"props":1758,"children":1760},{"className":1759},[],[1761],{"type":22,"value":1762},"git archive HEAD",{"type":22,"value":157},{"type":16,"tag":284,"props":1765,"children":1767},{"id":1766},"c8-profil-argon2id-α-light-obsolète-alors-que-le-module-natif-est-en-place",[1768],{"type":22,"value":1769},"C8 — Profil Argon2id Α-light obsolète alors que le module natif est en place",{"type":16,"tag":25,"props":1771,"children":1772},{},[1773],{"type":16,"tag":29,"props":1774,"children":1775},{},[1776],{"type":22,"value":1777},"Priorité : haute (durcissement, issu de l'analyse section 3)",{"type":16,"tag":25,"props":1779,"children":1780},{},[1781,1787,1789,1795,1796,1801,1803,1808,1810,1815,1817,1823,1825,1830,1832,1837],{"type":16,"tag":51,"props":1782,"children":1784},{"className":1783},[],[1785],{"type":22,"value":1786},"lib/auth/KdfMetadata.ts:113",{"type":22,"value":1788}," : le profil actif ",{"type":16,"tag":51,"props":1790,"children":1792},{"className":1791},[],[1793],{"type":22,"value":1794},"ARGON2ID_PARAMS_V2",{"type":22,"value":937},{"type":16,"tag":29,"props":1797,"children":1798},{},[1799],{"type":22,"value":1800},"Α-light (m = 16 MiB, t = 3, p = 1)",{"type":22,"value":1802},", explicitement documenté comme ",{"type":16,"tag":818,"props":1804,"children":1805},{},[1806],{"type":22,"value":1807},"temporaire",{"type":22,"value":1809},", choisi à cause des performances de l'implémentation JS pure ",{"type":16,"tag":51,"props":1811,"children":1813},{"className":1812},[],[1814],{"type":22,"value":789},{"type":22,"value":1816}," sous Hermes (~30 s pour le profil cible). Or ",{"type":16,"tag":51,"props":1818,"children":1820},{"className":1819},[],[1821],{"type":22,"value":1822},"lib/auth/argon2-impl.native.ts",{"type":22,"value":1824}," montre que le module natif ",{"type":16,"tag":51,"props":1826,"children":1828},{"className":1827},[],[1829],{"type":22,"value":1699},{"type":22,"value":1831}," (phc-winner-argon2, RFC 9106) est intégré, sélectionné automatiquement par Metro sur iOS/Android, bit-à-bit identique au JS, et exécute le ",{"type":16,"tag":29,"props":1833,"children":1834},{},[1835],{"type":22,"value":1836},"profil Β cible (m = 64 MiB, t = 4, p = 1) en ~892 ms sur iPhone et ~430 ms sur Xiaomi",{"type":22,"value":157},{"type":16,"tag":25,"props":1839,"children":1840},{},[1841],{"type":22,"value":1842},"La contrainte qui justifiait Α-light a disparu. Le profil actuel reste au niveau « minimum OWASP » (facteur de coût attaquant ×1 500 vs ×12 000 pour Β, selon les commentaires du code lui-même), alors que RFC 9106 §4 recommande m = 64 MiB en second choix. Pour un produit visant la CSPN, rester sur le profil minimum sans justification technique est un point que l'évaluateur relèvera.",{"type":16,"tag":25,"props":1844,"children":1845},{},[1846,1850,1852,1858,1860,1866,1868,1874],{"type":16,"tag":29,"props":1847,"children":1848},{},[1849],{"type":22,"value":889},{"type":22,"value":1851}," : activer le profil Β. La mécanique de migration existe déjà : ",{"type":16,"tag":51,"props":1853,"children":1855},{"className":1854},[],[1856],{"type":22,"value":1857},"KdfMetadataV2",{"type":22,"value":1859}," embarque ses paramètres par wrap (",{"type":16,"tag":51,"props":1861,"children":1863},{"className":1862},[],[1864],{"type":22,"value":1865},"params",{"type":22,"value":1867}," sérialisés), donc les comptes existants restent déverrouillables avec leurs anciens paramètres, et un re-wrap au prochain login (ou au prochain changement de mot de passe) migre vers Β. Prévoir le fallback web : ",{"type":16,"tag":51,"props":1869,"children":1871},{"className":1870},[],[1872],{"type":22,"value":1873},"argon2-impl.web.ts",{"type":22,"value":1875}," reste en JS — soit conserver Α-light côté web avec métadonnées distinctes, soit accepter la latence, à trancher avant le desktop Electron.",{"type":16,"tag":159,"props":1877,"children":1878},{},[],{"type":16,"tag":163,"props":1880,"children":1882},{"id":1881},"_3-analyse-du-protocole-post-quantique-et-conformité-nist",[1883],{"type":22,"value":1884},"3. Analyse du protocole post-quantique et conformité NIST",{"type":16,"tag":25,"props":1886,"children":1887},{},[1888,1890,1895,1897,1902],{"type":22,"value":1889},"Cette section couvre l'intégralité de la pile cryptographique active : primitives, flux protocolaires, dérivation d'identité, et conformité aux FIPS 203/204 et aux référentiels associés. Toutes les vérifications ont été faites sur le code réel, y compris le source de ",{"type":16,"tag":51,"props":1891,"children":1893},{"className":1892},[],[1894],{"type":22,"value":147},{"type":22,"value":1896}," 0.5.4 installé dans ",{"type":16,"tag":51,"props":1898,"children":1900},{"className":1899},[],[1901],{"type":22,"value":155},{"type":22,"value":1903}," (pas la documentation de la bibliothèque).",{"type":16,"tag":284,"props":1905,"children":1907},{"id":1906},"_31-inventaire-des-primitives-et-vérification-des-paramètres",[1908],{"type":22,"value":1909},"3.1 Inventaire des primitives et vérification des paramètres",{"type":16,"tag":175,"props":1911,"children":1912},{},[1913,1944],{"type":16,"tag":179,"props":1914,"children":1915},{},[1916],{"type":16,"tag":183,"props":1917,"children":1918},{},[1919,1924,1929,1934,1939],{"type":16,"tag":187,"props":1920,"children":1921},{},[1922],{"type":22,"value":1923},"Primitive",{"type":16,"tag":187,"props":1925,"children":1926},{},[1927],{"type":22,"value":1928},"Référence",{"type":16,"tag":187,"props":1930,"children":1931},{},[1932],{"type":22,"value":1933},"Implémentation",{"type":16,"tag":187,"props":1935,"children":1936},{},[1937],{"type":22,"value":1938},"Paramètres vérifiés dans le code",{"type":16,"tag":187,"props":1940,"children":1941},{},[1942],{"type":22,"value":1943},"Conforme",{"type":16,"tag":198,"props":1945,"children":1946},{},[1947,1988,2034,2075,2114,2153,2180,2218],{"type":16,"tag":183,"props":1948,"children":1949},{},[1950,1955,1960,1970,1983],{"type":16,"tag":205,"props":1951,"children":1952},{},[1953],{"type":22,"value":1954},"ML-KEM-768",{"type":16,"tag":205,"props":1956,"children":1957},{},[1958],{"type":22,"value":1959},"FIPS 203 (final)",{"type":16,"tag":205,"props":1961,"children":1962},{},[1963,1968],{"type":16,"tag":51,"props":1964,"children":1966},{"className":1965},[],[1967],{"type":22,"value":147},{"type":22,"value":1969}," 0.5.4",{"type":16,"tag":205,"props":1971,"children":1972},{},[1973,1975,1981],{"type":22,"value":1974},"ek 1184 B, dk 2400 B, ct 1088 B, ss 32 B (",{"type":16,"tag":51,"props":1976,"children":1978},{"className":1977},[],[1979],{"type":22,"value":1980},"mlkem.ts:70-73",{"type":22,"value":1982},") ; keygen seed 64 B = d‖z",{"type":16,"tag":205,"props":1984,"children":1985},{},[1986],{"type":22,"value":1987},"✅",{"type":16,"tag":183,"props":1989,"children":1990},{},[1991,1996,2001,2010,2030],{"type":16,"tag":205,"props":1992,"children":1993},{},[1994],{"type":22,"value":1995},"ML-DSA-65",{"type":16,"tag":205,"props":1997,"children":1998},{},[1999],{"type":22,"value":2000},"FIPS 204 (final)",{"type":16,"tag":205,"props":2002,"children":2003},{},[2004,2009],{"type":16,"tag":51,"props":2005,"children":2007},{"className":2006},[],[2008],{"type":22,"value":147},{"type":22,"value":1969},{"type":16,"tag":205,"props":2011,"children":2012},{},[2013,2015,2021,2022,2028],{"type":22,"value":2014},"pk 1952 B, sk 4032 B, sig 3309 B (",{"type":16,"tag":51,"props":2016,"children":2018},{"className":2017},[],[2019],{"type":22,"value":2020},"IdentityDerivationService.ts:100-104",{"type":22,"value":97},{"type":16,"tag":51,"props":2023,"children":2025},{"className":2024},[],[2026],{"type":22,"value":2027},"group-message-cipher.ts:68",{"type":22,"value":2029},") ; keygen seed ξ 32 B",{"type":16,"tag":205,"props":2031,"children":2032},{},[2033],{"type":22,"value":1987},{"type":16,"tag":183,"props":2035,"children":2036},{},[2037,2042,2047,2058,2070],{"type":16,"tag":205,"props":2038,"children":2039},{},[2040],{"type":22,"value":2041},"XChaCha20-Poly1305",{"type":16,"tag":205,"props":2043,"children":2044},{},[2045],{"type":22,"value":2046},"draft-irtf-cfrg-xchacha",{"type":16,"tag":205,"props":2048,"children":2049},{},[2050,2056],{"type":16,"tag":51,"props":2051,"children":2053},{"className":2052},[],[2054],{"type":22,"value":2055},"@noble/ciphers",{"type":22,"value":2057}," 2.1.1",{"type":16,"tag":205,"props":2059,"children":2060},{},[2061,2063,2069],{"type":22,"value":2062},"clé 32 B, nonce 24 B, tag 16 B (",{"type":16,"tag":51,"props":2064,"children":2066},{"className":2065},[],[2067],{"type":22,"value":2068},"xchacha.ts:29-36",{"type":22,"value":669},{"type":16,"tag":205,"props":2071,"children":2072},{},[2073],{"type":22,"value":2074},"⚠️ hors NIST, voir 3.5.d",{"type":16,"tag":183,"props":2076,"children":2077},{},[2078,2083,2088,2097,2109],{"type":16,"tag":205,"props":2079,"children":2080},{},[2081],{"type":22,"value":2082},"ChaCha20-Poly1305",{"type":16,"tag":205,"props":2084,"children":2085},{},[2086],{"type":22,"value":2087},"RFC 8439",{"type":16,"tag":205,"props":2089,"children":2090},{},[2091,2096],{"type":16,"tag":51,"props":2092,"children":2094},{"className":2093},[],[2095],{"type":22,"value":2055},{"type":22,"value":2057},{"type":16,"tag":205,"props":2098,"children":2099},{},[2100,2102,2108],{"type":22,"value":2101},"nonce 12 B, enveloppe DEV-010 uniquement (",{"type":16,"tag":51,"props":2103,"children":2105},{"className":2104},[],[2106],{"type":22,"value":2107},"chacha-std.ts",{"type":22,"value":669},{"type":16,"tag":205,"props":2110,"children":2111},{},[2112],{"type":22,"value":2113},"✅ IETF",{"type":16,"tag":183,"props":2115,"children":2116},{},[2117,2122,2127,2137,2149],{"type":16,"tag":205,"props":2118,"children":2119},{},[2120],{"type":22,"value":2121},"HKDF-SHA-256/512",{"type":16,"tag":205,"props":2123,"children":2124},{},[2125],{"type":22,"value":2126},"RFC 5869 / SP 800-56C rev2",{"type":16,"tag":205,"props":2128,"children":2129},{},[2130,2135],{"type":16,"tag":51,"props":2131,"children":2133},{"className":2132},[],[2134],{"type":22,"value":789},{"type":22,"value":2136}," 2.0.1",{"type":16,"tag":205,"props":2138,"children":2139},{},[2140,2142,2148],{"type":22,"value":2141},"extract-then-expand, salt + info systématiques (",{"type":16,"tag":51,"props":2143,"children":2145},{"className":2144},[],[2146],{"type":22,"value":2147},"hkdf.ts",{"type":22,"value":669},{"type":16,"tag":205,"props":2150,"children":2151},{},[2152],{"type":22,"value":1987},{"type":16,"tag":183,"props":2154,"children":2155},{},[2156,2160,2165,2170,2175],{"type":16,"tag":205,"props":2157,"children":2158},{},[2159],{"type":22,"value":324},{"type":16,"tag":205,"props":2161,"children":2162},{},[2163],{"type":22,"value":2164},"RFC 9106",{"type":16,"tag":205,"props":2166,"children":2167},{},[2168],{"type":22,"value":2169},"phc-winner-argon2 natif vendored",{"type":16,"tag":205,"props":2171,"children":2172},{},[2173],{"type":22,"value":2174},"m=16 MiB, t=3, p=1 (profil Α-light)",{"type":16,"tag":205,"props":2176,"children":2177},{},[2178],{"type":22,"value":2179},"⚠️ voir C8",{"type":16,"tag":183,"props":2181,"children":2182},{},[2183,2188,2193,2204,2214],{"type":16,"tag":205,"props":2184,"children":2185},{},[2186],{"type":22,"value":2187},"BIP39",{"type":16,"tag":205,"props":2189,"children":2190},{},[2191],{"type":22,"value":2192},"—",{"type":16,"tag":205,"props":2194,"children":2195},{},[2196,2202],{"type":16,"tag":51,"props":2197,"children":2199},{"className":2198},[],[2200],{"type":22,"value":2201},"@scure/bip39",{"type":22,"value":2203}," 2.2.0",{"type":16,"tag":205,"props":2205,"children":2206},{},[2207,2209],{"type":22,"value":2208},"24 mots = 256 bits d'entropie + checksum, entropie via ",{"type":16,"tag":51,"props":2210,"children":2212},{"className":2211},[],[2213],{"type":22,"value":603},{"type":16,"tag":205,"props":2215,"children":2216},{},[2217],{"type":22,"value":1987},{"type":16,"tag":183,"props":2219,"children":2220},{},[2221,2226,2231,2241,2246],{"type":16,"tag":205,"props":2222,"children":2223},{},[2224],{"type":22,"value":2225},"X25519 / Ed25519",{"type":16,"tag":205,"props":2227,"children":2228},{},[2229],{"type":22,"value":2230},"RFC 7748 / 8032",{"type":16,"tag":205,"props":2232,"children":2233},{},[2234,2239],{"type":16,"tag":51,"props":2235,"children":2237},{"className":2236},[],[2238],{"type":22,"value":935},{"type":22,"value":2240}," 1.9.7",{"type":16,"tag":205,"props":2242,"children":2243},{},[2244],{"type":22,"value":2245},"volet classique de l'hybridation",{"type":16,"tag":205,"props":2247,"children":2248},{},[2249],{"type":22,"value":1987},{"type":16,"tag":25,"props":2251,"children":2252},{},[2253,2255,2260,2261,2267,2268,2274,2275,2281,2282,2288,2289,2295,2297,2303],{"type":22,"value":2254},"Les tailles ne sont pas seulement déclarées : le code actif ",{"type":16,"tag":29,"props":2256,"children":2257},{},[2258],{"type":22,"value":2259},"valide les tailles avant chaque opération",{"type":22,"value":342},{"type":16,"tag":51,"props":2262,"children":2264},{"className":2263},[],[2265],{"type":22,"value":2266},"payload-encrypt.ts:281-291",{"type":22,"value":97},{"type":16,"tag":51,"props":2269,"children":2271},{"className":2270},[],[2272],{"type":22,"value":2273},"group-message-cipher.ts:217-222",{"type":22,"value":97},{"type":16,"tag":51,"props":2276,"children":2278},{"className":2277},[],[2279],{"type":22,"value":2280},"device-certification.ts:101-105",{"type":22,"value":97},{"type":16,"tag":51,"props":2283,"children":2285},{"className":2284},[],[2286],{"type":22,"value":2287},"envelope/client.ts:131-135",{"type":22,"value":97},{"type":16,"tag":51,"props":2290,"children":2292},{"className":2291},[],[2293],{"type":22,"value":2294},"assertSize",{"type":22,"value":2296}," sur les six clés du trousseau dans ",{"type":16,"tag":51,"props":2298,"children":2300},{"className":2299},[],[2301],{"type":22,"value":2302},"IdentityDerivationService",{"type":22,"value":2304},"). C'est une discipline de défense en profondeur rare et appréciable pour l'évaluation.",{"type":16,"tag":284,"props":2306,"children":2308},{"id":2307},"_32-vérification-de-lusage-de-lapi-noble-source-installé-pas-la-doc",[2309],{"type":22,"value":2310},"3.2 Vérification de l'usage de l'API noble (source installé, pas la doc)",{"type":16,"tag":25,"props":2312,"children":2313},{},[2314,2316,2322],{"type":22,"value":2315},"Trois points critiques ont été vérifiés directement dans ",{"type":16,"tag":51,"props":2317,"children":2319},{"className":2318},[],[2320],{"type":22,"value":2321},"node_modules/@noble/post-quantum/ml-dsa.js",{"type":22,"value":2323}," :",{"type":16,"tag":25,"props":2325,"children":2326},{},[2327,2332,2334,2339,2341,2347,2349,2354,2355,2361,2362,2368,2369,2375,2376,2382,2383,2389,2390,2396,2397,2403,2405,2410],{"type":16,"tag":29,"props":2328,"children":2329},{},[2330],{"type":22,"value":2331},"a) Ordre des arguments.",{"type":22,"value":2333}," L'API 0.5.4 est ",{"type":16,"tag":51,"props":2335,"children":2337},{"className":2336},[],[2338],{"type":22,"value":871},{"type":22,"value":2340}," / ",{"type":16,"tag":51,"props":2342,"children":2344},{"className":2343},[],[2345],{"type":22,"value":2346},"verify(sig, msg, pubKey, opts?)",{"type":22,"value":2348},". Les ",{"type":16,"tag":29,"props":2350,"children":2351},{},[2352],{"type":22,"value":2353},"11 points d'appel actifs",{"type":22,"value":342},{"type":16,"tag":51,"props":2356,"children":2358},{"className":2357},[],[2359],{"type":22,"value":2360},"group-message-cipher.ts:224/369",{"type":22,"value":97},{"type":16,"tag":51,"props":2363,"children":2365},{"className":2364},[],[2366],{"type":22,"value":2367},"device-certification.ts:107",{"type":22,"value":97},{"type":16,"tag":51,"props":2370,"children":2372},{"className":2371},[],[2373],{"type":22,"value":2374},"prekey-bundle.ts:57/108",{"type":22,"value":97},{"type":16,"tag":51,"props":2377,"children":2379},{"className":2378},[],[2380],{"type":22,"value":2381},"BlobService.ts:487",{"type":22,"value":97},{"type":16,"tag":51,"props":2384,"children":2386},{"className":2385},[],[2387],{"type":22,"value":2388},"StorageServiceClient.ts:292",{"type":22,"value":97},{"type":16,"tag":51,"props":2391,"children":2393},{"className":2392},[],[2394],{"type":22,"value":2395},"manifestCanonical.ts:88",{"type":22,"value":97},{"type":16,"tag":51,"props":2398,"children":2400},{"className":2399},[],[2401],{"type":22,"value":2402},"accountRecoveryService.ts:125",{"type":22,"value":2404},", plus les verify associés) respectent tous cet ordre. Seul le code mort ",{"type":16,"tag":51,"props":2406,"children":2408},{"className":2407},[],[2409],{"type":22,"value":848},{"type":22,"value":2411}," utilise l'ordre inversé de l'ancienne API (→ C1.3).",{"type":16,"tag":25,"props":2413,"children":2414},{},[2415,2420,2422,2428,2430,2436,2438,2443,2445,2451],{"type":16,"tag":29,"props":2416,"children":2417},{},[2418],{"type":22,"value":2419},"b) Signature hedgée (recommandation FIPS 204 §3.4).",{"type":22,"value":2421}," Aucun appel ne passe d'options — j'ai vérifié dans le source noble le comportement par défaut : quand ",{"type":16,"tag":51,"props":2423,"children":2425},{"className":2424},[],[2426],{"type":22,"value":2427},"extraEntropy",{"type":22,"value":2429}," est absent, ",{"type":16,"tag":51,"props":2431,"children":2433},{"className":2432},[],[2434],{"type":22,"value":2435},"rnd = randomBytes(32)",{"type":22,"value":2437}," (ml-dsa.js:386-390), soit la ",{"type":16,"tag":29,"props":2439,"children":2440},{},[2441],{"type":22,"value":2442},"variante hedgée",{"type":22,"value":2444}," recommandée par le FIPS 204 (protection contre les fautes et certaines attaques par canaux auxiliaires, par opposition au mode déterministe ",{"type":16,"tag":51,"props":2446,"children":2448},{"className":2447},[],[2449],{"type":22,"value":2450},"extraEntropy: false",{"type":22,"value":2452},"). Comportement conforme sans action requise.",{"type":16,"tag":25,"props":2454,"children":2455},{},[2456,2461,2463,2469,2471,2477,2479,2485,2487,2492,2494,2500],{"type":16,"tag":29,"props":2457,"children":2458},{},[2459],{"type":22,"value":2460},"c) Framing pure ML-DSA (FIPS 204 Algorithm 2).",{"type":22,"value":2462}," L'API publique noble applique ",{"type":16,"tag":51,"props":2464,"children":2466},{"className":2465},[],[2467],{"type":22,"value":2468},"M′ = 0x00 ‖ len(ctx) ‖ ctx ‖ M",{"type":22,"value":2470}," avec contexte vide par défaut (ml-dsa.js:522-527, ",{"type":16,"tag":51,"props":2472,"children":2474},{"className":2473},[],[2475],{"type":22,"value":2476},"getMessage",{"type":22,"value":2478},"), puis ",{"type":16,"tag":51,"props":2480,"children":2482},{"className":2481},[],[2483],{"type":22,"value":2484},"µ = H(tr ‖ M′)",{"type":22,"value":2486},". AKARUP utilise donc bien ",{"type":16,"tag":29,"props":2488,"children":2489},{},[2490],{"type":22,"value":2491},"pure ML-DSA.Sign conforme",{"type":22,"value":2493},", pas l'API interne. Le paramètre ",{"type":16,"tag":51,"props":2495,"children":2497},{"className":2496},[],[2498],{"type":22,"value":2499},"context",{"type":22,"value":2501}," FIPS 204 n'est pas utilisé — la séparation de domaine est faite en amont, dans le contenu haché (voir 3.4) : choix défendable et cohérent avec l'interop Go.",{"type":16,"tag":284,"props":2503,"children":2505},{"id":2504},"_33-architecture-kem-dem-et-flux-protocolaires",[2506],{"type":22,"value":2507},"3.3 Architecture KEM-DEM et flux protocolaires",{"type":16,"tag":25,"props":2509,"children":2510},{},[2511,2529],{"type":16,"tag":29,"props":2512,"children":2513},{},[2514,2516,2522,2523,2528],{"type":22,"value":2515},"Bus ",{"type":16,"tag":51,"props":2517,"children":2519},{"className":2518},[],[2520],{"type":22,"value":2521},"pending_actions",{"type":22,"value":342},{"type":16,"tag":51,"props":2524,"children":2526},{"className":2525},[],[2527],{"type":22,"value":381},{"type":22,"value":669},{"type":22,"value":2530}," — le cœur du Blind Relay :",{"type":16,"tag":989,"props":2532,"children":2534},{"code":2533},"ml_kem768.encapsulate(pub destinataire) → (kem_ct 1088 B, ss 32 B)\nHKDF-SHA-256(ss, salt=\"AKARUP/bus/v1\") → clé AEAD 32 B\nnonce aléatoire 24 B → XChaCha20-Poly1305(clé, plaintext paddé, nonce)\nformat versionné : version ‖ nonce ‖ ciphertext+tag, taille = bucket exact\n",[2535],{"type":16,"tag":51,"props":2536,"children":2537},{"__ignoreMap":7},[2538],{"type":22,"value":2533},{"type":16,"tag":25,"props":2540,"children":2541},{},[2542,2544,2549],{"type":22,"value":2543},"C'est le schéma KEM-DEM canonique (celui du draft SP 800-227 du NIST sur l'usage des KEM) : le secret encapsulé n'est ",{"type":16,"tag":29,"props":2545,"children":2546},{},[2547],{"type":22,"value":2548},"jamais utilisé directement comme clé",{"type":22,"value":2550}," mais passe par un KDF avec séparation de domaine — exactement ce que le NIST prescrit. Le padding par buckets avec tirage aléatoire chunké à 65 536 octets neutralise à la fois l'analyse de taille côté serveur et le plafond WebCrypto. La clé étant fraîche à chaque encapsulation (une par action), le nonce aléatoire 24 B est très largement au-delà du nécessaire — aucune possibilité structurelle de réutilisation nonce/clé.",{"type":16,"tag":25,"props":2552,"children":2553},{},[2554,2566],{"type":16,"tag":29,"props":2555,"children":2556},{},[2557,2559,2565],{"type":22,"value":2558},"Enveloppe transport DEV-010 (",{"type":16,"tag":51,"props":2560,"children":2562},{"className":2561},[],[2563],{"type":22,"value":2564},"envelope/client.ts",{"type":22,"value":669},{"type":22,"value":2323},{"type":16,"tag":989,"props":2568,"children":2570},{"code":2569},"encapsulate(pub serveur) → ss\nrequête : HKDF(ss, salt=\"ENVELOPE_REQUEST_v1\", info=\"aead\") → clé sens client→serveur\nréponse : HKDF(ss, salt=\"ENVELOPE_RESPONSE_v1\", info=\"aead\") → clé sens serveur→client\nChaCha20-Poly1305 RFC 8439 (nonce 12 B) par sens\n",[2571],{"type":16,"tag":51,"props":2572,"children":2573},{"__ignoreMap":7},[2574],{"type":22,"value":2569},{"type":16,"tag":25,"props":2576,"children":2577},{},[2578,2580,2585,2587,2593],{"type":22,"value":2579},"Les ",{"type":16,"tag":29,"props":2581,"children":2582},{},[2583],{"type":22,"value":2584},"clés directionnelles distinctes",{"type":22,"value":2586}," dérivées du même secret par salts différents éliminent tout risque de réflexion requête/réponse et tout partage de flux nonce entre les deux sens. Le rejet silencieux sur mauvais ",{"type":16,"tag":51,"props":2588,"children":2590},{"className":2589},[],[2591],{"type":22,"value":2592},"keyID",{"type":22,"value":2594}," (« réponse opaque, oracle d'erreur évité », commentaire ligne 113) montre une prise en compte des oracles côté conception. Bonne architecture.",{"type":16,"tag":25,"props":2596,"children":2597},{},[2598,2610,2612,2617,2619,2625,2627,2633,2635,2640],{"type":16,"tag":29,"props":2599,"children":2600},{},[2601,2603,2609],{"type":22,"value":2602},"Établissement de session PQXDH (",{"type":16,"tag":51,"props":2604,"children":2606},{"className":2605},[],[2607],{"type":22,"value":2608},"lib/crypto/pqxdh/",{"type":22,"value":669},{"type":22,"value":2611}," : trousseau ",{"type":16,"tag":29,"props":2613,"children":2614},{},[2615],{"type":22,"value":2616},"hybride X25519 + ML-KEM-768",{"type":22,"value":2618}," (3 keypairs, DEV-009 Scope γ), avec prékeys signées ML-DSA-65 (",{"type":16,"tag":51,"props":2620,"children":2622},{"className":2621},[],[2623],{"type":22,"value":2624},"prekey-bundle.ts",{"type":22,"value":2626},") et rotation SPK à 7 jours (",{"type":16,"tag":51,"props":2628,"children":2630},{"className":2629},[],[2631],{"type":22,"value":2632},"SPKRotationManager.ts:35",{"type":22,"value":2634},"). Point fort décisif pour la CSPN : ",{"type":16,"tag":29,"props":2636,"children":2637},{},[2638],{"type":22,"value":2639},"l'hybridation classique + post-quantique est exactement la posture exigée par l'ANSSI",{"type":22,"value":2641}," (avis sur la migration post-quantique : le PQ ne doit pas remplacer mais s'ajouter à la cryptographie éprouvée tant que le recul manque). AKARUP est alignée à la fois sur la doctrine ANSSI et sur l'état de l'art industriel (Signal PQXDH, Apple PQ3).",{"type":16,"tag":25,"props":2643,"children":2644},{},[2645,2657,2659,2664],{"type":16,"tag":29,"props":2646,"children":2647},{},[2648,2650,2656],{"type":22,"value":2649},"Chiffrement de groupe (",{"type":16,"tag":51,"props":2651,"children":2653},{"className":2652},[],[2654],{"type":22,"value":2655},"group-message-cipher.ts",{"type":22,"value":669},{"type":22,"value":2658}," : kGroup aléatoire 32 B (",{"type":16,"tag":51,"props":2660,"children":2662},{"className":2661},[],[2663],{"type":22,"value":603},{"type":22,"value":2665},"), chiffrement XChaCha par message avec nonce frais, métadonnées liées à la signature via un hash canonique à séparateurs null-byte (anti-ambiguïté de concaténation) incluant group_id, message_id, device_id, ciphertext, nonce et timestamp — le ciphertext et le nonce étant dans le hash signé, toute altération est détectée (construction sign-the-ciphertext propre).",{"type":16,"tag":284,"props":2667,"children":2669},{"id":2668},"_34-dérivation-didentité-déterministe-bip39-et-séparation-de-domaine",[2670],{"type":22,"value":2671},"3.4 Dérivation d'identité déterministe (BIP39) et séparation de domaine",{"type":16,"tag":25,"props":2673,"children":2674},{},[2675,2681,2683,2689],{"type":16,"tag":51,"props":2676,"children":2678},{"className":2677},[],[2679],{"type":22,"value":2680},"IdentityDerivationService.ts",{"type":22,"value":2682}," reproduit ",{"type":16,"tag":51,"props":2684,"children":2686},{"className":2685},[],[2687],{"type":22,"value":2688},"recovery.GeneratePQIdentityFromSeed",{"type":22,"value":2690}," (Go) :",{"type":16,"tag":989,"props":2692,"children":2694},{"code":2693},"mnémonique 24 mots (256 bits, entropie getRandomValues) → seed BIP39 64 B\nHKDF-SHA-256(seed, salt=\"AKARUP-recovery-v1\", info=\"x25519-v1\") → 32 B = clé privée X25519\nHKDF-SHA-256(seed, salt=\"AKARUP-recovery-v1\", info=\"mldsa-v1\")  → 32 B = ξ pour ml_dsa65.keygen\nHKDF-SHA-256(seed, salt=\"AKARUP-recovery-v1\", info=\"mlkem-v1\")  → 64 B = d‖z pour ml_kem768.keygen\n",[2695],{"type":16,"tag":51,"props":2696,"children":2697},{"__ignoreMap":7},[2698],{"type":22,"value":2693},{"type":16,"tag":25,"props":2700,"children":2701},{},[2702,2704,2710],{"type":22,"value":2703},"Les tailles de seeds correspondent exactement aux entrées de keygen des FIPS 203 (§7.1, d et z de 32 B) et FIPS 204 (§6.1, ξ de 32 B). Les trois branches sont indépendantes par ",{"type":16,"tag":51,"props":2705,"children":2707},{"className":2706},[],[2708],{"type":22,"value":2709},"info",{"type":22,"value":2711}," distincts — la compromission d'une clé dérivée ne donne aucune prise sur les autres. La conformité byte-pour-byte avec le Go est garantie par les 21 vecteurs d'interopérabilité (M-Test-Interop-Go), ce qui constitue une preuve de correction d'implémentation bien plus forte que des tests unitaires isolés.",{"type":16,"tag":25,"props":2713,"children":2714},{},[2715,2720,2722,2728,2729,2735,2736,2742,2743,2749,2750,2756,2757,2763,2764,2770,2771,2777,2778,2784,2785,2791,2792,2798,2799,2805,2806,2812,2813,2818,2819,2825],{"type":16,"tag":29,"props":2716,"children":2717},{},[2718],{"type":22,"value":2719},"Séparation de domaine — inventaire exhaustif",{"type":22,"value":2721}," : 15 préfixes versionnés relevés dans le code actif (",{"type":16,"tag":51,"props":2723,"children":2725},{"className":2724},[],[2726],{"type":22,"value":2727},"AKARUP/bus/v1",{"type":22,"value":97},{"type":16,"tag":51,"props":2730,"children":2732},{"className":2731},[],[2733],{"type":22,"value":2734},"AKARUP/group-msg/v2",{"type":22,"value":97},{"type":16,"tag":51,"props":2737,"children":2739},{"className":2738},[],[2740],{"type":22,"value":2741},"AKARUP/msg-action/v1",{"type":22,"value":97},{"type":16,"tag":51,"props":2744,"children":2746},{"className":2745},[],[2747],{"type":22,"value":2748},"AKARUP/device-cert/v1",{"type":22,"value":97},{"type":16,"tag":51,"props":2751,"children":2753},{"className":2752},[],[2754],{"type":22,"value":2755},"AKARUP/blob/capability/v1",{"type":22,"value":97},{"type":16,"tag":51,"props":2758,"children":2760},{"className":2759},[],[2761],{"type":22,"value":2762},"AKARUP/blob/chunk/",{"type":22,"value":97},{"type":16,"tag":51,"props":2765,"children":2767},{"className":2766},[],[2768],{"type":22,"value":2769},"AKARUP/blob/merkle-leaf/v1",{"type":22,"value":97},{"type":16,"tag":51,"props":2772,"children":2774},{"className":2773},[],[2775],{"type":22,"value":2776},"AKARUP/blob/merkle-node/v1",{"type":22,"value":97},{"type":16,"tag":51,"props":2779,"children":2781},{"className":2780},[],[2782],{"type":22,"value":2783},"AKARUP/blob/nonce/v1",{"type":22,"value":97},{"type":16,"tag":51,"props":2786,"children":2788},{"className":2787},[],[2789],{"type":22,"value":2790},"AKARUP/blob/notification-sig/v2",{"type":22,"value":97},{"type":16,"tag":51,"props":2793,"children":2795},{"className":2794},[],[2796],{"type":22,"value":2797},"AKARUP/media/nonce/v1",{"type":22,"value":97},{"type":16,"tag":51,"props":2800,"children":2802},{"className":2801},[],[2803],{"type":22,"value":2804},"AKARUP/pairing/fingerprint/v1",{"type":22,"value":97},{"type":16,"tag":51,"props":2807,"children":2809},{"className":2808},[],[2810],{"type":22,"value":2811},"AKARUP/pairing/masterkey-wrap/v1",{"type":22,"value":97},{"type":16,"tag":51,"props":2814,"children":2816},{"className":2815},[],[2817],{"type":22,"value":340},{"type":22,"value":97},{"type":16,"tag":51,"props":2820,"children":2822},{"className":2821},[],[2823],{"type":22,"value":2824},"AKARUP/secure-store/user-namespace/v1/",{"type":22,"value":2826},"). Chaque contexte cryptographique est isolé et versionné : une signature ou une clé produite dans un contexte est inutilisable dans un autre, et chaque format peut évoluer indépendamment. C'est une des meilleures disciplines de séparation de domaine que l'on puisse présenter à un évaluateur.",{"type":16,"tag":25,"props":2828,"children":2829},{},[2830,2835,2837,2843,2845,2851,2853,2859,2861,2867,2869,2875,2877,2883],{"type":16,"tag":29,"props":2831,"children":2832},{},[2833],{"type":22,"value":2834},"Hygiène mémoire",{"type":22,"value":2836}," : 40 points d'effacement défensif (",{"type":16,"tag":51,"props":2838,"children":2840},{"className":2839},[],[2841],{"type":22,"value":2842},"fill(0)",{"type":22,"value":2844},") relevés sur les matériaux sensibles — KEK (",{"type":16,"tag":51,"props":2846,"children":2848},{"className":2847},[],[2849],{"type":22,"value":2850},"password-wrap.ts:164/239/245",{"type":22,"value":2852},"), MasterKey (",{"type":16,"tag":51,"props":2854,"children":2856},{"className":2855},[],[2857],{"type":22,"value":2858},"password-wrap.ts:276",{"type":22,"value":2860},"), wrapKeys de pairing (",{"type":16,"tag":51,"props":2862,"children":2864},{"className":2863},[],[2865],{"type":22,"value":2866},"wrap.ts:64/88",{"type":22,"value":2868},"), clé cachée du PasswordManager (",{"type":16,"tag":51,"props":2870,"children":2872},{"className":2871},[],[2873],{"type":22,"value":2874},"PasswordManager.ts:278",{"type":22,"value":2876},") — auxquels s'ajoute le ",{"type":16,"tag":51,"props":2878,"children":2880},{"className":2879},[],[2881],{"type":22,"value":2882},"cleanBytes",{"type":22,"value":2884}," interne de noble sur les intermédiaires de signature. Les limites de l'effacement mémoire en JavaScript (GC, copies immuables) sont connues et devront être mentionnées dans la cible de sécurité, mais l'effort systématique est réel.",{"type":16,"tag":284,"props":2886,"children":2888},{"id":2887},"_35-points-de-conformité-nist-à-nuancer-pour-la-cible-de-sécurité-cspn-et-le-marketing",[2889],{"type":22,"value":2890},"3.5 Points de conformité NIST à nuancer (pour la cible de sécurité CSPN et le marketing)",{"type":16,"tag":25,"props":2892,"children":2893},{},[2894],{"type":22,"value":2895},"Conformément au principe fondateur d'honnêteté totale marketing/technique, voici les cinq nuances exactes entre « conforme NIST » et ce que le code fait réellement. Aucune n'est un défaut de sécurité ; toutes doivent être formulées correctement dans la documentation.",{"type":16,"tag":25,"props":2897,"children":2898},{},[2899,2904,2906,2911],{"type":16,"tag":29,"props":2900,"children":2901},{},[2902],{"type":22,"value":2903},"a) Conformité algorithmique ≠ validation FIPS 140-3.",{"type":22,"value":2905}," ",{"type":16,"tag":51,"props":2907,"children":2909},{"className":2908},[],[2910],{"type":22,"value":147},{"type":22,"value":2912}," implémente les FIPS 203/204 finaux (vérifié : framing Algorithm 2, hedging, tailles), mais n'est pas — et aucune bibliothèque JavaScript n'est — un module validé CMVP. La CSPN n'exige pas de validation FIPS (l'ANSSI évalue l'implémentation elle-même, et les 21 vecteurs d'interop sont un excellent support), mais le vocabulaire marketing doit être « implémente ML-KEM-768 (FIPS 203) et ML-DSA-65 (FIPS 204) », jamais « FIPS-validated » ni « certifié NIST ».",{"type":16,"tag":25,"props":2914,"children":2915},{},[2916,2921,2923,2928,2930,2935,2937,2942],{"type":16,"tag":29,"props":2917,"children":2918},{},[2919],{"type":22,"value":2920},"b) Keygen dérivé de seed vs RBG approuvé.",{"type":22,"value":2922}," Les FIPS 203/204 exigent, pour une implémentation ",{"type":16,"tag":818,"props":2924,"children":2925},{},[2926],{"type":22,"value":2927},"validée",{"type":22,"value":2929},", que les seeds de keygen proviennent d'un RBG approuvé à la frontière du module. Chez AKARUP, elles proviennent de HKDF(seed BIP39), dont l'entropie initiale (256 bits) vient de ",{"type":16,"tag":51,"props":2931,"children":2933},{"className":2932},[],[2934],{"type":22,"value":603},{"type":22,"value":2936}," (CSPRNG OS). La chaîne d'entropie est cryptographiquement saine et le keygen déterministe est ",{"type":16,"tag":29,"props":2938,"children":2939},{},[2940],{"type":22,"value":2941},"la",{"type":22,"value":2943}," propriété qui rend possible la recovery BIP39 portable — c'est un choix d'architecture assumé, pas une faiblesse. À documenter explicitement dans la cible de sécurité : « keygen déterministe par dérivation HKDF d'une seed maîtresse de 256 bits d'entropie OS », avec la justification recovery.",{"type":16,"tag":25,"props":2945,"children":2946},{},[2947,2952,2954,2960,2962,2968,2969,2975,2976,2981,2982,2987,2988,2993,2995,3000],{"type":16,"tag":29,"props":2948,"children":2949},{},[2950],{"type":22,"value":2951},"c) Pré-hachage SHA-256 + pure ML-DSA (le point technique le plus substantiel).",{"type":22,"value":2953}," Le code ne signe jamais les messages bruts : il signe systématiquement ",{"type":16,"tag":51,"props":2955,"children":2957},{"className":2956},[],[2958],{"type":22,"value":2959},"sha256(canonical)",{"type":22,"value":2961}," via pure ML-DSA.Sign (",{"type":16,"tag":51,"props":2963,"children":2965},{"className":2964},[],[2966],{"type":22,"value":2967},"group-message-cipher.ts:223-224",{"type":22,"value":97},{"type":16,"tag":51,"props":2970,"children":2972},{"className":2971},[],[2973],{"type":22,"value":2974},"device-certification.ts:106-107",{"type":22,"value":97},{"type":16,"tag":51,"props":2977,"children":2979},{"className":2978},[],[2980],{"type":22,"value":2388},{"type":22,"value":97},{"type":16,"tag":51,"props":2983,"children":2985},{"className":2984},[],[2986],{"type":22,"value":2395},{"type":22,"value":97},{"type":16,"tag":51,"props":2989,"children":2991},{"className":2990},[],[2992],{"type":22,"value":2402},{"type":22,"value":2994},"). Le FIPS 204 prévoit pour ce cas le mode ",{"type":16,"tag":29,"props":2996,"children":2997},{},[2998],{"type":22,"value":2999},"HashML-DSA",{"type":22,"value":3001}," (§5.4), qui encode l'OID du hash dans le message signé ; pré-hacher en dehors de ce mode a deux conséquences : (1) la sécurité de la signature se rabat sur la résistance aux collisions du pré-hash — SHA-256 offre 128 bits de résistance aux collisions, sous la catégorie 3 (~192 bits) visée par ML-DSA-65 ; (2) l'absence de framing OID signifie qu'un même digest signé vaut pour tout message y menant.",{"type":16,"tag":25,"props":3003,"children":3004},{},[3005],{"type":22,"value":3006},"En pratique le risque est faible : les messages signés sont des structures internes canoniques à préfixe de domaine et faible malléabilité (pas des documents fournis par un adversaire), et une attaque par collision exigerait de construire deux structures canoniques valides en collision SHA-256. Trois options, par ordre de préférence :",{"type":16,"tag":765,"props":3008,"children":3009},{},[3010,3020,3053],{"type":16,"tag":295,"props":3011,"children":3012},{},[3013,3018],{"type":16,"tag":29,"props":3014,"children":3015},{},[3016],{"type":22,"value":3017},"Documenter et assumer",{"type":22,"value":3019}," dans la cible de sécurité (coût nul, position défendable : « signatures sur digests SHA-256 de structures canoniques à domaine séparé, sécurité collision 128 bits »).",{"type":16,"tag":295,"props":3021,"children":3022},{},[3023,3028,3030,3035,3037,3043,3045,3051],{"type":16,"tag":29,"props":3024,"children":3025},{},[3026],{"type":22,"value":3027},"Passer les pré-hash en SHA-512",{"type":22,"value":3029}," (déjà disponible via ",{"type":16,"tag":51,"props":3031,"children":3033},{"className":3032},[],[3034],{"type":22,"value":789},{"type":22,"value":3036},"), ce qui remonte la résistance collision à 256 bits, au-dessus de la catégorie 3 — mais casse l'interop : à synchroniser avec le Go et les vecteurs, donc à traiter comme un sprint versionné (",{"type":16,"tag":51,"props":3038,"children":3040},{"className":3039},[],[3041],{"type":22,"value":3042},"/v2",{"type":22,"value":3044}," → ",{"type":16,"tag":51,"props":3046,"children":3048},{"className":3047},[],[3049],{"type":22,"value":3050},"/v3",{"type":22,"value":3052}," des domaines concernés).",{"type":16,"tag":295,"props":3054,"children":3055},{},[3056,3058,3064],{"type":22,"value":3057},"Utiliser le mode ",{"type":16,"tag":51,"props":3059,"children":3061},{"className":3060},[],[3062],{"type":22,"value":3063},"prehash",{"type":22,"value":3065}," de noble (HashML-DSA complet avec OID) — conformité maximale, même contrainte d'interop.",{"type":16,"tag":25,"props":3067,"children":3068},{},[3069,3071,3076],{"type":22,"value":3070},"La décision mérite d'être prise ",{"type":16,"tag":818,"props":3072,"children":3073},{},[3074],{"type":22,"value":3075},"avant",{"type":22,"value":3077}," le dépôt CSPN, car changer après coup invalide les vecteurs.",{"type":16,"tag":25,"props":3079,"children":3080},{},[3081,3086,3088,3093],{"type":16,"tag":29,"props":3082,"children":3083},{},[3084],{"type":22,"value":3085},"d) XChaCha20-Poly1305 n'est pas un algorithme NIST.",{"type":22,"value":3087}," L'AEAD approuvé NIST est AES-GCM (SP 800-38D) ; ChaCha20-Poly1305 est un standard IETF (RFC 8439) accepté par le référentiel ANSSI ; XChaCha (nonce étendu 24 B) est resté au stade de draft CFRG. Le choix est techniquement excellent (constant-time naturel, marge nonce énorme, aligné Signal/WireGuard) et ",{"type":16,"tag":29,"props":3089,"children":3090},{},[3091],{"type":22,"value":3092},"sans impact CSPN",{"type":22,"value":3094}," — mais interdit de revendiquer « 100 % algorithmes NIST ». Formulation correcte : « primitives post-quantiques NIST (FIPS 203/204), chiffrement authentifié état de l'art (famille ChaCha20-Poly1305) ». Noter que l'enveloppe DEV-010 utilise, elle, le ChaCha20-Poly1305 RFC 8439 standard — distinction à conserver dans la doc.",{"type":16,"tag":25,"props":3096,"children":3097},{},[3098,3103,3105,3110],{"type":16,"tag":29,"props":3099,"children":3100},{},[3101],{"type":22,"value":3102},"e) Racine d'entropie unique.",{"type":22,"value":3104}," Toute la pile (keygens, nonces, seeds hedgées ML-DSA, entropie BIP39, salts) repose sur ",{"type":16,"tag":51,"props":3106,"children":3108},{"className":3107},[],[3109],{"type":22,"value":371},{"type":22,"value":3111},". C'est correct (délégation aux CSPRNG OS), mais cela fait du chargement du polyfill un point de défaillance unique → renforce C3 en priorité haute.",{"type":16,"tag":284,"props":3113,"children":3115},{"id":3114},"_36-synthèse-conformité",[3116],{"type":22,"value":3117},"3.6 Synthèse conformité",{"type":16,"tag":175,"props":3119,"children":3120},{},[3121,3142],{"type":16,"tag":179,"props":3122,"children":3123},{},[3124],{"type":16,"tag":183,"props":3125,"children":3126},{},[3127,3132,3137],{"type":16,"tag":187,"props":3128,"children":3129},{},[3130],{"type":22,"value":3131},"Exigence / recommandation",{"type":16,"tag":187,"props":3133,"children":3134},{},[3135],{"type":22,"value":3136},"État",{"type":16,"tag":187,"props":3138,"children":3139},{},[3140],{"type":22,"value":3141},"Référence code",{"type":16,"tag":198,"props":3143,"children":3144},{},[3145,3172,3189,3212,3235,3252,3269,3292,3314,3332,3350,3368],{"type":16,"tag":183,"props":3146,"children":3147},{},[3148,3153,3157],{"type":16,"tag":205,"props":3149,"children":3150},{},[3151],{"type":22,"value":3152},"ML-KEM-768 conforme FIPS 203 (tailles, seed d‖z, KEM-DEM via KDF)",{"type":16,"tag":205,"props":3154,"children":3155},{},[3156],{"type":22,"value":1987},{"type":16,"tag":205,"props":3158,"children":3159},{},[3160,3166,3167],{"type":16,"tag":51,"props":3161,"children":3163},{"className":3162},[],[3164],{"type":22,"value":3165},"mlkem.ts",{"type":22,"value":97},{"type":16,"tag":51,"props":3168,"children":3170},{"className":3169},[],[3171],{"type":22,"value":381},{"type":16,"tag":183,"props":3173,"children":3174},{},[3175,3180,3184],{"type":16,"tag":205,"props":3176,"children":3177},{},[3178],{"type":22,"value":3179},"ML-DSA-65 conforme FIPS 204 (tailles, framing Alg. 2, hedged)",{"type":16,"tag":205,"props":3181,"children":3182},{},[3183],{"type":22,"value":1987},{"type":16,"tag":205,"props":3185,"children":3186},{},[3187],{"type":22,"value":3188},"11 sites d'appel + source noble vérifié",{"type":16,"tag":183,"props":3190,"children":3191},{},[3192,3197,3201],{"type":16,"tag":205,"props":3193,"children":3194},{},[3195],{"type":22,"value":3196},"Hybridation classique+PQ (doctrine ANSSI)",{"type":16,"tag":205,"props":3198,"children":3199},{},[3200],{"type":22,"value":1987},{"type":16,"tag":205,"props":3202,"children":3203},{},[3204,3210],{"type":16,"tag":51,"props":3205,"children":3207},{"className":3206},[],[3208],{"type":22,"value":3209},"pqxdh/identity.ts",{"type":22,"value":3211}," (X25519 + ML-KEM-768)",{"type":16,"tag":183,"props":3213,"children":3214},{},[3215,3220,3224],{"type":16,"tag":205,"props":3216,"children":3217},{},[3218],{"type":22,"value":3219},"Séparation de domaine systématique et versionnée",{"type":16,"tag":205,"props":3221,"children":3222},{},[3223],{"type":22,"value":1987},{"type":16,"tag":205,"props":3225,"children":3226},{},[3227,3229],{"type":22,"value":3228},"15 préfixes ",{"type":16,"tag":51,"props":3230,"children":3232},{"className":3231},[],[3233],{"type":22,"value":3234},"AKARUP/*",{"type":16,"tag":183,"props":3236,"children":3237},{},[3238,3243,3247],{"type":16,"tag":205,"props":3239,"children":3240},{},[3241],{"type":22,"value":3242},"Clés directionnelles distinctes (enveloppe)",{"type":16,"tag":205,"props":3244,"children":3245},{},[3246],{"type":22,"value":1987},{"type":16,"tag":205,"props":3248,"children":3249},{},[3250],{"type":22,"value":3251},"salts REQUEST/RESPONSE",{"type":16,"tag":183,"props":3253,"children":3254},{},[3255,3260,3264],{"type":16,"tag":205,"props":3256,"children":3257},{},[3258],{"type":22,"value":3259},"Interop prouvée TS↔Go",{"type":16,"tag":205,"props":3261,"children":3262},{},[3263],{"type":22,"value":1987},{"type":16,"tag":205,"props":3265,"children":3266},{},[3267],{"type":22,"value":3268},"21 vecteurs byte-pour-byte",{"type":16,"tag":183,"props":3270,"children":3271},{},[3272,3277,3282],{"type":16,"tag":205,"props":3273,"children":3274},{},[3275],{"type":22,"value":3276},"Zeroization des matériaux sensibles",{"type":16,"tag":205,"props":3278,"children":3279},{},[3280],{"type":22,"value":3281},"✅ (limites JS à documenter)",{"type":16,"tag":205,"props":3283,"children":3284},{},[3285,3287],{"type":22,"value":3286},"40 sites ",{"type":16,"tag":51,"props":3288,"children":3290},{"className":3289},[],[3291],{"type":22,"value":2842},{"type":16,"tag":183,"props":3293,"children":3294},{},[3295,3300,3305],{"type":16,"tag":205,"props":3296,"children":3297},{},[3298],{"type":22,"value":3299},"Rotation des prékeys signées",{"type":16,"tag":205,"props":3301,"children":3302},{},[3303],{"type":22,"value":3304},"✅ (7 jours)",{"type":16,"tag":205,"props":3306,"children":3307},{},[3308],{"type":16,"tag":51,"props":3309,"children":3311},{"className":3310},[],[3312],{"type":22,"value":3313},"SPKRotationManager.ts",{"type":16,"tag":183,"props":3315,"children":3316},{},[3317,3322,3327],{"type":16,"tag":205,"props":3318,"children":3319},{},[3320],{"type":22,"value":3321},"Pré-hachage SHA-256 vs HashML-DSA",{"type":16,"tag":205,"props":3323,"children":3324},{},[3325],{"type":22,"value":3326},"⚠️ décision à formaliser avant CSPN",{"type":16,"tag":205,"props":3328,"children":3329},{},[3330],{"type":22,"value":3331},"3.5.c",{"type":16,"tag":183,"props":3333,"children":3334},{},[3335,3340,3345],{"type":16,"tag":205,"props":3336,"children":3337},{},[3338],{"type":22,"value":3339},"Profil Argon2id aligné sur le module natif disponible",{"type":16,"tag":205,"props":3341,"children":3342},{},[3343],{"type":22,"value":3344},"⚠️ à migrer vers Β",{"type":16,"tag":205,"props":3346,"children":3347},{},[3348],{"type":22,"value":3349},"C8",{"type":16,"tag":183,"props":3351,"children":3352},{},[3353,3358,3363],{"type":16,"tag":205,"props":3354,"children":3355},{},[3356],{"type":22,"value":3357},"Hoist du polyfill CSPRNG",{"type":16,"tag":205,"props":3359,"children":3360},{},[3361],{"type":22,"value":3362},"⚠️",{"type":16,"tag":205,"props":3364,"children":3365},{},[3366],{"type":22,"value":3367},"C3",{"type":16,"tag":183,"props":3369,"children":3370},{},[3371,3376,3381],{"type":16,"tag":205,"props":3372,"children":3373},{},[3374],{"type":22,"value":3375},"Vocabulaire « conforme FIPS » vs « validé FIPS »",{"type":16,"tag":205,"props":3377,"children":3378},{},[3379],{"type":22,"value":3380},"⚠️ règle de rédaction",{"type":16,"tag":205,"props":3382,"children":3383},{},[3384],{"type":22,"value":3385},"3.5.a",{"type":16,"tag":25,"props":3387,"children":3388},{},[3389,3394],{"type":16,"tag":29,"props":3390,"children":3391},{},[3392],{"type":22,"value":3393},"Conclusion de la section",{"type":22,"value":3395}," : la pile post-quantique est solide, correctement paramétrée, et son architecture (KEM-DEM, hybridation, séparation de domaine, interop prouvée) est au niveau attendu pour une évaluation CSPN. Les quatre points ⚠️ sont tous des décisions de documentation ou des durcissements à coût maîtrisé, pas des vulnérabilités — le plus structurant étant le choix 3.5.c (pré-hachage), à trancher tant que les vecteurs d'interop peuvent encore évoluer.",{"type":16,"tag":159,"props":3397,"children":3398},{},[],{"type":16,"tag":163,"props":3400,"children":3402},{"id":3401},"_4-récapitulatif-des-actions-recommandées",[3403],{"type":22,"value":3404},"4. Récapitulatif des actions recommandées",{"type":16,"tag":175,"props":3406,"children":3407},{},[3408,3434],{"type":16,"tag":179,"props":3409,"children":3410},{},[3411],{"type":16,"tag":183,"props":3412,"children":3413},{},[3414,3419,3424,3429],{"type":16,"tag":187,"props":3415,"children":3416},{},[3417],{"type":22,"value":3418},"#",{"type":16,"tag":187,"props":3420,"children":3421},{},[3422],{"type":22,"value":3423},"Action",{"type":16,"tag":187,"props":3425,"children":3426},{},[3427],{"type":22,"value":3428},"Priorité",{"type":16,"tag":187,"props":3430,"children":3431},{},[3432],{"type":22,"value":3433},"Effort estimé",{"type":16,"tag":198,"props":3435,"children":3436},{},[3437,3471,3492,3525,3547,3587,3616,3638,3668],{"type":16,"tag":183,"props":3438,"children":3439},{},[3440,3445,3461,3466],{"type":16,"tag":205,"props":3441,"children":3442},{},[3443],{"type":22,"value":3444},"C1",{"type":16,"tag":205,"props":3446,"children":3447},{},[3448,3450,3455,3456],{"type":22,"value":3449},"Purge du cluster legacy V1 + retrait ",{"type":16,"tag":51,"props":3451,"children":3453},{"className":3452},[],[3454],{"type":22,"value":781},{"type":22,"value":662},{"type":16,"tag":51,"props":3457,"children":3459},{"className":3458},[],[3460],{"type":22,"value":904},{"type":16,"tag":205,"props":3462,"children":3463},{},[3464],{"type":22,"value":3465},"Haute",{"type":16,"tag":205,"props":3467,"children":3468},{},[3469],{"type":22,"value":3470},"1 sprint court",{"type":16,"tag":183,"props":3472,"children":3473},{},[3474,3478,3483,3487],{"type":16,"tag":205,"props":3475,"children":3476},{},[3477],{"type":22,"value":3349},{"type":16,"tag":205,"props":3479,"children":3480},{},[3481],{"type":22,"value":3482},"Migration Argon2id profil Α-light → Β (natif en place, re-wrap au login)",{"type":16,"tag":205,"props":3484,"children":3485},{},[3486],{"type":22,"value":3465},{"type":16,"tag":205,"props":3488,"children":3489},{},[3490],{"type":22,"value":3491},"0,5–1 jour + décision web",{"type":16,"tag":183,"props":3493,"children":3494},{},[3495,3499,3515,3520],{"type":16,"tag":205,"props":3496,"children":3497},{},[3498],{"type":22,"value":3367},{"type":16,"tag":205,"props":3500,"children":3501},{},[3502,3504,3509,3510],{"type":22,"value":3503},"Hoist ",{"type":16,"tag":51,"props":3505,"children":3507},{"className":3506},[],[3508],{"type":22,"value":1067},{"type":22,"value":1502},{"type":16,"tag":51,"props":3511,"children":3513},{"className":3512},[],[3514],{"type":22,"value":1249},{"type":16,"tag":205,"props":3516,"children":3517},{},[3518],{"type":22,"value":3519},"Haute (relevée)",{"type":16,"tag":205,"props":3521,"children":3522},{},[3523],{"type":22,"value":3524},"Trivial",{"type":16,"tag":183,"props":3526,"children":3527},{},[3528,3532,3537,3542],{"type":16,"tag":205,"props":3529,"children":3530},{},[3531],{"type":22,"value":3331},{"type":16,"tag":205,"props":3533,"children":3534},{},[3535],{"type":22,"value":3536},"Décision pré-hachage (documenter / SHA-512 / HashML-DSA) avant dépôt CSPN",{"type":16,"tag":205,"props":3538,"children":3539},{},[3540],{"type":22,"value":3541},"Haute (décision)",{"type":16,"tag":205,"props":3543,"children":3544},{},[3545],{"type":22,"value":3546},"Décision + éventuel sprint interop",{"type":16,"tag":183,"props":3548,"children":3549},{},[3550,3555,3578,3583],{"type":16,"tag":205,"props":3551,"children":3552},{},[3553],{"type":22,"value":3554},"C2",{"type":16,"tag":205,"props":3556,"children":3557},{},[3558,3560,3565,3567,3572,3573],{"type":22,"value":3559},"Suppression des 4 ",{"type":16,"tag":51,"props":3561,"children":3563},{"className":3562},[],[3564],{"type":22,"value":977},{"type":22,"value":3566}," + ",{"type":16,"tag":51,"props":3568,"children":3570},{"className":3569},[],[3571],{"type":22,"value":1046},{"type":22,"value":1502},{"type":16,"tag":51,"props":3574,"children":3576},{"className":3575},[],[3577],{"type":22,"value":1054},{"type":16,"tag":205,"props":3579,"children":3580},{},[3581],{"type":22,"value":3582},"Moyenne",{"type":16,"tag":205,"props":3584,"children":3585},{},[3586],{"type":22,"value":3524},{"type":16,"tag":183,"props":3588,"children":3589},{},[3590,3595,3607,3611],{"type":16,"tag":205,"props":3591,"children":3592},{},[3593],{"type":22,"value":3594},"C4",{"type":16,"tag":205,"props":3596,"children":3597},{},[3598,3600,3605],{"type":22,"value":3599},"Stage ",{"type":16,"tag":51,"props":3601,"children":3603},{"className":3602},[],[3604],{"type":22,"value":1373},{"type":22,"value":3606}," en CI GitLab + vecteurs interop vendorés ou chemin configurable",{"type":16,"tag":205,"props":3608,"children":3609},{},[3610],{"type":22,"value":3582},{"type":16,"tag":205,"props":3612,"children":3613},{},[3614],{"type":22,"value":3615},"0,5 jour",{"type":16,"tag":183,"props":3617,"children":3618},{},[3619,3624,3629,3633],{"type":16,"tag":205,"props":3620,"children":3621},{},[3622],{"type":22,"value":3623},"3.5.a/d",{"type":16,"tag":205,"props":3625,"children":3626},{},[3627],{"type":22,"value":3628},"Règles de vocabulaire « conforme FIPS 203/204 » / « AEAD état de l'art » dans la doc marketing et la cible de sécurité",{"type":16,"tag":205,"props":3630,"children":3631},{},[3632],{"type":22,"value":3582},{"type":16,"tag":205,"props":3634,"children":3635},{},[3636],{"type":22,"value":3637},"Rédaction",{"type":16,"tag":183,"props":3639,"children":3640},{},[3641,3646,3658,3663],{"type":16,"tag":205,"props":3642,"children":3643},{},[3644],{"type":22,"value":3645},"C5",{"type":16,"tag":205,"props":3647,"children":3648},{},[3649,3651,3656],{"type":22,"value":3650},"Correction des 5 erreurs eslint + passe ",{"type":16,"tag":51,"props":3652,"children":3654},{"className":3653},[],[3655],{"type":22,"value":1567},{"type":22,"value":3657}," sur les warnings",{"type":16,"tag":205,"props":3659,"children":3660},{},[3661],{"type":22,"value":3662},"Basse",{"type":16,"tag":205,"props":3664,"children":3665},{},[3666],{"type":22,"value":3667},"1 h",{"type":16,"tag":183,"props":3669,"children":3670},{},[3671,3676,3689,3693],{"type":16,"tag":205,"props":3672,"children":3673},{},[3674],{"type":22,"value":3675},"C6",{"type":16,"tag":205,"props":3677,"children":3678},{},[3679,3681,3687],{"type":22,"value":3680},"Purge au boot des ",{"type":16,"tag":51,"props":3682,"children":3684},{"className":3683},[],[3685],{"type":22,"value":3686},".tmp",{"type":22,"value":3688}," automations orphelins",{"type":16,"tag":205,"props":3690,"children":3691},{},[3692],{"type":22,"value":3662},{"type":16,"tag":205,"props":3694,"children":3695},{},[3696],{"type":22,"value":3667},{"type":16,"tag":25,"props":3698,"children":3699},{},[3700,3702,3707,3708,3713],{"type":22,"value":3701},"C2, C3 et C5 peuvent être regroupés dans le même commit d'hygiène que C1. Le workflow CSPN (",{"type":16,"tag":51,"props":3703,"children":3705},{"className":3704},[],[3706],{"type":22,"value":125},{"type":22,"value":3566},{"type":16,"tag":51,"props":3709,"children":3711},{"className":3710},[],[3712],{"type":22,"value":132},{"type":22,"value":3714},") devra être repassé après la purge C1 pour confirmer qu'aucune chaîne d'import résiduelle ne casse.",{"type":16,"tag":159,"props":3716,"children":3717},{},[],{"type":16,"tag":163,"props":3719,"children":3721},{"id":3720},"_5-environnement-daudit",[3722],{"type":22,"value":3723},"5. Environnement d'audit",{"type":16,"tag":291,"props":3725,"children":3726},{},[3727,3739,3751,3790,3795],{"type":16,"tag":295,"props":3728,"children":3729},{},[3730,3732,3737],{"type":22,"value":3731},"Node/npm : ",{"type":16,"tag":51,"props":3733,"children":3735},{"className":3734},[],[3736],{"type":22,"value":118},{"type":22,"value":3738}," propre (0 vulnérabilité bloquante remontée à l'install)",{"type":16,"tag":295,"props":3740,"children":3741},{},[3742,3744,3750],{"type":22,"value":3743},"TypeScript ~5.9.2, Vitest ^4.0.17, ESLint ^9.25.0 (config ",{"type":16,"tag":51,"props":3745,"children":3747},{"className":3746},[],[3748],{"type":22,"value":3749},"eslint-config-expo",{"type":22,"value":669},{"type":16,"tag":295,"props":3752,"children":3753},{},[3754,3756,3761,3763,3768,3770,3775,3777,3782,3784,3789],{"type":22,"value":3755},"Bibliothèques crypto effectivement installées : ",{"type":16,"tag":51,"props":3757,"children":3759},{"className":3758},[],[3760],{"type":22,"value":147},{"type":22,"value":3762}," 0.5.4, ",{"type":16,"tag":51,"props":3764,"children":3766},{"className":3765},[],[3767],{"type":22,"value":2055},{"type":22,"value":3769}," 2.1.1, ",{"type":16,"tag":51,"props":3771,"children":3773},{"className":3772},[],[3774],{"type":22,"value":789},{"type":22,"value":3776}," 2.0.1, ",{"type":16,"tag":51,"props":3778,"children":3780},{"className":3779},[],[3781],{"type":22,"value":935},{"type":22,"value":3783}," 1.9.7, ",{"type":16,"tag":51,"props":3785,"children":3787},{"className":3786},[],[3788],{"type":22,"value":2201},{"type":22,"value":2203},{"type":16,"tag":295,"props":3791,"children":3792},{},[3793],{"type":22,"value":3794},"Durée vitest : 24,7 s (888 tests)",{"type":16,"tag":295,"props":3796,"children":3797},{},[3798,3800,3805,3807,3813],{"type":22,"value":3799},"Copie auditée strictement identique au HEAD ",{"type":16,"tag":51,"props":3801,"children":3803},{"className":3802},[],[3804],{"type":22,"value":64},{"type":22,"value":3806}," après restauration des dossiers exclus (vérifié via ",{"type":16,"tag":51,"props":3808,"children":3810},{"className":3809},[],[3811],{"type":22,"value":3812},"git status",{"type":22,"value":3814}," : zéro fichier modifié)",{"title":7,"searchDepth":3816,"depth":3816,"links":3817},2,[3818,3822,3835,3843,3844],{"id":165,"depth":3816,"text":168,"children":3819},[3820],{"id":286,"depth":3821,"text":289},3,{"id":618,"depth":3816,"text":621,"children":3823},[3824,3825,3827,3829,3830,3831,3833,3834],{"id":624,"depth":3821,"text":627},{"id":968,"depth":3821,"text":3826},"C2 — Quatre fichiers .bak versionnés dans git",{"id":1058,"depth":3821,"text":3828},"C3 — Polyfill react-native-get-random-values non hoisté",{"id":1285,"depth":3821,"text":1288},{"id":1432,"depth":3821,"text":1435},{"id":1571,"depth":3821,"text":3832},"C6 — Écriture transitoire en clair dans automationsDrive.saveStringToDrive",{"id":1650,"depth":3821,"text":1653},{"id":1766,"depth":3821,"text":1769},{"id":1881,"depth":3816,"text":1884,"children":3836},[3837,3838,3839,3840,3841,3842],{"id":1906,"depth":3821,"text":1909},{"id":2307,"depth":3821,"text":2310},{"id":2504,"depth":3821,"text":2507},{"id":2668,"depth":3821,"text":2671},{"id":2887,"depth":3821,"text":2890},{"id":3114,"depth":3821,"text":3117},{"id":3401,"depth":3816,"text":3404},{"id":3720,"depth":3816,"text":3723},"markdown","content:transparence:2026-07-21-audit-pq-akarup-mobile.md","content","transparence/2026-07-21-audit-pq-akarup-mobile.md","transparence/2026-07-21-audit-pq-akarup-mobile","md",1784759105685]