Adding Sign-In to BookNest

The practice API gained the server half in about sixty lines: a discovery document, a login page at /authorize that redirects with a one-time code, POST /token for both grants, and GET /me. Its token endpoint deletes each code on first use and answers invalid_grant unless the base64url SHA-256 of the posted code_verifier equals the saved challenge; a Node script that sent a wrong verifier got exactly that 400. In the app, SessionProvider now offers signIn(tokens) and signOut(), loads the user from GET /me, and calls unlock() first on a cold start with saved tokens; the cart gained Sign out Ana. Tapping Checkout while signed out:

BookNest's sign-in screen, the login page in a Chrome Custom Tab, and the checkout after the redirect
BookNest's sign-in screen, the login page in a Chrome 1 Custom Tab, and the checkout after the redirect
Output of 204
18:55:10 GET /.well-known/openid-configuration 200
18:55:34 GET /authorize 200
18:55:52 POST /authorize 302 -> booknest://redirect
18:55:54 POST /token 200
18:55:57 GET /me 200

The first attempt exposed a trap. Android delivers booknest://redirect?code=... to MainActivity as a deep link, and Expo Router 6,418 , which listens for links too, opened a "No page at /redirect" screen over the (successful) sign-in. Returning null from redirectSystemPath in +native-intent.tsx (Deep Links) for that URL makes the router ignore it. On a fresh emulator, Chrome also showed its first-run screen once, before the login page.