Three intertwined fixes for the torn-write that corrupted the prod
data/chat-cache.json mid-session:
- ChatCache.save / persistCooldown now write via temp file + rename.
rename(2) is atomic on the same filesystem, so a crashed or
concurrent writer can never leave NULs in the middle of the file.
A small serialising write queue stops two concurrent saves from
racing to the same temp name.
- ChatCache throws if constructed without a filePath under NODE_ENV=test.
The old default (./data/chat-cache.json) silently routed test
writes into the production cache — exactly how the corruption
happened. Future test that forgets to pass a tmp path fails loudly
instead of stomping data.
- Cooldown / delta-media / username-persist tests now pass an
explicit tmp ChatCache so the new guard is satisfied.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a durable mapping so the UI never has to show raw t2_xxx IDs or
MXIDs just because the in-memory cache is cold after a restart.
ChatService seeds from the table on construction and writes through
every resolution path; cached chats whose username is still t2_xxx
get upgraded from the DB on loadCache.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>