DB backup script and alembic auto-backup hook #6

Merged
claude-code merged 4 commits from feat/5-db-backups into main 2026-04-17 11:57:19 -06:00
2 changed files with 63 additions and 0 deletions
Showing only changes of commit 9ee934629a - Show all commits

46
CLAUDE.md Normal file
View file

@ -0,0 +1,46 @@
# Quartermaster (repo instructions)
## Database safety rule
The SQLite database at `./quartermaster.db` (or whatever path
`QUARTERMASTER_DB_URL` points at) holds real user data. It is
`.gitignored`, so losing it means the data is gone.
**Before any operation that interacts with the database at the schema
or destructive level**, run:
```sh
./scripts/backup-db.sh <reason>
```
That includes:
* `rm`, `mv`, truncate, or otherwise replace `quartermaster.db`
* Ad-hoc `sqlite3` sessions that might `DROP`, `DELETE`, or `UPDATE`
* Any script that does data migration or cleanup outside the running
application
Alembic runs `scripts/backup-db.sh alembic` automatically on every
`alembic upgrade`, `alembic downgrade`, or `alembic revision --autogenerate`
via the hook in `alembic/env.py`, so you do not need to call it
manually for ordinary schema work. The hook is defense in depth, not
a substitute for thinking.
Routine writes through the running web application are NOT covered by
this rule. Those are normal application behaviour, not "interactions"
in the sense meant here.
## Where backups go
Default: `<dir-of-db-file>/backups/quartermaster-YYYYMMDD-HHMMSS-{slug}.db`.
For the standard `./quartermaster.db` that resolves to `./backups/`.
Override with `QUARTERMASTER_BACKUP_DIR=/some/path`.
The `backups/` directory is `.gitignored`. Retention is forever:
backups are small. Prune manually if you need to.
## Restoring
A backup is a complete SQLite file. To restore, stop the app, replace
`quartermaster.db` with the chosen backup (`cp backups/... quartermaster.db`),
then restart.

View file

@ -47,6 +47,23 @@ uv run pytest
Tests run against an in-memory SQLite database; no migration step needed.
## Backups
The SQLite data file is precious and gitignored. Before any schema
change or destructive operation, back it up:
```sh
./scripts/backup-db.sh <reason>
```
Backups land next to the database in `./backups/` by default
(`QUARTERMASTER_BACKUP_DIR=/some/path` to override) as
`quartermaster-YYYYMMDD-HHMMSS-{slug}.db` using SQLite's online backup
API (safe even while the app is writing). Alembic invokes the script
automatically before every migration via `alembic/env.py`; retention
is forever for now. To restore, stop the app, copy the chosen backup
over `quartermaster.db`, and restart.
## Project Layout
```