From 532483e7827bb39a01d2b05b6937fde6e62ae8d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 10 Sep 2026 09:28:12 +0200 Subject: [PATCH] fix(admin): say where error reports go, and stop calling a silent target configured MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no default error-reporting DSN in this tree and there should not be: a self-hoster's crash reports must not leave their host because nobody told them not to. That part was already right, so nothing here adds a default. What was wrong is what the console said about it. The GlitchTip card showed a green "Configured" badge as soon as a DSN existed, whether or not the switch that actually sends anything was on, and it never said where reports go. An operator reading that badge has been told their errors are being collected somewhere, which may be true of neither half. The badge now tracks reports actually leaving, and one line under the switch states the case: the host they go to, or that they stay here, or that tracking is on with no target. The host only — the public key in the DSN answers a different question. The deploy runbook says the same thing for a maintainer-operated instance. --- docs/ops/deploy.md | 12 ++++++++ messages/de.json | 3 ++ messages/en.json | 3 ++ messages/es.json | 3 ++ messages/fr.json | 3 ++ messages/it.json | 3 ++ messages/ko.json | 3 ++ messages/pl.json | 3 ++ src/components/admin/glitchtip-section.tsx | 34 ++++++++++++++++++++-- 9 files changed, 65 insertions(+), 2 deletions(-) diff --git a/docs/ops/deploy.md b/docs/ops/deploy.md index 6700f779e..68106fe17 100644 --- a/docs/ops/deploy.md +++ b/docs/ops/deploy.md @@ -143,6 +143,18 @@ itself still works: it walks the journey against an in-process instance once per leg with that leg broken, and fails if any of them comes back green. +## Error reporting + +HealthLog ships no default error-reporting target and never will: an +operator's crash reports must not leave their host because nobody told them +not to. Reporting starts only when someone types a DSN into **Admin → +Integrations → GlitchTip**, and that card states plainly whether reports are +going anywhere and which host they go to. + +For a maintainer-operated instance, set the DSN there after the first deploy — +it lives in the database, not in the environment, so it survives an image +upgrade and does not need a compose change. + ## Verify the image signature Every release image (the multi-arch manifest **index**, covering both diff --git a/messages/de.json b/messages/de.json index 84d2a27b9..d2b1c9cbb 100644 --- a/messages/de.json +++ b/messages/de.json @@ -6597,6 +6597,9 @@ "glitchtipDsnPlaceholder": "https://@glitchtip.example.com/", "glitchtipEnvironment": "GlitchTip Environment", "glitchtipEnvironmentPlaceholder": "production", + "glitchtipTargetOn": "Fehlerberichte gehen an {host}.", + "glitchtipTargetOff": "Fehlerberichte bleiben auf diesem Host. Es wird nichts verschickt.", + "glitchtipTargetNoTarget": "Fehler-Tracking ist an, aber kein Ziel gesetzt, also wird nichts verschickt.", "webPushVapidDescription": "Konfiguriere VAPID-Schlüssel und Subject direkt hier, damit Browser-Push ohne ENV-Variablen funktioniert.", "webPushVapidPublicKey": "VAPID Public Key", "webPushVapidPublicKeyPlaceholder": "BElx... (Base64URL)", diff --git a/messages/en.json b/messages/en.json index dcd603d32..2f4a06eb6 100644 --- a/messages/en.json +++ b/messages/en.json @@ -6597,6 +6597,9 @@ "glitchtipDsnPlaceholder": "https://@glitchtip.example.com/", "glitchtipEnvironment": "GlitchTip environment", "glitchtipEnvironmentPlaceholder": "production", + "glitchtipTargetOn": "Error reports go to {host}.", + "glitchtipTargetOff": "Error reports stay on this host. Nothing is sent anywhere.", + "glitchtipTargetNoTarget": "Error tracking is on, but no target is set, so nothing is sent.", "webPushVapidDescription": "Configure VAPID keys and subject here so browser push works without environment variables.", "webPushVapidPublicKey": "VAPID public key", "webPushVapidPublicKeyPlaceholder": "BElx... (Base64URL)", diff --git a/messages/es.json b/messages/es.json index 0188dd089..28aab6313 100644 --- a/messages/es.json +++ b/messages/es.json @@ -6597,6 +6597,9 @@ "glitchtipDsnPlaceholder": "https://@glitchtip.example.com/", "glitchtipEnvironment": "Entorno de GlitchTip", "glitchtipEnvironmentPlaceholder": "production", + "glitchtipTargetOn": "Los informes de errores van a {host}.", + "glitchtipTargetOff": "Los informes de errores se quedan en este host. No se envía nada.", + "glitchtipTargetNoTarget": "El seguimiento de errores está activado, pero no hay destino, así que no se envía nada.", "webPushVapidDescription": "Configura aquí las claves VAPID y el subject para que el push del navegador funcione sin variables de entorno.", "webPushVapidPublicKey": "Clave pública VAPID", "webPushVapidPublicKeyPlaceholder": "BElx... (Base64URL)", diff --git a/messages/fr.json b/messages/fr.json index 38dc08eb9..2e40628d5 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -6597,6 +6597,9 @@ "glitchtipDsnPlaceholder": "https://@glitchtip.example.com/", "glitchtipEnvironment": "Environnement GlitchTip", "glitchtipEnvironmentPlaceholder": "production", + "glitchtipTargetOn": "Les rapports d'erreur vont vers {host}.", + "glitchtipTargetOff": "Les rapports d'erreur restent sur cet hôte. Rien n'est envoyé.", + "glitchtipTargetNoTarget": "Le suivi des erreurs est activé, mais aucune cible n'est définie, donc rien n'est envoyé.", "webPushVapidDescription": "Configurez ici les clés VAPID et le subject pour que le push du navigateur fonctionne sans variables d'environnement.", "webPushVapidPublicKey": "Clé publique VAPID", "webPushVapidPublicKeyPlaceholder": "BElx... (Base64URL)", diff --git a/messages/it.json b/messages/it.json index 973619366..d883b2f5d 100644 --- a/messages/it.json +++ b/messages/it.json @@ -6597,6 +6597,9 @@ "glitchtipDsnPlaceholder": "https://@glitchtip.example.com/", "glitchtipEnvironment": "Ambiente GlitchTip", "glitchtipEnvironmentPlaceholder": "production", + "glitchtipTargetOn": "Le segnalazioni di errore vanno a {host}.", + "glitchtipTargetOff": "Le segnalazioni di errore restano su questo host. Non viene inviato nulla.", + "glitchtipTargetNoTarget": "Il tracciamento degli errori è attivo, ma non c'è una destinazione, quindi non viene inviato nulla.", "webPushVapidDescription": "Configura qui le chiavi VAPID e il subject affinché il push del browser funzioni senza variabili d'ambiente.", "webPushVapidPublicKey": "Chiave pubblica VAPID", "webPushVapidPublicKeyPlaceholder": "BElx... (Base64URL)", diff --git a/messages/ko.json b/messages/ko.json index 800afd943..549935a1a 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -6577,6 +6577,9 @@ "glitchtipDsnPlaceholder": "https://@glitchtip.example.com/", "glitchtipEnvironment": "GlitchTip 환경", "glitchtipEnvironmentPlaceholder": "production", + "glitchtipTargetOn": "오류 보고서는 {host}(으)로 전송됩니다.", + "glitchtipTargetOff": "오류 보고서는 이 호스트에 남습니다. 아무것도 전송되지 않습니다.", + "glitchtipTargetNoTarget": "오류 추적은 켜져 있지만 대상이 없어 아무것도 전송되지 않습니다.", "webPushVapidDescription": "환경 변수 없이 브라우저 푸시가 동작하도록 VAPID 키와 subject를 여기서 설정하세요.", "webPushVapidPublicKey": "VAPID 공개 키", "webPushVapidPublicKeyPlaceholder": "BElx... (Base64URL)", diff --git a/messages/pl.json b/messages/pl.json index 698a2e2c5..6bd2d6b15 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -6597,6 +6597,9 @@ "glitchtipDsnPlaceholder": "https://@glitchtip.example.com/", "glitchtipEnvironment": "Środowisko GlitchTip", "glitchtipEnvironmentPlaceholder": "production", + "glitchtipTargetOn": "Zgłoszenia błędów trafiają do {host}.", + "glitchtipTargetOff": "Zgłoszenia błędów zostają na tym hoście. Nic nie jest wysyłane.", + "glitchtipTargetNoTarget": "Śledzenie błędów jest włączone, ale nie ustawiono celu, więc nic nie jest wysyłane.", "webPushVapidDescription": "Skonfiguruj tutaj klucze VAPID i subject, aby push przeglądarki działał bez zmiennych środowiskowych.", "webPushVapidPublicKey": "Klucz publiczny VAPID", "webPushVapidPublicKeyPlaceholder": "BElx... (Base64URL)", diff --git a/src/components/admin/glitchtip-section.tsx b/src/components/admin/glitchtip-section.tsx index 746c8059e..1a7bdfc93 100644 --- a/src/components/admin/glitchtip-section.tsx +++ b/src/components/admin/glitchtip-section.tsx @@ -34,7 +34,30 @@ export function GlitchtipSection() { const glitchtipEnvironmentValue = glitchtipEnvironmentDraft ?? settings?.glitchtipEnvironment ?? "production"; - const configured = Boolean(settings?.glitchtipDsn); + /** + * The host the DSN addresses, and nothing else from it. An operator asking + * "where do my errors go" is asking for a hostname; the public key in the + * DSN answers a different question and does not belong in a status line. + * + * There is deliberately no default here and none anywhere else in the tree: + * a self-hoster's crash reports must not leave their host because nobody + * told them not to. Reporting starts when this operator types a target. + */ + const targetHost = ((): string | null => { + const dsn = settings?.glitchtipDsn; + if (!dsn) return null; + try { + return new URL(dsn).host || null; + } catch { + return null; + } + })(); + + // "Configured" has to mean reports are actually going somewhere. A DSN with + // the switch off sends nothing, and a green badge over that is the kind of + // reassurance an operator only discovers was wrong when they go looking for + // a crash that was never reported. + const reporting = Boolean(settings?.glitchtipEnabled && targetHost); const testGlitchtip = useMutation({ mutationFn: async () => { @@ -76,7 +99,7 @@ export function GlitchtipSection() { icon={AlertTriangle} title={t("admin.glitchtipTitle")} description={t("admin.glitchtipDescription")} - status={configured ? : null} + status={reporting ? : null} />
@@ -89,6 +112,13 @@ export function GlitchtipSection() { } disabled={updateSettings.isPending} /> +

+ {reporting && targetHost + ? t("admin.glitchtipTargetOn", { host: targetHost }) + : settings?.glitchtipEnabled + ? t("admin.glitchtipTargetNoTarget") + : t("admin.glitchtipTargetOff")} +