diff --git a/docs/superpowers/plans/2026-08-07-v2-account-manager-startup.md b/docs/superpowers/plans/2026-08-07-v2-account-manager-startup.md new file mode 100644 index 0000000..8f224a9 --- /dev/null +++ b/docs/superpowers/plans/2026-08-07-v2-account-manager-startup.md @@ -0,0 +1,208 @@ +# 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. diff --git a/docs/superpowers/specs/2026-08-07-v2-account-manager-startup-design.md b/docs/superpowers/specs/2026-08-07-v2-account-manager-startup-design.md new file mode 100644 index 0000000..1b4c156 --- /dev/null +++ b/docs/superpowers/specs/2026-08-07-v2-account-manager-startup-design.md @@ -0,0 +1,25 @@ +# V2.0.1 Account Manager und Startup + +## Ziel + +Multi-Hoster-Upload wird als sichtbare Produktversion `2.0.1` ausgeliefert. Das Hinzufügen und Bearbeiten eines Accounts validiert und speichert in einem Klick. Ein fehlgeschlagener, abgebrochener oder veralteter Check verändert weder die persistierte noch die im Renderer gehaltene Account-Konfiguration. Der intermittierende weiße Startzustand wird durch einen deterministischen Software-Renderer und ein erst nach erfolgreichem Laden sichtbares Hauptfenster verhindert. + +## Account-Flow + +Der Button lautet im Anlegefall `Prüfen und anlegen`, im Bearbeitungsfall `Prüfen und speichern`. Der bestehende Credential-Check bleibt die einzige fachliche Validierung. `ok` und `warn` führen unmittelbar zum Save, `error`, `skipped`, IPC-Fehler und `otp_required` nicht. OTP zeigt das Eingabefeld; der nächste Klick validiert und speichert in einem Lauf. + +Ein einziger Busy-Zustand umfasst Check und Save. Vor dem Save werden Modal-Session, Hoster, Account-ID und Credential-Snapshot erneut abgeglichen. Hoster- oder Credential-Änderung, Schließen oder erneutes Öffnen invalidieren die laufende Operation. Der Kandidat wird auf einer Kopie der Hoster-Konfiguration aufgebaut. Erst nach erfolgreichem `saveConfig` ersetzt er den Renderer-State. Bei Save-Fehler bleibt das Modal offen und der bisherige State unverändert. + +## Startup + +Die App benötigt keine GPU-beschleunigten Canvas-, WebGL- oder Video-Oberflächen. Hardwarebeschleunigung wird deshalb bei jedem Start vor `app.whenReady()` deaktiviert, unabhängig von `SESSIONNAME` und einem späteren GPU-Crash. Das Hauptfenster startet mit `show: false`, wird auf `ready-to-show` eingeblendet und wertet das Promise von `loadFile` aus. Load- und Renderer-Fehler bleiben sichtbar diagnostizierbar. + +## Versions- und Update-Brücke + +`package.json`, UI, Installer-Metadaten und öffentliche GitHub-Version lauten `2.0.1` beziehungsweise `v2.0.1`. Der ausgelieferte 3.3.108-Client vergleicht den privaten Gitea-Tag numerisch und würde einen Tag `v2.0.1` ablehnen. Außerdem existiert dort bereits ein historischer Tag `v2.0.1`. + +Der private Updater-Transport verwendet deshalb für diese Veröffentlichung den neuen internen Tag `v3.3.109`, während Release-Titel und Build `v2.0.1` anzeigen. Der neue Updater liest die Produktversion aus dem Release-Titel und fällt nur bei fehlender Produktversion auf den Tag zurück. Dadurch sieht 3.3.108 den höheren Transport-Tag, während 2.0.1 denselben Release anhand des Titels als bereits installiert erkennt. Künftige 2.x-Releases verwenden fortlaufende interne Transport-Tags oberhalb 3.3.108 und sichtbare 2.x-Titel. + +## Verifikation + +Regressionsfälle prüfen den real verwendeten Account-Submit-Core, die Startup-Konfiguration und die Produkt-/Transport-Versionsauflösung. Danach folgen vollständige Unit-Tests, UI-Smoke, wiederholte reale Starts, Windows-Build, entpackte Artefaktprüfung, Secret-Scans, isolierter Installer-/Updater-Test und erst anschließend die kuratierten privaten und öffentlichen Releases mit erneutem Download und Hashvergleich.