This page documents which notifications Dockrev sends, the payload format (v2 schemas), and how to configure the Instance Public Base URL so Telegram / Email / Web Push / Webhook messages can include clickable links to your Dockrev instance.
Purpose: turn internal paths (e.g. queue/{jobId}) into absolute URLs (e.g. https://dockrev.example.com/queue/job_...).
Settings -> System settings -> Instance Public Base URLGET /api/settings -> instance.publicBaseUrlPUT /api/settings -> instance.publicBaseUrlnull or empty string clears the settinghttp:// or https:// URL/links.*Url will fall back to internal paths (starting with /)| kind | schema | Trigger (high level) |
|---|---|---|
job_finished |
dockrev.notification.job.v2 |
An update job finishes (success / failed / rolled back) and is not filtered out |
new_version_discovered |
dockrev.notification.new_version_discovered.v2 |
Scheduled checks or GHCR-webhook-triggered checks discover new versions (aggregated per check job) |
ghcr_webhook_anomaly |
dockrev.notification.ghcr_webhook_anomaly.v2 |
Scheduled GHCR webhook audit (audit_all) detects missing/conflict/error repos |
notification_test |
dockrev.notification.test.v2 |
POST /api/notifications/test |
Webhook receivers should always route by
schema(the switch todockrev.notification.job.v2is a breaking change).
Path: Settings -> Notifications
Per-event switches:
Update finished notification -> controls job_finishedNew version discovered (scheduled / webhook check) -> controls new_version_discoveredGitHub webhook anomaly (audit) -> controls ghcr_webhook_anomalyBehavior:
dockrev.notification.job.v2)Top-level:
schema: dockrev.notification.job.v2kind: job_finishedsentAt: RFC3339 timestamp (string)channel: telegram / email / webhook / webPushjob: job metadatalinks: URLs inside your Dockrev instance (the important part)human: Chinese title/summary/detail used for renderingdebug: build/version metadatalinks example:
Internal routes:
/queue/{jobId}/services/{stackId}/{serviceId}When instance.publicBaseUrl is configured, Dockrev produces absolute URLs; otherwise it falls back to internal paths.
primaryUrl selection:
primaryUrl = serviceUrlprimaryUrl = jobUrlUniquely mapped means:
service and the job record includes serviceId, ORlinks.serviceUrls is capped at 10 entrieslinks.truncated.serviceUrlsOmitteddockrev.notification.new_version_discovered.v2)Trigger: scheduled update checks and GHCR-webhook-triggered service checks. A notification is sent when a check run discovers new versions. UI-triggered manual checks stay silent.
Dispatch timing, dedupe, and lifecycle:
success before any notification wait starts; only dispatch is delayedsnapshot_worker task_finished event before one final display-tag recompute; the fixed 10 second cap is now only a safety fallback when the event/result does not arrive cleanlytags[] still cannot produce a readable version, notifications also try OCI org.opencontainers.image.version as a display-tag fallback while leaving raw tag fields untouched for compatibilityserviceId + candidateDigestpending / sent records block repeatsimageRef:imageTag changes, the previous active record is marked supersededfailed and later jobs may retryKey fields:
check.jobId: check job idcheck.servicesChecked: total services checkedcheck.newVersions: number of services with newly discovered versionslinks.jobUrl: /queue/{jobId}links.serviceUrls[]: /services/{stackId}/{serviceId}links.serviceUrls[].currentTag / candidateTag: raw tags kept for backward compatibilitylinks.serviceUrls[].currentDisplayTag / candidateDisplayTag: priority is snapshot inference > frozen/live resolved tag > OCI explicit version > raw tag; raw fields remain unchanged for compatibilitylinks.primaryUrl: service URL when exactly one service is affected, otherwise job URLhuman.title: a compact headline for the Email subject / Web Push title; single-service payloads use the service name, while multi-service payloads use an aggregate counthuman.summary: the human-facing copy is tightened without changing the schema versionHuman-readable summary rules:
blog / api has a new version available (1.0.0 -> 1.1.0).blog / api has a new version available (1.0.0 -> latest).blog / api has a new version available. (never latest -> latest)Channel rendering rules:
Service details action; no generic banner title, no trailing Details suffix, no Service list block, and no duplicate link listtitle uses the compact human.title headline, body is exactly human.summary, and the click target still uses links.primaryUrlTruncation:
links.serviceUrls keeps at most 10 entrieslinks.truncated.serviceUrlsOmitteddockrev.notification.ghcr_webhook_anomaly.v2)Trigger: scheduled GHCR webhook audit (audit_all) only. Sent when missing/conflict/error repos are found.
Key fields:
job.id: audit job idjob.missing/conflict/error: anomaly countslinks.settingsUrl: settings page URL for remediationlinks.jobUrl: job detail URL for audit logslinks.primaryUrl: defaults to links.jobUrl (Web Push click target)links.repos[]: failing repo list with state and error excerpthuman.summary: directly lists visible failing repos (example: Found 2 anomalous repos: acme/api [missing], acme/worker [error].)Dockrev: GitHub Webhook audit anomaly 任务.Truncation:
links.repos keeps at most 10 entrieslinks.truncated.reposOmitteddockrev.notification.test.v2)url points to the settings page (/settings) to demonstrate a clickable linktitle / body / urlChinese title with an inline clickable 详情 link + summary + per-service list + optional error excerpt (<pre>...).
Subject includes status (no internal job id). Body is sent as both HTML and plain text.
Raw JSON payload is POSTed. Route by schema:
dockrev.notification.job.v2dockrev.notification.new_version_discovered.v2dockrev.notification.ghcr_webhook_anomaly.v2dockrev.notification.test.v2The payload includes title / body / url. Clicking opens url (service page, job page, or settings page depending on event type).