diff --git a/projects/ProvinceSystem/DEPLOY.md b/projects/ProvinceSystem/DEPLOY.md index 3eef19d..8eb12ef 100644 --- a/projects/ProvinceSystem/DEPLOY.md +++ b/projects/ProvinceSystem/DEPLOY.md @@ -71,7 +71,7 @@ the owner of both checkouts. Deploys to the same site run one at a time. 1. Refuses commits not on `origin/main` (exit 4) and, on www, a checkout with uncommitted changes to tracked files (exit 1). On dev, `git checkout --detach` keeps the expected local edits and refuses if they would be overwritten. -2. Backs up `province.db` with SQLite's backup API inside the backend container as `province.db.before-deploy--`, keeping the newest 10. +2. Backs up `province.db` with SQLite's backup API inside the backend container as `province.db.before-deploy--`, keeping the newest 10. When the compose file has a `db` service, it starts it and writes `postgres.before-deploy--.dump` (`pg_dump --format=custom`), also keeping 10. 3. Rebuilds only what changed: `frontend/`, `shared/` or `docker-compose*` rebuild the frontend; `backend/`, `shared/`, `frontend/lib/skins/` or `docker-compose*` rebuild the backend (`up -d --build --no-deps`). Other changes only move the checkout. @@ -118,6 +118,23 @@ files out of images, so a local `docker-compose.staging.yml` run gets only the s sync to the site go to `backend/src/data/plugin-assets/`, inside the data mount. Both compose files run the backend and frontend with `init: true`; in the backend it reaps the renderer's Chromium processes. +### The site's Postgres + +Each compose project has a `db` service (`pgvector/pgvector:pg17`) holding Precedent and patch notes, in the +volume `provincesystem_db` (www) or `tfmc-staging_db` (Dev). It has no host port; the backend reaches it as `db` +and waits until it is healthy. Each site's password is `POSTGRES_PASSWORD` in its project's `.env` +(`/home/tfmc/ProvinceSystem/.env` or `/home/tfmc/tfmc-staging/.env`, mode 600; hex, as it goes into a URL), and www's +`backend/.env` sets +`DATABASE_URL=postgresql://provincesystem:@db:5432/provincesystem`. Dev's compose file builds `DATABASE_URL` +from the same password, and its override repeats it because its `environment: !override` replaces the list. +Postgres reads `POSTGRES_PASSWORD` only when it creates the volume; to change the password later, run +`ALTER USER provincesystem PASSWORD '…'` in `psql` and update both files. + +```bash +sudo -u tfmc ps-compose main exec db psql -U provincesystem provincesystem # a shell +sudo -u tfmc ps-compose main exec -T db pg_restore -U provincesystem -d provincesystem --clean --if-exists < backup.dump +``` + ## Keys and secrets | Secret | Where | Used by | diff --git a/projects/ProvinceSystem/docs/integrations/precedent.md b/projects/ProvinceSystem/docs/integrations/precedent.md index 54179f5..a7b467d 100644 --- a/projects/ProvinceSystem/docs/integrations/precedent.md +++ b/projects/ProvinceSystem/docs/integrations/precedent.md @@ -9,7 +9,7 @@ similar incidents get similar rulings. Bot never decides punishments — it's ad 1. Staff run `/case-log` after handling an incident (players, rule broken, evidence summary, ruling, punishment) → cog POSTs to ProvinceSystem → ProvinceSystem embeds - the case (Voyage AI) and stores it in Supabase Postgres (`pgvector`). + the case (Voyage AI) and stores it in the site's Postgres (`pgvector`). **Only the summary is embedded** (`_case_text` in `precedent_routes.py`). A search query is always a description of what happened: staff cannot cite the rule number @@ -117,9 +117,10 @@ Implementation: `backend/src/api/precedent_routes.py`, `backend/src/precedent/{d ## Audit trail -Every write to `precedent_cases` appends a row to `precedent_audit` in the same Supabase -database. There is **no API route to read it** — inspecting it requires direct Supabase -access, so staff cannot review or erase their own trail from the website. +Every write to `precedent_cases` appends a row to `precedent_audit` in the same database. +There is **no API route to read it**: inspecting it takes database access (the root-only +[Database studio](../ops/database-studio.md) or `psql` on the host), so staff cannot review or +erase their own trail from the website. | Column | Meaning | |--------|---------| @@ -161,8 +162,9 @@ corpus). Ids that already exist are skipped rather than overwritten, so the scri re-run and safe to use while the corpus is only partly damaged. Restores are themselves audited, as `action='restore'`, `source='script'`. -**This only covers deletions made through the API.** Direct SQL against Supabase bypasses the -audit trail entirely — Supabase's own backups are the recovery path for that. +**This only covers deletions made through the API.** Direct SQL bypasses the audit trail; the +`postgres.before-deploy-*.dump` files that each deploy writes ([DEPLOY.md](../../DEPLOY.md)) are +the recovery path for that. Useful queries: @@ -180,19 +182,19 @@ SELECT before FROM precedent_audit WHERE action = 'delete' AND case_id = ' ## Storage -Supabase Postgres, `pgvector` extension. Two tables: `precedent_cases` (id, logged_by, +The site's Postgres (the `db` service in each site's compose project), `pgvector` +extension. Two tables: `precedent_cases` (id, logged_by, players, summary, rule, ruling, punishment, embedding `vector(1024)`, created_at) and `precedent_audit` (see above). Tables + extension are created lazily on first request (`migrate()` in `precedent/db.py`). -This is separate infrastructure from the existing SQLite skins/drinks DB — ProvinceSystem -had no Postgres/Supabase usage before this feature. +Patch notes share the same database; the rest of the site is still in SQLite (`province.db`). ## Configuration | Env (ProvinceSystem `backend/.env`) | Purpose | |--------------------------------------|---------| -| `SUPABASE_DB_URL` | Postgres connection string (Supabase project) | +| `DATABASE_URL` | The site's Postgres, `postgresql://provincesystem:@db:5432/provincesystem` | | `VOYAGE_API_KEY` | Voyage AI embeddings | | `ANTHROPIC_API_KEY` | Claude synthesis | diff --git a/projects/ProvinceSystem/docs/ops/database-studio.md b/projects/ProvinceSystem/docs/ops/database-studio.md index 4540d43..81a00fe 100644 --- a/projects/ProvinceSystem/docs/ops/database-studio.md +++ b/projects/ProvinceSystem/docs/ops/database-studio.md @@ -15,7 +15,7 @@ Each site lists the databases it can reach: |----|------|--------| | `site` | `province.db`: accounts, characters, wardrobes, chronicle and ledger indexes, the staff audit log | Read and edit | | `coreprotect` | The CoreProtect SQLite file named by `COREPROTECT_DB` (Main on www, Dev on the Dev site) | Read only | -| `supabase` | The Postgres database in `SUPABASE_DB_URL` (Precedent and patch notes), `public` schema; www only | Read and edit | +| `postgres` | The site's Postgres in `DATABASE_URL` (Precedent and patch notes), `public` schema | Read and edit | The list shows each database's tables, size and how many audited queries it has had. Opening one shows its tables with columns and approximate row counts (`max(rowid)` on