backups: show that a check happened, not just that a change did
Some checks failed
CI / backend (push) Failing after 7s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 9s
CI / migrations-mysql (push) Failing after 7s

lastseenat already recorded it and the API already returned it; nothing
displayed it, so from the UI a healthy machine still looked abandoned - one
revision from last spring and no sign anything had looked at it since.

The history page gains a Last verified column beside Captured, and the asset
panel a Verified field. Only the CURRENT revision carries one: an older
revision was superseded, so saying it was verified today would be false - what
was verified is the configuration the PC holds now.

A current revision with no check yet says "not yet checked" rather than showing
a blank or borrowing the captured date. That state is real and temporary: the
column is new, so every chain reports it until its PC next posts.
This commit is contained in:
cproudlock
2026-08-11 15:00:25 -04:00
parent e0e4cce8bd
commit 294ddbb38e
4 changed files with 51 additions and 0 deletions

View File

@@ -20,6 +20,7 @@
<thead>
<tr>
<th>Captured</th>
<th>Last verified</th>
<th>Kind</th>
<th>From PC</th>
<th>Hash</th>
@@ -34,6 +35,22 @@
{{ formatWhen(rev.collectedat || rev.createdat) }}
<span v-if="rev.islatest" class="bh-badge">current</span>
</td>
<!-- CAPTURED is when this configuration was written; LAST VERIFIED is
when a PC last posted it and the hash still matched. They differ
by design: an unchanged config writes no new revision, so a
machine can be checked daily for a year and still show one
revision from last spring. Without this column that machine
looked abandoned. Only the current revision is verified - an
older one was superseded, so it is not what the PC holds now. -->
<td>
<template v-if="rev.islatest && rev.lastseenat">
{{ formatWhen(rev.lastseenat) }}
</template>
<span v-else-if="rev.islatest" class="bh-muted"
title="No check recorded since this was introduced. The next
collection will record one.">not yet checked</span>
<span v-else class="bh-muted">-</span>
</td>
<td>{{ rev.backupkind }}</td>
<td>{{ rev.sourcehostname || '-' }}</td>
<td class="bh-mono">{{ rev.shorthash }}</td>

View File

@@ -101,6 +101,12 @@ class BackupsPlugin(BasePlugin):
'title': 'label',
'meta': [
{'key': 'collectedat', 'label': 'Captured', 'format': 'date'},
# Captured is when this config was WRITTEN; verified is
# when a PC last posted it and the hash still matched.
# An unchanged config writes no revision, so without
# this a machine checked daily for a year shows one
# entry from last spring and reads as abandoned.
{'key': 'lastseenat', 'label': 'Verified', 'format': 'date'},
{'key': 'sourcehostname', 'label': 'From'},
{'key': 'shorthash', 'label': 'Hash', 'mono': True},
],