hub v0.61.0 + felhom-tenantsync v1.1.0: Customer RESET (middle lifecycle tier)
One operator action returns a customer to pre-first-install: all operational state dies (offsite repo, PBS namespace+backups, DR recipe, one-time secret, claim state, retained escrow custody); identity + basic config + provenance + events survive. Sits between host delete and customer Delete. - store/customer_reset.go: customer_resets journal, live inventory, ack-gated purge (never touches identity/provenance/events), DeleteClaim. - claim.ResetToUnclaimed: delete claim row -> fresh code next onboarding. - offsite.Deprovision (idempotent) + OffsiteIdentifier + ClearProvisionedDescriptor. - tenantsync.Deprovision + felhom-tenantsync.sh deprovision op (destroys ns + backup groups + token; shared user untouched; idempotent). - web/customer_reset.go: GET reset -> inventory JSON; POST -> orchestration (external teardown FIRST, DB purge LAST; refuse-while-hosts; typed-id + separate escrow ack). Amber RESET card distinct from red Danger-zone Delete. - Red-proofs: ack-gate + partial-failure resumability (both proven red); store ack-gating + journal round-trip; offsite idempotency + descriptor clear; RESET-card render. Green: build + vet + test.
This commit is contained in:
@@ -55,6 +55,7 @@
|
||||
{{else if eq .Flash "log_tail_requested"}}Log tail requested — the controller delivers it on its next report cycle (a few minutes). A customer-visible event line was recorded.
|
||||
{{else if eq .Flash "claim-resent"}}Code re-sent to the registered address. A kód a doboz következő jelentésekor (~15 percen belül) aktiválódik.
|
||||
{{else if eq .Flash "claim-resend-failed"}}Claim code resend FAILED — check the hub log (email delivery / send error).
|
||||
{{else if eq .Flash "reset_done"}}Customer RESET complete — every operational trace was destroyed (offsite repo, PBS namespace, DR recipe, claim state, retained escrow custody). Identity and basic config survive; the audit event stream records it.
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -702,6 +703,84 @@
|
||||
{{end}}
|
||||
|
||||
{{if .HasConfig}}
|
||||
<!-- Reset customer (v0.61.0): the MIDDLE lifecycle tier — host delete < RESET < customer Delete.
|
||||
One action returns the customer to pre-first-install: every OPERATIONAL trace dies (offsite
|
||||
repo, PBS namespace, DR recipe, one-time secret, claim state, retained escrow custody), while
|
||||
IDENTITY and the basic config SURVIVE. Amber (--warn), deliberately distinct from the red
|
||||
Danger-zone Delete below it. Refuses while any host row exists (delete hosts first). -->
|
||||
<section class="card" style="border-color: var(--warn);">
|
||||
<h2>Ügyfél-visszaállítás <span class="text-muted" style="font-size: 0.8em; font-weight: normal;">(RESET — pre-első-telepítés)</span></h2>
|
||||
<p class="text-muted">Egyetlen művelettel visszaállítja az ügyfelet az első telepítés előtti állapotba: <strong>minden működési állapot törlődik</strong> (offsite tároló, PBS névtér, DR-recept, egyszeri jelszó, azonosítási állapot). Az <strong>azonosság és az alapkonfiguráció megmarad</strong> (ügyfélrekord, előzmények, események). Ez NEM törli a hostokat — ha még van host, előbb azt kell törölni. Kevesebb, mint a Danger zone Delete: az ügyfél megmarad, csak a működési nyomok tűnnek el.</p>
|
||||
<button type="button" class="btn btn-sm" style="border-color: var(--warn); color: var(--warn);" onclick="customerResetConfirm('{{.CustomerID}}')">Ügyfél visszaállítása…</button>
|
||||
<div id="cust-reset-confirm-{{.CustomerID}}" style="display: none; margin-top: 0.75rem; padding: 0.75rem; border: 1px solid var(--warn); background: var(--warn-dim); border-radius: var(--radius); max-width: 46em;">
|
||||
<p id="cust-reset-inv-{{.CustomerID}}" style="margin: 0 0 0.5rem; font-size: 0.9em;">…</p>
|
||||
<label id="cust-reset-escrow-row-{{.CustomerID}}" style="display: none; margin: 0 0 0.6rem; font-size: 0.85em; color: var(--crit);">
|
||||
<input type="checkbox" id="cust-reset-escrow-{{.CustomerID}}">
|
||||
<strong>Megőrzött helyreállítási-kulcs letét megsemmisítése</strong> — külön megerősítés (ez visszafordíthatatlanul törli a megőrzött escrow blobokat).
|
||||
</label>
|
||||
<p style="margin: 0 0 0.4rem; font-size: 0.85em; color: var(--text-2);">Írd be az ügyfél azonosítóját a megerősítéshez:</p>
|
||||
<form method="POST" action="/configs/{{.CustomerID}}/reset" id="cust-reset-form-{{.CustomerID}}" style="display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;">
|
||||
{{.CSRFField}}
|
||||
<input type="hidden" name="confirm_id" id="cust-reset-confirm-hidden-{{.CustomerID}}" value="">
|
||||
<input type="hidden" name="escrow_ack" id="cust-reset-escrow-hidden-{{.CustomerID}}" value="">
|
||||
<input type="text" id="cust-reset-input-{{.CustomerID}}" placeholder="ügyfél-azonosító…" style="padding: 0.3em 0.5em; width: 16em;">
|
||||
<button type="button" class="btn btn-sm" id="cust-reset-go-{{.CustomerID}}" style="border-color: var(--warn); color: var(--warn);" onclick="customerResetSubmit('{{.CustomerID}}')">Megerősítés & visszaállítás</button>
|
||||
<button type="button" class="btn btn-sm btn-outline" onclick="document.getElementById('cust-reset-confirm-{{.CustomerID}}').style.display='none';">Mégse</button>
|
||||
</form>
|
||||
<p id="cust-reset-err-{{.CustomerID}}" style="margin: 0.4em 0 0; font-size: 0.8em; color: var(--crit);"></p>
|
||||
</div>
|
||||
</section>
|
||||
<script>
|
||||
function customerResetConfirm(cid) {
|
||||
var box = document.getElementById('cust-reset-confirm-' + cid);
|
||||
var inv = document.getElementById('cust-reset-inv-' + cid);
|
||||
var go = document.getElementById('cust-reset-go-' + cid);
|
||||
document.getElementById('cust-reset-input-' + cid).value = '';
|
||||
document.getElementById('cust-reset-err-' + cid).textContent = '';
|
||||
box.style.display = 'block';
|
||||
inv.textContent = 'Leltár lekérése…';
|
||||
go.disabled = false;
|
||||
fetch('/configs/' + encodeURIComponent(cid) + '/reset')
|
||||
.then(function(r){ return r.json(); })
|
||||
.then(function(d){
|
||||
if (d.refused) {
|
||||
inv.innerHTML = '<strong style="color: var(--crit)">Elutasítva:</strong> ehhez az ügyfélhez még ' + d.host_count +
|
||||
' host tartozik. A RESET soha nem töröl hostot — előbb töröld a host(oka)t.';
|
||||
go.disabled = true;
|
||||
document.getElementById('cust-reset-escrow-row-' + cid).style.display = 'none';
|
||||
return;
|
||||
}
|
||||
var dies = [];
|
||||
if (d.offsite_enabled) dies.push('offsite tároló' + (d.offsite_identifier ? ' (' + d.offsite_identifier + ')' : ''));
|
||||
if (d.pbs_tenancy_configured) dies.push('PBS névtér + mentések');
|
||||
if (d.dr_recipe_present) dies.push('DR-recept');
|
||||
if (d.one_time_secret) dies.push('egyszeri jelszó');
|
||||
if (d.claim_present) dies.push('azonosítási állapot (friss kód a következő onboardingnál)');
|
||||
if (d.superseded_blobs > 0) dies.push(d.superseded_blobs + ' megőrzött escrow blob');
|
||||
inv.innerHTML = '<strong>Törlődik:</strong> ' + (dies.length ? dies.join(', ') : 'nincs működési állapot') +
|
||||
'. <strong>Megmarad:</strong> ügyfélrekord, alapkonfiguráció, előzmények, események.';
|
||||
var escrowRow = document.getElementById('cust-reset-escrow-row-' + cid);
|
||||
escrowRow.style.display = d.escrow_ack_required ? 'block' : 'none';
|
||||
document.getElementById('cust-reset-escrow-' + cid).checked = false;
|
||||
})
|
||||
.catch(function(){ inv.textContent = 'A leltár nem kérhető le — a szerver minden feltételt így is kikényszerít.'; });
|
||||
}
|
||||
function customerResetSubmit(cid) {
|
||||
var typed = document.getElementById('cust-reset-input-' + cid).value.trim();
|
||||
var err = document.getElementById('cust-reset-err-' + cid);
|
||||
if (typed !== cid) { err.textContent = 'A beírt azonosító nem egyezik.'; return; }
|
||||
var escrowRow = document.getElementById('cust-reset-escrow-row-' + cid);
|
||||
var escrowCb = document.getElementById('cust-reset-escrow-' + cid);
|
||||
if (escrowRow.style.display !== 'none' && !escrowCb.checked) {
|
||||
err.textContent = 'A megőrzött kulcs-letét megsemmisítéséhez pipáld be a külön megerősítést.';
|
||||
return;
|
||||
}
|
||||
document.getElementById('cust-reset-confirm-hidden-' + cid).value = typed;
|
||||
document.getElementById('cust-reset-escrow-hidden-' + cid).value = escrowCb.checked ? '1' : '';
|
||||
document.getElementById('cust-reset-form-' + cid).submit();
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Danger zone (v0.48.0 edit-a): the Block/Delete forms relocated verbatim from the
|
||||
Customer Info header — endpoints and confirm() handlers unchanged. -->
|
||||
<section class="card">
|
||||
|
||||
Reference in New Issue
Block a user