# V2.0.1 Account Manager und Startup Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Einen atomaren Ein-Klick-Account-Flow, einen deterministischen White-Screen-sicheren Start und eine funktionierende Update-Brücke von 3.3.108 auf die sichtbare Version 2.0.1 liefern. **Architecture:** Browserunabhängige Kernlogik kapselt Validate-then-Commit und Release-Versionsauflösung und wird vom bestehenden Renderer beziehungsweise Updater verwendet. Der Electron-Main-Prozess erzwingt Software-Rendering vor Ready und zeigt das Hauptfenster erst nach `ready-to-show`. **Tech Stack:** Electron 41, Node.js 24, `node:test`, electron-builder 26, Gitea Releases, GitHub Releases. ## Global Constraints - Keine Code-Kommentare, XML-Dokumentation, TODOs oder Platzhalter hinzufügen. - Sichtbare Produktversion, UI, Build und öffentlicher GitHub-Tag sind exakt `2.0.1` beziehungsweise `v2.0.1`. - Der private Gitea-Transport-Tag für diese Version ist exakt `v3.3.109`; der Release-Titel ist exakt `Multi-Hoster-Upload v2.0.1`. - Fehlgeschlagene, abgebrochene, veraltete oder OTP-erfordernde Prüfungen persistieren keinen Account. - Release nur aus frischer Positivliste, ohne interne KI-/Task-/Log-/Backup-/Testdaten und nach Quell-, Build-, Archiv- und Secret-Prüfung. --- ### Task 1: Startup-Renderer absichern **Files:** - Create: `lib/startup-renderer.js` - Modify: `main.js` - Create: `tests/startup-renderer.test.js` **Interfaces:** - Produces: `configureStartupRenderer(app)` deaktiviert Hardwarebeschleunigung genau einmal vor Ready. - Produces: `createWindow()` erstellt das Hauptfenster unsichtbar und zeigt es auf `ready-to-show`. - [ ] **Step 1: Failing Tests schreiben** ```js test('configureStartupRenderer disables hardware acceleration', () => { let calls = 0; configureStartupRenderer({ disableHardwareAcceleration() { calls++; } }); assert.equal(calls, 1); }); ``` - [ ] **Step 2: RED verifizieren** Run: `node --test tests/startup-renderer.test.js` Expected: FAIL, weil `lib/startup-renderer.js` noch fehlt. - [ ] **Step 3: Minimale Implementierung schreiben** ```js function configureStartupRenderer(app) { app.disableHardwareAcceleration(); } module.exports = { configureStartupRenderer }; ``` `main.js` ruft die Funktion unmittelbar nach dem Electron-Import auf, entfernt das heuristische RDP-/Flag-Gate, setzt `show: false`, registriert `ready-to-show` vor `loadFile` und behandelt einen abgelehnten Load. - [ ] **Step 4: GREEN und Startup-Smoke verifizieren** Run: `node --test tests/startup-renderer.test.js` Run: `$env:RUN_UI_SMOKE='1'; node tests/ui-smoke.js` - [ ] **Step 5: Commit erstellen** ```powershell git add lib/startup-renderer.js main.js tests/startup-renderer.test.js git commit -m "fix(startup): make renderer initialization deterministic" ``` ### Task 2: Account in einem Lauf prüfen und anlegen **Files:** - Create: `renderer/account-submit.js` - Modify: `renderer/index.html` - Modify: `renderer/app.js` - Replace: `tests/validate-credentials.test.js` **Interfaces:** - Produces: `submitValidatedAccount({ validate, commit, isCurrent })` mit den Resultaten `committed`, `rejected`, `otp_required`, `stale` und `error`. - Consumes: bestehendes `window.api.validateCredentials` und `window.api.saveConfig`. - [ ] **Step 1: Failing Tests für Ein-Klick- und Fehlerpfade schreiben** ```js test('ok validates and commits exactly once in one submission', async () => { let commits = 0; const result = await submitValidatedAccount({ validate: async () => ({ status: 'ok' }), commit: async () => { commits++; }, isCurrent: () => true }); assert.equal(result.status, 'committed'); assert.equal(commits, 1); }); ``` Zusätzliche Tests decken `warn`, `error`, `skipped`, Throw, OTP, stale vor Commit und Save-Fehler ab. - [ ] **Step 2: RED verifizieren** Run: `node --test tests/validate-credentials.test.js` Expected: FAIL, weil `submitValidatedAccount` noch fehlt. - [ ] **Step 3: Submit-Core und Renderer-Integration implementieren** Der Submit-Core validiert, prüft `isCurrent`, committet ausschließlich `ok|warn` und gibt strukturierte Ergebnisse zurück. `saveAccount()` hält Busy bis zum Ende, vergleicht Session und Credential-Snapshot, speichert einen kopierten Kandidaten und übernimmt ihn erst nach erfolgreichem IPC. Der Button bleibt bis zum Schließen deaktiviert. - [ ] **Step 4: GREEN und UI-Vertrag verifizieren** Run: `node --test tests/validate-credentials.test.js` Run: `node --test tests/*.test.js` Run: `$env:RUN_UI_SMOKE='1'; node tests/ui-smoke.js` - [ ] **Step 5: Commit erstellen** ```powershell git add renderer/account-submit.js renderer/index.html renderer/app.js tests/validate-credentials.test.js git commit -m "feat(accounts): validate and save in one action" ``` ### Task 3: Produktversion und Updater-Brücke implementieren **Files:** - Modify: `lib/updater.js` - Modify: `scripts/release_gitea.mjs` - Modify: `package.json` - Modify: `package-lock.json` - Create: `tests/updater-version.test.js` **Interfaces:** - Produces: `resolveReleaseVersion(release)` liest zuerst eine semantische Version aus `release.name`, dann aus `tag_name`. - Produces: Release-CLI `node scripts/release_gitea.mjs 2.0.1 --transport-tag v3.3.109 `. - [ ] **Step 1: Failing Tests für Release-Auflösung und Bridge schreiben** ```js test('bridge title resolves product version instead of transport tag', () => { assert.equal(resolveReleaseVersion({ name: 'Multi-Hoster-Upload v2.0.1', tag_name: 'v3.3.109' }), '2.0.1'); assert.equal(isNewer('2.0.1', '2.0.1'), false); assert.equal(isNewer('2.0.2', '2.0.1'), true); }); ``` - [ ] **Step 2: RED verifizieren** Run: `node --test tests/updater-version.test.js` Expected: FAIL, weil `resolveReleaseVersion` noch fehlt. - [ ] **Step 3: Produkt-/Transport-Trennung implementieren** `checkForUpdate()` verwendet die aufgelöste Produktversion für UI und Vergleich. Der Transport-Tag bleibt im Ergebnis diagnostizierbar. Das Release-Skript validiert `--transport-tag`, baut `2.0.1`, taggt `v3.3.109`, benennt den privaten Release `Multi-Hoster-Upload v2.0.1` und erzeugt `latest.yml` mit `2.0.1`. - [ ] **Step 4: Version auf 2.0.1 setzen und GREEN verifizieren** Run: `npm version 2.0.1 --no-git-tag-version` Run: `node --test tests/updater-version.test.js` Run: `npm test` - [ ] **Step 5: Commit erstellen** ```powershell git add lib/updater.js scripts/release_gitea.mjs package.json package-lock.json tests/updater-version.test.js git commit -m "feat(updater): bridge 3.3.108 clients to v2.0.1" ``` ### Task 4: Build, Laufzeit und Veröffentlichung verifizieren **Files:** - Modify: `tasks/todo.md` **Interfaces:** - Consumes: Tasks 1 bis 3. - Produces: geprüfte private Bridge und kuratierten öffentlichen Release v2.0.1. - [ ] **Step 1: Vollständige lokale Gates ausführen** Run: `npm test` Run: `npx eslint .` Run: `npm audit --omit=dev --json` Run: `npm run release:win` - [ ] **Step 2: Build und Archive prüfen** Portable, Setup, Blockmap und `latest.yml` werden vollständig entpackt, auf Version, Struktur, Hashes, private Endpunkte, Credentials und interne Dateien geprüft. Gitleaks und TruffleHog laufen über Quell-Positivliste und entpackte Artefakte. - [ ] **Step 3: Update-Brücke isoliert testen** Ein unveränderter 3.3.108-Updater muss den privaten Transport-Tag `v3.3.109` als neuer erkennen. Der gebaute 2.0.1-Updater muss denselben Release-Titel als installiert erkennen. Setup und Portable werden separat gestartet; UI, Account-Modal und sauberer Teardown werden geprüft. - [ ] **Step 4: Private und öffentliche Releases veröffentlichen** Der private Gitea-Release nutzt Transport-Tag `v3.3.109` und Titel `Multi-Hoster-Upload v2.0.1`. Der öffentliche GitHub-Release wird aus einem neuen Positivlisten-Ordner als `v2.0.1` mit ausschließlich benötigtem Source und vier Release-Artefakten erstellt. - [ ] **Step 5: Veröffentlichte Downloads erneut verifizieren** Alle öffentlichen und privaten Assets werden neu heruntergeladen, byte- und hashverglichen, `latest.yml` wird gegen das Setup geprüft und der veröffentlichte Build wird erneut gestartet. Erst danach wird `tasks/todo.md` mit den exakten Belegen aktualisiert.