5.2 KiB
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:
./scripts/backup-db.sh <reason>
That includes:
rm,mv, truncate, or otherwise replacequartermaster.db- Ad-hoc
sqlite3sessions that mightDROP,DELETE, orUPDATE - 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.
Current Project State
- Phase: shipped MVP + posting ledger + template-entry edit +
platform-deploy prep (
/healthz, structured JSON logs). Working daily-use tool; first production deploy to home-ctr-onyx pending. - Last worked on: 2026-04-19
- Last commit on main:
1296258— chore: silence jsonlogger deprecation, fix LogQL example (#26, #27) - Open PRs: none
- Open issues: #28 Dockerfile, #29 compose.yml, #30 Forgejo Actions deploy workflow (dependency-chained); #31 small cleanups (non-blocking polish)
- Test count: 148 / 148 passing
- Migrations: 5 applied; latest
cc60e7f73a1c(no schema change in #26 or #27) - Blocking issues: none
After pulling new work, always:
uv run alembic upgrade head
The backup hook fires before any migration, so this is safe against the live DB.
Session Log
Most recent 3 sessions (full history in the wiki).
Session 2 — 2026-04-19
Platform contract intake (#25) filled out and accepted; platform team
provisioned DNS (quartermaster.unbiasedgeek.com), Traefik middlewares
(basic-auth + rate-limit), the /mnt/quartermaster/ bind mount, and
basic-auth creds. Two issues landed on main (#26 /healthz, #27
structured JSON logs) via the superpowers brainstorm → spec → plan →
subagent-driven-TDD workflow. Thirteen commits on a single branch
(feat/platform-deploy-prep), rebased onto origin/main so history
stays linear despite the unrelated MCP-doc PR that landed alongside.
Key decisions: single-source-of-truth logconfig.json (not a Python
dict + YAML shim, which would need pyyaml and introduce drift); five
seed app events (month_created, month_closed,
template_entry_updated, posting_added, posting_deleted) placed
after commit + refresh so they only fire on durable success; /healthz
on a dedicated router as a file boundary, with auth living in Traefik
per the platform contract.
Two real misses caught by code review mid-flight: the autouse-fixture
workaround for Task 3's dictConfig state leak was wrong (fix: make
the contaminating test save/restore state itself); the third LogQL
example in README used {{.path}} on month_closed records that
carry year_month, not path. Both landed as fix commits.
Deploy-pipeline work queued as #28 (Dockerfile), #29 (compose.yml), #30 (Forgejo Actions), dependency-chained. Polish umbrella at #31.
Full retro: Session2.
Session 1 — 2026-04-17
Greenfield to working ledger. 10 PRs merged in one sitting: scaffold (#2) → monthly view with snapshot + deviation (#4) → backups + CLAUDE.md safety rule (#6) → zero amount header (#8) → gitignore wiki (#10) → section groups + sinking funds (#12) → notes field (#14) → month lifecycle Planning / Active / Closed (#16) → UI redesign in Barlow Condensed with logo (#18) → posting transaction ledger (#20).
Key architectural decisions: snapshot-over-mirror for months;
Primary Debt Target is a pointer, not a pre-allocated amount;
nothing auto-sweeps — close requires applied zero at $0; applied
is derived from postings only, no column. UI went through three
mockups before settling on Barlow Condensed + cream paper +
burgundy accent sampled from the logo shield.
One incident: I wiped the live DB several times during early dev churn before the backup script existed. The script + alembic hook
- repo-level CLAUDE.md safety rule are the fix.
Full retro: Session1.