From fd176f621d79180ff43237f337f53296e09329d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 10 Sep 2026 05:26:31 +0200 Subject: [PATCH] fix(backup): say what the backups console actually does MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two places claimed a stored payload cannot leave the page: the card's own description ("payloads are not downloadable from this page") and the listing route's comment ("admins can trigger a re-snapshot but not download another user's payload from the UI"). Both have been false since the download button shipped — every row carries one, and the route hands back the decrypted JSON. The description now says what happens instead: sizes are the encrypted blob, Download decrypts the snapshot for the admin who asks, the ciphertext stays in the database. Seven catalogues, and the route comment points at the route that owns the payload. --- messages/de.json | 2 +- messages/en.json | 2 +- messages/es.json | 2 +- messages/fr.json | 2 +- messages/it.json | 2 +- messages/ko.json | 2 +- messages/pl.json | 2 +- src/app/api/admin/backups/route.ts | 8 +++++--- 8 files changed, 12 insertions(+), 10 deletions(-) diff --git a/messages/de.json b/messages/de.json index 0250283cd..932b71e3a 100644 --- a/messages/de.json +++ b/messages/de.json @@ -6924,7 +6924,7 @@ "backups": { "title": "Backups", "subtitle": "Wöchentliche Daten-Snapshots pro Nutzer in PostgreSQL.", - "description": "Jeder Nutzer hat einen rollierenden Snapshot pro Backup-Typ. Größen zeigen den verschlüsselten Blob — die Inhalte sind hier nicht herunterladbar.", + "description": "Jeder Nutzer hat einen rollierenden Snapshot pro Backup-Typ. Größen zeigen den verschlüsselten Blob. Download entschlüsselt den Snapshot für den anfragenden Admin; der Chiffretext bleibt in der Datenbank.", "runNow": "Jetzt sichern", "runEnqueued": "Backup-Job eingeplant", "runFailed": "Backup konnte nicht eingeplant werden", diff --git a/messages/en.json b/messages/en.json index edc7470b9..aa0603e7c 100644 --- a/messages/en.json +++ b/messages/en.json @@ -6924,7 +6924,7 @@ "backups": { "title": "Backups", "subtitle": "Weekly per-user data snapshots stored in PostgreSQL.", - "description": "Each user gets one rolling snapshot per backup type. Sizes show the encrypted blob — payloads are not downloadable from this page.", + "description": "Each user gets one rolling snapshot per backup type. Sizes show the encrypted blob. Download decrypts the snapshot for the admin who asks; the ciphertext stays in the database.", "runNow": "Backup now", "runEnqueued": "Backup job enqueued", "runFailed": "Failed to enqueue backup", diff --git a/messages/es.json b/messages/es.json index 55614e377..6bbe5d2b2 100644 --- a/messages/es.json +++ b/messages/es.json @@ -6924,7 +6924,7 @@ "backups": { "title": "Copias de seguridad", "subtitle": "Instantáneas de datos semanales por usuario almacenadas en PostgreSQL.", - "description": "Cada usuario tiene una instantánea rotativa por tipo de copia. Los tamaños muestran el blob cifrado; los contenidos no se pueden descargar desde esta página.", + "description": "Cada usuario tiene una instantánea rotativa por tipo de copia. Los tamaños muestran el blob cifrado. Descargar descifra la instantánea para el administrador que la pide; el texto cifrado permanece en la base de datos.", "runNow": "Hacer copia ahora", "runEnqueued": "Tarea de copia de seguridad en cola", "runFailed": "No se pudo poner en cola la copia de seguridad", diff --git a/messages/fr.json b/messages/fr.json index d27bdaa27..acdaa0771 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -6924,7 +6924,7 @@ "backups": { "title": "Sauvegardes", "subtitle": "Instantanés de données hebdomadaires par utilisateur stockés dans PostgreSQL.", - "description": "Chaque utilisateur dispose d'un instantané glissant par type de sauvegarde. Les tailles indiquent le blob chiffré — les contenus ne sont pas téléchargeables depuis cette page.", + "description": "Chaque utilisateur dispose d'un instantané glissant par type de sauvegarde. Les tailles indiquent le blob chiffré. Télécharger déchiffre l'instantané pour l'administrateur qui le demande ; le texte chiffré reste dans la base de données.", "runNow": "Sauvegarder maintenant", "runEnqueued": "Tâche de sauvegarde mise en file d'attente", "runFailed": "Échec de la mise en file d'attente de la sauvegarde", diff --git a/messages/it.json b/messages/it.json index 0c7e55a20..14aaf831d 100644 --- a/messages/it.json +++ b/messages/it.json @@ -6924,7 +6924,7 @@ "backups": { "title": "Backup", "subtitle": "Istantanee settimanali dei dati per utente archiviate in PostgreSQL.", - "description": "Ogni utente ha un'istantanea a rotazione per tipo di backup. Le dimensioni mostrano il blob cifrato: i contenuti non sono scaricabili da questa pagina.", + "description": "Ogni utente ha un'istantanea a rotazione per tipo di backup. Le dimensioni mostrano il blob cifrato. Il download decifra l'istantanea per l'amministratore che la richiede; il testo cifrato resta nel database.", "runNow": "Esegui backup ora", "runEnqueued": "Processo di backup messo in coda", "runFailed": "Impossibile mettere in coda il backup", diff --git a/messages/ko.json b/messages/ko.json index 8e1982dfd..cc187e7cc 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -6904,7 +6904,7 @@ "backups": { "title": "백업", "subtitle": "PostgreSQL에 저장되는 주간 사용자별 데이터 스냅샷이에요.", - "description": "사용자마다 백업 유형별로 최신 스냅샷 하나를 굴려가며 보관해요. 크기는 암호화된 blob 기준이고, 이 페이지에서 내용을 내려받을 수는 없어요.", + "description": "사용자마다 백업 유형별로 최신 스냅샷 하나를 굴려가며 보관해요. 크기는 암호화된 blob 기준이에요. 내려받기는 요청한 관리자에게만 스냅샷을 복호화해 주고, 암호문은 데이터베이스에 그대로 남아요.", "runNow": "지금 백업", "runEnqueued": "백업 작업을 큐에 넣었어요", "runFailed": "백업을 큐에 넣지 못했어요", diff --git a/messages/pl.json b/messages/pl.json index 3ee8e1c1b..ecec02268 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -6924,7 +6924,7 @@ "backups": { "title": "Kopie zapasowe", "subtitle": "Cotygodniowe migawki danych dla każdego użytkownika przechowywane w PostgreSQL.", - "description": "Każdy użytkownik ma jedną przesuwaną migawkę na typ kopii. Rozmiary pokazują zaszyfrowany blob — zawartości nie można pobrać z tej strony.", + "description": "Każdy użytkownik ma jedną przesuwaną migawkę na typ kopii. Rozmiary pokazują zaszyfrowany blob. Pobieranie odszyfrowuje migawkę dla proszącego administratora; szyfrogram zostaje w bazie danych.", "runNow": "Utwórz kopię teraz", "runEnqueued": "Zadanie kopii zapasowej dodano do kolejki", "runFailed": "Nie udało się dodać kopii do kolejki", diff --git a/src/app/api/admin/backups/route.ts b/src/app/api/admin/backups/route.ts index 985e82e22..04a8c2139 100644 --- a/src/app/api/admin/backups/route.ts +++ b/src/app/api/admin/backups/route.ts @@ -2,9 +2,11 @@ * GET /api/admin/backups — admin-only listing of `DataBackup` rows. * * Returns one row per (userId, type) pair. The `data` payload is NOT - * shipped — only metadata (id, userId, username, type, size in bytes, - * createdAt). The encrypted blob remains server-side; admins can trigger - * a re-snapshot but not download another user's payload from the UI. + * shipped by THIS route — only metadata (id, userId, username, type, size in + * bytes, createdAt), so the listing costs a count and not a decrypt. The + * payload has its own route: `/api/admin/backups//download` decrypts one + * snapshot for the admin who asks for it, and the ciphertext stays in the + * database either way. * * Alongside the rows, the response says whether the SCHEDULE is still alive: * how old the newest scheduled copy is and how the last scheduled run ended.