Skip to content

English {#english}

Purpose

Safely remove test-only emails and related assets in production after an explicit inventory and sign-off. This runbook does not replace legal/finance review; do not bulk-delete real customer data.

Related: Trial email (www) and admin handoff, Control Plane deletion-policy.ts (staged deletion with retention). For emergency teardown, align with ops and document deviation from the 30-day queue.

SQL helpers (replace placeholders, never commit secrets): prego-control-plane/scripts/production-test-data-reset/01-inventory-by-email.sql, 02-inventory-by-tenant.sql, 03-delete-tenant-data.sql, 04-delete-trial-rows-by-email.sql.

Operator UI (optional): When TEST_DATA_RESET_ENABLED and allowlists are set on the Control Plane Worker, open /cp/test-data-reset in the operator React app. It calls GET/POST /internal/test-data-reset/* (same D1 + TENANT_ORIGINS scope as the SQL helpers). Frappe, Auth KV, and Stripe remain manual steps below.

1. Inventory (tests emails, tenant_id, site_name, Stripe ids)

  1. Build a written list: normalized emails, tenant_id, site_name, host, Stripe customer/subscription ids, and confirmation these rows are test-only (not production customers).

  2. From Control Plane D1 (read-only), run inventory scripts after substituting __EMAIL_LOWER__ / __TENANT_ID__:

    Terminal window
    cd /path/to/prego-control-plane
    # Example: copy SQL, replace placeholder, then:
    wrangler d1 execute prego-d1 --remote --file=scripts/production-test-data-reset/01-inventory-by-email.sql
  3. Cross-check tenant_runtime.site_name and host for Frappe/MariaDB teardown on the correct node.

  4. Gate: two-person review — inventory matches intent; no production tenant ids on the list.

2. Backup (D1, KV, MariaDB, snapshots)

  1. D1: Export or snapshot per Cloudflare / team procedure (wrangler d1 backup / dashboard) immediately before any write.
  2. MariaDB / Frappe: Dump the site database or take a VM snapshot per infra policy; record site name and node.
  3. KV: List keys to be deleted (wrangler kv key list --prefix=… for TENANT_ORIGINS, AUTH_STORE, prego_ai erp_cred: prefix if used); save output.
  4. Record timestamp and owner of each artifact.

3. Infra: Frappe bench and MariaDB

  1. On the app/db node identified from tenant_runtime, use your standard procedure (aligned with Ansible frappe_site layout): bench drop-site SITE_NAME (or equivalent), drop the MariaDB database for that site, remove the corresponding directory under sites/ if still present.
  2. Confirm no remaining site: bench list-sites / directory check.
  3. Order: typically after blocking new traffic for that tenant (optional gateway flag) and before or in parallel with CP row deletes — coordinate so URLs do not point at removed sites while KV still serves an origin.

4. Edge: KV (TENANT_ORIGINS, AUTH_STORE, prego_ai cache)

  1. TENANT_ORIGINS: delete keys for the tenant subdomain/origin per your key naming convention.
  2. Auth Worker AUTH_STORE: remove keys such as user:map: plus the normalized email, and passcode_reset:* entries for test users (see test-passcode-reset-flow.md for key patterns).
  3. prego_ai: if connector_credential_ref / erp_cred: KV entries were used for this tenant, remove those keys out-of-band (prego_ai deployment docs).

5. Control Plane D1 deletes

  1. Prefer official staged deletion flows (requestTenantDeletion / ops tooling) when they meet your timeline; otherwise use scripted SQL in a transaction after backups.
  2. For a full tenant row bundle, use 03-delete-tenant-data.sql (replace __TENANT_ID__). It removes traces, jobs, billing rows, contracts, allocations, tenants_master, etc., in dependency-safe order.
  3. For email-only trial rows (no tenant), use 04-delete-trial-rows-by-email.sql (replace __EMAIL_LOWER__).
  4. Orphan users: if a users row has no remaining user_tenants, optionally delete sessions, otps, and the users row per privacy policy (see comments at end of 03-delete-tenant-data.sql).
  5. SQLite: if your environment enforces FOREIGN KEY, verify PRAGMA foreign_keys=ON and test on a copy first.

6. Stripe (production)

  1. With finance approval: cancel subscriptions, issue refunds if required by policy, then archive or delete test Stripe customers only.
  2. Keep audit records required for tax/accounting even if CP rows are removed.

7. Verification

  • D1: re-run inventory queries — zero rows for the target email / tenant_id.
  • KV: prefix list shows no keys for that tenant/email.
  • Node: site and DB absent.
  • Optional: repeat a clean trial signup with the same email (new browser profile) to confirm no stale state.

8. Governance and rollback

ArtifactAction
Change recordDate, operator, approver, list of tenant ids/emails, ticket link
RollbackRestore D1/KV/DB from backups taken in §2; document if only full snapshot restore is possible
Legal / DPARequired if any row could be real customer or PII

Rollback: restoring D1 from export is the primary path; partial KV/DB restore may require manual key restore from saved lists.


한국어 {#korean}

목적

프로덕션에서 테스트용으로만 쓰인 이메일·테넌트 자산을 인벤토리·승인 후 안전하게 제거합니다. 실제 고객 데이터 일괄 삭제 용도가 아닙니다.

참고: Trial email (www) and admin handoff, Control Plane 삭제 정책(deletion-policy.ts, 30일 보존 단계). 긴급 삭제 시 운영 합의 및 기록 필수.

SQL 보조 스크립트: prego-control-plane/scripts/production-test-data-reset/ (01~04, 플레이스홀더 치환 후 사용).

운영자 UI(선택): Worker에 TEST_DATA_RESET_ENABLED와 허용 목록이 있으면 Control Plane React 앱 /cp/test-data-reset 에서 동일 범위(D1 + TENANT_ORIGINS)를 호출할 수 있습니다.

1. 인벤토리

정규화 이메일, tenant_id, site_name, Stripe id 목록을 문서화하고, 테스트 전용임을 두 명이 확인합니다. wrangler d1 execute prego-d1 --remote --file=...01·02 SQL을 실행합니다.

2. 백업

D1 익스포트, MariaDB 덤프 또는 노드 스냅샷, KV 키 목록 저장. 시각·담당자 기록.

3. 인프라 (Frappe / MariaDB)

tenant_runtime 기준 노드에서 bench drop-site, DB 삭제, sites/ 정리. Ansible frappe_site 경로와 일치하는지 확인.

4. KV

TENANT_ORIGINS, AUTH_STORE(user:map:, passcode_reset:), 필요 시 prego_ai erp_cred: 키 삭제.

5. D1 삭제

공식 삭제 큐/도구 우선. 단건 테넌트는 03-delete-tenant-data.sql, 이메일만 트라이얼 잔여면 04-delete-trial-rows-by-email.sql. 트랜잭션·백업 후 실행.

6. Stripe

재무 합의 하에 테스트 고객만 구독 해지·정리. 회계·세무상 보관이 필요한 기록은 유지.

7. 검증

인벤토리 쿼리 재실행(0건), KV·사이트 확인, 선택적 클린 재가입 스모크.

8. 거버넌스·롤백

변경 기록(일시·승인자·대상 id/이메일), D1/KV/DB 백업에서 복구 절차, 필요 시 법무·개인정보 검토.

Help