#5816 "Restoring mode": while a backup goes back in, the scheduler holds, ingest and HTMX answer 503 with Retry-After (agents keep their samples), and every page says what is happening. A safety backup of Steward as it stands is made first, to /data/backups and the bucket. The backup's key is put in place, the restore audited, and Steward exits with code 3 so Swarm, compose or systemd starts it fresh. A failed in-place restore changes nothing and says why on Backups; a full replace that fails after the wipe restarts into first-run setup. #5817 "Settings → Backups: Restore": a Restore button on each sent backup and on the file card. The chosen backup is checked (the same comparison as Check, now a shared partial) and held server-side for an hour under a token; it starts only once the admin types "restore", and an older backup also needs "Replace everything" ticked. A newer backup, or one whose key can't open its secrets, gets no button. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
62 lines
3.7 KiB
HTML
62 lines
3.7 KiB
HTML
{# settings/_backup_report.html — what a check found (#5823), shown on the check
|
|
page and on the restore confirm page (#5817): the verdict, what the backup
|
|
is, each area's count, then each difference. Needs `report`. #}
|
|
{% set tone = "tone-crit" if not report.ok else ("tone-ok" if not report.changes else "tone-warn") %}
|
|
<p class="page-verdict"><span class="{{ tone }}">{{ report.summary() }}</span></p>
|
|
|
|
<div class="card" style="max-width:640px;margin-bottom:1.25rem;">
|
|
<dl class="kv">
|
|
<dt>File</dt><dd>{{ report.name }}</dd>
|
|
<dt>Made</dt><dd>{% if report.made_at %}{{ report.made_at|when }}{% else %}—{% endif %}
|
|
by Steward {{ report.manifest.steward_version or "—" }}</dd>
|
|
<dt>Schema</dt><dd>
|
|
{%- if report.schema == "same" %}The same as this Steward's.
|
|
{%- elif report.schema == "older" %}<span class="tone-warn">Older than this Steward's.</span> A restore would replace everything, and Steward would bring it up to date on start.
|
|
{%- else %}<span class="tone-crit">Newer than this Steward's.</span> This Steward can't restore it; update Steward first.{% endif %}</dd>
|
|
<dt>Secret key</dt><dd>
|
|
{%- if report.key_same %}The one in use here.{% else %}<span class="tone-warn">A different one.</span> A restore would put it in place, and passwords and keys stored since would need entering again.{% endif %}
|
|
{%- if report.sealed %} It opens {{ report.sealed - report.unopened }} of the backup's {{ report.sealed }} sealed value{{ "s" if report.sealed != 1 }}.{% endif %}</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<div class="card-flush" style="margin-bottom:1.25rem;">
|
|
<table class="table">
|
|
<thead><tr><th>Area</th><th>Same</th><th>Differ</th><th>Only in the backup</th><th>Only here</th></tr></thead>
|
|
<tbody>
|
|
{% for a in report.areas %}
|
|
{% set differ = a.tables|sum(attribute="differ", start=[])|length %}
|
|
{% set only_b = a.tables|sum(attribute="only_backup", start=[])|length %}
|
|
{% set only_h = a.tables|sum(attribute="only_here", start=[])|length %}
|
|
<tr>
|
|
<td>{{ a.name }}</td>
|
|
<td>{{ a.same }}</td>
|
|
<td>{% if differ %}<span class="tone-warn">{{ differ }}</span>{% else %}—{% endif %}</td>
|
|
<td>{% if only_b %}<span class="tone-warn">{{ only_b }}</span>{% else %}—{% endif %}</td>
|
|
<td>{% if only_h %}<span class="tone-warn">{{ only_h }}</span>{% else %}—{% endif %}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{% for a in report.areas if a.changes or a.tables|selectattr("note")|list %}
|
|
<h2 class="section-title" style="margin:1.5rem 0 0.75rem;">{{ a.name }}</h2>
|
|
<ul class="check-list">
|
|
{% for t in a.tables %}
|
|
{% for d in t.differ %}
|
|
<li><strong>{{ d.label }}</strong> differs
|
|
{%- if d.secret %} (a sealed value; not shown).
|
|
{%- elif d.backup_value is not none or d.here_value is not none %}: the backup has <code>{{ d.backup_value if d.backup_value is not none else "nothing" }}</code>, here it is <code>{{ d.here_value if d.here_value is not none else "nothing" }}</code>.
|
|
{%- else %} in {{ d.columns|join(", ") }}.{% endif %}</li>
|
|
{% endfor %}
|
|
{% for label in t.only_backup %}<li><strong>{{ label }}</strong> is only in the backup: a restore brings it back.</li>{% endfor %}
|
|
{% for label in t.only_here %}<li><strong>{{ label }}</strong> is only here: a restore removes it.</li>{% endfor %}
|
|
{% if t.note %}<li class="tone-dim">{{ t.table }}: {{ t.note }}</li>{% endif %}
|
|
{% endfor %}
|
|
</ul>
|
|
{% endfor %}
|
|
|
|
<p class="field-hint" style="margin-top:1rem;">Left out of the comparison: what Steward records as it runs
|
|
(when an agent or monitor was last seen, a schedule's last run, the backup history), since it changes by the
|
|
minute. A restore still brings those back as they were in the backup.</p>
|