mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
refactor: keep the size, cast and error-code guards where they were
The fixes above grew six files over 800 lines and three long functions, added casts in tests and one error code the catalogue did not list. The claimable profile check moves into its own module, the guardian count is reused by the revoke path, the lifecycle fallback lives beside the lifecycle rules, the key-needs list is its own component, the coach sweep wraps its filters with ownedByActiveAccount, comments are tightened, and the test fixtures are typed instead of cast. The enumeration guard reads a write keyed by one handed id (id: runId, id: job.data.jobId) as scoped, so those need no marker. account.deletion.no_guardian joins the catalogue; two baselines go down.
This commit is contained in:
1 parent
42940c3a98
commit
d2b8da7839
27 files changed
+302
-279
No files matched your search
@@ -49,8 +49,12 @@ describe("<DatabaseDumpRow>", () => {
|
||||
it("names the newest good dump, where it is, and how long dumps keep deleted accounts", () => {
|
||||
const html = render(HEALTHY);
|
||||
expect(html).toContain("kept on this server and off-host");
|
||||
expect(html).toContain("the newest 7 nightly dumps are kept on this server");
|
||||
expect(html).toContain("before the latest update stays until the next update");
|
||||
expect(html).toContain(
|
||||
"the newest 7 nightly dumps are kept on this server",
|
||||
);
|
||||
expect(html).toContain(
|
||||
"before the latest update stays until the next update",
|
||||
);
|
||||
expect(html).toContain("removed after 30 days");
|
||||
expect(html).not.toContain('data-slot="database-dump-failed"');
|
||||
expect(html).not.toContain('data-slot="database-dump-setup"');
|
||||
|
||||
@@ -279,76 +279,7 @@ export function EncryptionSection() {
|
||||
description={t("admin.section.encryption.backupsDescription")}
|
||||
/>
|
||||
<p className="text-sm">{t("admin.section.encryption.backupsDetail")}</p>
|
||||
<ul className="space-y-1 text-sm" data-slot="encryption-backup-keys">
|
||||
{s.backups.stored.map((row) => (
|
||||
<li key={`stored-${row.keyId}`}>
|
||||
{t("admin.section.encryption.backupsStoredLine", {
|
||||
key: row.keyId,
|
||||
count: row.copies,
|
||||
when: fmt.dateTime(row.oldestAt),
|
||||
})}
|
||||
</li>
|
||||
))}
|
||||
{s.backups.unrecorded.copies > 0 && s.backups.unrecorded.oldestAt ? (
|
||||
<li>
|
||||
{t("admin.section.encryption.backupsUnrecordedLine", {
|
||||
count: s.backups.unrecorded.copies,
|
||||
when: fmt.dateTime(s.backups.unrecorded.oldestAt),
|
||||
})}
|
||||
</li>
|
||||
) : null}
|
||||
{s.backups.offhost.map((row) => (
|
||||
<li key={`offhost-${row.keyId}`}>
|
||||
{row.neededUntil
|
||||
? t("admin.section.encryption.backupsOffhostLine", {
|
||||
key: row.keyId,
|
||||
when: fmt.dateTime(row.lastWrittenAt),
|
||||
until: fmt.dateTime(row.neededUntil),
|
||||
})
|
||||
: t("admin.section.encryption.backupsOffhostLineUnknown", {
|
||||
key: row.keyId,
|
||||
when: fmt.dateTime(row.lastWrittenAt),
|
||||
})}
|
||||
</li>
|
||||
))}
|
||||
{s.backups.dumps.map((row) => (
|
||||
<li key={`dump-${row.keyId}`}>
|
||||
{[
|
||||
row.local > 0
|
||||
? t("admin.section.encryption.backupsDumpLocalLine", {
|
||||
key: row.keyId,
|
||||
count: row.local,
|
||||
})
|
||||
: null,
|
||||
row.offhost
|
||||
? row.offhost.neededUntil
|
||||
? t("admin.section.encryption.backupsDumpOffhostLine", {
|
||||
key: row.keyId,
|
||||
when: fmt.dateTime(row.offhost.lastWrittenAt),
|
||||
until: fmt.dateTime(row.offhost.neededUntil),
|
||||
})
|
||||
: t(
|
||||
"admin.section.encryption.backupsDumpOffhostLineUnknown",
|
||||
{
|
||||
key: row.keyId,
|
||||
when: fmt.dateTime(row.offhost.lastWrittenAt),
|
||||
},
|
||||
)
|
||||
: null,
|
||||
]
|
||||
.filter((line): line is string => line !== null)
|
||||
.join(" ")}
|
||||
</li>
|
||||
))}
|
||||
{s.backups.stored.length === 0 &&
|
||||
s.backups.unrecorded.copies === 0 &&
|
||||
s.backups.offhost.length === 0 &&
|
||||
s.backups.dumps.length === 0 ? (
|
||||
<li className="text-muted-foreground">
|
||||
{t("admin.section.encryption.backupsNone")}
|
||||
</li>
|
||||
) : null}
|
||||
</ul>
|
||||
<BackupKeyNeedsList backups={s.backups} />
|
||||
</SettingsCard>
|
||||
|
||||
{/* ── Rotation status + trigger ──────────────────────────────── */}
|
||||
@@ -565,6 +496,85 @@ export function ColumnCoverage({
|
||||
);
|
||||
}
|
||||
|
||||
/** Per key id, the copies and dumps that still need it. */
|
||||
function BackupKeyNeedsList({
|
||||
backups,
|
||||
}: {
|
||||
backups: EncryptionStatus["backups"];
|
||||
}) {
|
||||
const { t } = useTranslations();
|
||||
const fmt = useFormatters();
|
||||
return (
|
||||
<ul className="space-y-1 text-sm" data-slot="encryption-backup-keys">
|
||||
{backups.stored.map((row) => (
|
||||
<li key={`stored-${row.keyId}`}>
|
||||
{t("admin.section.encryption.backupsStoredLine", {
|
||||
key: row.keyId,
|
||||
count: row.copies,
|
||||
when: fmt.dateTime(row.oldestAt),
|
||||
})}
|
||||
</li>
|
||||
))}
|
||||
{backups.unrecorded.copies > 0 && backups.unrecorded.oldestAt ? (
|
||||
<li>
|
||||
{t("admin.section.encryption.backupsUnrecordedLine", {
|
||||
count: backups.unrecorded.copies,
|
||||
when: fmt.dateTime(backups.unrecorded.oldestAt),
|
||||
})}
|
||||
</li>
|
||||
) : null}
|
||||
{backups.offhost.map((row) => (
|
||||
<li key={`offhost-${row.keyId}`}>
|
||||
{row.neededUntil
|
||||
? t("admin.section.encryption.backupsOffhostLine", {
|
||||
key: row.keyId,
|
||||
when: fmt.dateTime(row.lastWrittenAt),
|
||||
until: fmt.dateTime(row.neededUntil),
|
||||
})
|
||||
: t("admin.section.encryption.backupsOffhostLineUnknown", {
|
||||
key: row.keyId,
|
||||
when: fmt.dateTime(row.lastWrittenAt),
|
||||
})}
|
||||
</li>
|
||||
))}
|
||||
{backups.dumps.map((row) => (
|
||||
<li key={`dump-${row.keyId}`}>
|
||||
{[
|
||||
row.local > 0
|
||||
? t("admin.section.encryption.backupsDumpLocalLine", {
|
||||
key: row.keyId,
|
||||
count: row.local,
|
||||
})
|
||||
: null,
|
||||
row.offhost
|
||||
? row.offhost.neededUntil
|
||||
? t("admin.section.encryption.backupsDumpOffhostLine", {
|
||||
key: row.keyId,
|
||||
when: fmt.dateTime(row.offhost.lastWrittenAt),
|
||||
until: fmt.dateTime(row.offhost.neededUntil),
|
||||
})
|
||||
: t("admin.section.encryption.backupsDumpOffhostLineUnknown", {
|
||||
key: row.keyId,
|
||||
when: fmt.dateTime(row.offhost.lastWrittenAt),
|
||||
})
|
||||
: null,
|
||||
]
|
||||
.filter((line): line is string => line !== null)
|
||||
.join(" ")}
|
||||
</li>
|
||||
))}
|
||||
{backups.stored.length === 0 &&
|
||||
backups.unrecorded.copies === 0 &&
|
||||
backups.offhost.length === 0 &&
|
||||
backups.dumps.length === 0 ? (
|
||||
<li className="text-muted-foreground">
|
||||
{t("admin.section.encryption.backupsNone")}
|
||||
</li>
|
||||
) : null}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
function Stat({ label, value }: { label: string; value: string }) {
|
||||
return <StatTile label={label} value={value} valueClassName="font-mono" />;
|
||||
}
|
||||
Reference in new issue
Block a user