# AEG-VS-00-05: Job Run 스키마 & 운영 정책 승인 요청

**WBS Item:** AEG-VS-00-05  
**Status:** ⏳ IN_PROGRESS → DECISION_REQUIRED  
**Decision Owner:** SRE/DBA, Architecture  
**Blocks:** Event/Job/Inbox 계약 완료, 재처리 정책 확정  
**Impact:** Job 실행 추적 미완료, 재시도 정책 불명확, 감시 불완전  

---

## 현재 상태

**구현 완료:**
- ✅ db/migrations/0000_building_blocks.sql (building_blocks.job_run 생성)
- ✅ DapperJobRunRepository.cs (CRUD 구현)
- ✅ OutboxPollerJob (이벤트 폴링)
- ✅ DownstreamConsumerJob (Inbox 처리)
- ✅ Architecture tests 6/6 PASS

**검증 대기:**
- ⏳ Fresh/upgrade/re-run/failure 리허설 증거 (DB 필요)
- ⏳ 보존 정책 (retention policy)
- ⏳ 인덱싱 전략
- ⏳ 운영 SLA 계약

---

## 필요한 4가지 결정

### 1️⃣ Job Run 상태 모델 (State Machine Contract)

**결정:** Job 실행의 허용된 상태 전이 정의

```
Current schema (building_blocks.job_run):
- id: UUID
- job_type: enum (ShadowRun, OutboxPoller, TradeStatusPolling, etc.)
- status: enum (Queued, Running, Completed, Failed, ???)
- created_at: timestamp
- completed_at: timestamp (nullable)
- duration_ms: integer
- error_message: text
- result_summary: JSONB
- retry_count: integer
- idempotency_key: UUID (unique, for replay safety)

Questions:
✅ 허용 상태: [ ] (Queued → Running → Completed/Failed/BusinessHold?)
✅ 중간 상태 필요: [ ] (Retrying? Paused?)
✅ 상태별 재시도 정책: [ ] (transient/permanent/dq/business-hold 분류?)
✅ 최대 재시도: [ ] (count)

Linked Items:
- Hangfire job status (how to map?)
- DEBT-024 (retry classification)
- Exponential backoff policy
```

### 2️⃣ Job 실행 재처리 정책 (Replay Semantics)

**결정:** 실패 Job의 재처리 조건과 안전성

```
Idempotency guarantee:
- Current: idempotency_key (UUID unique constraint)
- Goal: Same key → Same result (deterministic)

Questions:
✅ Determinism 범위: [ ] (모든 Job? 일부만?)
✅ 외부 API 호출: [ ] (재시도 시 replay 가능?)
✅ 부분 실패: [ ] (일부 성공 + 일부 실패 → 어떻게?)
✅ 재처리 기한: [ ] (24h? 7일? 무제한?)

Linked Items:
- OutboxPollerJob (exactly-once semantics)
- DapperInboxStore (deduplication)
- Distributed transaction boundaries
```

### 3️⃣ 보존 정책 & 정리 (Retention & Archival)

**결정:** Job 실행 기록을 얼마나 오래 보관할 것인가

```
Current state:
- No archival or cleanup defined
- Table growth: unbounded (2-3 jobs/second × 365 days = ~60M rows/year)

Questions:
✅ 보존 기간: [ ] (30일? 90일? 1년? 영구?)
✅ 정리 정책: [ ] (DELETE? Archive to S3? Summarize?)
✅ 감사 대상: [ ] (특정 job_type만? 모두?)
✅ GDPR 대응: [ ] (actor/IP/data redaction?)

Linked Items:
- GDPR retention (docs/CURRENT/AEG-X-007_*)
- Compliance retention periods
- Database archival strategy
- Grafana metric retention
```

### 4️⃣ 운영 모니터링 & SLA (Operational Contract)

**결정:** Job 성능과 SLA 목표

```
Metrics needed:
- P95/P99 job duration (by job_type)
- Failure rate (% per hour)
- Retry rate (successful retries vs give-up)
- Queue depth (pending jobs)

Questions:
✅ SLA 목표: [ ] (e.g., P95 < 5s, failure rate < 0.1%)
✅ Alert 임계값: [ ] (error rate > 5%? retry rate > 10%?)
✅ 주간 보고: [ ] (job success rate, avg duration, anomalies)
✅ 에스컬레이션: [ ] (SRE pager? on-call runbook?)

Linked Items:
- Serilog structured logging (job_run_id in logs)
- OpenTelemetry spans (job execution tracing)
- Grafana dashboards (job health)
- Runbook (failure scenarios & recovery)
```

---

## 제출 형식

**승인자는 다음 정보 제공:**

### 1. Job Run State Machine
```
Allowed States:
  [x] Queued → Running → Completed
  [ ] Queued → Running → Retrying → Running → Completed
  [ ] Queued → Running → Failed → [terminal]
  
Max Retries: [ ] (count)

Retry Classification:
  - Transient: [ ] (e.g., timeout, 503)
  - Permanent: [ ] (e.g., 400, bad input)
  - DQ (Data Quality): [ ] (e.g., missing field)
  - BusinessHold: [ ] (e.g., awaiting approval)
```

### 2. Replay Semantics
```
Idempotency Guarantee:
  Applies to all jobs: [ ] (Yes/No)
  
External API retry policy:
  Retry on 5xx: [ ] (Yes/No)
  Retry on timeout: [ ] (Yes/No)
  
Partial failure handling:
  Strategy: [ ] (all-or-nothing / partial-OK)
  
Replay deadline: [ ] (hours)
```

### 3. Retention Policy
```
Retention Period:
  All jobs: [ ] (days)
  Failed/Retry jobs: [ ] (days, if different)
  Archived jobs: [ ] (S3 path or delete)
  
GDPR Compliance:
  Redact actor/IP: [ ] (Yes/No)
  Retention audit: [ ] (Yes/No)
```

### 4. Operational SLA
```
Performance Target:
  P95 duration: [ ] (ms)
  P99 duration: [ ] (ms)
  
Availability:
  Target failure rate: [ ] (%)
  Alert threshold: [ ] (%)
  
Monitoring:
  Dashboard link: [ ] (Grafana path)
  Runbook: [ ] (ops/runbook link)
```

---

## 의존성

- **Blocks:** Event/Job/Inbox 완전 구현, VS-26/28/29 프로덕션 등록
- **Related:** Hangfire 스케줄링, Outbox/Inbox 패턴, 감시
- **Prerequisite:** SRE/DBA/Architecture 팀 협력

---

**제출 기한:** 2026-08-21 (1주)  
**승인자:** SRE Lead, DBA Lead, Architecture  
**Escalation:** CTO (정책 논쟁 시)
