English {#english}
Purpose : Stepwise implementation plan for the v4.0 technical specification (Enterprise-Grade Architecture, Multi-Region, GitHub Actions Pulumi Preview/Up separation). No code generation — scope, dependencies, completion criteria, and risk decisions only.
Reference : (separate) PREGO SaaS Control Platform technical specification v4.0
Date : February 2026
Contents : §0 Overview · §1 Three immediate decisions · §2 Phase roadmap (E2E, Trace Stage, kickoff, state machines, blockers) · §3 Phase 1 — SG + CI/CD · §4 Phase 2 — Usage Billing · §5 Phase 3 — LogPath, PDPA, D1 0006 · §6 Phase 4 — US + Autoscaler · §7 Phase 5 — EU + GDPR · §8 Cross-phase (Fail Sanely, security, alerts, retry) · §9 Dependencies & schedule · §10–§18 (codebase, risks, decision log, D1 schema, Runbook, glossary, v4.0 mapping, changelog).
0. Document Overview
Scope : SG single region → Multi-Region (SG/US/EU), CI/CD (Preview/Up), Billing, LogPath, PDPA, Autoscaler. Deliverables : Phase task lists, dependencies, completion criteria, three immediate decisions (§1).
Completeness : §0.1 maps v4.0 items (Multi-Region, Pulumi split, Atomic Workflow, D1 0001–0006, Usage R2→Aggregator→Stripe, LogPath, PDPA Purge, Autoscaler, Fail Sanely) to sections.
Quick ref : §0.2 table — E2E/Trace (§2.1, §2.2), kickoff (§2.3), Phase 1–5 tasks and checks (§3–§7), D1/Queue (§13), Runbook (§8, §14), implementation order (§9.10), release checklist (§9.11).
Maintenance : §0.3 — update §18 changelog, TOC, §16 v4.0 mapping when editing.
Exclusions : §0.4 — Frappe/HRMS app code, client-web UI detail, third-party SLA/pricing, dev/staging pipeline, code/config generation (on request).
Executive summary : §0.5 — Goal: tenant lifecycle, Usage Billing, infra automation, PDPA, LogPath, multi-region. Phases 1–5 summary. Three immediate decisions : ① Provision executor (recommended: GitHub Actions workflow_dispatch callback) ② Zuplo Soft Quota KV backend ③ trace_events high-frequency storage (R2 offload etc.). Next: §1 agreement → §2.3 kickoff → Phase 1 (P1-1…P1-13) → Phases 2–5.
Can do / Cannot do : §0.6 — Define scope, tasks, dependencies, criteria, decisions; cannot generate code or replace v4.0 spec body.
Three items must be decided before Phase 1–2 scope is fixed.
# Risk Decision needed Recommendation Status 1 Provision executor Who runs provision jobs from the queue (GitHub Actions callback vs separate Worker vs manual) GitHub Actions callback — Queue consumer calls workflow_dispatch so only that region stack runs pulumi up[ ] Open 2 Zuplo Soft Quota backend When to move from in-memory to KV; KV schema (key, TTL, per-region) KV backend required — key e.g. usage:{tenant_id}:{meter_key}:{cycle_start}[ ] Open 3 trace_events high-frequency append D1 write load and R2 offload (sync D1 vs async R2 batch vs hybrid) Define R2 offload — batch interval and index (e.g. by trace_id, by time) without breaking SEV1 analysis <1s[ ] Open
Next: Stakeholder agreement → update “Status” and §1 with decision summary.
2. Phase Roadmap Summary
Phase Period Focus Done when 1 M1–M2 SG single region, Pulumi(SG)+Ansible+D1 0001–0005, GitHub Actions Preview/Up SG tenant auto-provisioning success 2 M3–M4 Billing — Stripe Webhook, R2 Raw, Aggregator, usage_rollups Usage → Stripe E2E success 3 M5–M6 LogPath, Audit, PDPA Purge, D1 0006 multiregion PDPA + LogPath SEV1 analysis 4 M7–M8 US (Ashburn), Autoscaler, SLA, Enterprise tier US tenant provisioning success 5 M9+ EU (Falkenstein), GDPR, Predictive Scaling, admin dashboard EU customer readiness
E2E (Atomic Workflow, §2.1) : (1) Stripe Webhook → (2) D1 tenants_master/provision_jobs → (3) Queue enqueue → (4) GitHub Actions Pulumi up → (5) Ansible (Docker+Frappe+bench) → (6) Zuplo Sync → (7) Control Plane COMPLETED.
LogPath stages (§2.2): STRIPE_WEBHOOK_RECEIVED, BILLING_STATUS_UPDATED, PROVISION_JOB_CREATED, INFRA_RUNNING, SITE_CREATED, GATEWAY_REGISTERED, COMPLETED — mapped to Phase 1 tasks.
Kickoff (§2.3): Decisions ①–③, Stripe/Hetzner/CF/Pulumi/GitHub accounts and secrets, D1 migrations 0001–0005, Queue (or alternative) and consumer.
State machines : tenants_master.status (§2.4), provision_jobs (§2.5), purge_jobs (§2.6). Dependencies (§2.7): Decisions → Kickoff → Phase 1 → Phase 2 → Phase 3 → Phase 4 → Phase 5. Blockers (§2.8): Per-phase prerequisites (e.g. Phase 1: decision ①, kickoff complete).
§§3–§18 (Phase 1–5 task breakdown, Stripe mapping, first-deploy checklists, Billing Cycle, LogPath/trace_events, Hard Purge order, US/EU checks, Cross-Phase Fail Sanely/security/alerts/retry, dependencies §9, codebase §10, risks §11, decision log §12, D1 schema §13, Runbook §14, glossary §15, v4.0 mapping §16, links §17, changelog §18) — full tables, task IDs, completion criteria, and runbook index are in the Korean section below.
한국어 {#korean}
문서 목적 : 기술개발기획서 v4.0(Enterprise-Grade Architecture, Multi-Region, GitHub Actions Pulumi Preview/Up 분리)의 구현을 위한 단계별 기획서. 코드 생성은 포함하지 않으며, 작업 범위·의존성·완료 기준·리스크 결정만 정의.
참조 문서 : (별도) PREGO SaaS Control Platform 기술개발기획서 v4.0
작성일 : 2026년 2월
목차
절 제목 0 문서 개요 · 0.1 완성도 · 0.2 빠른 참조 · 0.3 유지보수 · 0.4 제외 범위 · 0.5 Executive Summary · 0.6 할 수 있는 것/없는 것 1 즉시 결정 필요 사항 (최우선 3가지) 2 Phase별 로드맵 · 2.1~2.8 (E2E, Trace Stage, 킥오프, 상태 전이, Phase 간 의존성, 블로커) 3 Phase 1 — SG 단일 리전 및 CI/CD · 3.6~3.9 (세부 체크, Stripe 매핑, Webhook 이벤트, 첫 배포 전 점검) 4 Phase 2 — Usage-Based Billing · 4.7 Billing Cycle · 4.8 첫 Cycle Close 전 점검 5 Phase 3 — Governance: LogPath, PDPA, D1 0006 · 5.7 trace_events · 5.8 Hard Purge 순서 · 5.9 첫 Purge 전 점검 6 Phase 4 — US 리전 및 Autoscaler · 6.6~6.9 (세부 체크, 메트릭, nodes.status, 첫 US 전 점검) 7 Phase 5 — EU 리전 및 GDPR · 7.5 태스크별 세부 체크 · 7.6 첫 EU 전 점검 8 Cross-Phase · 8.1 Fail Sanely · 8.2 보안 · 8.3 Slack·Alert · 8.4 재시도·에러 · 8.5 역할·에스컬레이션 · 8.6 에러 시나리오 9 의존성 및 일정 · 9.1~9.16 (Actions, 산출물, 인수테스트, 리전매트릭스, plan_tier, R2, Health Score, 태스크 인덱스, CF LB, 구현 순서, 릴리스 검수, 5-Layer↔Phase, scaling_events, Phase별 산출물 한 줄, 데이터 흐름, 시그니오프 템플릿) 10 기존 코드베이스 연계 11 리스크·가정·제약 · 11.4 다음 문서·산출물 12 결정 로그 템플릿 13 D1 마이그레이션 스키마 요약 · 13.1 핵심 컬럼 · 13.2 Provision Queue 메시지 스키마 14 운영 Runbook 요약 · 14.1 Phase별 Runbook·문서 갱신 15 용어·약어 정리 · 15.1 기술개발기획서 v4.0 인용 문구 16 기술개발기획서 v4.0 절 대응표 · 16.1 역방향(본→v4.0) 17 외부 참조 링크 18 변경 이력
0. 문서 개요
항목 내용 문서 버전 본 기획서 §18 변경 이력 참조. 참조: 기술개발기획서 v4.0 대상 Prego SaaS Control Platform v4.0 전 영역 (Control / Data / Infrastructure / Gateway / Event Plane) 범위 SG 단일 리전 → Multi-Region(SG/US/EU), CI/CD(Preview/Up 분리), Billing, LogPath, PDPA, Autoscaler 산출물 Phase별 태스크 목록, 의존성, 완료 기준, 즉시 결정 필요 사항 코드 생성 본 문서는 기획만 포함. 코드/설정 파일 생성은 별도 요청 시 진행
0.1 기획서 완성도·반영 체크 (기술개발기획서 v4.0 대비)
본 구현 기획서가 기술개발기획서 v4.0 주요 항목을 반영했는지 점검용.
v4.0 항목 본 기획서 반영 절 Multi-Region (SG→US→EU) ✓ §2, §3~§7, §9.4, §9.5 Pulumi Preview/Up 분리 ✓ §3.3~3.5, §9.1 Atomic Workflow (7단계) ✓ §2.1, §2.2, §3 D1 0001~0006 스키마 ✓ §13, §3.2, P1-8 Usage R2→Aggregator→Stripe ✓ §4, §9.6 LogPath Trace/Stage ✓ §2.1, §2.2, §5 PDPA Soft Delete 30일→Purge ✓ §5, §8.1, §2.4 Autoscaler Health Score ✓ §9.7, §6, §6.7 Fail Sanely·보안 ✓ §8.1, §8.2, §8.4 최우선 리스크 3가지 ✓ §1
0.2 빠른 참조: 주제별 절 안내
찾는 내용 절 결정 3건·권장안 §1 E2E 7단계·Trace Stage §2.1, §2.2 킥오프·사전 준비 §2.3 테넌트·provision_jobs 상태 전이 §2.4, §2.5 Phase 1 태스크·세부 체크·Stripe 매핑 §3.3, §3.6, §3.7 Billing·R2·Aggregator·Cycle Close §4, §9.6 LogPath·Audit·PDPA Purge·0006 §5 US/EU 리전·Autoscaler·메트릭 §6, §6.7, §9.7 GitHub Actions·리전·스택·Secrets §9.1, §9.4 D1 스키마·Queue 메시지 §13, §13.1, §13.2 Runbook·Fail Sanely·보안 §8, §14 구현 순서·릴리스 전 검수 §9.10, §9.11 주요 에러 시나리오·대응 §8.6 Phase 1 첫 배포 전 최종 점검 §3.9 Phase 2 첫 Cycle Close 전 점검 §4.8 Phase 3 첫 Hard Purge 전 점검 §5.9 Phase 4 첫 US 프로비저닝 전 점검 §6.9 Phase 5 첫 EU 프로비저닝 전 점검 §7.6
0.3 문서 유지보수 체크리스트
본 기획서를 수정할 때 확인할 항목.
항목 확인 버전 §18 변경 이력에 새 버전·변경 내용·작성일 추가 목차 상단 목차표에 신규·변경 절 반영 절 번호 새 절 추가 시 기존 절 번호 밀림 여부 확인 (목차·본문·상호 참조) §16 대응표 기술개발기획서 v4.0 절과 매핑 변경 시 §16 갱신 §0.1 완성도 v4.0 신규 항목 반영 시 §0.1 표에 행 추가
0.4 제외 범위·Known Gaps
본 기획서에서 의도적으로 다루지 않는 항목.
항목 설명 Frappe/HRMS 앱 코드 bench new-site·API Key 생성까지만 범위, Frappe 커스텀 모듈·앱 로직은 별도 client-web UI 상세 플랜/리전 선택 UI(Phase 4+), 온보딩 플로우 상세는 별도 기획·디자인 제3자 SLA·가격 Stripe·Hetzner·Cloudflare·Pulumi의 구체적 SLA·가격 정책은 해당 업체 문서 참조 개발 환경(dev/staging) 본 문서는 prod(sg→us→eu) 중심; dev/staging 파이프라인은 필요 시 별도 코드·설정 파일 본문 기획·태스크·완료 기준만 정의, 실제 코드 생성은 별도 요청 시
0.5 Executive Summary (한 페이지)
목표 : Prego를 테넌트 라이프사이클·Usage Billing·인프라 자동화·PDPA·LogPath·멀티리전을 갖춘 SaaS Control Platform으로 구현. 기술개발기획서 v4.0 기준.
Phase 요약 : (1) SG 단일 리전 + Pulumi Preview/Up 분리 + 테넌트 자동 프로비저닝 (2) Usage→R2→Aggregator→Stripe 청구 (3) LogPath·Audit·PDPA Purge·D1 0006 (4) US(Ashburn) 리전·Autoscaler (5) EU(Falkenstein)·GDPR·대시보드.
즉시 결정 3건 : ① Provision 실행 주체(권장: GitHub Actions workflow_dispatch 콜백) ② Zuplo Soft Quota KV 백엔드 ③ trace_events 고빈도 저장(R2 오프로드 등). §1.
다음 단계 : §1 결정 합의 → §2.3 킥오프 → Phase 1(P1-1…P1-13) → Phase 2~5. 상세는 §2·§9.10·§9.11.
0.6 이 문서로 할 수 있는 것·할 수 없는 것
할 수 있는 것 할 수 없는 것 구현 범위·태스크·의존성·완료 기준 정의 실제 코드·설정 파일 생성 (별도 요청 시) 결정 ①·②·③ 및 킥오프·블로커 정리 Frappe/HRMS·client-web UI 상세 설계 (§0.4) Phase별 산출물·Runbook 갱신 포인트·시그니오프 제3자 SLA·가격·dev/staging 파이프라인 v4.0 대비 반영 여부·역방향 절 참조 (§0.1, §16, §16.1) 기술개발기획서 본문 대체 (상세 수식·코드는 v4.0 §X)
1. 즉시 결정 필요 사항 (최우선 3가지)
기술개발기획서 v4.0 최종 결론에서 명시한 최우선 구현 리스크 3가지 에 대한 결정이 선행되어야 Phase 1~2 구현 범위가 확정됩니다.
# 리스크 항목 결정 필요 내용 권장안 (기술개발기획서 기준) 결정 상태 1 Provision 실행 주체 Queue에 쌓인 프로비저닝 작업을 누가 실행할지 (GitHub Actions 콜백 vs 별도 Worker vs 수동 트리거) GitHub Actions 콜백 방식 권장 — main 병합 시가 아닌 Queue Consumer가 GitHub Actions workflow_dispatch 호출 하여 해당 리전 스택에만 pulumi up 실행 [ ] 미결정 2 Zuplo Soft Quota 백엔드 In-memory에서 KV 백엔드로 전환 시점 및 KV 스키마(키 구조, TTL, 리전별 분리 여부) KV 백엔드 전환 필수 — 영속성·재시작 시 카운트 유지. 키: usage:{tenant_id}:{meter_key}:{cycle_start} 등 [ ] 미결정 3 trace_events 고빈도 append D1 write 부하 및 R2 오프로드 전략 (동기 D1 vs 비동기 R2 배치 vs 하이브리드) R2 오프로드 전략 결정 — SEV1 분석 1초 이내 요구사항과 충돌하지 않도록 배치 주기·인덱스(예: by trace_id, by time) 정의 [ ] 미결정
다음 단계 : 위 3건에 대해 이해관계자(SRE/Lead/Product) 합의 후 “결정 상태” 체크 및 본 기획서 1절에 결정 요약을 반영할 것.
2. Phase별 구현 로드맵 요약
Phase 기간 예상 소요(참고) 핵심 목표 완료 기준 (기술개발기획서 §14) Phase 1 M1–M2 약 8주 (변동 가능) SG 단일 리전, Pulumi(SG) + Ansible + D1 0001~0005, GitHub Actions Preview/Up SG 테넌트 자동 프로비저닝 성공 Phase 2 M3–M4 약 8주 Billing — Stripe Webhook, R2 Raw, Aggregator, usage_rollups Usage 집계 → Stripe 청구 E2E 성공 Phase 3 M5–M6 약 8주 Governance — LogPath, Audit Dashboard, PDPA Purge 자동화, D1 0006 multiregion PDPA 감사 대응 + LogPath SEV1 분석 가능 Phase 4 M7–M8 약 8주 Ashburn(US) 리전 활성화, Autoscaler, SLA 모니터링, Enterprise Tier 분리 US 리전 테넌트 프로비저닝 성공 Phase 5 M9+ 조건부 Falkenstein(EU) 리전, GDPR 대응, Predictive Scaling, 관리자 대시보드 고도화 EU 고객 대응 완료
예상 소요(참고)는 팀·리소스·결정 일정에 따라 변동 가능.
2.1 신규 테넌트 생성 E2E 시퀀스 (Atomic Workflow)
기술개발기획서 §6.1 기준. 단계별 실행 주체·산출·LogPath Stage 요약.
단계 실행 주체 동작 LogPath Stage 1 Stripe Webhook 결제 완료 이벤트 수신, 멱등성 체크 STRIPE_WEBHOOK_RECEIVED 2 Control Plane (D1) tenants_master status=Active, provision_jobs 등록 BILLING_STATUS_UPDATED 3 CF Queue provision job enqueue (tenant_id, trace_id, region) PROVISION_JOB_CREATED 4 GitHub Actions (결정 ①) pulumi up 실행 (해당 리전 스택) INFRA_RUNNING 5 Ansible Docker + Frappe + HRMS + bench new-site SITE_CREATED 6 Zuplo Sync API Key 등록, Rate Limit 정책 적용 GATEWAY_REGISTERED 7 Control Plane status=Completed, 테넌트 알림 발송 COMPLETED
2.2 LogPath Trace Stage ↔ 구현 태스크 매핑
Stage 구현 Phase 대응 태스크 STRIPE_WEBHOOK_RECEIVED Phase 1 P1-9 (Stripe Webhook → D1) BILLING_STATUS_UPDATED Phase 1 P1-9 PROVISION_JOB_CREATED Phase 1 P1-9, P1-10 (Queue enqueue) INFRA_RUNNING Phase 1 P1-10 (Pulumi up 트리거), P1-4 SITE_CREATED Phase 1 P1-11 (Ansible) GATEWAY_REGISTERED Phase 1 P1-12 (Zuplo Sync) COMPLETED Phase 1 P1-9 (status 갱신), P1-13 (E2E 검증)
Phase 3에서 trace_events에 region, pulumi_stack, gh_run_id 추가 시 동일 Stage를 리전별로 구분 추적.
2.3 킥오프·사전 준비 체크리스트
Phase 1 착수 전에 완료할 결정·환경 준비.
구분 항목 완료 결정 §1 결정 ① Provision 실행 주체 (권장: GitHub Actions workflow_dispatch 콜백) [ ] 결정 §1 결정 ② Zuplo Soft Quota KV 스키마·TTL [ ] 결정 §1 결정 ③ trace_events 고빈도 저장 전략 (R2 오프로드 등) [ ] 계정·토큰 Stripe 계정, Webhook 엔드포인트 URL [ ] 계정·토큰 Hetzner API 토큰 (SG), Cloudflare API 토큰, Pulumi Cloud 계정 [ ] 계정·토큰 GitHub repo, Environments (production-sg, production-destroy), Secrets 등록 [ ] 환경 D1 데이터베이스 생성, 마이그레이션 0001~0005 적용 가능 상태 [ ] 환경 CF Queue(또는 선택 Queue) 생성, Consumer 연동 방식 확정 [ ]
2.4 테넌트 상태 전이 (tenants_master.status)
상태 설명 다음 상태 Pending 구독 생성 직후, 프로비저닝 대기 Active (프로비저닝 완료), Failed (실패·재시도 소진) Active 서비스 이용 가능 Pending_Deletion (삭제 요청), Suspended (Fraud 등) Pending_Deletion Soft Delete, 30일 유예, 접근 차단 — (30일 후 Hard Purge → row 삭제) Suspended 수동·자동 정지 (Fraud 등) Active (검토 후 복구) Failed 프로비저닝 실패 (재시도 소진) 수동 재시도 또는 보류
Purge 완료 시 tenants_master row 삭제. audit_logs는 삭제하지 않음.
2.5 provision_jobs 상태 전이
상태 설명 다음 상태 Pending Queue enqueue 직후, 실행 대기 Running (Consumer가 작업 수락) Running Pulumi/Ansible/Zuplo 실행 중 Completed, Failed (에러·타임아웃) Completed 프로비저닝 성공, tenants_master.status=Active 반영 — Failed 재시도 소진 또는 치명 오류, Slack Alert 수동 재시도 시 새 job 또는 status 갱신
재시도: 지수 백오프, max 5회 (§8.1). Failed 시 trace_id로 LogPath 추적.
2.6 purge_jobs 상태 전이
상태 설명 다음 상태 Pending 30일 경과 후 Hard Purge 예약 또는 수동 등록 Running (Purge Job 시작) Running Hetzner·R2·D1 삭제 실행 중 (§5.8) Completed, Failed Completed Purge 완료, tenants_master row 삭제 반영 — Failed 오류 시 재시도 또는 수동 개입 Pending (재실행)
audit_logs는 어떤 상태에서도 삭제하지 않음.
2.7 Phase 간 의존성 다이어그램
[결정 ①·②·③] ──┬── [킥오프 §2.3]
└── Phase 1 (P1-1…P1-13) ──► Phase 2 (P2-1…P2-6)
Phase 3 (P3-1…P3-9) ◄── (P1-8, P1-9)
Phase 4 (P4-1…P4-7) ──► Phase 5 (P5-1…P5-8)
결정 ①·②는 Phase 1·2, 결정 ③은 Phase 3에 직접 영향. Phase 4·5는 P1-2(리전 분기)·P3-8(0006)에 의존.
2.8 Phase별 블로커 요약
각 Phase 착수 전 해소해야 할 선행 조건. 미충족 시 해당 Phase 지연.
Phase 블로커(선행 조건) Phase 1 §1 결정 ① 미합의(Provision 실행 주체), §2.3 킥오프 미완료(Stripe·Hetzner·CF·Pulumi·GitHub·D1·Queue) Phase 2 P1-8(D1 0001~0005) 미적용, 결정 ②(KV 스키마) 미합의 Phase 3 P1-9(Control Plane·trace_id) 미구현, 결정 ③(trace_events 저장) 미합의, P1-8 미적용 Phase 4 P1-2(REGION_CONFIG·resolveRegion) 미반영, P3-8(D1 0006) 미적용 Phase 5 P4-1~P4-4(US 스택·CF LB) 미완료
3. Phase 1 — SG 단일 리전 및 CI/CD (M1–M2)
3.1 목표
Singapore 단일 리전으로 테넌트 자동 프로비저닝 E2E 동작
Pulumi Preview(PR) / Up(main) 분리 파이프라인 구축
D1 스키마 0001~0005 적용, Control Plane · Infra · Gateway 연동
3.2 산출물
산출물 설명 위치/형식 Pulumi SG 스택 prego/sg, Hetzner nbg1-dc3(sin) + Cloudflare DNS/SSLinfra/, Pulumi.sg.yaml리전 분기 로직 REGION_CONFIG, resolveRegion() (Basic/Pro → sg, Enterprise → tenant 선택)infra/index.ts (설계 반영, Phase 4 전까지 sg만 사용) GitHub Actions pulumi-preview.yml, pulumi-up.yml, pulumi-destroy.yml .github/workflows/ D1 마이그레이션 0001~0005 (tenants_master, billing, jobs_runtime, logpath_audit, usage_metering) migrations/ Ansible 플레이북 Docker + Frappe + HRMS + bench new-site, API Key 생성 config/ (또는 기존 infra/ansible) Zuplo 연동 신규 테넌트 API Key 등록, Rate Limit 정책 (zuplo_sync) infra/zuplo_sync.ts 등
3.3 태스크 분해
ID 태스크 선행 조건 담당 유형 완료 기준 P1-1 Pulumi 프로젝트 구조 정리 (infra/, providers/, modules/) — Infra index.ts, server/dns/firewall 모듈, Pulumi.sg.yaml 존재 P1-2 REGION_CONFIG 및 resolveRegion() 반영 (sg만 활성) P1-1 Infra sg 리전으로 서버·DNS 생성 가능 P1-3 pulumi-preview.yml (PR 시 preview, matrix region: [sg]) P1-1 DevOps PR 코멘트에 preview 결과 출력 P1-4 pulumi-up.yml (main push + workflow_dispatch, environment: production-sg) P1-3 DevOps main 병합 또는 수동 실행 시 prego/sg 스택에 up 적용 P1-5 pulumi-destroy.yml (workflow_dispatch, confirm 입력, production-destroy) P1-4 DevOps 수동 트리거 시에만 destroy, 2단계 확인 동작 P1-6 GitHub Secrets 정리 (HCLOUD_TOKEN_SG, CLOUDFLARE_API_TOKEN, PULUMI_*, SLACK_WEBHOOK_URL) — DevOps 문서화 및 저장 P1-7 GitHub Environment Protection (production-sg, production-destroy, Required Reviewers) P1-4 DevOps 규칙 적용 완료 P1-8 D1 마이그레이션 0001~0005 적용 — Backend tenants_master, billing, jobs_runtime, logpath_audit, usage_metering 테이블 사용 가능 P1-9 Control Plane: Stripe Webhook 수신 → D1 tenants_master/provision_jobs 갱신 P1-8 Backend STRIPE_WEBHOOK_RECEIVED → BILLING_STATUS_UPDATED → PROVISION_JOB_CREATED P1-10 Provision 실행 주체 연동 (결정 ① 반영) — Queue → Pulumi 실행 트리거 P1-4, 결정① Backend/DevOps 신규 구독 시 해당 리전 Pulumi up 트리거 (콜백 또는 동등 방식) P1-11 Ansible: Docker + Frappe + bench new-site + API Key 생성 P1-2 Infra 프로비저닝된 서버에 사이트 생성 및 키 발급 P1-12 Zuplo Sync: API Key 등록, Rate Limit 정책 적용 P1-11 Gateway GATEWAY_REGISTERED 단계까지 완료 P1-13 테넌트 생성 E2E 검증 (Stripe → Provision → Site → Zuplo → COMPLETED) P1-9~P1-12 QA/SRE SG 테넌트 자동 프로비저닝 성공
3.4 의존성 다이어그램 (Phase 1)
P1-1 ─┬─ P1-2 ──────────────────────────────────────────── P1-11 ─┬─ P1-12 ─┬─ P1-13
├─ P1-3 ─ P1-4 ─ P1-5 │ │
│ └── P1-10 (결정①) ──────────────────────────────────┘ │
P1-8 ─────── P1-9 ────────────────────────────────────────────────────────────┘
3.5 Phase 1 완료 기준 체크리스트
3.6 Phase 1 태스크별 세부 체크 항목
구현·검증 시 각 태스크별로 확인할 하위 항목.
태스크 세부 체크 P1-1 infra/index.ts 진입점 존재; providers/에 hetzner·cloudflare; modules/에 server, dns, firewall P1-2 REGION_CONFIG.sg 정의, resolveRegion() 반환 ‘sg’ (Phase 4 전), Pulumi.sg.yaml config P1-3 paths: prego-pulumi/**, pull-requests: write, comment-on-pr: true, stack-name prego/sg P1-4 push branches: main, workflow_dispatch inputs(region), environment production-sg P1-5 workflow_dispatch only, inputs: tenant_id, region, confirm; confirm=“DESTROY” Guard P1-6 HCLOUD_TOKEN_SG, CLOUDFLARE_API_TOKEN, PULUMI_ACCESS_TOKEN, PULUMI_PASSPHRASE, SLACK_WEBHOOK_URL 문서화 P1-7 production-sg Required Reviewers 1인 이상; production-destroy 2인 권장 P1-8 0001~0005 순서 적용, tenants_master.region DEFAULT ‘sg’, 외래키·인덱스 확인 P1-9 Webhook 멱등성(provider_events 또는 이벤트 ID), tenants_master.status·provision_jobs INSERT P1-10 Queue 메시지에 tenant_id, trace_id, region; 결정 ①에 따른 workflow_dispatch 또는 동등 호출 P1-11 대상 서버 SSH·Docker·bench new-site·API Key 출력; 실패 시 재시도 정책 P1-12 Zuplo API Key·Rate Limit 정책 반영; GATEWAY_REGISTERED trace 기록 P1-13 E2E: 결제 → Webhook → D1 → Queue → Pulumi → Ansible → Zuplo → status=Completed, 알림
3.7 Stripe ↔ Control Plane 필드·이벤트 매핑 (Phase 1 Webhook 참조)
Stripe 측 Control Plane (D1/Queue) 비고 event.type (예: checkout.session.completed, customer.subscription.created) provider_events에 event_id 저장, 멱등 처리 동일 event_id 재수신 시 스킵 customer.id, subscription.id billing_customers, subscriptions 테이블 Stripe ID ↔ tenant_id 매핑 유지 subscription.items[].price Lookup plan_tier, plan_entitlements 결정 Basic/Pro/Enterprise 분기 metadata.tenant_id 또는 신규 생성 tenants_master.tenant_id, provision_jobs.tenant_id trace_id UUID 생성 후 전 구간 전달 — tenants_master.status = Active, region = ‘sg’(기본) Phase 4+ 시 requested_region 반영 — provision_jobs (tenant_id, trace_id, region, status) INSERT → Queue enqueue PROVISION_JOB_CREATED Stage
3.8 Stripe Webhook 처리 대상 이벤트 (P1-9 참조)
event.type 용도 Control Plane 동작 checkout.session.completed 결제 완료, 신규 구독 tenant 생성·provision_jobs 등록·Queue enqueue customer.subscription.created 구독 생성 billing_customers·subscriptions 연동, plan_tier 결정 customer.subscription.updated 플랜 변경·갱신 plan_entitlements·region(Enterprise) 반영 customer.subscription.deleted 구독 해지 Pending_Deletion 전환 또는 30일 유예 시작 invoice.paid / invoice.payment_failed 청구 결과 provider_events·invoices 갱신 (Phase 2와 연동)
모든 이벤트는 provider_events에 event.id(또는 동등 키)로 멱등 저장 후 처리.
3.9 Phase 1 첫 배포 전 최종 점검
Production에서 첫 테넌트 프로비저닝 을 돌리기 전 한 번만 할 점검. §2.3 킥오프·§3.5 완료 기준과 중복되는 항목은 통과한 것으로 간주.
구분 항목 결정 §1 결정 ① 반영 완료(Queue → Pulumi 트리거 방식 확정) Secrets HCLOUD_TOKEN_SG, CLOUDFLARE_API_TOKEN, PULUMI_ACCESS_TOKEN, PULUMI_PASSPHRASE, SLACK_WEBHOOK_URL 저장·검증 Environment production-sg Required Reviewers 지정, production-destroy(2인 권장) 설정 D1 0001~0005 마이그레이션 적용, tenants_master·provision_jobs·provider_events 사용 가능 Stripe Webhook 엔드포인트 URL 등록·검증, 테스트 이벤트 수신 확인 Queue CF Queue(또는 선택 Queue) 생성, Consumer가 결정 ① 방식으로 Pulumi 트리거 가능한지 확인 Pulumi prego/sg 스택으로 수동 pulumi preview 성공, Pulumi Cloud State 접근 가능 Ansible 대상 서버 SSH·Docker·bench 실행 가능, API Key 출력 검증
위 통과 후 테스트 구독 1건으로 E2E(P1-13) 검증 권장.
4. Phase 2 — Usage-Based Billing (M3–M4)
4.1 목표
Zuplo Soft Metering → R2 Raw Log → Aggregator → usage_rollups → Billing Cycle Close → Stripe 청구 E2E
4.2 산출물
산출물 설명 Zuplo Soft Quota 결정 ② 반영 — KV 백엔드, 키 구조, TTL (In-memory 제거) R2 Raw 파티셔닝 usage_raw/tenant_id=…/dt=…/hour=…/part-*.jsonl.gz Aggregator Worker Cron: R2 파티션 집계 → D1 usage_rollups Upsert (5분~1시간 단위) Billing Cycle Close included 차감, overage 계산, Stripe 전송 (월말)
4.3 태스크 분해
ID 태스크 선행 조건 완료 기준 P2-1 Zuplo Soft Quota KV 백엔드 설계 및 적용 (결정 ②) — KV에 요청 카운트 영속, 재시작 후에도 유지 P2-2 R2 버킷 및 파티셔닝 구조 생성 (tenant_id, dt, hour) — JSONL+gzip 적재 구조 확정 및 쓰기 권한 설정 P2-3 Zuplo → R2 Raw 로그 적재 파이프라인 (로그 형식 명세 반영) P2-2 ts, tenant_id, meter_key, qty, path, status 등 필드 저장 P2-4 Aggregator Cron: R2 읽기 → usage_rollups Upsert P1-8, P2-2 5분/1시간 단위 집계, 멱등성 보장 P2-5 Billing Cycle Close Job (included, overage, Stripe 전송) P2-4 월말 실행, Stripe Invoice/Usage 연동 P2-6 E2E 검증: API 호출 → R2 → Aggregator → usage_rollups → Cycle Close → Stripe P2-1~P2-5 Usage 집계 → Stripe 청구 E2E 성공
4.4 의존성 다이어그램 (Phase 2)
P2-1 (결정②) ──────────────────────────────────────────────────────────────┐
P2-2 ───────────────────┬─ P2-3 ────────────────────────────────────────── │
P1-8 ───────────────────┴─ P2-4 ── P2-5 ────────────────────────────────── │
4.5 Phase 2 완료 기준 체크리스트
4.6 Phase 2 태스크별 세부 체크 항목
태스크 세부 체크 P2-1 KV 네임스페이스·키 구조(usage:{tenant_id}:{meter_key}:{cycle_start}), TTL, Zuplo 설정 반영 P2-2 R2 버킷 생성, tenant_id/dt/hour 파티션 prefix, 쓰기 권한(Worker/엣지) P2-3 Zuplo 또는 엣지에서 요청 시 ts, tenant_id, meter_key, qty, path, status JSONL 적재 P2-4 Cron 주기(5분/1시간), R2 List+Get, usage_rollups Upsert 멱등 키(tenant_id, meter_key, dt, hour 등) P2-5 Cycle Close 일정(월말), included 차감·overage 계산, Stripe Usage/Invoice API 호출 P2-6 E2E: API 호출 → R2 → Aggregator → usage_rollups → Cycle Close → Stripe 청구서 생성 확인
4.7 Billing Cycle·included·overage 요약 (Phase 2)
항목 설명 Billing Cycle 월 단위 (예: 1일~말일). usage_cycle_totals·meter_rates와 연동 included 플랜별 포함량 (plan_entitlements). Cycle 내 사용량이 included 이하면 추가 과금 없음 overage 포함량 초과분. usage_rollups 합계 − included, meter_rates 적용 후 Stripe Usage Record·Invoice 항목 반영 Cycle Close 월말(또는 설정일) 실행: included 차감, overage 계산, Stripe API 호출 (P2-5)
D1: meters, usage_rollups, usage_cycle_totals, meter_rates (§13).
4.8 Phase 2 첫 Cycle Close 전 점검
첫 월말 Cycle Close 실행 전 확인.
항목 확인 §4.5 완료 기준 KV·R2·Aggregator·usage_rollups·P2-6 E2E 통과 meter_rates·plan_entitlements D1에 반영, included/overage 계산 로직 검증 Stripe API Usage Record·Invoice 연동 권한·테스트 모드 해제(prod 시) Cycle Close 일정 Cron/스케줄러 월말 실행 시간·타임존 확정
5. Phase 3 — Governance: LogPath, PDPA, D1 0006 (M5–M6)
5.1 목표
LogPath Trace/Stage 전 구간 연결, SEV1 분석 1초 이내
Audit Log 영구 보존, PDPA Soft Delete 30일 → Hard Purge 자동화
D1 0006_multiregion (nodes, scaling_events, tenants_master preferred_region/failover_region) 적용
5.2 산출물
산출물 설명 Trace Stage 정의 STRIPE_WEBHOOK_RECEIVED ~ COMPLETED (기술개발기획서 §9.1) trace_events 고빈도 전략 결정 ③ 반영 — R2 오프로드/하이브리드, 인덱스(trace_id, time, region) Audit Dashboard audit_logs 조회·필터 (append-only, Delete 금지) PDPA Purge 자동화 Soft Delete 30일 → Hard Purge(Hetzner, R2, Snapshot) → D1 tenant 삭제 D1 0006_multiregion nodes, node_metrics_rollups, scaling_events, placement_history, tenants_master 컬럼 추가
5.3 태스크 분해
ID 태스크 선행 조건 완료 기준 P3-1 trace_events 고빈도 append 전략 확정 및 구현 (결정 ③) — R2 오프로드 또는 하이브리드 적용, SEV1 분석 1초 요구 충족 P3-2 전 구간 trace_id 주입 (Stripe Webhook, Control Plane, Queue, Pulumi/Ansible, Zuplo) P1-9 동일 trace_id로 전체 Stage 추적 가능 P3-3 trace_events에 region, pulumi_stack, gh_run_id 필드 추가 (멀티리전 대비) P3-1 리전별 프로비저닝 경로 추적 가능 P3-4 Audit Log 저장 정책 (write-only, Delete 금지) 및 CF Access 권한 분리 — audit_logs 영구 보존 P3-5 Audit Dashboard (조회·필터, 리전/테넌트/시간) P3-4 PDPA 감사 대응 가능 P3-6 PDPA Soft Delete (status=Pending_Deletion, 30일 유예) P1-8 접근 차단, 30일 후 Hard Purge 트리거 P3-7 Hard Purge Job: Hetzner DB, R2, Snapshot 삭제 → D1 tenant row 삭제 P3-6 30일 후 자동 실행, Audit Log는 유지 P3-8 D1 0006_multiregion 마이그레이션 적용 P1-8 nodes, scaling_events, tenants_master preferred_region/failover_region 등 사용 가능 P3-9 LogPath SEV1 분석 시나리오 검증 (trace_id 기준 1초 이내 조회) P3-1, P3-2 PDPA 감사 대응 + LogPath SEV1 분석 완료
5.4 의존성 다이어그램 (Phase 3)
결정③ ── P3-1 ──┬─ P3-3 ────────────────────────────────────────────────────┐
P1-9 ────────────┴─ P3-2 ───────────────────────────────────────────────── │
P1-8 ──┬─ P3-6 ── P3-7 (Purge) │
└─ P3-8 (0006_multiregion) ────────────────────────────────────────────┘
P3-4 ── P3-5 (Audit Dashboard)
5.5 Phase 3 완료 기준 체크리스트
5.6 Phase 3 태스크별 세부 체크 항목
태스크 세부 체크 P3-1 결정 ③ 반영: R2 파티션 또는 D1 배치 쓰기, trace_id·time 인덱스, 1초 이내 조회 검증 P3-2 Webhook·Control Plane·Queue·Ansible 콜백·Zuplo에서 동일 trace_id 전달·기록 P3-3 trace_events 테이블 또는 R2 스키마에 region, pulumi_stack, gh_run_id 컬럼/필드 P3-4 audit_logs write-only 정책, Delete 금지, CF Access로 쓰기 권한 분리 P3-5 Dashboard에서 리전/테넌트/시간 범위 필터, export(선택) P3-6 tenants_master.status=Pending_Deletion 시 접근 차단, 30일 후 purge_jobs 또는 Cron 트리거 P3-7 Hard Purge: Hetzner 서버/볼륨 삭제, R2 테넌트 prefix 삭제, Snapshot 삭제, D1 tenant row 삭제; audit_logs 유지 P3-8 0006 마이그레이션 적용, nodes·scaling_events·placement_history, tenants_master preferred_region/failover_region P3-9 trace_id로 전 Stage 1초 이내 조회 시나리오, PDPA 감사 요청 시 Audit 로그 제출 시나리오
5.7 trace_events 스키마 요약 (결정 ③ 구현 참조)
D1 또는 R2(결정 ③) 저장 시 참조. SEV1 조회: trace_id·time(또는 region) 인덱스 권장.
필드 타입 설명 trace_id string (UUID) 전 구간 동일, LogPath 추적 키 stage string STRIPE_WEBHOOK_RECEIVED, BILLING_STATUS_UPDATED, … COMPLETED (§2.1) region string sg / us / eu (P3-3 멀티리전) pulumi_stack string prego/sg 등 (P3-3) gh_run_id string GitHub Actions Run ID (P3-3) created_at ISO8601 이벤트 시각 payload_json string (선택) 추가 메타데이터
5.8 Hard Purge 실행 순서 (P3-7)
30일 경과 후 자동(또는 예외 수동) 실행 시 순서. audit_logs는 삭제하지 않음.
순서 대상 동작 1 Hetzner 해당 테넌트 서버·볼륨·Snapshot 삭제 (또는 Pulumi destroy 해당 리소스) 2 R2 테넌트 prefix (usage_raw/tenant_id=… 등) 삭제 3 기타 스토리지 해당 테넌트 Snapshot·백업 있으면 삭제 4 D1 tenants_master·provision_jobs 등 tenant_id 기준 row 삭제 (purge_jobs 완료 갱신) — audit_logs 삭제 금지 (append-only, 감사 보존)
수동 트리거 시 §14 Runbook “Hard Purge 수동 트리거” 참조.
5.9 Phase 3 첫 Hard Purge 전 점검
첫 30일 경과 Hard Purge 실행 전 확인.
항목 확인 §5.5 완료 기준 P3-6·P3-7·Purge Job·0006 적용 완료 §5.8 순서 Hetzner → R2 → Snapshot → D1, audit_logs 삭제 없음 purge_jobs 상태 Pending → Running → Completed/Failed 전이·에러 시 재시도 테스트 (선택) 테스트 테넌트로 Soft Delete 30일 시뮬레이션 후 Purge 1건 검증
6. Phase 4 — US 리전 및 Autoscaler (M7–M8)
6.1 목표
Hetzner Ashburn(US) 리전 활성화, Enterprise Tier US 전용 노드
Autoscaler (Health Score, Scale Out/In 트리거), SLA 모니터링
6.2 산출물
산출물 설명 Pulumi prego/us 스택 ash-dc3, HCLOUD_TOKEN_US, Pulumi.us.yaml resolveRegion() 확장 Enterprise + tenant_region=us → us 스택 사용 Cloudflare Load Balancing us-pool, Geo Steering (선택), Health Check Autoscaler Health Score 공식(기술개발기획서 §10.1), 10분 지속·2개 이상 시 Scale Out scaling_events 기록 ScaleOut/ScaleIn/Rebalance/Drain, D1 nodes 갱신
6.3 태스크 분해
ID 태스크 선행 조건 완료 기준 P4-1 Pulumi us 스택 및 REGION_CONFIG.us (ash-dc3) 추가 P1-2 prego/us 스택으로 Ashburn 서버 생성 가능 P4-2 GitHub Actions matrix region: [sg, us], HCLOUD_TOKEN_US Secrets/Environment P1-3, P1-4 PR Preview / main Up 시 us 스택 포함 P4-3 resolveRegion() — Enterprise + requestedRegion=us → us P4-1 테넌트 프로비저닝 시 US 리전 선택 반영 P4-4 Cloudflare Load Balancing: sg-pool, us-pool, Health Check 30초 — 리전별 오리진 풀 구성 P4-5 D1 0006 nodes 테이블 활용, 노드 상태(Active/Draining 등) 갱신 P3-8 nodes.region, status 반영 P4-6 Autoscaler: Health Score 계산 (CPU/Mem/Disk/Latency/Err/Density), 10분 지속 + 2개 이상 시 Scale Out P4-5 scaling_events 생성, 신규 노드 프로비저닝 트리거 P4-7 US 리전 테넌트 E2E (Enterprise US 선택 → prego/us → Ansible → Zuplo) P4-1~P4-4 US 리전 테넌트 프로비저닝 성공
6.4 의존성 다이어그램 (Phase 4)
P1-2 ── P4-1 ──┬─ P4-3 ────────────────────────────────────────────────────┐
P1-3,P1-4 ──────┴─ P4-2 (matrix sg,us) │
P3-8 ── P4-5 ── P4-6 (Autoscaler) ──────────────────────────────────────────┘
(선택) P4-4 (CF Load Balancing) — P4-4는 P4-7 전 완료 권장
6.5 Phase 4 완료 기준 체크리스트
6.6 Phase 4 태스크별 세부 체크 항목
태스크 세부 체크 P4-1 Pulumi.us.yaml, REGION_CONFIG.us (ash-dc3), HCLOUD_TOKEN_US 사용, prego/us 스택 생성·실행 P4-2 matrix region: [sg, us], production-us Environment, HCLOUD_TOKEN_US Secrets P4-3 resolveRegion()에서 plan_tier=Enterprise && requestedRegion=us → ‘us’ 반환, 프로비저닝 플로우에 반영 P4-4 CF Load Balancer, sg-pool·us-pool, Health Check 30초, (선택) Geo Steering P4-5 nodes 테이블 INSERT/UPDATE (node_id, region, status, hostname, ip_address, infra_mode), 메트릭 수집 연동 P4-6 Health Score 공식 적용, 10분 윈도우·2개 이상 임계 초과 시 Scale Out, scaling_events INSERT P4-7 E2E: Enterprise US 선택 → provision_jobs region=us → prego/us up → Ansible → Zuplo → COMPLETED
6.7 Autoscaler 메트릭 수집 항목 (node_metrics_rollups)
Health Score(§9.7) 계산을 위해 수집·집계할 메트릭. D1 0006 node_metrics_rollups 또는 동등 저장소.
메트릭 설명 Health Score 용도 cpu_avg 노드 CPU 사용률 평균 (%) CPU 패널티 (가중치 0.30) mem_avg 메모리 사용률 평균 (%) Memory 패널티 (0.25) disk_pct 디스크 사용률 (%) Disk 패널티 (0.15) p95_latency_ms API p95 지연 (ms) Latency 패널티 (0.15) err_5xx_rate 5xx 에러 비율 Error 패널티 (0.10) tenant_count 해당 노드 테넌트 수 Density 패널티 (0.05) max_tenants 노드 최대 테넌트 수 (nodes 테이블) Density 분모
수집 주기: 1~5분 단위 권장. 10분 윈도우로 2개 이상 임계 초과 시 Scale Out (§9.7).
6.8 nodes.status 전이 (D1 0006)
상태 설명 다음 상태 Active 정상 배치·트래픽 수신 Draining (Scale In·유지보수 전), Maintenance Draining 신규 테넌트 배치 중단, 기존 트래픽만 유지 Active (복구), Disabled (정리 완료) Maintenance 수동 점검·업데이트 Active Disabled 비활성·삭제 예정 — (리소스 정리 후 제거)
Autoscaler Scale In 시 노드 → Draining 후 테넌트 이전 완료 시 Disabled 또는 삭제.
6.9 Phase 4 첫 US 프로비저닝 전 점검
첫 Enterprise US(Ashburn) 테넌트 프로비저닝 전 확인.
항목 확인 §6.5 완료 기준 P4-1~P4-4, prego/us 스택·HCLOUD_TOKEN_US·CF us-pool·Health Check resolveRegion() plan_tier=Enterprise && requestedRegion=us → ‘us’ 반환, 프로비저닝 플로우 반영 Ansible·Zuplo US 리전 서버 대상 배포·API Key 등록 동작 (선택) 테스트 Enterprise US 플랜으로 테스트 구독 1건 E2E
7. Phase 5 — EU 리전 및 GDPR (M9+)
7.1 목표
Hetzner Falkenstein(EU) 리전 활성화, GDPR 대응
D1 리전별 인스턴스 검토 (d1-prego-eu), Predictive Scaling, 관리자 대시보드 고도화
7.2 산출물
산출물 설명 Pulumi prego/eu 스택 fsn1-dc14, HCLOUD_TOKEN_EU D1 리전별 인스턴스 (선택) d1-prego-eu, 데이터 주권 GDPR 대응 EU 고객 데이터 처리 정책, Purge 시 EU 전용 플로우 Predictive Scaling (선택) 예측 기반 Scale Out 관리자 대시보드 멀티리전 현황, 노드/테넌트/청구 요약
7.3 태스크 분해
ID 태스크 선행 조건 담당 유형 완료 기준 P5-1 Pulumi eu 스택, REGION_CONFIG.eu, resolveRegion() eu 분기 P4-1 Infra prego/eu 스택 Falkenstein 서버 생성 P5-2 GitHub Actions matrix [sg, us, eu], production-eu Environment P4-2 DevOps PR/Up 시 eu 포함 P5-3 Cloudflare eu-pool, Geo Steering (EU 고객), Health Check P4-4 Infra EU 리전 라우팅 P5-4 D1 리전별 인스턴스 검토 및 마이그레이션 (d1-prego-eu) P3-8 Backend 데이터 주권 정책 반영 P5-5 GDPR Purge·접근 제어 정책 정리 및 구현 (EU 전용 Purge 플로우) P3-7 Backend/Compliance EU 고객 대응 완료 P5-6 Predictive Scaling (선택): 메트릭 기반 예측 Scale Out P4-6 Infra 필요 시 도입 P5-7 관리자 대시보드 (리전별 노드/테넌트/청구, Audit 링크) P4-5, P3-5 Frontend/Backend 운영 가시화 P5-8 EU 리전 테넌트 E2E (Enterprise EU 선택 → prego/eu → COMPLETED) P5-1~P5-3 QA/SRE Falkenstein 테넌트 프로비저닝 성공
7.4 Phase 5 완료 기준 체크리스트
7.5 Phase 5 태스크별 세부 체크 항목
태스크 세부 체크 P5-1 Pulumi.eu.yaml, REGION_CONFIG.eu (fsn1-dc14), resolveRegion() eu 분기 P5-2 matrix region: [sg, us, eu], production-eu Environment, HCLOUD_TOKEN_EU Secrets P5-3 eu-pool 추가, Geo Steering(EU), Health Check, Failover 정책 P5-4 d1-prego-eu 검토(데이터 주권), 필요 시 마이그레이션·라우팅 분리 P5-5 GDPR Purge 플로우(EU 테넌트 전용), 접근 제어·동의 기록 정책 P5-6 (선택) 메트릭 기반 예측 Scale Out 로직 P5-7 대시보드: 리전별 노드/테넌트 수, 청구 요약, audit_logs 링크 P5-8 E2E: Enterprise EU 선택 → prego/eu → Ansible → Zuplo → COMPLETED
7.6 Phase 5 첫 EU 프로비저닝 전 점검
첫 Enterprise EU(Falkenstein) 테넌트 프로비저닝 전 확인.
항목 확인 §7.4 완료 기준 P5-1~P5-3, prego/eu 스택·HCLOUD_TOKEN_EU·eu-pool·Geo Steering resolveRegion() plan_tier=Enterprise && requestedRegion=eu → ‘eu’ 반환 GDPR·Purge P5-5 EU 전용 Purge·접근 제어 정책 반영 (선택) d1-prego-eu 데이터 주권 요구 시 P5-4 검토 완료 (선택) 테스트 Enterprise EU 플랜으로 테스트 구독 1건 E2E
8. Cross-Phase 공통 작업
영역 내용 적용 Phase 보안 API Key Vault/CF Secrets 참조, NRIC Zuplo 마스킹, Magic Link TTL 48h+ 2차 인증, Admin Cloudflare Access+MFA 전 단계 Fail Sanely 아래 §8.1 상세 표 참조 Phase 1~5 문서 GitHub Secrets 로테이션 주기(90/180일), Environment Protection Rules, Runbook (Pulumi rollback, Purge 수동 트리거) Phase 1 정리, 이후 유지
8.1 Fail Sanely 상세 (상황별 정책·자동화)
기술개발기획서 v4.0 §12 기준.
상황 정책 자동화 Stripe 일시 장애 기존 Active 테넌트 7일 Grace 유지 자동 — status 유지, Webhook 재전송 대비 멱등 Provision 실패 Queue 재시도 (지수 백오프, max 5회) 자동 + Slack Alert Fraud 의심 즉시 Suspend + 수동 검토 자동 Suspend Webhook 지연/중복 provider_events 멱등성 처리 자동 Pulumi 스택 에러 GitHub Actions 실패 알림, 수동 rollback Alert 자동, 복구 수동 D1 write 실패 낙관적 락 + 재시도 3회 자동 리전 장애 (Phase 4+) Cloudflare Failover → SG 리전 폴백 자동 (Phase 1 기준 SG 단일)
8.2 보안 설계 체크리스트 (기술개발기획서 v4.0 §13)
영역 항목 적용 API Key 실제 키는 Vault/CF Secrets에만 저장, D1에는 참조(secret_refs)만 Phase 1 Magic Link TTL 48시간 + 생년월일 등 2차 인증 전 단계 NRIC/FIN Zuplo 미들웨어에서 API 레이어 마스킹, 저장 전 필터링 Phase 1~2 Admin 접근 Cloudflare Access (Zero Trust) + MFA Phase 1 정리 GitHub Secrets 리전별 분리(HCLOUD_TOKEN_SG 등), 90일 로테이션 §9.4 Pulumi State Pulumi Cloud 암호화, PULUMI_PASSPHRASE 관리 Phase 1 audit_logs CF Access write-only 권한 분리, Delete 금지 Phase 3
8.3 Slack·Alert 메시지 포맷 (참조)
이벤트 메시지 요약 비고 Pulumi Up 성공 ✅ Pulumi Up 완료 — Region: {region}§4.3 pulumi-up.yml Pulumi Up 실패 🚨 Pulumi Up 실패 — Region: {region} — 즉시 확인 필요SLACK_WEBHOOK_URL Provision 실패 Provision 재시도 소진 시 tenant_id, trace_id, region 포함 Alert 권장 Queue Consumer 또는 Control Plane 리전 장애 (Phase 4+) Failover 발생 시 리전·풀 정보 포함 알림 (선택) CF Notification
8.4 재시도·에러 정책 요약
대상 정책 비고 Provision (Queue) 지수 백오프, max 5회, 실패 시 Slack Alert §8.1 D1 write 낙관적 락 + 재시도 3회 동시성 제어 Stripe Webhook provider_events 멱등성 키로 중복 스킵 event.id 또는 동등 키 Pulumi Up GitHub Actions 실패 시 수동 rollback, Alert 자동 Runbook §14 Aggregator → usage_rollups Upsert 멱등 키(tenant_id, meter_key, dt, hour) Phase 2
8.5 역할·에스컬레이션 요약
역할 주 담당 에스컬레이션 Infra/SRE Pulumi·Ansible·GitHub Actions·리전·Autoscaler (P1-1~P1-5, P1-11, P4, P5) Pulumi 실패·리전 장애 시 수동 복구·Runbook 실행 Backend D1·Control Plane·Webhook·Queue·Purge·trace (P1-8~P1-10, P3, D1 마이그레이션) D1·Queue 이상 시 로그·trace_id 추적, Purge 예외 처리 DevOps Secrets·Environment·워크플로우 설정 (P1-6, P1-7, P4-2, P5-2) Secrets 로테이션·Environment 승인 정책 Gateway Zuplo·KV·Rate Limit·zuplo_sync (P1-12, P2-1) KV·Quota 이슈 시 Zuplo·R2 연동 확인 QA/SRE E2E 검증·릴리스 전 검수 (P1-13, §9.11) 실패 시 해당 Phase 담당으로 에스컬레이션
결정 ①·②·③ 및 정책 변경은 SRE/Lead·Product 합의.
8.6 주요 에러 시나리오·대응 한 줄
시나리오 대응 한 줄 Stripe Webhook 실패·중복 provider_events 멱등 스킵; 7일 Grace 유지 (§8.1) Provision Queue 재시도 소진 Slack Alert, trace_id로 LogPath 추적, 수동 재시도 또는 보류 (§2.5, §8.1) Pulumi Up 실패 GitHub Actions 로그 → refresh/수동 up, State lock 확인 (§14) D1 write 실패 낙관적 락 + 3회 재시도 (§8.4) Aggregator·Cycle Close 지연 멱등 Upsert·다음 Cycle 보정; Stripe 재전송 정책 확인 리전(US/EU) 장애 CF Failover → SG 폴백 (§9.9, §8.1) Hard Purge 오류 §5.8 순서 확인, audit_logs 삭제 금지, 수동 재실행 (§14)
9. 의존성 및 일정 요약
Phase 1 이 전체 기반: CI/CD, D1, Control Plane, Provision E2E. 결정 ①·②·③은 Phase 1~3 범위에 직접 영향.
Phase 2 는 P1-8(D1 0001~0005) 및 결정 ②에 의존.
Phase 3 은 P1-9(Control Plane trace_id), 결정 ③, P1-8 및 D1 0006에 의존.
Phase 4 는 P1-2(리전 분기), P3-8(D1 0006)에 의존.
Phase 5 는 P4(US 리전 및 Autoscaler) 경험을 재사용.
권장 순서 : 결정 ①·②·③ 합의 → Phase 1 집중 → Phase 2 → Phase 3 → Phase 4 → Phase 5.
9.1 GitHub Actions 워크플로우 요약
워크플로우 트리거 Pulumi 명령 Environment 비고 pulumi-preview.yml pull_request (branches: main, paths: prego-pulumi/**) pulumi preview— PR 코멘트 출력, matrix region: [sg] (Phase 4+ 시 [sg,us,eu]) pulumi-up.yml push (main), workflow_dispatch (region, dry_run) pulumi up 또는 previewproduction-sg / production-us / production-eu 승인자 게이트, dry_run 시 preview만 pulumi-destroy.yml workflow_dispatch (tenant_id, region, confirm) pulumi destroyproduction-destroy confirm=“DESTROY” 필수, 2인 승인 권장
필요 Secrets: PULUMI_ACCESS_TOKEN, PULUMI_PASSPHRASE, CLOUDFLARE_API_TOKEN, 리전별 Hetzner 토큰(HCLOUD_TOKEN_SG, HCLOUD_TOKEN_US, HCLOUD_TOKEN_EU), SLACK_WEBHOOK_URL.
9.2 Phase별 산출물 체크리스트 (파일·리소스 관점)
Phase 생성/수정 대상 (요약) Phase 1 infra/index.ts, infra/providers/.ts, infra/modules/ .ts, Pulumi.sg.yaml, .github/workflows/pulumi-*.yml, migrations/0001~0005, Control Plane(Webhook+D1), config/ Ansible, infra/zuplo_sync.ts Phase 2 Zuplo KV 스키마·설정, R2 버킷·파티셔닝, Aggregator Worker, Billing Cycle Close Job Phase 3 trace_events 저장 전략(결정 ③), 전 구간 trace_id 주입, audit_logs 정책·Dashboard, PDPA Soft/Hard Purge Job, migrations/0006_multiregion Phase 4 Pulumi.us.yaml, REGION_CONFIG.us, GitHub matrix [sg,us], CF Load Balancing, nodes·scaling_events 활용, Autoscaler Phase 5 Pulumi.eu.yaml, REGION_CONFIG.eu, matrix [sg,us,eu], eu-pool, (선택) d1-prego-eu, GDPR Purge 플로우, 관리자 대시보드
9.3 Phase별 인수 테스트 시나리오 요약
Phase 시나리오 (요약) 완료 판정 Phase 1 Given 신규 구독 결제 완료 When Webhook 수신 Then D1 갱신 → Queue → Pulumi(해당 리전) → Ansible → Zuplo 등록 → status=CompletedSG 테넌트 자동 프로비저닝 성공 Phase 1 Given prego-pulumi/** 변경 PR When PR Open/Update Then Pulumi Preview 실행, PR 코멘트에 결과 표시Preview 자동 실행·코멘트 확인 Phase 2 Given 테넌트 API 호출 When Aggregator Cron·Cycle Close 실행 Then usage_rollups 반영, Stripe 청구 생성Usage → Stripe E2E 성공 Phase 3 Given trace_id When LogPath 조회 Then 1초 이내 전 Stage 조회 가능; Soft Delete 30일 후 Hard Purge 실행SEV1 분석·PDPA Purge 검증 Phase 4 Given Enterprise + region=us When 프로비저닝 Then prego/us 스택으로 Ashburn 서버 생성, 테넌트 ReadyUS 리전 프로비저닝 성공 Phase 5 Given Enterprise + region=eu When 프로비저닝 Then prego/eu 스택으로 Falkenstein 서버 생성, GDPR Purge 적용EU 리전·GDPR 대응 완료
9.4 리전·스택·환경·Secrets 매트릭스
정책 : Hetzner는 리전별로 다른 토큰을 사용한다 (HCLOUD_TOKEN_SG / HCLOUD_TOKEN_US / HCLOUD_TOKEN_EU). 과금·계정·규제 분리 목적.
Phase 4·5 적용 시 리전별 Pulumi 스택·GitHub Environment·Hetzner 토큰 일람.
리전 Pulumi 스택 GitHub Environment Hetzner Secret Hetzner 위치 sg prego/sg production-sg HCLOUD_TOKEN_SG nbg1-dc3 (또는 sin) us prego/us production-us HCLOUD_TOKEN_US ash-dc3 (Ashburn) eu prego/eu production-eu HCLOUD_TOKEN_EU fsn1-dc14 (Falkenstein)
Destroy 전용: Environment production-destroy (2인 승인 권장). 공통 Secrets: PULUMI_ACCESS_TOKEN, PULUMI_PASSPHRASE, CLOUDFLARE_API_TOKEN, SLACK_WEBHOOK_URL.
9.5 plan_tier ↔ 리전·인프라 모드 매트릭스
기술개발기획서 v4.0 §6.2 기준. 테넌트 생성 시 플랜에 따른 리전·인프라·Pulumi 스택.
Plan Tier 리전 인프라 모드 Pulumi 스택 Basic / Professional sg (고정) shared_node (Frappe Multi-site) prego/sg Enterprise (SG) sg dedicated_node (전용 서버) prego/sg Enterprise (US) us dedicated_node prego/us Enterprise (EU) eu dedicated_node prego/eu
resolveRegion(planTier, requestedRegion): Enterprise일 때만 requestedRegion 사용, 그 외는 'sg'.
9.6 R2 Raw 로그 스키마 요약 (Usage 파이프라인)
기술개발기획서 v4.0 §8.2. 경로: usage_raw/tenant_id=<uuid>/dt=YYYY-MM-DD/hour=HH/part-*.jsonl.gz.
필드 타입 설명 ts ISO8601 요청 시각 tenant_id string 테넌트 UUID meter_key string 미터 키 (예: api_calls) qty number 수량 (예: 1) path string API 경로 (예: /api/v1/employee) status number HTTP 상태 (예: 200)
Aggregator는 위 파티션을 읽어 D1 usage_rollups에 Upsert (5분~1시간 단위, 멱등).
9.7 Autoscaler Health Score 패널티 요약
기술개발기획서 v4.0 §10.1. Final Score = max(0, 100 - total_penalty). 스케일 아웃: 10분 지속 + 2개 이상 메트릭 임계 초과.
패널티 조건 가중치(weight) CPU cpu_avg > 50 → (cpu_avg - 50) * 1.2 0.30 Memory mem_avg > 50 → (mem_avg - 50) * 1.0 0.25 Disk disk_pct > 70 → (disk_pct - 70) * 0.8 0.15 Latency p95 > 600ms → (p95 - 600) / 20 0.15 Error 5xx > 0.5% → err_rate * 200 0.10 Density tenant_count / max_tenants * 15 0.05
9.8 태스크 ID → 절 참조 인덱스
태스크 ID Phase 절 P1-1 ~ P1-13 Phase 1 §3.3 (태스크 분해), §3.6 (세부 체크) P2-1 ~ P2-6 Phase 2 §4.3 P3-1 ~ P3-9 Phase 3 §5.3 P4-1 ~ P4-7 Phase 4 §6.3 P5-1 ~ P5-8 Phase 5 §7.3
9.9 Cloudflare Load Balancing 요약 (Phase 4·5)
기술개발기획서 v4.0 §3.4. 리전 확장 시 적용.
구성 요소 내용 Origin Pool sg-pool (Phase 1), us-pool (Phase 4), eu-pool (Phase 5) — 리전별 오리진 IP/호스트 Health Check HTTP, 30초 간격, 각 리전 노드 라우팅 테넌트 subdomain 또는 Geo Steering으로 리전 고정 (선택) Failover 주 리전 장애 시 SG 리전 폴백 (Phase 1 기준 단일 리전) SSL Cloudflare Full Strict, 리전별 오리진 인증서 별도 발급
9.10 구현 순서 한 페이지 요약
순서 단계 내용 0 결정 §1 결정 ①·②·③ 합의 1 킥오프 §2.3 체크리스트: Stripe·Hetzner·CF·Pulumi·GitHub·D1·Queue 준비 2 Phase 1 P1-1 → P1-2, P1-3→P1-5, P1-6·P1-7, P1-8 → P1-9 → P1-10 → P1-11 → P1-12 → P1-13 (§3.4 의존성 참조) 3 Phase 2 P2-1·P2-2 병렬 → P2-3 → P2-4 → P2-5 → P2-6 4 Phase 3 P3-1, P3-4, P3-8 병렬 가능 → P3-2·P3-3, P3-6→P3-7, P3-5, P3-9 5 Phase 4 P4-1 → P4-2·P4-3, P4-4·P4-5 → P4-6 → P4-7 6 Phase 5 P5-1 → P5-2·P5-3, P5-4·P5-5, P5-7 → P5-8 (P5-6 선택)
마일스톤 : Phase 1 완료 = SG 테넌트 자동 프로비저닝 성공. Phase 2 = Usage→Stripe E2E. Phase 3 = LogPath SEV1·PDPA Purge. Phase 4 = US 리전 프로비저닝. Phase 5 = EU 리전·GDPR.
9.11 Phase별 릴리스 전 검수 체크리스트
각 Phase 완료 후 다음 Phase 착수 전 확인.
Phase 검수 항목 Phase 1 §3.5 완료 기준 전부 체크, 결정 ① 반영 동작, D1 0001~0005 정상, Runbook·Secrets 문서화 Phase 2 §4.5 완료 기준, KV·R2·Aggregator·Cycle Close E2E, 결정 ② 반영 Phase 3 §5.5 완료 기준, trace 전 구간·SEV1 1초, Audit·Purge 자동화, 0006 적용 Phase 4 §6.5 완료 기준, US 스택·resolveRegion(us)·CF LB·Autoscaler 동작. 첫 US 프로비저닝 전 §6.9 점검 Phase 5 §7.4 완료 기준, EU 스택·GDPR Purge·대시보드. 첫 EU 프로비저닝 전 §7.6 점검
9.12 5-Layer 아키텍처 ↔ Phase 매핑
기술개발기획서 v4.0 §2. Control / Data / Infrastructure / Gateway / Event Plane이 어느 Phase에서 구현되는지.
Layer 구성 요소 구현 Phase Control Plane CF Pages Functions, D1, Stripe Webhook, 테넌트 상태·Queue enqueue Phase 1 (P1-8, P1-9, P1-10) Data Plane R2 Raw Logs, Aggregator, Billing Engine, usage_rollups Phase 2 (P2-2~P2-5) Infrastructure Plane Pulumi, Ansible, GitHub Actions (Preview/Up 분리) Phase 1 (P1-1~P1-5, P1-11), Phase 4·5 (us/eu 스택) Gateway Plane Zuplo API Gateway, Rate Limit, API Key, Soft Quota(KV) Phase 1 (P1-12), Phase 2 (P2-1 KV) Event Plane LogPath Trace/Stage, audit_logs, trace_events Phase 1 (D1 0004), Phase 3 (P3-1~P3-9)
9.13 scaling_events 액션·상태 요약 (D1 0006)
필드 값 설명 action ScaleOut 신규 노드 추가 (Health Score 임계 초과) action ScaleIn 노드 감소, 해당 노드 Draining 후 제거 action Rebalance 테넌트 재배치 (선택) action Drain 특정 노드 Draining 전환 status Pending 이벤트 생성, 실행 대기 status Running 실행 중 (Pulumi/이전 작업 등) status Completed / Failed 완료 또는 실패, completed_at 기록
P4-6 Autoscaler에서 ScaleOut 시 scaling_events INSERT 후 해당 리전 Pulumi up 트리거.
9.14 Phase별 핵심 산출물 한 줄 요약
Phase 한 줄 산출 Phase 1 SG 리전에서 Stripe 결제 → Pulumi·Ansible·Zuplo까지 테넌트 자동 프로비저닝 E2E 동작 Phase 2 API 호출 → R2 Raw → Aggregator → usage_rollups → Cycle Close → Stripe 청구서 생성 Phase 3 trace_id로 전 구간 1초 조회, Audit Log 영구 보존, Soft Delete 30일 후 Hard Purge 자동, D1 0006 적용 Phase 4 Enterprise US 선택 시 prego/us(Ashburn) 프로비저닝, Autoscaler Health Score·Scale Out/In Phase 5 Enterprise EU 선택 시 prego/eu(Falkenstein) 프로비저닝, GDPR Purge·관리자 대시보드
9.15 데이터 흐름 요약 (텍스트)
프로비저닝 : Stripe Webhook → Control Plane (D1 tenants_master, provision_jobs) → CF Queue → (결정 ①) GitHub Actions Pulumi up → Ansible (서버·Frappe·API Key) → Zuplo Sync → Control Plane (status=Completed).
Usage·Billing : API 요청 → Zuplo (Soft Quota KV) → R2 Raw (tenant_id/dt/hour) → Aggregator Cron → D1 usage_rollups → Cycle Close → Stripe Usage/Invoice.
LogPath : trace_id는 Webhook·Control Plane·Queue·Pulumi/Ansible 콜백·Zuplo에서 동일 전달 → trace_events(D1 또는 R2, 결정 ③) → SEV1 조회(trace_id·time).
Purge : Pending_Deletion 30일 경과 → purge_jobs → Hetzner·R2·Snapshot 삭제 → D1 tenant row 삭제; audit_logs 유지.
9.16 Phase 완료 시그니오프 템플릿 (선택)
Phase 완료·다음 Phase 착수 전 승인 기록용. 팀 정책에 따라 사용.
Phase 완료일 검수 항목 통과 승인자 비고 Phase 1 ____ §3.5 전부 ________ SG 프로비저닝 E2E 확인 Phase 2 ____ §4.5 전부 ________ Usage→Stripe E2E 확인 Phase 3 ____ §5.5 전부 ________ LogPath SEV1·Purge 확인 Phase 4 ____ §6.5 전부 ________ US 리전·Autoscaler 확인 Phase 5 ____ §7.4 전부 ________ EU·GDPR·대시보드 확인
10. 기존 코드베이스 연계
구현 시 수정·참조할 저장소 및 경로 매핑입니다. (현재 구조 기준, 추후 폴더 정리 시 본 절 업데이트 권장.)
기획서 항목 저장소 경로/비고 Pulumi 인프라 Prego prego-pulumi/ — Cloudflare·Hetzner provider, 리전 분기(sg/us/eu)Ansible Prego config/ 또는 infra/ansible/ — Docker·Frappe·bench new-site·API Key 롤GitHub Actions Prego .github/workflows/ — pulumi-preview.yml, pulumi-up.yml, pulumi-destroy.yml 신규Control Plane (Stripe Webhook, D1) Prego CF Pages Functions 또는 동등 엣지 — Stripe Webhook 핸들러, D1 tenants_master/provision_jobs 갱신 D1 마이그레이션 Prego migrations/ 또는 D1 프로젝트 내 — 0001~0006 SQL 파일client-web (온보딩·앱 UI) Prego apps/client-web/ — 플랜/리전 선택 UI는 Phase 4+ Enterprise 분기 시 확장Zuplo Gateway, Soft Quota, NRIC 마스킹 prego-zuplo Gateway 설정, KV 백엔드(결정 ②), 미들웨어 Zuplo Sync 스크립트 Prego infra/zuplo_sync.ts — API Key 등록, Rate Limit 정책 반영R2 Raw, Aggregator Worker Prego 또는 별도 R2 버킷·파티셔닝, Cron Worker (Cloudflare Worker 또는 동등) LogPath / trace_events Prego Control Plane·Queue·Ansible 콜백에서 trace_id 전달; 저장소는 결정 ③에 따라 D1/R2/하이브리드 Audit Dashboard Prego apps/ 내 관리자 대시보드 또는 별도 앱 — audit_logs 조회·필터
참고 : saas-unified-architecture-hetzner-cloudflare-zuplo-plan.md 의 목표 디렉터리 구조와 본 Phase 산출물 위치를 맞출 것.
11. 리스크·가정·제약
11.1 리스크 (요약)
리스크 영향 대응 Provision 실행 주체 미결정(결정 ①) Phase 1 E2E 지연 §1 권장안(GitHub Actions 콜백)으로 조기 확정 Zuplo KV 미전환(결정 ②) Billing 정확성·재시작 시 카운트 손실 Phase 2 전 KV 스키마·TTL 확정 trace_events D1 집중(결정 ③ 미반영) D1 write 병목, SEV1 조회 지연 R2 오프로드 또는 배치 쓰기 설계 Hetzner 리전 가용성/레이턴시 US/EU 확장 일정 변동 Phase 1 SG 안정화 우선, Phase 4/5는 조건부 활성화 D1 리전별 인스턴스 비용·운영 복잡도 Phase 5 EU 비용 증가 d1-prego-eu는 “검토” 단계로 두고, 규제 요구 시 도입
11.2 가정
Stripe Webhook·D1·R2·Cloudflare·Hetzner API 가정상의 SLA 내 동작.
Frappe/HRMS·Ansible 롤은 기존 또는 별도 레포에서 유지·재사용.
“승인자 게이트”는 GitHub Environment Required Reviewers로 충족.
Phase 1~2 완료 시점에 실제 결제·프로비저닝 트래픽이 소규모로 존재한다고 가정.
11.3 제약
코드 생성은 본 문서에 포함하지 않음 — 별도 요청 시 Phase/태스크 단위로 진행.
Pulumi State는 Pulumi Cloud 이외 외부 저장소 비사용 권장(기술개발기획서 정책).
audit_logs는 append-only, Delete 금지(감사 요구사항).
11.4 다음 문서·산출물
본 기획서를 기준으로 이후 작성·갱신할 문서. 구현 순서에 따라 단계별 작성 권장.
문서·산출물 시점 내용 Runbook 상세 Phase 1 완료 후 §14 요약을 절차별 상세화 (Pulumi Up/Destroy, Provision 재시도, Secrets 로테이션, Hard Purge 수동) Stripe 연동 명세 Phase 1·2 Webhook 이벤트·필드 매핑, provider_events 스키마, Cycle Close→Stripe API 호출 순서 D1 마이그레이션 파일 Phase 1~3 0001~0006 SQL (기술개발기획서 §7·본 §13 참조) API·Queue 메시지 명세 Phase 1 §13.2 확장, Consumer 계약 (tenant_id, trace_id, region 등) 관리자 대시보드 요구사항 Phase 5 리전별 노드/테넌트/청구, Audit 링크, 권한 (§14.1) 첫 US/EU 프로비저닝 체크리스트 Phase 4·5 §6.9·§7.6 점검표를 Runbook 또는 운영 문서에 반영
12. 결정 로그 템플릿 (§1 외 추가 결정)
§1의 3건 외에 Phase 진행 중 발생하는 설계·운영 결정을 기록할 때 사용합니다. 아래는 §1 즉시 결정 3건을 로그에 반영한 예시.
일자 결정 제목 내용 결정자 (예) 2026-02-xx 결정 ① Provision 실행 주체 GitHub Actions + workflow_dispatch 콜백 vs Control Plane 직접 호출 → 권장안 반영 후 기록 SRE/Lead (예) 2026-02-xx 결정 ② Zuplo Soft Quota KV 백엔드 Cloudflare KV vs 외부 KV → 권장안 반영 후 기록 Backend/Lead (예) 2026-02-xx 결정 ③ trace_events 고빈도 저장 R2 오프로드 vs 하이브리드 → 권장안 반영 후 기록 SRE/Lead (추가 결정)
13. D1 마이그레이션 스키마 요약
기술개발기획서 v4.0 §7 기준. 구현 시 마이그레이션 파일 순서·외래키 의존성 준수.
Migration 테이블(주요) 목적 0001_init tenants_master, plans, plan_entitlements 테넌트 기본 상태, 플랜 정의 0002_billing billing_customers, subscriptions, provider_events, invoices Stripe 연동, 청구 상태 0003_jobs_runtime tenant_runtime, secret_refs, provision_jobs, purge_jobs 비동기 작업, 런타임 정보 0004_logpath_audit traces, trace_events, audit_logs LogPath 이벤트 추적, 감사 (append-only) 0005_usage_metering meters, usage_rollups, usage_cycle_totals, meter_rates Usage 집계, 청구 계산 0006_multiregion nodes, node_metrics_rollups, scaling_events, placement_history; tenants_master.preferred_region, failover_region 멀티리전 Node Pool, 오토스케일러
참고 : tenants_master.region 기본값 'sg'. Phase 3에서 0006 적용 후 nodes·scaling_events 사용.
13.1 D1 tenants_master · provision_jobs 핵심 컬럼 (구현 참조)
Phase 1 Webhook·Queue 연동 시 참조. 마이그레이션 0001, 0003 정의와 일치시키면 됨.
테이블 컬럼(핵심) 용도 tenants_master tenant_id (PK), status, region, plan_tier, preferred_region (0006), failover_region (0006) 테넌트 상태·리전; status=Active/Pending_Deletion 등 tenants_master created_at, updated_at 감사 provision_jobs job_id (PK), tenant_id, trace_id, region, status, created_at Queue enqueue 시 INSERT; status=Pending/Running/Completed/Failed provision_jobs plan_tier, infra_mode (선택) resolveRegion·Pulumi 스택 분기 provider_events (0002) event_id (Stripe event.id 등), idempotency Webhook 멱등 처리
13.2 Provision Queue 메시지 스키마
CF Queue(또는 결정 ①에 따른 Queue)에 넣는 프로비저닝 작업 페이로드. Consumer가 Pulumi 트리거 시 동일 필드 전달.
필드 타입 필수 설명 tenant_id string (UUID) ✓ 테넌트 식별자 trace_id string (UUID) ✓ LogPath 전 구간 동일 ID region string ✓ ‘sg’ / ‘us’ / ‘eu’ — Pulumi 스택 선택 plan_tier string 선택 Basic / Professional / Enterprise infra_mode string 선택 shared_node / dedicated_node job_id string 선택 provision_jobs.job_id (상태 갱신용)
14. 운영 Runbook 요약
Phase 1 정리 후 유지·보완. 상세 절차는 별도 Runbook 문서 권장.
상황 조치 요약 Pulumi Up 실패 GitHub Actions 로그 확인 → 필요 시 pulumi refresh / 수동 pulumi up (동일 스택). State 충돌 시 Pulumi Cloud에서 lock 확인 후 재시도. Pulumi Destroy (테넌트/노드 제거) .github/workflows/pulumi-destroy.yml workflow_dispatch 실행, tenant_id·region 입력, confirm에 “DESTROY” 입력. production-destroy 환경 2인 승인 후 실행.Provision 재시도 Queue 재처리(지수 백오프, max 5회). 실패 시 Slack Alert 확인, provision_jobs 상태·trace_id로 LogPath 추적. Stripe Webhook 지연/중복 provider_events 멱등성 키로 중복 무시. 7일 Grace 기간 동안 Active 유지. Secrets 로테이션 HCLOUD_TOKEN_* 90일, PULUMI_ACCESS_TOKEN 180일, CLOUDFLARE_API_TOKEN 90일. 로테이션 후 해당 Environment 사용 워크플로우 재실행 검증. Hard Purge 수동 트리거 30일 미만 테넌트는 정책상 수동 Purge 비권장. 예외 시 Purge Job 수동 실행 후 D1·R2·Hetzner 순서 확인. 리전 장애 (Phase 4+) Cloudflare Failover → SG 리전 폴백. Health Check 복구 후 수동으로 라우팅 복원 가능 여부 검토.
14.1 Phase별 Runbook·문서 갱신 포인트
각 Phase 완료 시 업데이트할 운영 문서·Runbook 항목.
Phase 갱신 대상 Phase 1 Runbook: Pulumi Up/Destroy 절차, Provision 재시도, Secrets 목록·로테이션 주기, Environment Protection Rules Phase 2 Runbook: R2 버킷·파티션, Aggregator Cron, Cycle Close 일정·Stripe 연동, KV 스키마 Phase 3 Runbook: Hard Purge 순서(§5.8), trace 조회·SEV1 절차, Audit Dashboard 접근, 0006 스키마 Phase 4 Runbook: US 스택·리전, CF Load Balancing·Failover, Autoscaler 메트릭·Scale Out/In 절차. 첫 US 전 §6.9 점검 절차 포함 Phase 5 Runbook: EU 스택·GDPR Purge, 리전별 Secrets·Environment, 관리자 대시보드. 첫 EU 전 §7.6 점검 절차 포함
15. 용어·약어 정리
용어/약어 의미 SG Singapore 리전 (Phase 1 기본) US / IAD Ashburn, VA (미주) — Phase 4 EU / FSN Falkenstein (유럽) — Phase 5 D1 Cloudflare D1 (SQLite 호환 State DB) R2 Cloudflare R2 (Raw Log, Usage 파티셔닝) KV Cloudflare Workers KV (Zuplo Soft Quota 백엔드) Control Plane CF Pages Functions + D1, Stripe Webhook, 테넌트 상태 관리 Data Plane R2 Raw, Aggregator, Billing Engine Gateway Plane Zuplo API Gateway, Rate Limit, API Key Event Plane LogPath Trace/Stage, audit_logs PDPA Personal Data Protection Act (Singapore) GDPR EU 일반 개인정보 보호 규칙 (Phase 5) SEV1 Severity 1 — LogPath 기준 1초 이내 분석 목표 plan_tier Basic / Professional / Enterprise (리전 선택은 Enterprise) infra_mode shared_node(멀티사이트) / dedicated_node(전용 서버) Cycle Close Billing Cycle 월말 실행 — included 차감·overage 계산·Stripe 전송 (§4.7) ScaleOut / ScaleIn Autoscaler가 노드 추가/감소 시 scaling_events action (§9.13) Draining nodes.status — 신규 배치 중단, 기존 트래픽만 유지 후 제거 (§6.8) workflow_dispatch GitHub Actions 수동 트리거; pulumi-up·pulumi-destroy에서 사용 (§9.1)
15.1 기술개발기획서 v4.0 인용 문구
구현 시 상세 수식·코드 예시·구문은 기술개발기획서 v4.0 해당 절 참조.
참조 내용 v4.0 절 REGION_CONFIG·resolveRegion() 코드 예시 §3.2 Pulumi preview/up/destroy 워크플로우 예시 §4.2~4.4 0006_multiregion SQL 예시 §7.2 R2 파티셔닝·JSONL 레코드 예시 §8.2 Health Score 패널티 수식 §10.1 Trace Stage 순서·멀티리전 trace 확장 §9.1, §9.2
16. 기술개발기획서 v4.0 ↔ 본 기획서 절 대응표
참조 문서(기술개발기획서 v4.0) 섹션 번호와 본 구현 기획서 절 번호 매핑.
기술개발기획서 v4.0 본 기획서 §0 문서 목적·버전 — §1 프로젝트 목표 §0, §2 §2 아키텍처 5-Layer §0, §10 §3 Multi-Region 전략 §2, §3~§7, §9.4, §9.5 §4 GitHub Actions CI/CD (Preview/Up 분리) §3.3~3.5, §9.1, §9.4 §5 Pulumi 스택·디렉토리 §3.2, §9.2, §10 §6 신규 테넌트 Atomic Workflow §2.1, §2.2, §3 §7 D1 State DB 스키마 §13, §3.2 (P1-8) §8 Usage-Based Billing §4, §9.6 §9 LogPath Trace/Stage §2.1, §2.2, §5 §10 Autoscaler & Node Pool §6, §9.7 §11 PDPA 데이터 보호 §5, §8, §14 §12 Fail Sanely §8, §14 §13 보안 설계 §8 §14 개발 단계 로드맵 §2, §9.3 §15 확장성 평가 §11 §16 최종 결론·최우선 리스크 3가지 §1
16.1 본 기획서 절 → v4.0 절 (역방향)
구현 시 “이 절의 상세 수식·코드 예시는 v4.0 §X 참조”용 빠른 참조.
본 기획서 (주요 절) v4.0 참조 §2.1 E2E 시퀀스, §2.2 Trace Stage §6, §9.1 §3 (Phase 1, Pulumi·Ansible·Webhook) §4, §5, §6 §4 (Billing·R2·Aggregator) §8 §5 (LogPath·Purge·0006) §9, §11 §6 (US 리전·Autoscaler) §3, §10 §9.1 GitHub Actions §4.2~4.4 §9.7 Health Score §10.1 §13 D1 스키마 §7 §1 결정 3건 §16 최종 결론
17. 외부 참조 링크
구현 시 참조할 공식 문서·API (URL은 예시, 최신 문서로 확인 권장).
대상 참조 Stripe Webhooks (event types, idempotency), Billing (Usage, Invoice API) Hetzner Cloud API (Servers, SSH Keys, Datacenters), ash-dc3 / fsn1-dc14 / nbg1-dc3 Cloudflare D1 (SQLite, migrations), R2 (S3-compatible API), Workers KV, Load Balancing, Access Pulumi pulumi/actions (GitHub Actions), State (Pulumi Cloud), Hetzner/Cloudflare providers Zuplo API Key, Rate Limiting, Soft Quota, KV 백엔드(결정 ②)
18. 변경 이력
버전 변경 내용 작성일 0.1 초안 — Phase 1~5 태스크 분해, 즉시 결정 3건, 완료 기준 2026-02 0.2 §10 기존 코드베이스 연계, §11 리스크·가정·제약, §12 결정 로그 템플릿, Phase 5 태스크 세부화(P5-1~P5-8) 2026-02 0.3 Phase 2·3·4 의존성 다이어그램(§4.4, §5.4, §6.4), §13 D1 스키마 요약, §14 운영 Runbook 요약, §15 용어·약어 2026-02 0.4 §2.1 신규 테넌트 E2E 시퀀스, §2.2 Trace Stage↔태스크 매핑, §9.1 GitHub Actions 요약, §9.2 Phase별 산출물 체크리스트 2026-02 0.5 목차 추가, §9.3 Phase별 인수 테스트 시나리오 요약, §9.4 리전·스택·환경·Secrets 매트릭스 2026-02 0.6 §9.5 plan_tier↔리전·인프라 매트릭스, §9.6 R2 Raw 로그 스키마, §9.7 Health Score 패널티, §16 기술개발기획서 절 대응표 2026-02 0.7 §3.6 Phase 1 태스크별 세부 체크 항목, §3.7 Stripe↔Control Plane 매핑, §8.1 Fail Sanely 상세 표 2026-02 0.8 §9.8 태스크 ID→절 참조 인덱스, §13.1 D1 tenants_master·provision_jobs 핵심 컬럼, §13.2 Provision Queue 메시지 스키마 2026-02 0.9 §2.3 킥오프·사전 준비 체크리스트, §4.6 Phase 2·§5.6 Phase 3 태스크별 세부 체크, §8.2 보안 설계 체크리스트, §9.9 CF Load Balancing 요약 2026-02 0.10 §6.6 Phase 4·§7.5 Phase 5 태스크별 세부 체크, §9.10 구현 순서 한 페이지 요약 2026-02 0.11 §2.4 테넌트 상태 전이, §8.3 Slack·Alert 메시지 포맷, §9.11 Phase별 릴리스 전 검수, §17 외부 참조 링크 2026-02 0.12 §2.5 provision_jobs 상태 전이, §8.4 재시도·에러 정책 요약, §9.12 5-Layer↔Phase 매핑 2026-02 0.13 §0.1 기획서 완성도·반영 체크, §6.7 Autoscaler 메트릭 수집 항목 2026-02 0.14 §0.2 빠른 참조(주제별 절), §4.7 Billing Cycle·included·overage, §5.7 trace_events 스키마, §6.8 nodes.status 전이 2026-02 0.15 §5.8 Hard Purge 실행 순서, §9.13 scaling_events 액션·상태, §14.1 Phase별 Runbook·문서 갱신 포인트 2026-02 0.16 §2.6 purge_jobs 상태 전이, §3.8 Stripe Webhook 처리 대상 이벤트, §9.14 Phase별 핵심 산출물 한 줄 요약 2026-02 0.17 §0.3 문서 유지보수 체크리스트, §8.5 역할·에스컬레이션 요약, §15.1 기술개발기획서 v4.0 인용 문구 2026-02 0.18 §0.4 제외 범위·Known Gaps, §2.7 Phase 간 의존성 다이어그램, §9.15 데이터 흐름 요약 2026-02 0.19 §9.16 Phase 완료 시그니오프 템플릿, §11.4 다음 문서·산출물 2026-02 0.20 §0.5 Executive Summary, §8.6 주요 에러 시나리오·대응 한 줄, §16.1 본 기획서→v4.0 역방향 대응표 2026-02 0.21 로드맵 표에 예상 소요(참고) 열, §0.2 빠른 참조에 에러 시나리오, §2.8 Phase별 블로커 요약 2026-02 0.22 §3.9 Phase 1 첫 배포 전 최종 점검, §15 용어 추가(Cycle Close, ScaleOut/ScaleIn, Draining, workflow_dispatch) 2026-02 0.23 §0.6 이 문서로 할 수 있는 것·할 수 없는 것, §0.2 빠른 참조에 Phase 1 첫 배포 전 점검(§3.9) 2026-02 0.24 로드맵 예상 소요 주석, §0 문서 개요에 문서 버전 행, §4.8 Phase 2 첫 Cycle Close 전 점검, §5.9 Phase 3 첫 Hard Purge 전 점검 2026-02 0.25 §0.2 빠른 참조에 Phase 2·3 적용 전 점검(§4.8·§5.9), §6.9 Phase 4 첫 US 프로비저닝 전 점검, §7.6 Phase 5 첫 EU 프로비저닝 전 점검 2026-02 0.26 §0.2 Phase 4·5 첫 점검(§6.9·§7.6) 참조 추가, §9.11 Phase 4·5에 §6.9·§7.6 언급, §14.1 Runbook에 첫 US/EU 점검 포함, §11.4 첫 US/EU 체크리스트 문서 행, §12 결정 로그에 §1 3건 예시 행 2026-02
다음 단계 : §1 최우선 3가지 결정 합의 후 Phase 1 태스크(P1-1~P1-13) 착수 및 본 기획서 “결정 상태” 업데이트.