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:
@@ -596,6 +596,21 @@ func (s *Store) migrate() error {
|
||||
escrow_acked INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_host_deletions_customer ON host_deletions(customer_id, id DESC);
|
||||
|
||||
-- customer_resets (v0.61.0, F-14 style): the RESET provenance + resumable per-leg journal. One
|
||||
-- row per reset attempt; legs_json holds {hetzner,pbs,db_purge → pending|ok|failed|manual}. The
|
||||
-- DB purge runs LAST (publish-last), so a re-run reads the journal to know what still needs
|
||||
-- teardown. escrow_acked records the ruling-1 acknowledgment. NEVER pruned (audit outlives
|
||||
-- every lifecycle tier).
|
||||
CREATE TABLE IF NOT EXISTS customer_resets (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
customer_id TEXT NOT NULL,
|
||||
started_at DATETIME NOT NULL DEFAULT (datetime('now')),
|
||||
completed_at DATETIME,
|
||||
escrow_acked INTEGER NOT NULL DEFAULT 0,
|
||||
legs_json TEXT NOT NULL DEFAULT '{}'
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_customer_resets_customer ON customer_resets(customer_id, id DESC);
|
||||
`)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user