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:
@@ -186,6 +186,19 @@ func (e *Engine) ReissueForReenroll(cc *store.CustomerConfig) (gen int, reissued
|
||||
return gen, true, nil
|
||||
}
|
||||
|
||||
// ResetToUnclaimed returns a customer to the pre-first-install (unclaimed, no active code) state — the
|
||||
// customer-RESET leg (v0.61.0). It DELETES the claim row so the engine's EnsureIssued mints a FRESH
|
||||
// first code (generation reset, unclaimed) on the next onboarding: no parallel "revoked" flag, no stale
|
||||
// generation. The active code is invalidated (the row is gone → the gate has no hash) and claimed_at is
|
||||
// cleared (gone). Idempotent (a missing row is a no-op).
|
||||
func (e *Engine) ResetToUnclaimed(cc *store.CustomerConfig) error {
|
||||
if err := e.Store.DeleteClaim(cc.CustomerID); err != nil {
|
||||
return fmt.Errorf("claim: reset to unclaimed: %w", err)
|
||||
}
|
||||
e.logf("[INFO] [claim] reset to unclaimed for %s (customer RESET) — next onboarding mints a fresh code", cc.CustomerID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarkClaimed records a controller-reported successful claim and sends the one-time confirmation
|
||||
// email on the unclaimed→claimed transition (idempotent — repeated reports are no-ops).
|
||||
func (e *Engine) MarkClaimed(cc *store.CustomerConfig) error {
|
||||
|
||||
Reference in New Issue
Block a user