orb REQ-039/tsl REQ-024/kdh REQ-057/notifier REQ-001~008 역참조 추가 (confirm-req 완료 반영). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
18 KiB
0. 문서 상태
이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다.
- 상태: confirmed
- 문서 ID: dcy-033_20260621_suite-alarm-delivery-notifier
- 이슈명: 제품군 알람 전달 체계 — 모듈 발신 + 중앙 notifier(trex-notifier) → 텔레그램(P1 아웃바운드)
- 작성 시각(KST): 2026-06-21 (KST)
- 마지막 갱신 시각(KST): 2026-06-21 (KST, draft-req trex-core-dev)
- 대체됨: 없음
- 후속 Discovery 참조: 없음
- 생성된 REQ 참조:
- trex-core: REQ-098 (알람 envelope wire 계약), REQ-099 (trex.alerts exchange 토폴로지), REQ-100 (core CRITICAL emitter 배선), REQ-101 (알람 발신 흐름 baseline 정합) — 모두 Approved
- (cross-repo, 모듈 emitter/서비스 — 각 repo SRS) trex-orb-v1: REQ-039 / trex-tsl-v1: REQ-024 / kis-data-hub: REQ-057 / trex-notifier: REQ-001~008 — 모두 Approved (confirm-req 팀장 2026-06-21). ※각 dev가 trex-core 범위 밖이라 미기재한 역참조를 팀장이 보강.
1. 계획 상태 요약
현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다.
- 연계 문서 현황:
- 관련 점수 파일: 미생성
- 관련 TODO/메모:
/home/genichin/workspace/trex-lead/ALARM-INVENTORY.md(0단계 알람 인벤토리 스윕 결과 — core/orb/tsl/kdh ~100개 조건, 본 Discovery의 source-of-truth),repos/trex-notifier(부트스트랩 완료된 신규 서비스 repo)
- 해석:
- TREX 제품군엔 운영자에게 이상을 즉시 알리는 구조화된 알람 채널이 없다. ~100개 알람 후보가 로그(또는 예외)로만 존재하고, CRITICAL 상황도 운영자가 능동 인지해야 한다. M2(tsl 매도 라이브)에서 운영자가 첫 거래일을 수기 감시해야 하는 부담도 이 갭에서 나온다.
- 토론으로 큰 방향은 확정됐다: 신규
trex-notifier가 알람을 중앙 수집해 텔레그램으로 전달(P1 아웃바운드만). 본 Discovery는 그 알람 전달 계약과 아키텍처를 trex-core 변경 단위로 정식화한다(envelope는 trex-core 소유 wire 계약).
2. 요구사항 판정 결과
이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다.
- 판정: 신규
- 근거
- dcy-029(운영 관측성 — 로깅/PnL 뷰), dcy-031(이벤트 발행 신뢰성)은 인접하나 "이상을 운영자에게 능동 푸시"하는 알람 전달 체계는 어디서도 다루지 않았다. 기존은 전부 pull(로그/CLI) 기반이다.
- 제품군 횡단 신규 컴포넌트(trex-notifier)와 신규 wire 계약(알람 envelope)을 도입하므로 독립 주기로 추적하는 편이 명확하다.
3. 문제점의 요약
문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다.
- 현재 상태
- trex-core에 구조화 알람 채널 부재 — 운영자 표면은 CLI
trex-core report+ 구조화 로그(Loki)뿐(daemon.py:248에 alert 주석 1건). 푸시 메커니즘 없음. - 인벤토리 스윕(ALARM-INVENTORY.md) 결과: core/orb/tsl/kdh에 ~100개 알람 후보. 대부분 WARN/ERROR로 로깅되나 일부 CRITICAL은 예외 raise만 되고 로그조차 없다(예: 토큰 격리, RPC 타임아웃 누적). 등급도 모듈마다 제각각.
- 연쇄/상관 실재: kis-data-hub 인증실패/다운 1건 → orb
kdh_auth_failure+ tslkis_auth_failure_abort동시 발생. 단 core safety-sell은 직접 KIS(다른 키)라 독립. trex-notifierrepo는 부트스트랩 완료(골격+거버넌스+baseline, root commit078d37d, private). 단 전송 방식·의존성은 본 Discovery 확정까지 비어 있다.
- trex-core에 구조화 알람 채널 부재 — 운영자 표면은 CLI
- 기대 상태
- 각 모듈이 이상 조건을 표준 알람 envelope로 발신하면, 중앙
trex-notifier가 등급 판정·중복/상관 억제 후 CRITICAL은 텔레그램 즉시 푸시, WARN은 일일 다이제스트로 전달한다. - 크래시·정지로 자기 알람을 못 내는 데몬은 하트비트(침묵=장애) 로 탐지된다.
- 알람 전달이 기존 wire 계약(slots RPC/trex.events)·로그 저장 경로를 건드리지 않는다(가산·격리).
- 각 모듈이 이상 조건을 표준 알람 envelope로 발신하면, 중앙
- 이해관계자
- 사장님 — 운영자(알람 최종 수신자), 범위·보안·외부노출 결재자
- 팀장(Claude) — Discovery/게이트, 인벤토리 작성자
- trex-core-dev — envelope 계약 + core emitter delivery
- 각 모듈 dev(orb/tsl/kdh) — 모듈별 emitter delivery
- service-dev — trex-notifier 서비스 delivery
- 제약사항
- 기존 wire 계약(slots RPC, trex.events) 스키마 변경 금지 — 알람은 가산적 신규 채널로만.
- orb/tsl/kdh는
trex_core를 import하지 않는다 — 공유는 규약(envelope) 이지 런타임 코드가 아니다(모듈당 thin emitter). - notifier는 로그 firehose 게이트웨이가 아니다 — 로그 저장은 인프라 슈퍼(Vector/Promtail→Loki) 담당. notifier는 알람만.
- core는 텔레그램을 직접 호출하지 않는다(외부 의존·시크릿 격리). 시크릿(봇 토큰)은 notifier 1곳.
- 알람 채널이 의존하는 인프라(RabbitMQ/Loki)가 장애나면 그 경로 알람이 못 나간다 → 하트비트 필요.
주요 사용자 시나리오
사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다.
- 운영자: tsl 매도 라이브 첫날,
sell_signal_rejected_terminal(포지션 못 팜) 발생 → 즉시 텔레그램 CRITICAL 푸시로 인지하고 개입. 현재는 로그를 들여다봐야만 알 수 있다. - 운영자: kis-data-hub 인증 만료 → orb·tsl 동시 알람을 notifier가 "시세 허브 장애 — 2개 모듈 영향" 1건으로 묶어 전달(폭풍 억제).
- 운영자: tsl 데몬이 크래시해 침묵 → 하트비트 부재로 notifier가 "tsl 데몬 응답 없음" 알람.
- 운영자: 장마감 후 WARN 다이제스트("오늘 백필 2건, watchdog 인수 0건, stale 양보 0건")로 비긴급 이상을 한 번에 검토.
4. 이번에 정의할 변경
이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다.
- 변경 1 — 알람 envelope 계약(trex-core 소유):
source / severity(critical·warn·info) / code / title / fields / occurred_at / schema_version표준 메시지 스키마 정의. 전 모듈이 이 규약으로 발신. - 변경 2 — 알람 전송 채널: 전용
trex.alertsAMQP exchange(확정, 사장님 2026-06-21) — 가산·격리(기존 slots RPC/trex.events 불변). 모듈은 기존 RabbitMQ 연결로 발행, notifier가 단일 소비자. - 변경 3 — 모듈별 emitter: core/orb/tsl/kdh 각 repo에 thin 알람 발신기(기존 연결 재사용, ~십수 줄). 인벤토리 CRITICAL 집합부터 배선.
- 변경 4 — trex-notifier P1: 알람 수집 → 등급 판정 → 중복/상관 억제 → 텔레그램(CRITICAL 즉시 / WARN 다이제스트) + 하트비트.
영향 범위
변경이 미칠 코드/문서/운영 범위를 명시한다.
- 코드 영향:
- trex-core: 알람 emitter(신규) +
trex.alerts채널 선언(채택 시). 기존 execution/safety_sell 등의 CRITICAL 지점에서 emit 호출. - trex-orb-v1 / trex-tsl-v1 / kis-data-hub: 각 thin emitter + 주요 알람 지점 emit 호출(각 repo 별 batch).
- trex-notifier: classifier/deduplicator/sender/heartbeat 구현 + 진입점 + 의존성(텔레그램·AMQP 라이브러리) 확정.
- trex-core: 알람 emitter(신규) +
- 문서 영향:
- trex-core
docs/interface-contract.md— 알람 envelope +trex.alerts채널 계약 신설. - trex-core
docs/runtime-flows.md— 알람 발신 흐름 추가(baseline 갱신). - trex-notifier
docs/runtime-flows.md— TBD였던 전송 방식 확정 반영. docs/discovery/index.md갱신.
- trex-core
- 운영 영향:
- 운영자에게 텔레그램 알람 수신 채널·등급 정책이 신규 운영 절차로 추가(런북).
- 봇 토큰·화이트리스트 chat id 운영 비밀로 관리(notifier 1곳).
5. 요구사항 목록
실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다.
기능 요구사항
- FR-1: 표준 알람 envelope 스키마(
source/severity/code/title/fields/occurred_at/schema_version)를 trex-core가 wire 계약으로 정의하고docs/interface-contract.md에 명시한다. - FR-2: 각 모듈(core/orb/tsl/kdh)이 인벤토리 CRITICAL 집합(ALARM-INVENTORY.md §A)의 조건 발생 시 envelope로 알람을 발신한다.
- FR-3: trex-notifier가 알람을 수집해 등급별로 처리한다 — CRITICAL은 텔레그램 즉시 푸시, WARN은 일일 다이제스트, INFO는 제외(로그만).
- FR-4: trex-notifier가 동일 근본원인의 상관 알람을 묶고(예: 시세 허브 장애 → 다모듈), 반복 알람을 rate-limit/중복 억제한다.
- FR-5: trex-notifier가 하트비트(dead-man's switch)로 데몬 침묵=장애를 탐지·알린다.
- FR-6: trex-core
docs/runtime-flows.md에 알람 발신 흐름을, trex-notifierdocs/runtime-flows.md에 확정 전송 방식을 반영한다(baseline 갱신).
비기능 요구사항
성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다.
- NFR-1: 알람 채널은 가산·격리 — 기존 wire 계약(slots RPC, trex.events) 스키마를 변경하지 않는다. orb/tsl/kdh 기존 동작 무회귀.
- NFR-2: 보안 — 텔레그램 봇 토큰 시크릿은 notifier 1곳에만, 수신 대상은 화이트리스트(사장님 chat id). core/orb/tsl/kdh에 외부 시크릿 유입 없음.
- NFR-3: 신뢰성 — 알람 경로(notifier/RabbitMQ)가 죽어도 모듈 본업(매매)과 로그 저장은 영향 없음. notifier는 SPOF가 아니다.
- NFR-4: 모듈측 비용 최소 — emitter는 thin(기존 연결 재사용),
trex_coreimport 없이 envelope 규약만 공유.
범위 경계
이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다.
- In Scope
- 알람 envelope 계약 + 전송 채널 + 모듈 emitter(CRITICAL 집합) + trex-notifier P1(수집·등급·상관/중복억제·텔레그램·하트비트).
- Out of Scope
- 인바운드 명령 게이트(텔레그램으로 시스템 제어) — P2/P3 후속 별도 discovery(보안·인가·감사).
- 로그 저장/Loki 적재 — 인프라 슈퍼(Vector/Promtail) 담당. notifier 경유 금지.
- 인벤토리 ~100개 code 전량 배선 — CRITICAL 우선, WARN 다이제스트는 점진. INFO 제외.
- 후보 C(core가 외부 푸시 직접 호출), 기존 slots RPC/trex.events 스키마 변경.
6. 리스크/가정 목록
불확실성과 전제 조건을 분리해서 적는다.
리스크
- R-1 (Medium): 알람 폭풍 — 장애 시 다모듈·매사이클 알람이 쏟아져 알람 피로 유발.
- 완화 방안: notifier 상관/중복억제 + rate-limit(FR-4) + 등급화(CRITICAL만 즉시 푸시).
- R-2 (Medium): 알람의 역설 — 알람 채널이 의존하는 인프라(RabbitMQ/notifier) 장애 시 그 경로 알람 미전달.
- 완화 방안: 하트비트(침묵=장애, FR-5). 매매 안전망(core safety-sell)은 알람과 독립이라 알람 실패가 거래 보호를 깨지 않음.
- R-3 (Low): 보안 — 봇 토큰 유출 시 알람 수신 노출(P1은 읽기 방향이라 제어 위험은 없음).
- 완화 방안: 토큰 1곳 격리(NFR-2), 화이트리스트, 인바운드 명령은 범위 밖(P3로 분리).
가정
아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다.
- A-1: 모듈들은 이미 RabbitMQ 연결을 보유(core=broker, orb/tsl=intent/slots RPC)하므로 AMQP emitter는 기존 연결 재사용으로 저비용이다.
- A-2: 알람은 저빈도 이벤트라 전용 채널의 트래픽·복잡도 부담이 작다.
- A-3: 인프라 로그 슈퍼(Vector/Promtail→Loki)는 알람과 별개로 존재/구성된다(로그 저장은 본 범위 밖).
- A-4: trex-notifier는 단일 컨테이너 내 bare 프로세스로 다른 모듈과 공존 배포된다.
오픈 질문
답을 아직 모르는 항목을 적는다.
- OQ-1: 모듈→notifier 알람 전송 방식 — 전용
trex.alertsAMQP exchange(권고: 실시간·격리·소비자 상관억제) vs 로그-tee(슈퍼가 alert 라인 tee, 모듈측 코드 0이나 Loki 의존·지연).- 상태: Answered — 전용
trex.alertsAMQP exchange로 확정(사장님 2026-06-21). - 처리 방안: trex-notifier는
trex.alerts소비자. 각 모듈은 기존 RabbitMQ 연결로 발행. 가산·격리(orb/tsl 기존 계약 불변). trex-notifier 의존성(AMQP 클라이언트)·runtime-flows에 반영. - 종료 조건: 충족됨.
- 상태: Answered — 전용
- OQ-2: P1 즉시-푸시(CRITICAL paging) 대상 code 집합 확정 — ALARM-INVENTORY.md §A 제안 집합을 사장님이 검토해 실제 폰을 울릴 항목을 확정.
- 상태: Answered — ALARM-INVENTORY.md §A 전체(약 25개 code)를 P1 CRITICAL paging으로 채택(사장님 2026-06-21). 항목 축소 없음 — 알람 폭풍은 항목 삭제가 아니라 notifier 상관/rate-limit(FR-4)으로 제어.
- 처리 방안: §A의 core/tsl/orb/kdh CRITICAL code 전체가 즉시-푸시 대상. delivery에서 각 모듈 emitter가 해당 code 배선.
- 종료 조건: 충족됨.
7. 초기 성공 기준
이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다.
- S-1: 확정된 CRITICAL 조건 발생 시 운영자 텔레그램에 알람이 도달한다(엔드투엔드).
- S-2: 동일 근본원인의 다모듈 알람이 1건으로 묶이고, 반복 알람이 rate-limit된다(폭풍 억제).
- S-3: 데몬 침묵(크래시/정지) 시 하트비트 부재로 장애가 탐지된다. 기존 wire 계약·매매 동작은 무회귀.
측정 방식 및 데이터 출처
각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다.
- S-1 측정 방식: CRITICAL 조건 주입(테스트/시뮬) → 텔레그램 수신 확인 / 데이터 출처: notifier 로그 + 텔레그램 메시지.
- S-2 측정 방식: 다모듈 동시 알람·반복 알람 주입 → 묶임/억제 단언 / 데이터 출처: notifier 상관·rate-limit 테스트.
- S-3 측정 방식: 데몬 하트비트 중단 시뮬 → 장애 알람 발생 단언 + 기존 wire/매매 회귀 스위트 / 데이터 출처: notifier 테스트 + 각 모듈 회귀 테스트(interface-contract diff 0).
8. REQ로 넘기기 전 확인 체크
REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다.
- 범위(In Scope/Out of Scope) 확정
- 기준: P1(아웃바운드 알람)만 In Scope, 명령 게이트·로그 저장 제외에 사장님 동의 — 확정(토론 합의)
- 성공 지표의 측정 방식/데이터 출처 확정
- 기준: S-1~S-3 측정안 합의
- High 영향 리스크 우선순위 및 해소 책임자 지정
- 기준: 현재 High 리스크 없음(R-1/R-2 Medium) — 폭풍억제·하트비트 책임자(notifier service-dev) 지정
- 모든 오픈 질문(OQ)
Open상태 없음 확인- 기준: OQ-1(전송=
trex.alertsAMQP)·OQ-2(paging=§A 전체) 모두 Answered(사장님 2026-06-21)
- 기준: OQ-1(전송=
- Freeze 확정 담당자(CONFIRMED_BY) 지정
- 기준: confirm-discovery 시 팀장이 CONFIRMED_BY로 기록 — 팀장(Claude)
9. 파일 처리 결과
이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다.
- 처리 결과: 생성
- 생성 경로: docs/discovery/dcy-033_20260621_suite-alarm-delivery-notifier.md
- 참조 문서:
- /home/genichin/workspace/trex-lead/ALARM-INVENTORY.md (인벤토리 스윕 — 현재상태/요구사항 근거)
- docs/discovery/dcy-029_20260616_operational-observability-logging-and-pnl-view.md (운영 관측성 인접)
- docs/interface-contract.md, docs/runtime-flows.md (envelope/채널 계약 + 발신 흐름 baseline 갱신 대상)
10. 사용자 결정 필요 항목 요약
사용자나 승인자가 결정해야 하는 항목만 모아 정리한다.
DECIDE
- (해소) 알람 전송 방식 = 전용
trex.alertsAMQP exchange — 사장님 확정(2026-06-21, OQ-1). - (해소) P1 CRITICAL paging 집합 = ALARM-INVENTORY.md §A 전체(약 25개 code) — 사장님 확정(2026-06-21, OQ-2).
CONFIRM
- (확정) P1(아웃바운드 알람)만 범위, 인바운드 명령 게이트·로그 저장은 후속 분리 — 사장님 확정(2026-06-21).
DATA
- {{DATA_TELEGRAM_BOT}} — 텔레그램 봇 토큰 + 수신 chat id(화이트리스트). delivery 단계 필요(사장님 BotFather 생성).
11. Discovery Freeze
REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다.
섹션 참조
- 범위: # 5. 요구사항 목록 > 범위 경계
- 리스크/오픈 질문: # 6. 리스크/가정 목록
- 성공 기준: # 7. 초기 성공 기준
- 인계 전 확인: # 8. REQ로 넘기기 전 확인 체크
- 사용자 결정 필요: # 10. 사용자 결정 필요 항목 요약
Freeze 플래그
- Handoff Decision: REQ Drafting 진행 가능
- Handoff Rationale: confirm-discovery 완료. OQ-1(전송=
trex.alertsAMQP)·OQ-2(paging=§A 전체) 모두 사장님 확정 → Open OQ 0건. 범위(P1 아웃바운드)·성공기준·리스크 책임자 확정. DATA(텔레그램 봇 토큰)는 delivery 단계 필요(비차단). 단 구현(delivery)은 첫 tsl REL(M2) 이후 큐잉 — draft-req는 병렬 가능하나 delivery 우선순위는 M2 뒤. - Ready for REQ Drafting: true
- Confirmed By: 팀장(Claude)
- Confirmed At (KST): 2026-06-21 (KST)