refactor(js): extract crypto module from app.js monofile (§3.1 start)
First slice of the app.js split. Approach: ordered classic-script files loaded via separate <script> tags (argon2.js → app.crypto.js → app.js), NOT ES modules / a bundler. Classic scripts share one global lexical environment, so consts/functions cross-reference across files exactly as in the monofile — zero call-site rewrites, near-zero risk. Chosen over the audit's esbuild/ES-module suggestion because the code is written entirely in global scope (functions call each other by bare name everywhere). - js/app.crypto.js: KDF (PBKDF2 + Argon2id), verifier, AES-GCM encrypt/ decrypt, key persist/restore. Verified byte-for-byte identical to the original block before removal; no duplicate const across the two scripts. - index.html + BuildAssets whitelist + test harness updated for the load order. Harness CONCATENATES app.crypto.js + app.js (node:vm doesn't share top-level const across separate runInContext calls the way browsers share it across <script> tags); argon2.js stays a separate IIFE. - Runtime-validated: rebuilt exe unlocks via quick-unlock and loads/decrypts entries — the extracted crypto (restoreCryptoKey, verifierFromKeyHex, decryptPwd) works from the separate file. 42/42 tests green. - Docs: CLAUDE.md "Découpage frontend" (pattern + rules), file map, tests README, CODE_AUDIT §3.1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,34 @@ Toute modif `index.html` / `js/` / `css/` nécessite :
|
||||
Sans étape 1, l'exe embarque l'ancienne version des assets — le bug le
|
||||
plus courant après modif frontend.
|
||||
|
||||
### Découpage frontend (§3.1, en cours)
|
||||
|
||||
`app.js` (~12k lignes) est **progressivement scindé** en fichiers classic-script
|
||||
chargés **dans l'ordre** via des `<script>` séparés (PAS de bundler, PAS d'ES
|
||||
modules) : les classic scripts partagent **un seul environnement lexical
|
||||
global** dans le navigateur, donc les `const`/fonctions d'un fichier sont
|
||||
visibles des suivants exactement comme dans le monofichier. Ordre actuel :
|
||||
|
||||
```
|
||||
js/argon2.js (IIFE, globalThis.NobleArgon2)
|
||||
js/app.crypto.js (KDF, verifier, encrypt/decrypt — extrait §3.1)
|
||||
js/app.js (le reste)
|
||||
```
|
||||
|
||||
Règles pour extraire un nouveau module :
|
||||
- Il doit se charger **avant** ses consommateurs et **ne jamais redéclarer**
|
||||
un `const` d'un autre fichier (un `const` dupliqué entre deux classic
|
||||
scripts jette « already declared »).
|
||||
- Les corps de fonction peuvent référencer des globals d'un fichier chargé
|
||||
après (`state` vit dans `app.js`) car résolus au **call-time**, jamais au
|
||||
load-time. Ne pas mettre de code exécuté au top-level qui touche un global
|
||||
pas encore déclaré.
|
||||
- Ajouter le fichier au whitelist `BuildAssets.ps1` **dans l'ordre de chargement**
|
||||
+ au `<script>` d'index.html + à `APP_PARTS` du harness de test.
|
||||
- `node:vm` ne partage PAS les `const` top-level entre `runInContext` séparés
|
||||
(contrairement au navigateur) → le harness **concatène** `APP_PARTS` en un
|
||||
seul script. `argon2.js` reste séparé (IIFE autonome).
|
||||
|
||||
`BuildAssets.ps1` lance `node --check` sur chaque `.js` embarqué **avant**
|
||||
de générer `assets.res` : une erreur de syntaxe JS avorte le build (au
|
||||
lieu d'embarquer un bundle mort qui ne se révèle qu'après un rebuild
|
||||
@@ -33,9 +61,9 @@ Ensuite (même gate, node requis) il lance la **suite de tests frontend**
|
||||
invariant crypto/merge cassé avorte le build comme une erreur de syntaxe.
|
||||
`PM_SKIP_TESTS=1` pour bypasser en itération rapide. Lancer manuellement
|
||||
via `npm test`. Voir [js/tests/README.md](js/tests/README.md) — le harness
|
||||
charge `app.js` (monofichier sans exports) dans un `node:vm` avec les
|
||||
globals navigateur stubbés, puis expose les internals via un épilogue
|
||||
d'export. Couvre : round-trip crypto + dérivation verifier (legacy vs -v2),
|
||||
concatène `APP_PARTS` (`app.crypto.js` + `app.js`) et les charge dans un
|
||||
`node:vm` avec les globals navigateur stubbés (`argon2.js` chargé à part,
|
||||
c'est un IIFE), puis expose les internals via un épilogue d'export. Couvre : round-trip crypto + dérivation verifier (legacy vs -v2),
|
||||
parsing CSV d'import, et l'arbitrage merge/tombstone de sync
|
||||
(`applyRemoteSnapshot`, seule `api()` est stubbée).
|
||||
|
||||
@@ -57,7 +85,9 @@ parsing CSV d'import, et l'arbitrage merge/tombstone de sync
|
||||
| Start with Windows (HKCU Run) | `delphi-backend/Source/PM.AutoStart.pas` |
|
||||
| Favicon proxy (DuckDuckGo, async THTTPClient/WinHTTP) | `delphi-backend/Source/PM.Favicon.pas` |
|
||||
| Handlers REST | `delphi-backend/Handlers/PM.Handler.*.pas` |
|
||||
| Frontend complet | `js/app.js` |
|
||||
| Frontend principal (en cours de découpage §3.1) | `js/app.js` |
|
||||
| Crypto frontend (KDF, verifier, AES-GCM) — extrait §3.1 | `js/app.crypto.js` |
|
||||
| Argon2id vendé (bundle `@noble/hashes`, IIFE) | `js/argon2.js` |
|
||||
| HTML racine | `index.html` |
|
||||
| Styles | `css/style.css` |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user