# BAT-054: Implementation - Status: completed - Batch: BAT-054 ## Plan Summary BAT-053에서 스캐폴드로 처리된 양의 경로를 완성: 1. `KISBroker.reinitialize(credential)` 메서드 추가 — app_key/app_secret/account_ref 교체 + L1 token 무효화 2. `SnapshotScheduler`에 `kis_reinit_callback` 주입 지점 추가 — 그날-시작 성공 시 callback 호출 3. `daemon.py`에 `_build_kis_reinit_callback()` 헬퍼 + SnapshotScheduler 조립 수정 4. 신규 AC 테스트 12개 추가 (REQ-113 AC-2/AC-4 보강, REQ-115 AC-1) ## Changed Files | 파일 | 변경 유형 | 관련 REQ | | --- | --- | --- | | `trex_core/adapters/broker/kis.py` | 확장 (reinitialize 메서드 추가) | REQ-113 AC-2, REQ-115 AC-1 | | `trex_core/application/snapshot_scheduler.py` | 확장 (kis_reinit_callback 인자 + 성공 경로 callback 호출) | REQ-113 AC-2, REQ-115 AC-1 | | `trex_core/runtime/daemon.py` | 확장 (_build_kis_reinit_callback 헬퍼 + SnapshotScheduler 조립) | REQ-113 AC-2, REQ-115 AC-1 | | `tests/application/test_snapshot_scheduler.py` | 확장 (BAT-054 테스트 12개 추가) | REQ-113 AC-2/AC-4, REQ-115 AC-1 | ## Execution Log 1. `KISBroker.reinitialize()` 구현: - `self._account_ref/app_key/app_secret` 교체 - `self._token = None`, `self._token_exp = datetime.min(UTC)` L1 무효화 - `base_url/timeout/mock/allow_live` 불변 (env-sourced 인프라 설정) - docstring에 L2 Redis token cache 처리 방침(새 key miss → 자연 재발급) 기술 2. `SnapshotScheduler.__init__` 확장: - `kis_reinit_callback: Optional[Callable[[BrokerCredentialPayload], None]] = None` 추가 - `self._kis_reinit_callback` 저장 3. `SnapshotScheduler._maybe_fetch_credential()` 성공 경로 확장: - 기존 INFO 로그 뒤에 callback 호출 블록 추가 - callback 실패 시 ERROR 로그 + entry_allowed 유지(fail-safe) - break-glass 경로: callback 호출 없음 (env 인증정보 사용) 4. `daemon.py` 확장: - `_build_kis_reinit_callback(config, broker)` 헬퍼 추가 - `config.broker != 'kis'` → None - `not config.credential_fetch_enabled` → None - `broker.reinitialize` 없음 → None - 조건 충족 시 `broker.reinitialize` callable 반환 - `SnapshotScheduler` 생성 시 `kis_reinit_callback=_build_kis_reinit_callback(config, self.broker)` 전달 5. 테스트 추가 (12개): - `test_kis_reinit_callback_called_on_success` — AC-2: fetch 성공 시 callback 호출 - `test_kis_reinit_callback_not_called_when_fail_closed` — AC-2: fail-closed 시 callback 미호출 - `test_kis_reinit_callback_not_called_when_disabled` — AC-1 회귀: opt-in off 시 callback 미호출 - `test_kis_reinit_callback_failure_does_not_flip_entry_allowed` — 설계 안전망: reinit 실패 시 entry_allowed 유지 - `test_kis_reinit_callback_cached_for_day_not_called_twice` — REQ-115 AC-3: 그날 두 번째 run_once에서 재호출 없음 - `test_kis_reinit_callback_none_when_break_glass` — AC-3+AC-2: break-glass 시 callback 없음 - `test_break_glass_log_contains_break_glass_keyword` — REQ-113 AC-4 보강: break-glass 로그 content - `test_kis_broker_reinitialize_updates_credentials` — REQ-115 AC-1: 인증정보 교체 + L1 무효화 - `test_kis_broker_reinitialize_preserves_base_url_and_flags` — REQ-115 AC-1: 인프라 설정 불변 - `test_build_kis_reinit_callback_returns_none_for_paper` — AC-2: paper broker → None - `test_build_kis_reinit_callback_returns_none_when_disabled` — AC-1: fetch disabled → None - `test_build_kis_reinit_callback_returns_callable_for_kis` — AC-2/AC-1: kis+enabled → callable ## Validation ``` cd /home/genichin/workspace/trex-lead/repos/trex-core/.claude/worktrees/agent-a0d6ff73d43f2e96b python3 -m pytest tests/application/test_snapshot_scheduler.py -v ``` 결과: **29 passed** (BAT-053 기존 17 + BAT-054 신규 12) ``` python3 -m pytest tests/ -q ``` 결과: **757 passed, 47 skipped** (기존 베이스라인 745 대비 +12, 회귀 0) ## Remaining Risks - R1 (Low): 실 portfolio-hub 없이 stub 기반으로만 검증. 실 `/v1/user_info` 응답 스키마 호환은 portfolio-hub dcy-010 배포 후 통합 테스트에서 확인 필요. - R2 (Low): KISBroker.reinitialize()는 그날-시작(장 전) 1회 호출 설계이므로 in-flight HTTP 경쟁 조건 위험이 낮으나, 장중 reinitialize가 필요한 시나리오가 생기면 threading.Lock 추가 검토 필요. - R3 (Low): L2 Redis token cache(REQ-016) 명시적 무효화 없음 — 새 (account_ref, app_key) key miss로 자연 재발급 처리. 동일 account_ref/app_key인데 app_secret만 바뀐 경우 구 토큰이 TTL 만료 전까지 유효할 수 있음. 운영상 계좌 인증정보 전체가 함께 교체되는 구조라 실용적으로 문제 없음.