Operations
Backups
Section titled “Backups”Do not forget the three secrets from
Configuration. A database and bucket restored
without QNOP_AUTH_ENCRYPTION_KEY and QNOP_AUTH_ENCRYPTION_SALT will come up,
but everything encrypted at rest — stored OIDC client secrets among them — is
unreadable.
Upgrades
Section titled “Upgrades”- Read the release notes for the version you are moving to.
- Take a backup of both stores.
- Pin the new image version and restart.
Liquibase runs the schema migration on startup. The first boot on a new version therefore takes longer than usual; the health check’s start period accounts for this.
Migrations are forward-only. There is no downgrade path — going back to an older image after a migration means restoring from the backup you took in step two. This is the reason step two is not optional.
Upgrading to 1.3.0
Section titled “Upgrading to 1.3.0”Review e-mail changes cadence. The per-person switch for review mail used to be on or off; it now offers as it happens, daily digest and off, and the migration maps it like this:
- off stays off — nobody who opted out starts receiving mail;
- on, and every account that never touched the setting, becomes the daily digest.
So after the upgrade most people get one summary each morning instead of a mail per event. Mentions still arrive immediately. Anyone who wants the old behaviour picks as it happens in their profile. Tell your users before you upgrade.
Monitoring
Section titled “Monitoring”GET /actuator/health is anonymous; point your load balancer or orchestrator at
it, or at the liveness and readiness groups underneath it.
Everything else on /actuator/** — health details, metrics, the Prometheus
endpoint — requires an authenticated ADMIN. Scraping metrics means giving the
scraper admin credentials, which is a deliberate default: the operational
surface is not public.
Beyond the actuator, Administration → Scheduler shows the maintenance jobs and their last runs, and Administration → Storage consistency reports mismatches between the database and the bucket.
What runs on its own
Section titled “What runs on its own”qnop schedules several maintenance jobs. In a multi-instance deployment they are coordinated so exactly one instance runs each sweep.
| Job | Default schedule | What it does |
|---|---|---|
| Staged-object reaper | 0 30 3 * * * | removes uploads that were staged but never referenced, after a grace period |
| Orphan reaper | 0 15 4 * * * | removes bucket objects nothing points at any more |
| Review archive | 0 50 3 * * * | archives reviews older than the configured window |
| Review purge | 0 55 3 * * * | purges archived reviews after their retention window |
| Notification sweep | 0 15 4 * * * | deletes in-app notifications older than their retention window, read or not |
| Review digest | 0 5 * * * * | sends each recipient on daily mail one summary of their unread notifications, from 08:00 in their own timezone |
The archive, purge and notification retention windows are set in Administration → Settings, not in the environment. The digest runs hourly on purpose: it goes out on the first run at or after 08:00 in each recipient’s own timezone, at most once a day, and a quiet day sends nothing. Both archiving and purging are recorded in the audit trail.
Long-running work triggered by users — text extraction, re-anchoring annotations onto a new version — runs through a durable job queue held in PostgreSQL rather than in memory. A crash or restart mid-extraction resumes rather than losing the work.
The audit trail
Section titled “The audit trail”Every relevant action is appended to the audit trail: annotation lifecycle (created, classified, resolved, reopened, dismissed, auto-closed), placement changes, workflow transitions, review archive/unarchive/purge, due-date changes, extraction outcomes, orphan deletions and scheduler runs.
It is exposed at GET /api/v1/audit/events, filterable, and readable by the
AUDITOR role or an ADMIN — that is the only surface the auditor role
unlocks. Actor identity is deliberately resolved there even where the UI
pseudonymises it elsewhere, because the point of the trail is accountability.