mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
fix(admin): say what actually ages a stored account copy out
The backups page stated "Retention: 90 days", from a constant whose comment said it matched a backup-prune job. There is no such job: nothing deletes a stored copy by age. The weekly copy is replaced in place, one per account; the copy taken before "Delete all data" is deleted by the account-deletion purge when the grace window ends; an uploaded copy stays until its account is erased. The list now carries preWipeCopyDays (the grace window, 0 when no such copy is taken) instead of retentionDays, and the page says exactly the three facts above, in every language. Also drops a re-export of the JSON import row limit nothing imports.
This commit is contained in:
1 parent
459b5baa9d
commit
694befd635
17 files changed
+62
-37
No files matched your search
+3
-2
@@ -8177,7 +8177,6 @@
|
||||
"colSize": "Größe",
|
||||
"colCreatedAt": "Letzter Snapshot",
|
||||
"colActions": "Aktionen",
|
||||
"retentionLabel": "Aufbewahrung: {days} Tage",
|
||||
"scheduleStaleTitle": "Die wöchentliche Sicherung läuft nicht mehr",
|
||||
"scheduleStaleDescription": "Die neueste geplante Kopie ist {days} Tage alt. Ein funktionierender wöchentlicher Lauf lässt keine älter als {threshold} Tage werden.",
|
||||
"scheduleFailedTitle": "Der letzte geplante Sicherungslauf ist fehlgeschlagen",
|
||||
@@ -8330,7 +8329,9 @@
|
||||
"restoreSkippedVisitCiphertext": "Text zu Arztbesuch oder Praxis mit einem Schlüssel verschlüsselt, den dieser Server nicht hat (ohne ihn behalten)",
|
||||
"restoreSkippedVaccinationCiphertext": "Impf-Notiz mit einem Schlüssel verschlüsselt, den dieser Server nicht hat (Impfung ohne sie behalten)",
|
||||
"restoreSkippedEnvironmentLocationCiphertext": "Ort eines Umweltzeitraums oder -tags mit einem Schlüssel verschlüsselt, den dieser Server nicht hat (verschlüsselt behalten, diese Tage werden nicht neu abgerufen)",
|
||||
"typePreWipe": "Vor dem Löschen aller Daten"
|
||||
"typePreWipe": "Vor dem Löschen aller Daten",
|
||||
"retentionNote": "Die wöchentliche Kopie wird jeden Sonntag ersetzt. Eine Kopie, die vor „Alle Daten löschen“ angelegt wurde, wird nach {days} Tagen gelöscht. Hochgeladene Kopien bleiben, bis ihr Konto gelöscht wird.",
|
||||
"retentionNoteNoGrace": "Die wöchentliche Kopie wird jeden Sonntag ersetzt. Hochgeladene Kopien bleiben, bis ihr Konto gelöscht wird."
|
||||
},
|
||||
"danger-zone": {
|
||||
"title": "Gefahrenzone",
|
||||
|
||||
+3
-2
@@ -8177,7 +8177,6 @@
|
||||
"colSize": "Size",
|
||||
"colCreatedAt": "Last snapshot",
|
||||
"colActions": "Actions",
|
||||
"retentionLabel": "Retention: {days} days",
|
||||
"scheduleStaleTitle": "The weekly backup has stopped",
|
||||
"scheduleStaleDescription": "The newest scheduled copy is {days} days old. A working weekly run never leaves one older than {threshold} days.",
|
||||
"scheduleFailedTitle": "The last scheduled backup run failed",
|
||||
@@ -8330,7 +8329,9 @@
|
||||
"restoreSkippedVisitCiphertext": "Visit or practitioner text sealed with a key this server does not hold (kept without it)",
|
||||
"restoreSkippedVaccinationCiphertext": "Vaccination note sealed with a key this server does not hold (dose kept without it)",
|
||||
"restoreSkippedEnvironmentLocationCiphertext": "Location of an environment period or day sealed with a key this server does not hold (kept sealed, those days are not refreshed)",
|
||||
"typePreWipe": "Before all data was deleted"
|
||||
"typePreWipe": "Before all data was deleted",
|
||||
"retentionNote": "The weekly copy is replaced every Sunday. A copy taken before \"Delete all data\" is deleted after {days} days. Uploaded copies stay until their account is erased.",
|
||||
"retentionNoteNoGrace": "The weekly copy is replaced every Sunday. Uploaded copies stay until their account is erased."
|
||||
},
|
||||
"danger-zone": {
|
||||
"title": "Danger zone",
|
||||
|
||||
+3
-2
@@ -8177,7 +8177,6 @@
|
||||
"colSize": "Tamaño",
|
||||
"colCreatedAt": "Última instantánea",
|
||||
"colActions": "Acciones",
|
||||
"retentionLabel": "Conservación: {days} días",
|
||||
"scheduleStaleTitle": "La copia de seguridad semanal se ha detenido",
|
||||
"scheduleStaleDescription": "La copia programada más reciente tiene {days} días. Una ejecución semanal que funciona nunca deja ninguna con más de {threshold} días.",
|
||||
"scheduleFailedTitle": "La última ejecución programada de la copia de seguridad falló",
|
||||
@@ -8330,7 +8329,9 @@
|
||||
"restoreSkippedVisitCiphertext": "Texto de visita o profesional cifrado con una clave que este servidor no tiene (se conserva sin él)",
|
||||
"restoreSkippedVaccinationCiphertext": "Nota de vacunación cifrada con una clave que este servidor no tiene (la dosis se conserva sin ella)",
|
||||
"restoreSkippedEnvironmentLocationCiphertext": "Ubicación de un periodo o día ambiental cifrada con una clave que este servidor no tiene (se conserva cifrada, esos días no se actualizan)",
|
||||
"typePreWipe": "Antes de eliminar todos los datos"
|
||||
"typePreWipe": "Antes de eliminar todos los datos",
|
||||
"retentionNote": "La copia semanal se reemplaza cada domingo. Una copia tomada antes de «Eliminar todos los datos» se elimina al cabo de {days} días. Las copias subidas se quedan hasta que se borra su cuenta.",
|
||||
"retentionNoteNoGrace": "La copia semanal se reemplaza cada domingo. Las copias subidas se quedan hasta que se borra su cuenta."
|
||||
},
|
||||
"danger-zone": {
|
||||
"title": "Zona de peligro",
|
||||
|
||||
+3
-2
@@ -8177,7 +8177,6 @@
|
||||
"colSize": "Taille",
|
||||
"colCreatedAt": "Dernier instantané",
|
||||
"colActions": "Actions",
|
||||
"retentionLabel": "Conservation : {days} jours",
|
||||
"scheduleStaleTitle": "La sauvegarde hebdomadaire s'est arrêtée",
|
||||
"scheduleStaleDescription": "La copie planifiée la plus récente date de {days} jours. Une exécution hebdomadaire qui fonctionne n'en laisse jamais une dépasser {threshold} jours.",
|
||||
"scheduleFailedTitle": "La dernière exécution planifiée de la sauvegarde a échoué",
|
||||
@@ -8330,7 +8329,9 @@
|
||||
"restoreSkippedVisitCiphertext": "Texte de consultation ou de praticien chiffré avec une clé que ce serveur ne possède pas (conservé sans)",
|
||||
"restoreSkippedVaccinationCiphertext": "Note de vaccination chiffrée avec une clé que ce serveur ne possède pas (dose conservée sans)",
|
||||
"restoreSkippedEnvironmentLocationCiphertext": "Lieu d'une période ou d'un jour environnemental chiffré avec une clé que ce serveur ne possède pas (conservé chiffré, ces jours ne sont pas actualisés)",
|
||||
"typePreWipe": "Avant la suppression de toutes les données"
|
||||
"typePreWipe": "Avant la suppression de toutes les données",
|
||||
"retentionNote": "La copie hebdomadaire est remplacée chaque dimanche. Une copie prise avant « Supprimer toutes les données » est supprimée au bout de {days} jours. Les copies téléversées restent jusqu’à l’effacement de leur compte.",
|
||||
"retentionNoteNoGrace": "La copie hebdomadaire est remplacée chaque dimanche. Les copies téléversées restent jusqu’à l’effacement de leur compte."
|
||||
},
|
||||
"danger-zone": {
|
||||
"title": "Zone de danger",
|
||||
|
||||
+3
-2
@@ -8177,7 +8177,6 @@
|
||||
"colSize": "Dimensione",
|
||||
"colCreatedAt": "Ultima istantanea",
|
||||
"colActions": "Azioni",
|
||||
"retentionLabel": "Conservazione: {days} giorni",
|
||||
"scheduleStaleTitle": "Il backup settimanale si è fermato",
|
||||
"scheduleStaleDescription": "La copia pianificata più recente ha {days} giorni. Un'esecuzione settimanale funzionante non ne lascia mai una più vecchia di {threshold} giorni.",
|
||||
"scheduleFailedTitle": "L'ultima esecuzione pianificata del backup non è riuscita",
|
||||
@@ -8330,7 +8329,9 @@
|
||||
"restoreSkippedVisitCiphertext": "Testo di visita o professionista cifrato con una chiave che questo server non possiede (mantenuto senza)",
|
||||
"restoreSkippedVaccinationCiphertext": "Nota di vaccinazione cifrata con una chiave che questo server non possiede (dose mantenuta senza)",
|
||||
"restoreSkippedEnvironmentLocationCiphertext": "Luogo di un periodo o giorno ambientale cifrato con una chiave che questo server non possiede (mantenuto cifrato, quei giorni non vengono aggiornati)",
|
||||
"typePreWipe": "Prima dell’eliminazione di tutti i dati"
|
||||
"typePreWipe": "Prima dell’eliminazione di tutti i dati",
|
||||
"retentionNote": "La copia settimanale viene sostituita ogni domenica. Una copia presa prima di «Elimina tutti i dati» viene eliminata dopo {days} giorni. Le copie caricate restano finché il loro account non viene cancellato.",
|
||||
"retentionNoteNoGrace": "La copia settimanale viene sostituita ogni domenica. Le copie caricate restano finché il loro account non viene cancellato."
|
||||
},
|
||||
"danger-zone": {
|
||||
"title": "Zona pericolosa",
|
||||
|
||||
+3
-2
@@ -8152,7 +8152,6 @@
|
||||
"colSize": "크기",
|
||||
"colCreatedAt": "최근 스냅샷",
|
||||
"colActions": "동작",
|
||||
"retentionLabel": "보관 기간: {days}일",
|
||||
"scheduleStaleTitle": "주간 백업이 중단되었습니다",
|
||||
"scheduleStaleDescription": "가장 최근의 예약 사본이 {days}일 전 것입니다. 정상적으로 도는 주간 실행은 {threshold}일보다 오래된 사본을 남기지 않습니다.",
|
||||
"scheduleFailedTitle": "마지막 예약 백업 실행이 실패했습니다",
|
||||
@@ -8305,7 +8304,9 @@
|
||||
"restoreSkippedVisitCiphertext": "이 서버에 없는 키로 암호화된 진료 또는 의료진 텍스트(해당 내용 없이 유지됨)",
|
||||
"restoreSkippedVaccinationCiphertext": "이 서버에 없는 키로 암호화된 예방접종 메모(접종 기록은 메모 없이 유지됨)",
|
||||
"restoreSkippedEnvironmentLocationCiphertext": "이 서버에 없는 키로 암호화된 환경 기간 또는 날짜의 위치(암호화된 채 유지되며 해당 날짜는 새로 가져오지 않음)",
|
||||
"typePreWipe": "모든 데이터 삭제 전"
|
||||
"typePreWipe": "모든 데이터 삭제 전",
|
||||
"retentionNote": "주간 사본은 매주 일요일에 교체돼요. \"모든 데이터 삭제\" 전에 만든 사본은 {days}일 뒤에 삭제돼요. 올린 사본은 해당 계정이 지워질 때까지 남아요.",
|
||||
"retentionNoteNoGrace": "주간 사본은 매주 일요일에 교체돼요. 올린 사본은 해당 계정이 지워질 때까지 남아요."
|
||||
},
|
||||
"danger-zone": {
|
||||
"title": "위험 구역",
|
||||
|
||||
+3
-2
@@ -8177,7 +8177,6 @@
|
||||
"colSize": "Grootte",
|
||||
"colCreatedAt": "Laatste snapshot",
|
||||
"colActions": "Acties",
|
||||
"retentionLabel": "Bewaartermijn: {days} dagen",
|
||||
"scheduleStaleTitle": "De wekelijkse back-up is gestopt",
|
||||
"scheduleStaleDescription": "De nieuwste geplande kopie is {days} dagen oud. Een goed werkende wekelijkse run laat nooit een kopie ouder worden dan {threshold} dagen.",
|
||||
"scheduleFailedTitle": "De laatste geplande back-uprun is mislukt",
|
||||
@@ -8330,7 +8329,9 @@
|
||||
"restoreSkippedVisitCiphertext": "Tekst van bezoek of zorgverlener versleuteld met een sleutel die deze server niet heeft (behouden zonder)",
|
||||
"restoreSkippedVaccinationCiphertext": "Vaccinatienotitie versleuteld met een sleutel die deze server niet heeft (dosis behouden zonder)",
|
||||
"restoreSkippedEnvironmentLocationCiphertext": "Locatie van een omgevingsperiode of -dag versleuteld met een sleutel die deze server niet heeft (versleuteld behouden, die dagen worden niet bijgewerkt)",
|
||||
"typePreWipe": "Voor het verwijderen van alle gegevens"
|
||||
"typePreWipe": "Voor het verwijderen van alle gegevens",
|
||||
"retentionNote": "De wekelijkse kopie wordt elke zondag vervangen. Een kopie die vóór 'Alle gegevens verwijderen' is gemaakt, wordt na {days} dagen verwijderd. Geüploade kopieën blijven tot hun account gewist wordt.",
|
||||
"retentionNoteNoGrace": "De wekelijkse kopie wordt elke zondag vervangen. Geüploade kopieën blijven tot hun account gewist wordt."
|
||||
},
|
||||
"danger-zone": {
|
||||
"title": "Gevarenzone",
|
||||
|
||||
+3
-2
@@ -8177,7 +8177,6 @@
|
||||
"colSize": "Rozmiar",
|
||||
"colCreatedAt": "Ostatnia migawka",
|
||||
"colActions": "Akcje",
|
||||
"retentionLabel": "Przechowywanie: {days} dni",
|
||||
"scheduleStaleTitle": "Cotygodniowa kopia zapasowa przestała powstawać",
|
||||
"scheduleStaleDescription": "Najnowsza zaplanowana kopia ma {days} dni. Działające cotygodniowe uruchomienie nigdy nie zostawia kopii starszej niż {threshold} dni.",
|
||||
"scheduleFailedTitle": "Ostatnie zaplanowane uruchomienie kopii zapasowej nie powiodło się",
|
||||
@@ -8330,7 +8329,9 @@
|
||||
"restoreSkippedVisitCiphertext": "Tekst wizyty lub lekarza zaszyfrowany kluczem, którego ten serwer nie ma (zachowany bez niego)",
|
||||
"restoreSkippedVaccinationCiphertext": "Notatka szczepienia zaszyfrowana kluczem, którego ten serwer nie ma (dawka zachowana bez niej)",
|
||||
"restoreSkippedEnvironmentLocationCiphertext": "Lokalizacja okresu lub dnia środowiskowego zaszyfrowana kluczem, którego ten serwer nie ma (zachowana w postaci zaszyfrowanej, te dni nie są odświeżane)",
|
||||
"typePreWipe": "Przed usunięciem wszystkich danych"
|
||||
"typePreWipe": "Przed usunięciem wszystkich danych",
|
||||
"retentionNote": "Cotygodniowa kopia jest zastępowana w każdą niedzielę. Kopia wykonana przed „Usuń wszystkie dane” jest usuwana po {days} dniach. Przesłane kopie zostają, dopóki ich konto nie zostanie usunięte.",
|
||||
"retentionNoteNoGrace": "Cotygodniowa kopia jest zastępowana w każdą niedzielę. Przesłane kopie zostają, dopóki ich konto nie zostanie usunięte."
|
||||
},
|
||||
"danger-zone": {
|
||||
"title": "Strefa zagrożenia",
|
||||
|
||||
+3
-2
@@ -8177,7 +8177,6 @@
|
||||
"colSize": "Tamanho",
|
||||
"colCreatedAt": "Último instantâneo",
|
||||
"colActions": "Ações",
|
||||
"retentionLabel": "Retenção: {days} dias",
|
||||
"scheduleStaleTitle": "O backup semanal parou",
|
||||
"scheduleStaleDescription": "A cópia agendada mais recente tem {days} dias. Uma execução semanal funcional nunca deixa uma com mais de {threshold} dias.",
|
||||
"scheduleFailedTitle": "A última execução agendada de backup falhou",
|
||||
@@ -8330,7 +8329,9 @@
|
||||
"restoreSkippedVisitCiphertext": "Texto de consulta ou profissional selado com uma chave que este servidor não possui (mantido sem ele)",
|
||||
"restoreSkippedVaccinationCiphertext": "Nota de vacinação selada com uma chave que este servidor não possui (dose mantida sem ela)",
|
||||
"restoreSkippedEnvironmentLocationCiphertext": "Local de um período ou dia de ambiente selado com uma chave que este servidor não possui (mantido selado, esses dias não são atualizados)",
|
||||
"typePreWipe": "Antes da exclusão de todos os dados"
|
||||
"typePreWipe": "Antes da exclusão de todos os dados",
|
||||
"retentionNote": "A cópia semanal é substituída todo domingo. Uma cópia feita antes de \"Excluir todos os dados\" é excluída depois de {days} dias. As cópias enviadas ficam até a conta delas ser apagada.",
|
||||
"retentionNoteNoGrace": "A cópia semanal é substituída todo domingo. As cópias enviadas ficam até a conta delas ser apagada."
|
||||
},
|
||||
"danger-zone": {
|
||||
"title": "Zona de perigo",
|
||||
|
||||
@@ -153,6 +153,16 @@ describe("GET /api/admin/backups — off-host freshness", () => {
|
||||
expect(byName.get("account-five")?.lastAttemptAt).toBeNull();
|
||||
});
|
||||
|
||||
it("states what ages a stored copy out, and invents no retention", async () => {
|
||||
configuredMock.mockReturnValue(false);
|
||||
findManyMock.mockResolvedValue([]);
|
||||
vi.stubEnv("ACCOUNT_DELETION_GRACE_DAYS", "21");
|
||||
const body = await read();
|
||||
vi.unstubAllEnvs();
|
||||
expect(body.preWipeCopyDays).toBe(21);
|
||||
expect(body).not.toHaveProperty("retentionDays");
|
||||
});
|
||||
|
||||
it("says so when neither the environment nor the ledger knows of any upload", async () => {
|
||||
configuredMock.mockReturnValue(false);
|
||||
findManyMock.mockResolvedValue([
|
||||
|
||||
@@ -38,6 +38,7 @@ import {
|
||||
import { OFFHOST_BACKUP_QUEUE } from "@/lib/jobs/offhost-backup-queue";
|
||||
import { offhostPurgeDue } from "@/lib/jobs/offhost-purge-queue";
|
||||
import { ACTIVE_ACCOUNT } from "@/lib/account-deletion/active-account";
|
||||
import { accountDeletionGraceDays } from "@/lib/account-deletion/grace";
|
||||
import {
|
||||
classifyOffhostBackup,
|
||||
OFFHOST_BACKUP_PERIOD_HOURS,
|
||||
@@ -213,9 +214,11 @@ export const GET = apiHandler(async () => {
|
||||
|
||||
const payload: BackupsList = {
|
||||
rows: list,
|
||||
// Matches the retention window the backup-prune job enforces so the
|
||||
// backups page states the same number the worker acts on.
|
||||
retentionDays: 90,
|
||||
// What ages these copies out, and nothing more: no job prunes stored
|
||||
// copies by age. The weekly copy is replaced in place, a pre-wipe copy
|
||||
// is deleted by the account-deletion purge when its window ends, and an
|
||||
// uploaded copy stays until its account is erased.
|
||||
preWipeCopyDays: accountDeletionGraceDays(),
|
||||
schedule: summariseBackupSchedule({
|
||||
scheduledCreatedAt: rows
|
||||
.filter((row) => row.type === SCHEDULED_BACKUP_TYPE)
|
||||
|
||||
@@ -49,7 +49,7 @@ vi.mock("@tanstack/react-query", () => ({
|
||||
createdAt: "2026-09-01T03:00:00.000Z",
|
||||
},
|
||||
],
|
||||
retentionDays: 30,
|
||||
preWipeCopyDays: 14,
|
||||
schedule: {
|
||||
lastSuccessAt: "2026-09-01T03:00:00.000Z",
|
||||
lastSuccessAgeDays: 2,
|
||||
|
||||
@@ -19,7 +19,7 @@ const healthySchedule = {
|
||||
const mocks = vi.hoisted(() => ({
|
||||
// Mutable so one file can render both a healthy schedule and a broken one;
|
||||
// the query mock reads it on every render.
|
||||
queryData: { rows: [], retentionDays: 30 } as Record<string, unknown>,
|
||||
queryData: { rows: [], preWipeCopyDays: 14 } as Record<string, unknown>,
|
||||
}));
|
||||
|
||||
/**
|
||||
@@ -80,7 +80,7 @@ primeLocales("de");
|
||||
function render(locale: "en" | "de" = "en") {
|
||||
mocks.queryData = {
|
||||
rows: [],
|
||||
retentionDays: 30,
|
||||
preWipeCopyDays: 14,
|
||||
schedule: healthySchedule,
|
||||
};
|
||||
return renderToStaticMarkup(
|
||||
@@ -159,7 +159,7 @@ describe("BackupsSection — empty state", () => {
|
||||
*/
|
||||
describe("BackupsSection — schedule health", () => {
|
||||
function withSchedule(schedule: Record<string, unknown>) {
|
||||
mocks.queryData = { rows: [], retentionDays: 30, schedule };
|
||||
mocks.queryData = { rows: [], preWipeCopyDays: 14, schedule };
|
||||
return renderToStaticMarkup(
|
||||
<I18nProvider initialLocale="en">
|
||||
<BackupsSection />
|
||||
@@ -203,7 +203,7 @@ describe("BackupsSection — schedule health", () => {
|
||||
});
|
||||
|
||||
it("survives a response that predates the schedule field", () => {
|
||||
mocks.queryData = { rows: [], retentionDays: 30 };
|
||||
mocks.queryData = { rows: [], preWipeCopyDays: 14 };
|
||||
expect(() =>
|
||||
renderToStaticMarkup(
|
||||
<I18nProvider initialLocale="en">
|
||||
|
||||
@@ -36,7 +36,7 @@ function render(data: BackupsList["offhost"] | null): string {
|
||||
? null
|
||||
: ({
|
||||
rows: [],
|
||||
retentionDays: 90,
|
||||
preWipeCopyDays: 14,
|
||||
schedule: null,
|
||||
offhost: data,
|
||||
} as unknown as BackupsList),
|
||||
|
||||
@@ -197,9 +197,11 @@ export function BackupsSection() {
|
||||
<BackupRowsCards rows={rows} {...rowActions} />
|
||||
|
||||
<p className="text-muted-foreground mt-2 text-xs">
|
||||
{t("admin.section.backups.retentionLabel", {
|
||||
days: data!.retentionDays,
|
||||
})}
|
||||
{data!.preWipeCopyDays > 0
|
||||
? t("admin.section.backups.retentionNote", {
|
||||
days: data!.preWipeCopyDays,
|
||||
})
|
||||
: t("admin.section.backups.retentionNoteNoGrace")}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -37,7 +37,7 @@ import { SLEEP_STAGE_NAMES } from "@/lib/validations/sleep-stage-entry";
|
||||
import { fallbackMoodDateStart } from "./mood-instant";
|
||||
|
||||
import { JSON_IMPORT_MAX_ROWS } from "./limits";
|
||||
export { JSON_IMPORT_MAX_BYTES, JSON_IMPORT_MAX_ROWS } from "./limits";
|
||||
export { JSON_IMPORT_MAX_BYTES } from "./limits";
|
||||
|
||||
// The type is the canonical enum, so every type the exporters write comes
|
||||
// back; a hand-kept subset once dropped four of eleven.
|
||||
|
||||
@@ -102,11 +102,12 @@ export interface BackupsList {
|
||||
*/
|
||||
offhost: OffhostBackupOverview;
|
||||
/**
|
||||
* Soft retention hint — the worker is configured for weekly backups
|
||||
* (see `DATA_BACKUP_CRON` in `src/lib/jobs/reminder-worker.ts`), and
|
||||
* the model upserts in-place per (userId, type), so each user has
|
||||
* exactly one current snapshot. The frontend uses this to label the
|
||||
* grid; no server-side enforcement.
|
||||
* How long a copy taken before "Delete all data" is kept: the deletion
|
||||
* grace window, after which the account-deletion purge deletes it. 0 when
|
||||
* there is no window and no such copy is taken. Nothing else ages a stored
|
||||
* copy out: the weekly copy is replaced in place, one per account, and an
|
||||
* uploaded copy stays until its account is erased. The page states exactly
|
||||
* that.
|
||||
*/
|
||||
retentionDays: number;
|
||||
preWipeCopyDays: number;
|
||||
}
|
||||
Reference in new issue
Block a user