Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
7.5 KiB
7.5 KiB
req-114: 그날-시작 로드 게이트 — fail-closed 신규 진입 차단 + 알람
- Status: Approved
- Type: Integration
- Priority: High
- Owner: trex-core-dev
Intent
- dcy-036 C2/FR-2에 따라, 그날-시작 체크포인트(단기: 07:30 KST 스냅샷, 중장기: dcy-027 운영 프로파일 주기)에서 portfolio-hub가 불가하거나 broker 인증정보 부재(
broker: null) 또는trading_enabled: false이면 그날 신규 진입을 개시하지 않는다(fail-closed). 사유를 로깅하고 운영자 알람을 발신한다. - "그날 고정" 원칙: 로드 성공 후 그날 인증정보는 캐시로 유지되며, 장중 portfolio-hub 복구 시에도 그날 재fetch하지 않는다(결정론 — REQ-115 담당).
Requirement
- 그날-시작 체크포인트 후크:
SnapshotScheduler.run_once()(단기 07:30 KST 스냅샷 트리거)의credential_fetch_enabled = true경로에서, 스냅샷 전fetch_broker_credential()(REQ-112)를 호출해TradingContext를 획득한다. 중장기 인스턴스는 dcy-027 운영 프로파일 리밸런싱 주기의 동등한 후크 지점에서 동일 로직을 수행한다. - fail-closed 조건: 다음 중 하나라도 해당하면 그날
entry_allowed = False상태를 설정한다:PortfolioHubUnavailableError(네트워크 오류 / 비-2xx / 403)TradingContext.broker is None(인증정보 부재)TradingContext.trading_enabled is False
- 진입 차단:
entry_allowed = False상태에서 BuyIntent(신규 진입 의도)는 admission 단계에서 거부된다. 이미 진행 중인 주문(DISPATCHED 슬롯)과 청산(SellIntent) 경로는 차단하지 않는다. - 사유 로깅: fail-closed 진입 시 ERROR 레벨로 사유(portfolio-hub 불가 / broker null / trading_enabled false)와 인스턴스 정보를 로깅한다. app_secret은 로그에 포함하지 않는다.
- 알람 발신: fail-closed 진입 시 CRITICAL 알람을
AlarmEmitter를 통해 발신한다(trex.alertsexchange, REQ-099/100). 알람 코드:DAY_START_LOAD_FAILED. 알람 페이로드에는 사유 코드와 인스턴스 키를 포함한다. - 성공 로깅: 로드 성공 시 INFO 레벨로 fetch 소스, account_ref(app_secret 제외), trading_enabled를 기록한다.
Acceptance Criteria
- Given
credential_fetch_enabled = true이고 그날-시작 체크포인트에서PortfolioHubUnavailableError발생, When 체크포인트 실행, Thenentry_allowed = False설정 + ERROR 로그 + CRITICAL 알람(DAY_START_LOAD_FAILED) 발신. - Given
credential_fetch_enabled = true이고 그날-시작 체크포인트에서TradingContext.broker is None, When 체크포인트 실행, Thenentry_allowed = False설정 + ERROR 로그 + CRITICAL 알람 발신. - Given
credential_fetch_enabled = true이고 그날-시작 체크포인트에서TradingContext.trading_enabled = False, When 체크포인트 실행, Thenentry_allowed = False설정 + ERROR 로그 + CRITICAL 알람 발신. - Given
entry_allowed = False상태, When BuyIntent 수신, Then BuyIntent가 admission 단계에서 거부된다 (신규 진입 차단). - Given
entry_allowed = False상태, When SellIntent 수신, Then SellIntent는 차단되지 않고 정상 처리된다 (청산 경로 영향 없음). - Given
credential_fetch_enabled = true이고 그날-시작 체크포인트 성공(broker있음 +trading_enabled = True), When 체크포인트 실행, Thenentry_allowed = True설정 + INFO 로그(account_ref 포함, app_secret 제외). - Given
credential_fetch_enabled = false, When 그날-시작 체크포인트 실행, Thenfetch_broker_credential()호출 없이 기존 스냅샷 로직만 수행된다 (회귀 없음, opt-in 보존). - Given 알람 발신 성공, When
trex.alertsexchange 메시지 확인, ThenDAY_START_LOAD_FAILED코드와 instance_key를 포함한 알람 envelope가 존재한다. - Given fail-closed 후
entry_allowed = False상태에서 portfolio-hub가 복구됨, When 그날 중 재fetch 없이 운행, Thenentry_allowed상태는 그날 고정(재fetch로 자동 해제 안 됨) — 다음 그날-시작 체크포인트까지 유지.
Impacted Area
- Docs: 없음 (baseline 문서 갱신은 별도 scope)
- Modules:
trex_core/application/snapshot_scheduler.py—run_once()또는 그날-시작 후크 지점에fetch_broker_credential()호출 +entry_allowed상태 설정 + 알람 발신 추가trex_core/application/execution.py(또는 IntentService) — BuyIntent admission에entry_allowed게이트 추가trex_core/application/alarm_emitter.py—DAY_START_LOAD_FAILED알람 코드 추가(REQ-100 패턴 재사용)
- Tests:
tests/application/test_snapshot_scheduler.py— AC-13, AC-69 케이스 추가 (stub fetch_broker_credential + AlarmEmitter mock)tests/application/test_execution.py(또는 IntentService 테스트) — AC-4~5 케이스 추가
Notes
- OQ-4(그날-시작 로드 실패 알람 trex-notifier 연동): Deferred — 이 REQ는
trex.alertsexchange 발신(REQ-099/100 계약)까지만 정의한다. trex-notifier(dcy-033) 연동은 별도 REQ/Discovery로 추적한다. 알람 등급은 CRITICAL(거래 개시 불가). entry_allowed상태 저장소: in-process 상태 변수(process-local)로 충분하다. 재시작 시 그날-시작 체크포인트가 재실행되므로 내구성 저장소 불필요.- 중장기 인스턴스의 "그날-시작 체크포인트" 시점은 dcy-027 운영 프로파일 리밸런싱 주기의 구체적 후크 위치에 의존한다. 구현 단계에서 확인 후 조정.
- AC-9(그날 고정 상태 불변성): 장중 재fetch 없음이 REQ-115의 보완 요건이기도 하다. 이 REQ는 "진입 차단 상태의 그날 고정"만 명시하고, "장중 장애 후 인증정보 캐시 지속 운행"은 REQ-115가 담당.
- Source: dcy-036 C2, FR-2, OQ-1 Answered (단기 07:30 / 중장기 프로파일 주기), OQ-2 Answered (그날 고정).
Change Log
CHG-20260628-01
- Date: 2026-06-28
- Author: trex-core-dev
Change Summary
- 신규 생성 (Proposed) — dcy-036 C2/FR-2 산출물.
Intent
- dcy-036 FR-2(그날-시작 로드 시점 fail-closed 진입 차단 + 알람)를 Integration REQ로 정규화한다.
Acceptance Criteria Delta
- Added:
- AC-1~9 전체 (신규 초안)
- Updated: 없음
- Removed: 없음
Impacted Area Delta
- Docs: 없음
- Modules:
snapshot_scheduler.py그날-시작 후크 + entry_allowed 상태 + 알람execution.py/ IntentService BuyIntent admission 게이트alarm_emitter.py코드 추가
- Tests:
test_snapshot_scheduler.py,test_execution.py
Delivery Trace Delta
- Batches: 미정 (suggest-batch-reqs 대기)
- Releases: 미정
Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 REQ-112~115 일괄 batch 배정 검토.
Validation Plan
- pytest로 AC-1~9 각 케이스 확인. stub
fetch_broker_credential과 AlarmEmitter mock으로 I/O 격리. AC-4/5(차단 범위 경계: 매수 차단 / 매도 통과)가 가장 중요한 케이스.
CHG-20260628-02
- Date: 2026-06-28
- Author: 팀장(Claude)
- confirm-req:
Proposed→Approved. dcy-036 FR-2/OQ-1/OQ-2 추적. 진입 fail-closed(BuyIntent 차단) + 청산·DISPATCHED 통과(AC-4/5) 비대칭이 사장님 fail-safe 결정 정합 — 자본 갇힘 방지. CRITICAL 알람 기존 trex.alerts(REQ-099/100) 재사용·그날 고정(AC-9) 적절. OQ-4(trex-notifier 연동) Deferred 정당. blocker 없음.