Files
trex-core/.proofline/criteria/ac-0025.md
T

5.1 KiB

id, status
id status
ac-0025 active

재조정 경고에 따른 전략 주문 요청 최초 거부 알림

Criterion

trex-core는 해당 slot에 해제되지 않은 재조정 경고가 남아 있어 ReconcileWarningStore.is_warned(slot_id)가 참을 반환하고, 그 때문에 외부 전략의 새로운 매수 또는 매도 요청을 status="rejected", reason="reconcile_warned"로 거부한 경우, 그 결과를 IntentStore.finalize()에 저장한 뒤 해당 intent_id에 대한 경고를 한 건 발행해야 한다. 경고는 trex.alerts로 보내며 severity="warn", code="strategy_intent_rejected"를 사용한다. 같은 intent_id가 다시 들어오거나 최초 요청을 처리하는 도중 중복 요청이 들어오더라도 경고를 다시 발행해서는 안 된다. 반면, 같은 slot을 대상으로 하더라도 intent_id가 다르면 각각 별개의 최초 거부로 보고 경고를 발행해야 한다.

경고에는 instance_key, intent_id, intent_type, reason="reconcile_warned", broker_submitted=false를 반드시 포함한다. slot_id, portfolio_id, symbol, strategy_id는 신뢰할 수 있는 값이 확인된 경우에만 포함하며, 알 수 없는 값을 추정하거나 원본 요청에서 그대로 복사해서는 안 된다. 매수 요청의 strategy_id와 매도 요청의 sell_strategy_id는 경고에서 공통 필드인 strategy_id로 표현한다.

정상 승인된 요청, reconcile_warned 이외의 사유로 거부된 요청, 최종 결과 저장에 실패한 요청, 그리고 safety-sell·kill-switch·watchdog 같은 내부 안전 경로에서는 이 경고를 발행하지 않는다. 경고 발행기가 없거나 부가 정보를 조회하지 못하거나 메시지 전송이 실패하더라도 이미 결정된 거부 결과, RPC 응답, 재조정 경고, slot 상태 및 broker·ledger·portfolio-hub 동작을 중단하거나 변경해서는 안 된다. 경고와 이 처리 경로의 로그에는 계좌 식별정보, credential, token, password, DSN, 원본 요청, 전략의 extra, 외부 시스템의 원본 payload 또는 예외 원문을 포함해서는 안 된다.

Verification

  • 정상 동작: 재조정 경고가 설정된 slot에 새로운 매수 요청과 매도 요청을 각각 제출하면, 최종 거부 결과가 저장된 뒤 strategy_intent_rejected 경고가 warn 등급으로 요청마다 한 건씩 발행된다. 각 경고에는 필수 필드와 broker_submitted=false가 들어 있다. 매수의 strategy_id와 매도의 sell_strategy_id는 값이 있을 때 경고의 strategy_id로 나타나며, slot_id, portfolio_id, symbol은 저장소에서 확인된 값만 포함된다.
  • 중복 및 제외 조건: 같은 intent_id를 같은 프로세스에서 반복하거나 기존 영속 intent 저장소로 서비스를 다시 구성한 뒤 반복해도 경고는 추가로 발행되지 않고 저장된 기존 결과가 그대로 반환된다. 재조정 경고가 설정된 같은 slot에 서로 다른 intent_id 두 건을 제출하면 경고는 두 건 발행된다. 최초 요청을 처리하는 도중 들어온 중복 요청과 duplicate_in_flight, 정상 승인, reconcile_warning_unavailable, capacity_full, 입력 검증 실패 등 reconcile_warned가 아닌 결과는 경고를 만들지 않는다.
  • 처리 순서 및 장애 조건: 호출 순서를 기록하는 테스트용 저장소와 경고 발행기를 사용해 IntentStore.finalize()가 경고 발행보다 먼저 완료되는지 확인한다. 최종 결과 저장이 실패하면 경고를 발행하지 않는다. 경고 발행기가 없거나 실패를 반환하거나 전송 계층에 장애가 발생해도 원래의 reconcile_warned 거부 결과와 RPC 응답 본문은 유지된다. 이 과정에서 broker 주문 제출·취소, slot 상태 전이, 재조정 경고 설정·해제, ledger 기록 또는 portfolio-hub 쓰기가 추가로 발생하지 않는다.
  • 보안 및 호환성: 원본 요청과 extra에 credential·token·account·DSN·exception 식별용 값을 넣더라도 경고 제목, 필드, 직렬화된 전송 내용과 출력 로그에 해당 값이나 금지된 key가 나타나지 않는다. 부가 정보를 읽지 못하거나 값이 없으면 해당 선택 필드만 생략하고 필수 필드와 거부 결과는 유지한다. 운영 daemon의 IntentService에는 기존 공용 AlarmEmitter가 연결되며, 경고 발행기 없이 IntentService를 직접 생성하는 기존 사용 방식도 계속 동작한다.
  • 검사 방법: tests/application/test_reconcile_warning_blocking.py 또는 별도의 intent 경고 테스트에 매수·매도, 같은 intent_id와 다른 intent_id, 재시작을 모사할 수 있는 intent 저장소, 처리 순서, 발행 실패, 경고 필드 허용 목록과 부작용 없음 조건을 추가한다. 이어서 tests/application/test_messaging_intent_consumer.py, tests/application/test_alarm_emitter.py, daemon 연결 테스트, AC-0023·AC-0024 관련 회귀 테스트, 전체 저장소 테스트, Ruff, ProofLine validation과 git diff --check를 실행한다.