Files
trex-core/docs/srs/Integration/req-114_daystart-load-gate-fail-closed-entry.md
T

8.0 KiB

req-114: 그날-시작 로드 게이트 — fail-closed 신규 진입 차단 + 알람

  • Status: Implemented
  • 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 상태를 설정한다:
    1. PortfolioHubUnavailableError (네트워크 오류 / 비-2xx / 403)
    2. TradingContext.broker is None (인증정보 부재)
    3. 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.alerts exchange, REQ-099/100). 알람 코드: DAY_START_LOAD_FAILED. 알람 페이로드에는 사유 코드와 인스턴스 키를 포함한다.
  • 성공 로깅: 로드 성공 시 INFO 레벨로 fetch 소스, account_ref(app_secret 제외), trading_enabled를 기록한다.

Acceptance Criteria

  1. Given credential_fetch_enabled = true이고 그날-시작 체크포인트에서 PortfolioHubUnavailableError 발생, When 체크포인트 실행, Then entry_allowed = False 설정 + ERROR 로그 + CRITICAL 알람(DAY_START_LOAD_FAILED) 발신.
  2. Given credential_fetch_enabled = true이고 그날-시작 체크포인트에서 TradingContext.broker is None, When 체크포인트 실행, Then entry_allowed = False 설정 + ERROR 로그 + CRITICAL 알람 발신.
  3. Given credential_fetch_enabled = true이고 그날-시작 체크포인트에서 TradingContext.trading_enabled = False, When 체크포인트 실행, Then entry_allowed = False 설정 + ERROR 로그 + CRITICAL 알람 발신.
  4. Given entry_allowed = False 상태, When BuyIntent 수신, Then BuyIntent가 admission 단계에서 거부된다 (신규 진입 차단).
  5. Given entry_allowed = False 상태, When SellIntent 수신, Then SellIntent는 차단되지 않고 정상 처리된다 (청산 경로 영향 없음).
  6. Given credential_fetch_enabled = true이고 그날-시작 체크포인트 성공(broker 있음 + trading_enabled = True), When 체크포인트 실행, Then entry_allowed = True 설정 + INFO 로그(account_ref 포함, app_secret 제외).
  7. Given credential_fetch_enabled = false, When 그날-시작 체크포인트 실행, Then fetch_broker_credential() 호출 없이 기존 스냅샷 로직만 수행된다 (회귀 없음, opt-in 보존).
  8. Given 알람 발신 성공, When trex.alerts exchange 메시지 확인, Then DAY_START_LOAD_FAILED 코드와 instance_key를 포함한 알람 envelope가 존재한다.
  9. Given fail-closed 후 entry_allowed = False 상태에서 portfolio-hub가 복구됨, When 그날 중 재fetch 없이 운행, Then entry_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.alerts exchange 발신(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 없음.

CHG-20260628-03

  • Date: 2026-06-28
  • Author: 팀장(Claude)
  • confirm-req-implemented: Approved → Implemented. 근거: BAT-053 PR #34 머지(merge commit 01655ab). fail-closed 게이트 AC-1~9 pytest 검증 완료 — BuyIntent 차단/SellIntent 통과 비대칭, CRITICAL 알람(DAY_START_LOAD_FAILED), opt-in off 비활성(AC-7), 그날 고정(AC-9) 확인. QC PASS-WITH-NOTES(opus, blocker 0). 745 passed/0 회귀.