# RTGS 검증 하니스 (sim/)

복원력방안 **부록A**가 지목한 미검증 급소를, 로컬 1센터(DC1) 프로토타입으로 재현·측정한다.
점검대상 3축(기능성·복원성·가용성) 중 로컬에서 자동 검증 가능한 S1·S2·S4를 스크립트로 제공한다.

> 실행 환경: 포터블 **Git Bash**. 실행 중인 DC1 스택(인프라 + 6서비스)을 전제로 한다.
> 실행 예: `bash sim/s1_consistency.sh`

| 스크립트 | 점검축 | 검증 내용 | 합격 기준 |
|---|---|---|---|
| `s1_consistency.sh [건수]` | 기능성 | 평상시 부하 후 전 계층 대사 | 총액 보존 · 미완결 0 · 음수계좌 0 · 원장=조회사본 |
| `s2_failover.sh [건수]` | 복원성 | 부하 중 Hermes 강제종료·재기동 | 투입 전건 완결(유실 0) · 총액 보존 |
| `s4_order.sh` | 기능성 | 저널에 전역순번 **역전 주입** | 3건 전건 완결 · 저널 순번 순서 기록 · 총액 보존 |
| `reconcile.sql` | 기능성 | 수동 대사 리포트 | (판단용 6개 지표 출력) |

## 각 시나리오 원리

### S1 — 정합성 (기능성)
무작위 이체 N건을 정식 pacs.008.001.08로 투입 → 정산 드레인 대기 → 대사.
**총액 보존 불변식**(이체 전후 계좌 합계 동일 = 돈이 생기거나 사라지지 않음 = 이중지급 0)과
원장(transfer)·조회사본(settlement_view)·선저널(journal_log) 계층 일치를 확인한다.

### S2 — 무손실 승계 (복원성)
부하 투입 중 원장엔진 **Hermes를 강제 종료**했다가 재기동한다. Hermes는
- 정산 **전에 선저널(write-ahead)** 을 남기고(무손실 승계의 근거),
- Kafka 오프셋을 **record 커밋**하므로, 재기동 시 마지막 커밋 지점부터 저널을 **재생**한다.

→ 죽은 순간의 in-flight 건도 유실 없이 이어서 완결된다. 투입 전건이 ACCC/RJCT에 도달하고
총액이 보존되면 합격.

### S4 — 순서오류 탐지·교정 (기능성)
순번기를 잠시 멈춘 뒤(경쟁 발번 차단), 저널(rtgs.journal, 단일 파티션)에 전역순번을
**역전 순서(M+2 → M+3 → M+1)** 로 직접 주입한다. Hermes는 `expected` 순번과 비교해
- 앞선 순번(M+2, M+3)은 **pending 버퍼에 보관(gap 감지)**,
- 기다리던 M+1이 도착하면 적용 후 **버퍼를 순서대로 드레인**한다.

→ 3건이 저널에 M+1, M+2, M+3 순서로 기록되고 전건 완결되면 재정렬 성공.
검증 후 순번기를 재기동하면 **순번 영속화(2-1)** 덕에 MAX(global_seq) 다음부터 안전하게 이어서 발번한다.

## 주의
- **S2/S4는 서비스(Hermes/Sequencer)를 죽였다 살린다.** 양팀장님의 수동 기능 테스트와
  겹치지 않을 때 실행하세요(각 스크립트가 스스로 서비스를 재기동합니다).
- 스크립트는 계좌 잔액을 리셋하지 않는다(총액 보존만 검증). 상태를 깔끔히 하려면
  관리자 탭 → **DB 초기화** 후 실행.

## 향후 (고사양 PC 이관 후)
- **S3 정족수/펜싱**(가용성): 3센터에서 소수측 분할 → 1센터 다운 지속·2센터 다운 안전정지. 다센터 필요.
- **S5 스파이크**(성능): 순번기 상한 초과 부하 → Kafka 완충. k6 `MODE=spike`로 근사.
- 순번기 단독 처리량 상한(TPS) 측정.

## 검증 결과 (2026-07-10, 로컬 DC1)
- **S1 PASS** — 20건, 총액 190억 보존, 미완결 0, 원장=사본 일치.
- **S2 PASS** — 30건 투입 중 Hermes 강제종료·재기동, 전건 완결·유실 0·총액 보존.
- **S4 PASS** — seq 965→966→964 역전 주입 → 964,965,966 순서 기록·전건 ACCC·총액 보존.
