Honesty patch. Hours after v1.22.0 shipped, a careful re-audit found the atomic-write fix had been applied to only 2 of 13 sites. The other 11 are now patched too.
What v1.22.0 missed
Same bug class as v1.22.0 — `open(path, "w")` truncates the target file to 0 bytes immediately, before `json.dump` writes the new content. A kill between truncate and close leaves a partial file. v1.22.0 only fixed the high-symptom cases (`settings.json` + `groups.json` + 4 other dict files). The 11 sites missed:
| File | Affects |
|---|---|
| `container_store._save` | `pinned.json`, `autoupdate.json`, `ask_before_major.json` (list-format files) |
| `maintenance._write` | `maintenance.json` (active-window state) |
| `weekly_report._write_state` | weekly-report last-sent timestamp |
| `update_checker` x3 | history, pending updates, disk-warn state |
| `telegram_bot` x4 | selfupdate history, pending after single update, pending after auto-update batch, deferred-check marker |
| `web_ui` x2 | pending after Web UI single update, pending after Web UI bulk update |
| `main.py` | post-selfupdate history fixup |
For @famewolf's specific symptom (settings + groups gone) the v1.22.0 fix sufficed. But his pinned containers, autoupdate flags, history, or pending updates could have been wiped silently by the same bug class without him noticing.
Refactor
Shared `atomic_write_json(path, data, **dump_kwargs)` helper at module level in `container_store.py`. All 13 write sites now route through it instead of inlining the tmp+fsync+rename pattern. Single point of fix if we ever need to change the strategy.
Smoke-tested
- Helper write+read roundtrip ✓
- Helper cleans up `.tmp` after rename ✓
- Helper forwards `indent=2` kwarg ✓
- Helper overwrites existing file correctly ✓
- Live Docksentry backup-export → backup-import roundtrip ✓
Lesson learned
When fixing a bug class (vs a single bug), grep for the entire pattern across the codebase before declaring the fix complete. The 30-second `grep -rn 'json.dump' app/` would have caught all 11 missed sites yesterday.
Upgrade
```bash
docker pull amayer1983/docksentry:latest
docker compose up -d
```
No env vars or breaking changes.