The auth layer — PicaApi, TokenStorage, AuthRepository
Four files in the code column as tabs, in the order they depend on each other: PicaApi.kt → TokenStorage.kt → SecureTokenStorage.kt → AuthRepository.kt.
1. PicaApi.kt (modify) — the lesson-5 interface grows: it gains the register and login endpoints plus the AuthRequest/AuthResponse bodies. The diff shows only the new lines; the menu endpoint stays exactly as it was.
@POST("login")
suspend fun login(@Body request: AuthRequest): AuthResponse
@Serializable data class AuthResponse(val token: String) // ← the contract: server returns a token
2. TokenStorage.kt (create) — the storage contract (how we store a token, decoupled from where). AuthRepository depends on this interface, not on the encrypted class.
3. SecureTokenStorage.kt (create) — the encrypted implementation (DataStore + Google Tink AEAD). The point isn't Tink itself — it's that the token on disk is encrypted, and hasValidToken() checks validity by reading the JWT's exp field. The full file is in the tab; the crypto is boilerplate you can reuse.
4. AuthRepository.kt (create) — short, because the contract does all the work: login()/register() call the server and save the returned token. isLoggedIn() just checks whether the store holds a valid token.
Tip.
AuthResponse(val token: String)is the entire result of "logging in." No passwords, no user object: one token. The less you keep on the phone, the less you can lose.