feat(hub): v0.57.0 reinstall-of-existing-customer arc — claim/offsite/escrow continuity
F2 claim re-issue on clean-slate re-enroll (ReissueForReenroll, host-enroll mint path, single-bump, reset code; hub never stores the password so fork B). F3 offsite re-issue on re-enroll (ReissueOffsiteForCustomer, same machinery as the manual button). 2.3 escrow honesty (red-proofed): re-issuing offsite marks the escrow stale (MarkEscrowStale), withholds the mismatched restic hash from auto-confirm, DR checklist shows stale not done. Events: claim_reissued_reenroll / offsite_reissued / escrow_stale. Controller + scripts unchanged (source contradicted both premises): the controller reads escrow prereqs live from the agent; the installer can't know the descriptor-provisioned storage id. F4 root fix is agent-side -> ROADMAP R-22; demo unblocked live (Part 0 ACL grant). VALIDATION doc F2 erratum + F3/F4 dispositions. Green gate + Scenario-C red-proof pass.
This commit is contained in:
@@ -194,6 +194,36 @@ func (p *Provisioner) ReissueCredentials(ctx context.Context, customerID, typ st
|
||||
if err := p.Store.SaveOneTimeSecret(customerID, pw); err != nil {
|
||||
return fmt.Errorf("offsite: store re-issued one-time password: %w", err)
|
||||
}
|
||||
|
||||
// v0.57.0 (2.3, the escrow-honesty fix): the restic repo password just changed, so any existing
|
||||
// key-escrow blob — which sealed the OLD password — is now STALE. A recovery code minted against
|
||||
// it would decrypt a password that no longer opens the repo. Mark the escrow stale so the hub
|
||||
// stops advertising "ceremony done" and the customer's escrow wizard is offered again; a fresh
|
||||
// ceremony seals the new password and clears the flag. Every credential change also emits a
|
||||
// visible customer event (offsite_reissued always; escrow_stale only when a blob was invalidated).
|
||||
// Best-effort: the password reset already succeeded — a bookkeeping failure here must not fail it.
|
||||
escrowStaled := false
|
||||
if host, herr := p.Store.GetHostByCustomer(customerID); herr == nil && host != nil {
|
||||
if esc, eerr := p.Store.GetHostEscrow(host.HostID); eerr == nil && esc != nil {
|
||||
if serr := p.Store.MarkEscrowStale(host.HostID); serr != nil {
|
||||
p.logf("[offsite] WARN mark-escrow-stale for %s: %v", customerID, serr)
|
||||
} else {
|
||||
escrowStaled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, serr := p.Store.SaveEvent(customerID, "offsite_reissued", "info",
|
||||
"Az offsite (házon kívüli) mentési hozzáférést újra kiadtuk — az új egyszeri jelszót a vezérlő a következő frissítéskor átveszi.",
|
||||
"", "hub"); serr != nil {
|
||||
p.logf("[offsite] WARN save offsite_reissued event for %s: %v", customerID, serr)
|
||||
}
|
||||
if escrowStaled {
|
||||
if _, serr := p.Store.SaveEvent(customerID, "escrow_stale", "warning",
|
||||
"A helyreállítási kulcs-letét elavult az offsite jelszó cseréje miatt — futtasd le újra a helyreállítási szertartást (Biztonsági mentés → Helyreállítás).",
|
||||
"", "hub"); serr != nil {
|
||||
p.logf("[offsite] WARN save escrow_stale event for %s: %v", customerID, serr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user