Files
minstrel/internal/api
bvandeusen b970b87343
test-go / test (push) Successful in 32s
test-go / integration (push) Has been cancelled
fix(server): drift #578 — /api/me returns profile shape with display_name + email
Server-side fix for the drift audit finding (Scribe #578, parent
#552). Mirrored on Android (and Flutter) but the root cause and
the smallest blast-radius fix both live here.

The bug:
- Android MeApi.getProfile() calls GET /api/me and deserializes
  into MyProfileWire which has nullable display_name + email.
- Server's handleGetMe was emitting the narrower UserView shape
  (id, username, is_admin only).
- Android always saw displayName=null, email=null. The Settings →
  Profile screen rendered BLANK form fields for users with stored
  values.
- Saving from the blank state submitted empty strings to
  PUT /api/me/profile, which interprets empty as "clear to NULL"
  (me_profile.go:53-65) — DESTROYING the user's saved profile.
- Flutter (flutter_client/lib/api/endpoints/settings.dart:9-12)
  has the identical bug pattern.

The fix:
- handleGetMe now emits profileViewFromUser(user) — the same
  shape PUT /api/me/profile already returns (meProfileResp:
  id, username, display_name, email, is_admin).
- auth.UserFromContext already returns a full dbq.User row, so no
  extra DB lookup needed.
- Web's User TypeScript type is narrower than this response but
  doesn't care about the extra fields (TS structural typing).
- LoginResp.User still uses UserView; login response unchanged.

New test asserts the regression directly: a user with stored
display_name + email sees them in /api/me. Old test updated to
decode into meProfileResp and assert the nullable fields are
correctly null for an unset profile.

Android side needs no change — the existing wire shape already
expected display_name + email; this just delivers them.
2026-06-02 18:24:23 -04:00
..