본문으로 건너뛰기

복사 운영 알림 (Phase 2b)

안전 관련 복사 이벤트 — 대상 거부 브레이커 트리핑, 계정 보호 또는 프로프-Rule 위반, 패닉 플래튼에 대한所有者별 피드. 기본값 켜짐 (App:Copy:NotificationsEnabled, 기본값 true); 거짓으로 설정하여 음소거. 복사 컨텍스트의 자체 개념, 시장/AI AlertRule 애그리게이트와 별개.

작동 원리​

실행-투명성 로그와 동일한 대역 외 호스트→싱크→드레이너 패턴:

CopyEngineHost ──Notify(record)──▶ ICopyNotificationSink
│
(notifications off) NullCopyNotificationSink → discards (no-op; unchanged engine)
(notifications on) ChannelCopyNotificationSink → bounded DropOldest channel
│
▼
CopyNotificationDrainer (BackgroundService)
│ resolves each profile's owner, batches
▼
CopyNotification feed ◀── GET /api/copy/notifications
  • 호스트 Notify(...)는 논블로킹, 절대 예외 없음 — 절대 DBに触れない, 절대 복사를 지연시키지 않음.
  • 드레이너는 각 알림의 프로필에서 소유 UserId를 확인합니다; 프로필이 사라진 알림(소유자 해석 불가)은 고아가 아닌 드롭됩니다.
  • CopyNotification = 추가 전용, 행별 승인 가능 피드 (애그리게이트 아님).

무엇이 발생하는가​

종류심각도발생 시
DestinationTripped경고G8 거부 예산 소진; 새 개설이 쿨다운 동안 일시 중지됨.
AccountProtectionTriggered위험ZuluGuard equity 하한/상한 위반; 개설 래치됨 (SellOut 청산).
PropRuleBreached위험프로프 일일 손실 / 트레일링 드로다운 위반; 대상 플래튼 + 일 중 잠금.
FlattenAll위험패닉 플래튼 실행; 모든 대상 닫힘 + 잠김.
TokenInvalidated(예약됨)대상의 토큰이 무효화됨; 회전 대기 중.

API​

  • GET /api/copy/notifications (소유자 범위) — 모든 프로필에서 사용자의 최근 알림 (가장 최근 200개), plus 미승인 카운트.
  • POST /api/copy/notifications/{id}/acknowledge — 하나를 읽은 것으로 표시.

구성 (App:Copy)​

설정기본값효과
NotificationsEnabledtrue안전 알림发出 + 드레이너 실행. false → no-op 싱크.

테스트​

  • 단위 (CopyNotificationTests) — 트리핑된 대상이 DestinationTripped를 발생; 패닉 플래튼이 프로필 수준 FlattenAll을 발생. 캡처 싱크를 통해.
  • 통합 (CopyNotificationDrainerTests, 실제 Postgres) — 드레이너가 소유자 확인 + 지속; 알 수 없는 프로필의 알림 드롭.
  • DST — 호스트가 fire-and-forget를发出하고 기본값 no-op 싱크, 그래서 복사 스트레스 스위트가 초록 유지 (23/23).