mana-swift-core/devlog/2026-05-13/macher.md
Till JS 957a80251e devlog: 2 Tage geschrieben (v1.0.0 → v1.5.0)
Tag 1: initiale Extraktion aus memoro-native.
Tag 2: Reifung zu v1.5.0 (Account-Lifecycle, Guest-Mode +
Refresh-Resilience, 2FA, ProfileInfo).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 22:21:46 +02:00

4.5 KiB
Raw Blame History

date day view weekday commits review
2026-05-13 2 macher Mittwoch 8 written

Mittwoch, 2026-05-13 — Tag 2 (Macher-Sicht)

Reifung von v1.0.0 zu v1.5.0 in einer Schicht. Sechs Sinn-Abschnitte (Transport-Fix, Account-Lifecycle, Session-Token-Auth, Guest-Mode + Refresh-Resilience, 2FA-Login, 2FA-Enrollment, Profile) plus ein chore-Cleanup. Build-Verzeichnis war versehentlich committet — am Ende des Tages aufgeräumt.

Stats

8 Commits, +5 427 / 2 895 LoC, 408 Files. Achtung: 2 682 der Deletions kamen aus chore: untrack build/ — der eigentliche Code-Delta ist eher +2 700 / 200. Top-Dirs sind irreführend (alle build/-Sub-Dirs), weil der Initial-Push das build/ mit hatte. Tags: transport. Session 15:18 → 01:08, 62 aktive Minuten in 4 Blöcken, längster Fokus 48 Min.

Versions-Schritte

  • Transport-Fix — URL-Konstruktion encoded ?-Query nicht mehr. Klassischer Bug: Path-Encoding lief gegen Query-String, dadurch ?from=… als %3Ffrom%3D… rausgeschickt. 9 / 1 Zeilen.
  • v1.1.0 — Account-Lifecycle. Change-Email, Change-Password, Account-Delete als public API in ManaCore. ViewModels in mana-swift-ui ziehen morgen nach.
  • v1.1.1 — Session-Token statt JWT für Account-Calls. Account-Operationen sind sensibel, brauchen frischen Re-Auth-Token, nicht den allgemeinen JWT.
  • v1.2.0 — Guest-Mode + Refresh-Resilience. Wenn ein Refresh mit transienten Errors fehlschlägt (Netz-Timeout, 503), bleibt die Session aktiv und retried. Wenn der Refresh hart 401 macht, fällt der State auf .guest zurück statt blind alle Tokens zu wipen. Das war der wichtigste Fix — vorher hat mobiles Netz Memoro-User regelmäßig rausgeworfen.
  • v1.3.0 — 2FA-Login-Challenge. Wenn Login requires_2fa: true zurückgibt, dann zweiter Round-Trip mit Code.
  • v1.4.0 — 2FA-Enrollment. Enroll-Init (QR-Secret) + Enroll- Verify + Disable mit Passwort + Backup-Code-Regenerate.
  • v1.5.0 — getProfile() + ProfileInfo. Name, E-Mail, Mitgliedsstatus, Tier. +2 876 LoC — viel davon vendored swift- jose-Updates, die für RS256-JWKS-Verify nötig waren.
  • chore: untrack build/.gitignore für build/, vorhandene Tracked-Files raus.

Architektur-Entscheidungen

  • Session-Token (kurze TTL) für Account-Calls, nicht der allgemeine JWT. Begründung: bei Account-Delete oder Email-Change wäre ein gestohlener JWT katastrophal; frischer Session-Token begrenzt das Schaden-Fenster.
  • Refresh-Resilience: transient vs. permanent. Transiente Errors (Netz, 503, Timeout) halten Session, retry mit Backoff. Permanente Errors (401, invalid_grant) führen zu .guest. Vorher: jede Refresh-Failure → Wipe.
  • Guest-Mode als eigener State, nicht „signed-out". Apps können Inhalt anzeigen, der Read-Only ist, ohne dass sie eine Login-Wand zeigen müssen.
  • 2FA-API additiv, kein Breaking-Change. Apps, die kein 2FA unterstützen, ignorieren requires_2fa-Field.
  • ProfileInfo als eigenes DTO, nicht in AuthClient verbaut. Profile ist datenzentriert, AuthClient ist State-zentriert.
  • swift-jose vendored, statt SPM-Dependency. Public-API- Invariante „keine externen Dependencies" (Compliance-Direktive) bleibt.

Trade-offs

  • +2 876 LoC für v1.5.0 klingt monströs, ist aber zu 80 % vendored swift-jose. Eigentliche Profile-API ist klein.
  • Sechs Tags an einem Tag ist viel — bei strikter Semver wäre das eine Tagesserie, kein Sprint. Akzeptiert, weil jeder Tag einen klar abgegrenzten Sinn-Abschnitt hat.
  • build/-Verzeichnis untracken nachträglich war Aufwand (2 682 deletions in einem Commit). Ursache: SwiftPM-CLI legt build/ im Repo-Root an, statt unter DerivedData — .gitignore hätte Tag 1 schon gehört.
  • Session-Token-Mechanik in v1.1.1 nachgeschoben, weil v1.1.0 das nicht hatte. Hätte v1.1.0 direkt richtig machen sollen; akzeptiert als „erste Lernzyklen".

Offene Punkte

  • Refresh-Resilience Test-Coverage: Unit-Tests für transiente vs. permanente Fehler-Pfade existieren, aber kein Real-World-Test (instabiles Netz simulieren).
  • 2FA-Backup-Codes-Storage: ManaCore liefert sie als Strings zurück; UI muss sie sicher anzeigen + kopierbar machen. Liegt bei mana-swift-ui.
  • getProfile() Cache-Politik: derzeit kein Cache. Bei häufigen Calls hilft eine kurze TTL.
  • Schema-Drift gegen mana-auth: wenn der Server ProfileInfo- Schema ändert, gibt's keinen Wire-Check. Pre-Live-Smoke wäre sinnvoll.