refactor(js): extract TOTP module + add RFC 6238 tests (§3.1)

Fourth slice of the app.js split. Moves TOTP (base32Decode, generateTOTP,
parseOtpAuthUri) plus the TOTP-secret and custom-field AES-GCM wrappers to
js/app.totp.js. Loads before app.js (pure declarations), after app.crypto.js
(uses encryptPwd/decryptPwd). Also called by app.import.js and app.sync.js
via shared global scope.

- Byte-for-byte identical extraction; no duplicate const; syntax OK on all
  five app parts.
- NEW: js/tests/totp.test.js — 13 tests including the 5 RFC 6238 Appendix B
  reference vectors (generateTOTP reads Date.now(), so each case stubs the
  sandbox clock to the vector's fixed time), base32 decode edge cases, and
  parseOtpAuthUri. Extraction AND new coverage in one slice.
- Suite: 42 → 55 tests, all green.
- Assets regenerated (manifest now embeds all 6 ordered JS files:
  argon2 → crypto → totp → import → app → sync); also fixes the previous
  import commit's not-yet-rebuilt manifest.
- Delphi build artifacts (*.vrc, *.$manifest) gitignored.

app.js: 11936 → 10138 lines (4 modules extracted, ~1800 lines).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-07-05 16:35:29 +01:00
parent 97a19836a0
commit 5fc07aed7a
12 changed files with 253 additions and 124 deletions
+6 -3
View File
@@ -33,6 +33,7 @@ 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.totp.js (TOTP RFC 6238 + TOTP/custom-field crypto — extrait §3.1)
js/app.import.js (export container + import CSV/JSON — extrait §3.1)
js/app.js (le reste : state, Bridge, api, UI…)
js/app.sync.js (WebDAV + merge — extrait §3.1, APRÈS app.js car
@@ -75,9 +76,10 @@ invariant crypto/merge cassé avorte le build comme une erreur de syntaxe.
via `npm test`. Voir [js/tests/README.md](js/tests/README.md) — le harness
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).
c'est un IIFE), puis expose les internals via un épilogue d'export. Couvre : round-trip crypto + dérivation verifier (legacy vs -v2)
+ Argon2id (vecteur RFC 9106), TOTP (vecteurs RFC 6238), parsing CSV
d'import, et l'arbitrage merge/tombstone de sync (`applyRemoteSnapshot`,
seule `api()` est stubbée).
## Carte des fichiers
@@ -99,6 +101,7 @@ parsing CSV d'import, et l'arbitrage merge/tombstone de sync
| Handlers REST | `delphi-backend/Handlers/PM.Handler.*.pas` |
| 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` |
| TOTP (RFC 6238) + TOTP/custom-field crypto — extrait §3.1 | `js/app.totp.js` |
| Import/export frontend (CSV/JSON parse, export container) — extrait §3.1 | `js/app.import.js` |
| Sync frontend (WebDAV, snapshot, merge) — extrait §3.1 | `js/app.sync.js` |
| Argon2id vendé (bundle `@noble/hashes`, IIFE) | `js/argon2.js` |