Files
trex-core/docs/discovery/dcy-033_20260621_suite-alarm-delivery-notifier.md
T
genichinandClaude Opus 4.8 d4c5fcbba1 feat(alarm): trex-core 알람 emitter + trex.alerts exchange (dcy-033 BAT-049, Implemented)
AlarmEmitter(application, best-effort 비차단)+trex.alerts topic exchange 가산·격리+8 CRITICAL code 배선. 608 passed, opus QC PASS, 팀장 e2e(텔레그램 HTTP200) 통과. REQ-098~101 Implemented.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
2026-06-21 19:25:55 +09:00

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 / trex-notifier: REQ-001~008 — Approved (confirm-req 팀장 2026-06-21). ※각 dev가 trex-core 범위 밖이라 미기재한 역참조를 팀장이 보강.
    • kis-data-hub: REQ-057 — Deprecated (사장님 결정 2026-06-21: kdh는 당분간 trex-notifier 미사용 → 알람 범위 제외). 향후 재도입 시 새 REQ로 부활.

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 + tsl kis_auth_failure_abort 동시 발생. 단 core safety-sell은 직접 KIS(다른 키)라 독립.
    • trex-notifier repo는 부트스트랩 완료(골격+거버넌스+baseline, root commit 078d37d, private). 단 전송 방식·의존성은 본 Discovery 확정까지 비어 있다.
  • 기대 상태
    • 각 모듈이 이상 조건을 표준 알람 envelope로 발신하면, 중앙 trex-notifier가 등급 판정·중복/상관 억제 후 CRITICAL은 텔레그램 즉시 푸시, WARN은 일일 다이제스트로 전달한다.
    • 크래시·정지로 자기 알람을 못 내는 데몬은 하트비트(침묵=장애) 로 탐지된다.
    • 알람 전달이 기존 wire 계약(slots RPC/trex.events)·로그 저장 경로를 건드리지 않는다(가산·격리).
  • 이해관계자
    • 사장님 — 운영자(알람 최종 수신자), 범위·보안·외부노출 결재자
    • 팀장(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.alerts AMQP 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 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 갱신.
  • 운영 영향:
    • 운영자에게 텔레그램 알람 수신 채널·등급 정책이 신규 운영 절차로 추가(런북).
    • 봇 토큰·화이트리스트 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-notifier docs/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_core import 없이 envelope 규약만 공유.

범위 경계

이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다.

  • In Scope
    • 알람 envelope 계약 + 전송 채널 + 모듈 emitter(CRITICAL 집합) + trex-notifier P1(수집·등급·상관/중복억제·텔레그램·하트비트).
  • Out of Scope
    • kis-data-hub emitter — 사장님 결정(2026-06-21) kdh는 당분간 trex-notifier 미사용 → 알람 범위에서 제외(REQ-057 Deprecated). 모듈 emitter는 core/orb/tsl만. (허브 장애는 orb kdh_auth_failure·tsl kis_auth_failure_abort가 소비자 측에서 탐지하므로 가시성 부분 유지.) 향후 재도입 시 새 REQ.
    • 인바운드 명령 게이트(텔레그램으로 시스템 제어) — 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.alerts AMQP exchange(권고: 실시간·격리·소비자 상관억제) vs 로그-tee(슈퍼가 alert 라인 tee, 모듈측 코드 0이나 Loki 의존·지연).
    • 상태: Answered — 전용 trex.alerts AMQP exchange로 확정(사장님 2026-06-21).
    • 처리 방안: trex-notifier는 trex.alerts 소비자. 각 모듈은 기존 RabbitMQ 연결로 발행. 가산·격리(orb/tsl 기존 계약 불변). trex-notifier 의존성(AMQP 클라이언트)·runtime-flows에 반영.
    • 종료 조건: 충족됨.
  • 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.alerts AMQP)·OQ-2(paging=§A 전체) 모두 Answered(사장님 2026-06-21)
  • 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.alerts AMQP 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 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다.

섹션 참조

Freeze 플래그

  • Handoff Decision: REQ Drafting 진행 가능
  • Handoff Rationale: confirm-discovery 완료. OQ-1(전송=trex.alerts AMQP)·OQ-2(paging=§A 전체) 모두 사장님 확정 → Open OQ 0건. 범위(P1 아웃바운드)·성공기준·리스크 책임자 확정. DATA(텔레그램 봇 토큰)는 e2e 단계 필요(비차단). 알람은 M2 포함 확정(사장님 2026-06-21) — delivery 착수. (※이전 "M2 이후 큐잉"은 팀장 오판 정정. 원합의=가능하면 M2 포함이었고 BAT-048 완료로 착수 시점 도달. 알람은 best-effort·별도 채널이라 매매 위험 0.)
  • Ready for REQ Drafting: true
  • Confirmed By: 팀장(Claude)
  • Confirmed At (KST): 2026-06-21 (KST)