users: never cache a deleted user's base row

redisstore.userBaseValue has no Deleted/DeletedAt/Status field, so caching a
deleted user silently reset Deleted back to false (and Status to the zero
UserStatusUnknown) on every round trip. That never self-healed: each later
cache miss reloaded the correctly tombstoned DB row and immediately
re-corrupted it on write, so once anyone looked a deleted account up, it kept
showing a blank name with "last seen recently" instead of "Deleted Account".

Keep deleted users off the base cache entirely so lookups always hit the
authoritative store, and stop presence overlay from touching a Deleted user's
Status at all as defense in depth.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Astra 2026-09-13 22:08:06 +01:00
parent f823b2cb74
commit 4ca35d2000
3 changed files with 80 additions and 1 deletions

View file

@ -611,6 +611,13 @@ func (r *Router) withUserPresence(u domain.User) domain.User {
if u.Bot {
return u
}
// 已注销账号同理不参与 presencetgUser/tgSelfUser 对 Deleted 用户直接短路输出
// 精简 tombstone从不读取 Status这里覆盖与否本应无观测差异——但只靠那一层
// 短路里应外合:任何上游把 Deleted 弄丢的 bug例如缓存往返丢字段都会让这里
// 覆盖出的 Status 变成可见的“最近上线”,掩盖真正的 bug 而不是让它更早炸出来。
if u.Deleted {
return u
}
u.Status = r.userPresenceStatusForUser(u)
return u
}