spb/wp-spboucher-ai
Public
1# Operations runbook23## Where4- Node **M3U96b**, directory `~/apps/wp-spboucher-ai` (git clone, origin spbgit `wp-spboucher-ai.git`). PM2: `wp-web` (Next, :8560) and `wp-worker`.5- Data: `~/data/wp-spboucher-ai` (files/previews/inbox/tmp). Backups: `~/backups/wp-spboucher-ai` (+ rsync `M3U96a:backups/wp-spboucher-ai`).6- Secrets: `~/apps/wp-spboucher-ai/.env` (mode 600); laptop copy `~/Desktop/Cluster/secrets/wp-spboucher-ai/.env`; owner initial password in `owner-initial-password.txt` (must be changed at first login).7- Registry / route: `mld status`, `mld tunnel route wp-spboucher-ai`, manifest `M1M32:~/dispatch/apps/wp-spboucher-ai.json` (copy in `infra/mld/`).89## Everyday10```bash11ssh M3U96b12cd ~/apps/wp-spboucher-ai && pm2 logs wp-web --lines 100 ; pm2 logs wp-worker --lines 10013curl -s localhost:8560/api/health14```15Edit on the node → `pnpm build && pm2 restart wp-web wp-worker` → `git commit && git push` → laptop `git pull`.1617## Publishing a new working paper181. Put the PDF in `~/data/wp-spboucher-ai/inbox/` (or any directory listed in Settings → Ingestion) and click **Scan directories now** in `/admin/ingest` (or `pnpm ingest:scan`).192. Open the candidate: check integrity, duplicates, proposed title/authors/abstract/number/date; **Create draft paper** (or **Attach version** to an existing paper).203. Complete the record in `/admin/papers/<id>` (abstract paragraphs, findings, contributions, methodology, data, reproducibility, artifacts, keywords, JEL, topics, methods, datasets, primary domain).214. **Publish** from the status bar. The worker extracts the full text, builds previews, embeddings and relations. Verify the public page and `/api/v1/papers/<slug>`.2223Revisions: upload a new version on the paper page (kept immutable; previous versions remain downloadable unless withdrawn with a reason).2425## Schedules (worker, node local time)2600:10 daily statistics · 03:00 relations rebuild · 04:40 encrypted backup (pg_dump + manuscripts; 14-day retention; rsync to M3U96a). Manual: `/admin/system` or `pnpm backup`. Restore drill: `pnpm restore:drill`.2728## Restore29```bash30openssl enc -d -aes-256-cbc -pbkdf2 -in ~/backups/wp-spboucher-ai/wp-<stamp>.dump.enc -out /tmp/wp.dump -pass env:BK # BK = BACKUP_PASSPHRASE31createdb wp_spboucher_restored && pg_restore --no-owner -d wp_spboucher_restored /tmp/wp.dump32openssl enc -d -aes-256-cbc -pbkdf2 -in ~/backups/wp-spboucher-ai/wp-files-<stamp>.tar.enc -out /tmp/files.tar -pass env:BK && tar -xf /tmp/files.tar -C ~/data/wp-spboucher-ai33```3435## Rollback36`mld deploy` keeps the previous release; `mld move`/`deploy` roll back automatically on failed health checks. Manual: `git checkout <sha> && pnpm build && pm2 restart wp-web wp-worker` on the node. Migrations are additive; never edit an applied migration (checksums are verified).3738## Security notes39Admin: Argon2id passwords (policy ≥ 14 chars), TOTP, `__Host-` session cookie (HttpOnly/Strict/Secure), rotation every 12 h, idle 7 d / absolute 30 d, CSRF double-submit on every mutation, same-origin enforcement, login limiter (5 failures / 15 min, exponential lockout), audit log of every write. Public API: read-only role, 120 req/min per IP (60 for search/files). Uploads: PDF magic + poppler integrity, 150 MB max, content-addressed.4041## Known limits42- Semantic search/relations depend on the optional OpenAI key; without it the platform falls back to lexical signals (labelled).43- Rate limiting is in-process (single web process).44- No official UQO logo is used (`site.institution.logo_authorized = false` until permission is confirmed).45