Files
MMD e5d6c77c3c feat(data-safety): scheduled DB backups + audit trail + verified actor attribution
- db-backup sidecar: pg_dump -Fc of procurement+casdoor every
  BACKUP_INTERVAL_SECONDS into BACKUP_DIR, retention via BACKUP_KEEP_DAYS
- audit_log table (migration.sql + runtime ensure_audit_table) with
  model + transactional helper (utils/audit.record) — wired into user
  create/role-change and inventory transaction creation
- get_actor: quote_events.actor now stores the VERIFIED user's display
  name instead of the raw bearer token
2026-09-18 22:23:34 +03:30
..

Deploy webhook receiver (push-to-deploy, hardened)

Every push to the production branch triggers a rebuild on the VPS through this receiver (host port 9000). The receiver must verify the Gitea webhook signature — an open deploy endpoint is effectively remote code execution on the production server.

VPS setup (one time)

# 1) Files live here:
sudo mkdir -p /srv/erp && sudo chown $USER /srv/erp
#    copy the repo to /srv/erp (the receiver runs docker compose in this dir)

# 2) Secrets — add to /srv/erp/.env (git-ignored):
#    GITEA_WEBHOOK_SECRET=<long random string>

# 3) Install as a systemd service:
sudo cp infra/deploy-webhook/erp-deploy-webhook.service /etc/systemd/system/
#    adjust User= and paths inside, then:
sudo systemctl daemon-reload
sudo systemctl enable --now erp-deploy-webhook
curl http://127.0.0.1:9000/ping   # → {"status":"ok"}

Gitea webhook

Repo → Settings → Webhooks → Add webhook → Gitea:

  • Target URL: http://<server-ip>:9000/deploy
  • Method: POST — Secret: same value as GITEA_WEBHOOK_SECRET
  • Trigger: Push Events, Branch filter: production

Behavior

  • Verifies X-Gitea-Signature (HMAC-SHA256) — rejects everything else with 401.
  • Only pushes to refs/heads/production deploy; other branches are acknowledged and ignored.
  • Deploys are serialized with a lock (concurrent pushes don't race).
  • Runs docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build in /srv/erp.
  • After a successful build, polls the API /health/ready endpoint and logs a failed post-deploy check (surfaced by the monitoring stack).
  • Logs to journald (journalctl -u erp-deploy-webhook -f).