mana-swift-core/CHANGELOG.md
Till JS 3459c78731 v1.1.1 — Session-Token statt JWT für Account-Calls
Wire-Konvention für authenticated Account-Endpoints (changeEmail,
changePassword, deleteAccount) geklärt. Server-seitig wurde in
mana-auth Better Auths bearer-Plugin aktiviert (requireSignature:
false), das Session-Tokens zu Session-Cookies konvertiert. Native-
Apps senden daher jetzt den Session-Token (refreshToken-Feldwert)
statt des JWT als Authorization: Bearer für diese drei Endpoints.

Der JWT bleibt für app-eigene Backends (memoro-api, cardecky-api,
manaspur-api) der richtige Authorization-Header — die Trennung ist
nur für mana-auth interne Endpoints.

currentSessionToken() als public Helper hinzu (symmetrisch zu
currentAccessToken).

38/38 Tests grün.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 19:35:57 +02:00

6 KiB
Raw Blame History

Changelog

Alle Änderungen werden hier dokumentiert. Format orientiert an Keep a Changelog, Versionierung nach Semver.

[1.1.1] — 2026-05-13

Patch — Wire-Konvention für authenticated Account-Calls geklärt.

Geändert

  • AuthClient.changeEmail, changePassword, deleteAccount senden jetzt den Session-Token (refreshToken-Feldwert) statt des JWT als Authorization: Bearer. Hintergrund: Server-seitig wurde in mana-auth Better Auths bearer-Plugin aktiviert (requireSignature: false), das Session-Tokens zu Session-Cookies konvertiert. Damit funktionieren auth.api.changeEmail etc. für Native-Apps ohne Cookie-Container.
  • AuthClient.currentSessionToken() als public Helper hinzu. Symmetrisch zu currentAccessToken().

Trade-Off bewusst akzeptiert

Session-Token wird bei jedem Account-Call versendet (vorher nur beim /refresh). Mit TLS-Baseline akzeptables Risiko; Compromise-Surface nicht relevant größer als JWT-Leak. Alternative wäre ein Custom- Bearer-JWT-to-Cookie-Resolver im Server (40+ Zeilen Hono-Middleware, HMAC-Cookie-Synthese) — bewusst nicht gewählt, weil der bearer-Plugin genau für diesen Use-Case existiert.

Tests

  • Test changePassword schickt Bearer-Header umbenannt auf schickt Session-Token als Bearer (nicht JWT) und geupdated.

[1.1.0] — 2026-05-13

Phase 1 aus dem Native-Auth-Vollausbau-Plan (Option A — alles nativ, siehe mana/docs/MANA_SWIFT.md). Erweitert ManaCore um die Account-Lifecycle-Methoden, die jede native Verein-App für eine vollständige Auth-Reise braucht.

ManaCore — Neue API (additiv, keine Breaking Changes)

  • AuthClient.register(email:password:name:sourceAppUrl:) — Sign-Up gegen POST /api/v1/auth/register. Persistiert eine Session automatisch, wenn der Server Tokens mitliefert; sonst still und wartend auf Email-Verifikation.
  • AuthClient.forgotPassword(email:resetUniversalLink:) — Passwort- Reset-Mail anfordern gegen POST /api/v1/auth/forgot-password. Server antwortet immer 200 (keine User-Enumeration).
  • AuthClient.resetPassword(token:newPassword:) — Passwort mit Token aus Reset-Mail setzen.
  • AuthClient.resendVerification(email:sourceAppUrl:) — Verify-Mail erneut versenden, aufzurufen nach AuthError/emailNotVerified.
  • AuthClient.changeEmail(newEmail:callbackUniversalLink:) — Email ändern (verschickt Verify-Mail an neue Adresse). Aktuell server- seitig nicht Bearer-fähig — siehe Doc-Header von AuthClient+Account.swift.
  • AuthClient.changePassword(currentPassword:newPassword:) — Passwort ändern. Gleiche Bearer-Einschränkung wie changeEmail.
  • AuthClient.deleteAccount(password:) — Account löschen (App-Store-Guideline 5.1.1(v) Pflicht). Wiped Keychain bei Erfolg. Gleiche Bearer-Einschränkung wie oben.

ManaCore — AuthError ausgebaut

  • Präzise Cases pro Server-AuthErrorCode: .emailNotVerified, .emailAlreadyRegistered, .weakPassword(message:), .accountLocked(retryAfter:), .signupLimitReached, .rateLimited(retryAfter:), .tokenExpired, .tokenInvalid, .twoFactorRequired, .twoFactorFailed, .passkeyNotEnabled, .passkeyCancelled, .passkeyVerificationFailed, .validation(message:), .unauthorized, .notFound, .serviceUnavailable, .serverInternal.
  • AuthError.classify(status:data:retryAfterHeader:) — public, klassifiziert mana-auth-Fehler-Antworten in den passenden Case. Auch genutzt von signIn und refreshAccessToken (vorher: einfache .error(String)-Strings).
  • AuthError ist jetzt Equatable — erleichtert UI-Logik und Tests.
  • Alte Cases .invalidCredentials, .networkFailure, .encoding, .keychain, .decoding, .notSignedIn bleiben unverändert.
  • Breaking-Vermeidung: serverError(status:message:) wurde zu serverError(status:code:message:) (zusätzliches code-Argument). Theoretisch breaking, praktisch nutzt es niemand außerhalb von ManaCore selbst. Wenn ein App-Konsument darauf gepattern-matched hat, ist das ein Compile-Fehler, kein Runtime-Bug.

Tests

  • 14 neue Tests für AuthError.classify (jeder ErrorCode + Status- Heuristik + Retry-After-Header + kaputter Body).
  • 12 neue Tests für die neuen AuthClient-Methoden via URLProtocol-Mock (Wire-Format, Status-Mapping, Bearer-Header, Session-Persistenz bei register, Session-Wipe bei deleteAccount).

Bekannte Einschränkungen

  • changeEmail, changePassword, deleteAccount brauchen Server- seitig den bearer-Plugin von Better Auth oder einen Custom- Bearer-Resolver. Heute mountet mana-auth nur den Cookie-Pfad. Phase-3-Server-PR im mana-Repo dokumentiert.
  • 2FA-Verify, Magic-Link und Passkey-Flows sind in dieser Version bewusst NICHT enthalten. Laufen Server-seitig über Better-Auth- Native (/api/auth/*, Cookie) und brauchen eigene JWT-Pfade. Folgt in v1.2.0 zusammen mit dem Server-PR.

[1.0.1] — 2026-05-13

Behoben

  • AuthenticatedTransport: URL.appending(path:) URL-encoded das ? in Query-Strings zu %3F, was den Server-Route-Match brechen ließ (404 für /healthz?…). Ersetzt durch String-Concat; Caller liefert den Path inkl. führendem / und optionaler Query.

[1.0.0] — 2026-05-12

Initiale Extraktion aus memoro-native (Phase α aus mana/docs/MANA_SWIFT.md).

ManaCore (neu)

  • ManaAppConfig-Protocol für App-injizierbare Konfiguration (authBaseURL, keychainService, keychainAccessGroup).
  • AuthClient — mana-auth-Login per E-Mail+PW, Status-Maschine, Token-Speicherung im Keychain, proaktiver Refresh.
  • JWT — Token-Expiry-Berechnung (lokaler Parse, keine Signatur-Verifikation).
  • KeychainStore — generisches Token-Storage, konfigurierbarer Service-Identifier + Access-Group.
  • AuthError — sprechende Fehlertypen mit LocalizedError-Texten.
  • AuthenticatedTransport — URLSession-Wrapper mit Auth-Header und automatischem 401-Retry-mit-Refresh.

ManaTokens (neu)

  • Farben, Spacings, Typography, Radius — gespiegelt aus mana/docs/THEMING.md.