mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
Output of `node scripts/strip-planning-tags.mjs --write`: 3,157 comment lines in 1,308 files lose the work-item identifier at their head. Release versions and issue references stay; nothing outside comment text changes, which the script checks per file against a comment-free printout. healthlog/no-planning-tags is enabled at error level with this commit, so the tree it lands on is clean.
113 lines
4.2 KiB
TypeScript
113 lines
4.2 KiB
TypeScript
/**
|
|
* v1.4.41 (org-audit rec #2) — DTOs for `/api/admin/backups`.
|
|
*
|
|
* Pre-v1.4.41 these interfaces lived inside the route handler at
|
|
* `src/app/api/admin/backups/route.ts` and were imported directly from
|
|
* the route module by `src/components/admin/backups-section.tsx`. That
|
|
* was a textbook layer violation (component → route handler) and the
|
|
* only one of its kind in the codebase. Hoisting the shapes here gives
|
|
* both sides a route-handler-independent shared type home; the route
|
|
* keeps owning the HTTP contract, the component keeps owning the UI.
|
|
*/
|
|
import type { BackupPassActivity } from "@/lib/jobs/backup-pass-attempts";
|
|
import type { BackupScheduleStatus } from "@/lib/jobs/backup-schedule-status";
|
|
import type { OffhostBackupFreshness } from "@/lib/jobs/offhost-backup-freshness";
|
|
|
|
export interface BackupRow {
|
|
id: string;
|
|
userId: string;
|
|
username: string;
|
|
type: string;
|
|
/**
|
|
* Size of the encrypted blob in bytes — useful for capacity planning.
|
|
* The blob itself is never returned.
|
|
*/
|
|
sizeBytes: number;
|
|
createdAt: string;
|
|
}
|
|
|
|
/** One account's newest object in the operator's off-host bucket. */
|
|
export interface OffhostAccountRow {
|
|
userId: string;
|
|
username: string;
|
|
/**
|
|
* ISO instant a run last walked this account, or null when none has. Null
|
|
* is what the whole cohort reads until the first run after the upgrade that
|
|
* adds the ledger, and the card says so rather than claiming `never`.
|
|
*/
|
|
lastAttemptAt: string | null;
|
|
/** ISO instant the newest object landed, or null when there is none. */
|
|
lastSuccessAt: string | null;
|
|
/** Size of that object in bytes, or null when there is none. */
|
|
sizeBytes: number | null;
|
|
/** Whole hours since it landed, or null when there is none. */
|
|
ageHours: number | null;
|
|
freshness: OffhostBackupFreshness;
|
|
}
|
|
|
|
/**
|
|
* The off-host picture, per account.
|
|
*
|
|
* Computed from the ledger the nightly worker writes, never from the bucket:
|
|
* the page must be able to answer "does this account have a recent copy
|
|
* off-host" on a host whose worker holds no listing grant on the bucket.
|
|
*/
|
|
export interface OffhostBackupOverview {
|
|
/** Whether this host has the variables the nightly job needs. */
|
|
configured: boolean;
|
|
/** The run in progress, and accounts a run died under. */
|
|
activity: BackupPassActivity;
|
|
/** Hours between two scheduled runs — the number behind the verdicts. */
|
|
periodHours: number;
|
|
/** One row per account. Empty when off-host backup is not configured. */
|
|
rows: OffhostAccountRow[];
|
|
/**
|
|
* Deleted or wiped accounts whose copies are still in the bucket. A count
|
|
* above zero with an error means the bucket refused the deletion (most
|
|
* often a credential without DeleteObject); the job retries nightly.
|
|
*/
|
|
pendingDeletions: {
|
|
count: number;
|
|
oldestRequestedAt: string | null;
|
|
lastFailure: string | null;
|
|
};
|
|
/**
|
|
* Whether the bucket retires old copies by itself. Read from the bucket
|
|
* (`GetBucketLifecycleConfiguration`), cached for ten minutes; `unknown`
|
|
* when the credential may not read it.
|
|
*/
|
|
lifecycle: {
|
|
state: "configured" | "missing" | "unknown";
|
|
expirationDays: number | null;
|
|
};
|
|
}
|
|
|
|
export interface BackupsList {
|
|
rows: BackupRow[];
|
|
/**
|
|
* Whether the weekly schedule is still producing copies, and how the last
|
|
* scheduled run ended. A row's own timestamp cannot answer that — a copy
|
|
* made six weeks ago and one made on Sunday look identical in a table.
|
|
*/
|
|
schedule: BackupScheduleStatus;
|
|
/**
|
|
* The weekly run in progress, and accounts a run died under: a start
|
|
* without a finish, which a crash leaves and a caught failure does not.
|
|
*/
|
|
scheduleActivity: BackupPassActivity;
|
|
/**
|
|
* The off-host leg. A weekly row in this table says the copy that lives in
|
|
* this database is current; it says nothing about whether anything reached
|
|
* the operator's bucket, and those two fail independently.
|
|
*/
|
|
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.
|
|
*/
|
|
retentionDays: number;
|
|
}
|