v1.5.23
Hygiene pass from a full-plugin audit
Atomic JSON writes everywhere. All three JSON stores (user badges, playback completion, audit log) previously wrote via File.WriteAllText directly onto the live file. A process kill or power loss mid-write would truncate or corrupt the JSON, wiping every user's unlocked badges / playback counters.
They now serialize to <file>.tmp first, then File.Move(..., overwrite: true) — which is atomic on NTFS / ext4 / APFS when source and target are on the same volume, which they are because the temp file is a sibling.
StreamReader disposal in SidebarInjectionMiddleware — the reader was constructed without a using block. Now wrapped with leaveOpen: true so the outer MemoryStream using still handles cleanup.
No behaviour changes, no new features — just making the persistence layer safe against crashes.