docs: Q1c GREEN — reboot survival automatic since agent 0.84.0 (feature doc + audit §7 + CONTEXT + REPORT)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
2026-07-11 21:25:14 +02:00
parent ae950e5933
commit 146d165c26
11 changed files with 743 additions and 40 deletions
@@ -227,4 +227,74 @@
</div>
</div>
</section>
{{if .Deletable}}
<!-- Danger zone (v0.47.0): rendered ONLY for non-online hosts — deleting a live
host would brick its heartbeat channel, so the affordance never exists for one.
Impact + type-to-confirm dialog per the global-floor confirm pattern. -->
<section class="card" style="border-color: var(--crit);">
<h2>Danger zone</h2>
<p class="text-muted" style="font-size: 0.85rem;">
Removing this host deletes its reports, guests, log bundles and WireGuard peer, and
permanently invalidates its API key — a still-running agent would receive 401s.
Re-enrollment requires the Day-0 passphrase flow.
</p>
<button type="button" class="btn btn-danger btn-sm" onclick="hostDeleteConfirm('{{.HostID}}')">Remove host&hellip;</button>
<div id="host-delete-confirm-{{.HostID}}" style="display: none; margin-top: 0.75rem; padding: 0.75rem; border: 1px solid var(--crit); background: var(--crit-dim); border-radius: var(--radius); max-width: 44em;">
<p id="host-delete-impact-{{.HostID}}" style="margin: 0 0 0.5rem; font-size: 0.9em;">&hellip;</p>
<label id="host-delete-escrow-row-{{.HostID}}" style="display: none; margin: 0 0 0.5rem; font-size: 0.85em;">
<input type="checkbox" id="host-delete-escrow-{{.HostID}}">
Also delete the key escrow + DR bundle for this host
</label>
<p style="margin: 0 0 0.5rem; font-size: 0.85em; color: var(--text-2);">Type the host id to confirm:</p>
<form method="POST" action="/hosts/{{.HostID}}/delete" id="host-delete-form-{{.HostID}}" style="display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;">
<input type="hidden" name="_csrf" value="{{.CSRFToken}}">
<input type="hidden" name="confirm_host_id" id="host-delete-confirm-hidden-{{.HostID}}" value="">
<input type="hidden" name="delete_escrow" id="host-delete-escrow-hidden-{{.HostID}}" value="">
<input type="text" id="host-delete-confirm-input-{{.HostID}}" placeholder="retype the host id&hellip;" style="padding: 0.3em 0.5em; width: 16em;">
<button type="button" class="btn btn-danger btn-sm" onclick="hostDeleteSubmit('{{.HostID}}')">Confirm &amp; remove</button>
<button type="button" class="btn btn-sm btn-outline" onclick="document.getElementById('host-delete-confirm-{{.HostID}}').style.display='none';">Cancel</button>
</form>
<p id="host-delete-err-{{.HostID}}" style="margin: 0.4em 0 0; font-size: 0.8em; color: var(--crit);"></p>
</div>
</section>
<script>
function hostDeleteConfirm(hostID) {
var box = document.getElementById('host-delete-confirm-' + hostID);
var impact = document.getElementById('host-delete-impact-' + hostID);
document.getElementById('host-delete-confirm-input-' + hostID).value = '';
document.getElementById('host-delete-err-' + hostID).textContent = '';
box.style.display = 'block';
impact.textContent = 'Checking impact…';
fetch('/hosts/' + encodeURIComponent(hostID) + '/delete-impact')
.then(function(r){ return r.json(); })
.then(function(d){
var parts = ['Deleting ' + hostID + ' removes ' + d.guests + ' guest row(s), ' +
d.reports + ' host report(s), ' + d.log_bundles + ' agent log bundle(s)'];
if (d.wg_peer_bound) parts.push('the bound WireGuard peer');
if (d.pbs_secret_present) parts.push('the staged PBS secret');
if (d.recovery_present) parts.push('the break-glass recovery credential');
impact.textContent = parts.join(', ') + '. Host status: ' + d.status + '.' +
(d.deletable ? '' : ' Host is ONLINE — deletion will be refused.');
document.getElementById('host-delete-escrow-row-' + hostID).style.display =
d.escrow_present ? 'block' : 'none';
})
.catch(function(){ impact.textContent = 'Could not compute the impact — the server will still enforce every gate.'; });
}
function hostDeleteSubmit(hostID) {
var typed = document.getElementById('host-delete-confirm-input-' + hostID).value.trim();
var err = document.getElementById('host-delete-err-' + hostID);
if (typed !== hostID) { err.textContent = 'Confirmation does not match the host id.'; return; }
var escrowRow = document.getElementById('host-delete-escrow-row-' + hostID);
var escrowCb = document.getElementById('host-delete-escrow-' + hostID);
if (escrowRow.style.display !== 'none' && !escrowCb.checked) {
err.textContent = 'This host has a key escrow — tick the acknowledgement to delete it too.';
return;
}
document.getElementById('host-delete-confirm-hidden-' + hostID).value = typed;
document.getElementById('host-delete-escrow-hidden-' + hostID).value = escrowCb.checked ? '1' : '';
document.getElementById('host-delete-form-' + hostID).submit();
}
</script>
{{end}}
{{end}}