fix(backup): say what the backups console actually does

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.
This commit is contained in:
Marc-André Bombeck committed 2026-09-10 05:26:31 +02:00
1 parent d3f087475c
commit fd176f621d
8 files changed
+12 -10

No files matched your search

+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -6904,7 +6904,7 @@
"backups": {
"title": "백업",
"subtitle": "PostgreSQL에 저장되는 주간 사용자별 데이터 스냅샷이에요.",
"description": "사용자마다 백업 유형별로 최신 스냅샷 하나를 굴려가며 보관해요. 크기는 암호화된 blob 기준이고, 이 페이지에서 내용을 내려받을 수는 없어요.",
"description": "사용자마다 백업 유형별로 최신 스냅샷 하나를 굴려가며 보관해요. 크기는 암호화된 blob 기준이에요. 내려받기는 요청한 관리자에게만 스냅샷을 복호화해 주고, 암호문은 데이터베이스에 그대로 남아요.",
"runNow": "지금 백업",
"runEnqueued": "백업 작업을 큐에 넣었어요",
"runFailed": "백업을 큐에 넣지 못했어요",
+1 -1
View File
@@ -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",
+5 -3
View File
@@ -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/<id>/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.