import Foundation /// Account-management calls that aren't part of the core auth flow /// (`AuthAPI`) — password change and the irreversible delete-account flow. enum AccountAPI { struct ChangePasswordBody: Encodable { let currentPassword: String let newPassword: String let remember: Bool } /// `POST /api/auth/change-password`. On success the backend rotates /// EVERY session for the account (including this device's) and issues a /// brand-new one — but that new session is delivered as a cookie on the /// web path only. For a Bearer client the safest move is to log the user /// out locally and have them log back in with the new password, so do /// that here rather than trying to recover a token this endpoint doesn't /// return. static func changePassword(currentPassword: String, newPassword: String) async throws { let request = try APIRequest.json( path: "/api/auth/change-password", method: .post, body: ChangePasswordBody(currentPassword: currentPassword, newPassword: newPassword, remember: true) ) try await APIClient.shared.sendDiscardingResponse(request) } struct DeleteAccountBody: Encodable { let password: String? let confirmEmail: String } /// `DELETE /api/auth/delete-account`. Irreversible. `password` is /// required for accounts that have one (omit only for a Google-only /// account, which has no password to check); `confirmEmail` must equal /// the account's email exactly, case-sensitively, matching the web /// confirmation flow's "type your email to confirm" pattern. static func deleteAccount(password: String?, confirmEmail: String) async throws { let request = try APIRequest.json( path: "/api/auth/delete-account", method: .delete, body: DeleteAccountBody(password: password, confirmEmail: confirmEmail) ) try await APIClient.shared.sendDiscardingResponse(request) } }