users::list page-fetched users then looped calling
self.fetch_roles(cx.app_id, row.id) — one query per user row, with
default limit 50 and max 500 — so the admin "users" page did 51 to 501
round-trips. The same fetch_roles is also called from
verify_session_for_realtime on every authenticated SSE subscribe.
Add AppUserRoleRepo::list_for_users(app_id, &[user_ids]) returning a
HashMap<AppUserId, Vec<String>>; rewrite list to use it. Single query
with `WHERE user_id = ANY($2)`.
Empty-input fast path returns an empty map without touching Postgres.
AUDIT.md anchor: F-P-001.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>