# req-011: BrokerPort 추상화 + paper/stub async 더블 - Status: Implemented - Type: Integration - Priority: High - Owner: project maintainers ## Intent - 브로커를 코어에서 추상화하는 `BrokerPort` 를 정의하고(불변식 B 의 단일 경계), 결정적 검증용 paper/stub 어댑터를 제공한다. 이후 KIS 어댑터(REQ-012)와 집행 루프(REQ-013)가 이 포트 위에서 동작한다. ## Requirement - `BrokerPort`(application 포트)에 `submit_order(side, symbol, qty, ...) -> broker_order_id`, `cancel_order(broker_order_id)`, `poll_fill(broker_order_id) -> FillStatus(accepted/partially_filled/filled/rejected/cancelled, avg_price, filled_qty)` 를 정의한다. paper/stub 어댑터는 동기 단축 없이 submit→poll 비동기 계약을 따르되 체결 시점·부분체결·거부를 프로그래밍 가능한 결정적 더블로 제공한다. 어댑터는 adapters 레이어에 두고 도메인은 의존하지 않는다. - paper 어댑터의 order seq 발번은 optional seq store(주입 가능) 위에서 동작한다. seq store 가 주입되면 order seq 는 데몬 재시작 간에도 단조 증가해야 하며(Redis 영속, REQ-016 `RedisTokenCache` 패턴 재사용·best-effort), 미주입 시 기존 in-memory 카운터로 폴백한다. 이는 재시작 후 결정적 `execution_id` 재생성으로 인한 원장 `correlation_id` 충돌(매도 원장 누락)을 방지하기 위한 paper 한정 결정성 보강이다(issue #4). ## Acceptance Criteria 1. Given `BrokerPort` 정의, When paper 어댑터로 `submit_order`, Then `accepted` + broker_order_id 를 반환하고 즉시 `filled` 로 단축하지 않는다(다음 `poll_fill` 에서 체결). 2. Given paper 더블의 fill 시나리오 설정(즉시/N틱 후/부분/거부), When `poll_fill` 반복, Then 설정대로 결정적으로 상태가 진행된다. 3. Given 코드, When import 스윕, Then `trex_core.domain.slot` 은 broker/네트워크 의존이 0이고 BrokerPort 구현은 adapters 레이어에만 있다. (NFR-1/NFR-2) 4. Given paper 어댑터에 seq store 가 주입된 상태, When 데몬 재시작(seq store 영속)을 모사해 두 번째 인스턴스에서 `submit_order`, Then order seq 는 첫 인스턴스 이후로 단조 증가하고, 같은 자산·같은 수량의 매도가 직전 run 매수와 `correlation_id` 가 충돌하지 않는다. seq store 미주입 시 기존 in-memory `PAPER-000001` 발번으로 폴백하며 AC-1~3 비동기 계약은 불변이다. (issue #4) ## Impacted Area - Docs: docs/interface-contract.md(브로커 경계) — REQ-015 에서 정합 - Modules: trex_core/application(BrokerPort), trex_core/adapters/broker(paper/stub, `seq_store.py` 신규), trex_core/runtime(config `PaperBrokerConfig.redis_url`, daemon `_build_broker` wiring) - Tests: paper 더블 fill 시나리오 테스트, paper seq store 재시작 단조성 + correlation_id 비충돌 + in-memory 폴백 테스트 ## Notes - 불변식 B 의 단일 경계. KIS 어댑터는 REQ-012, 집행 루프는 REQ-013. - 출처: dcy-003 FR-1(포트+paper), NFR-1/NFR-2 흡수. - (issue #4/CHG-20260612-01) paper seq Redis 영속화는 paper 한정 테스트 하네스 결정성 보강이며 프로덕션(KIS `odno` 고유) 버그가 아니다. 원장 `correlation_id` 에 side 를 추가하는 대안 대신, 발번 단조성 보강(영향 최소·계약 불변)을 선택했다. Redis 인프라는 REQ-016 token_cache 패턴을 재사용한다. ## Change Log ### CHG-20260604-01 - Date: 2026-06-04 - Author: Justin Ko #### Change Summary - dcy-003 FR-1(포트+paper) 로부터 최초 생성(Proposed). #### Intent - BrokerPort + paper async 더블 요구사항을 backlog 로 정규화. #### Acceptance Criteria Delta - Added: - submit→poll 비동기 계약, 결정적 fill 시나리오, 도메인 순수성 3개 기준 - Updated: - 없음 - Removed: - 없음 #### Impacted Area Delta - Docs: - docs/interface-contract.md - Modules: - application(BrokerPort), adapters/broker(paper) - Tests: - paper 더블 시나리오 테스트 #### Delivery Trace Delta - Batches: - none - Releases: - none #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: keep-current - Follow-up Action: confirm-req 후 batch 편성 #### Validation Plan - paper 더블 비동기 체결 시나리오 단위테스트로 검증. ### CHG-20260604-02 - Date: 2026-06-04 - Author: Justin Ko #### Change Summary - Status Proposed → Approved (confirm-req). #### Intent - 승인 게이트(필수 필드·구체 AC·blocker 없음) 충족, source dcy-003(confirmed, handoff 승인)와 모순 없음 확인. #### Acceptance Criteria Delta - Added: - 없음 - Updated: - 없음 - Removed: - 없음 #### Impacted Area Delta - Docs: - docs/srs/index.md (Register 상태 Approved) - Modules: - 없음 - Tests: - 없음 #### Delivery Trace Delta - Batches: - none (batch 편성 전) - Releases: - none #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: keep-current - Follow-up Action: suggest-batch-reqs / draft-batch 로 delivery batch 편성 #### Validation Plan - 승인 후 batch planning 에서 본 REQ 의 Acceptance Criteria 를 검증 기준으로 사용. ### CHG-20260604-03 - Date: 2026-06-04 - Author: Justin Ko #### Change Summary - Status Approved → Implemented (confirm-req-implemented, 근거 batch BAT-004 release-candidate). #### Intent - BAT-004 verification.md 의 acceptance mapping + evidence(pytest 92 pass / 도메인 순수성 / 데몬 E2E / KIS VTS 모의투자 round-trip)로 AC 충족 → 구현 완료 동기화. #### Acceptance Criteria Delta - Added: - 없음 - Updated: - 없음 - Removed: - 없음 #### Impacted Area Delta - Docs: - docs/srs/index.md (Register Implemented) - Modules: - 없음 - Tests: - 없음 #### Delivery Trace Delta - Batches: - BAT-004 (release-candidate) - Releases: - none #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: keep-current - Follow-up Action: draft-release 로 release 편성(BAT-001~004) #### Validation Plan - BAT-004 verification evidence 재참조로 충분. ### CHG-20260612-01 - Date: 2026-06-12 - Author: Justin Ko #### Change Summary - (change-req, issue #4) paper 브로커 order seq 를 **재시작 간 단조 증가**하도록 영속화한다. 현재 `_seq` in-memory 카운터는 데몬 재시작 시 0 으로 리셋되어 `PAPER-000001` 부터 재발번 → 결정적 `execution_id`(`paper:{order_id}:{filled_qty}`) 재생성 → 원장 멱등 키 `correlation_id = {asset_id}:{order_id}:{execution_id}`(side 미포함)가 직전 run 의 매수와 충돌 → `ON CONFLICT DO NOTHING` dedup 으로 **정상 매도 원장 행이 조용히 누락**. paper 어댑터에 optional seq store(Redis-backed, REQ-016 `RedisTokenCache` 패턴 재사용)를 주입해 해소하고, Redis 미구성 시 기존 in-memory 동작으로 폴백. 신규 AC-4 가 추가 구현·검증을 필요로 하므로 **Implemented → Approved 되돌림**. #### Intent - paper 모드 테스트 하네스의 재시작 후 멱등 키 충돌(매도 원장 누락)을 제거한다. 실 KIS 는 broker order_id(`odno`)가 주문마다 고유해 충돌이 없으므로 **프로덕션 버그가 아닌 paper 한정 결정성 문제**다. 기존 BrokerPort/paper 비동기 계약(AC-1~3)은 불변, seq 발번 영속화만 추가. #### Acceptance Criteria Delta - Added: - AC-4: paper 브로커에 seq store 가 주입되면 order seq 는 재시작 후에도 단조 증가하고, 같은 자산·같은 수량의 매도가 직전 run 의 매수와 `correlation_id` 가 충돌하지 않는다. seq store 미주입(Redis 미구성) 시 기존 in-memory `_seq` 동작으로 폴백하며 비동기 fill 계약(AC-1~3)은 불변이다. - Updated: - 없음 - Removed: - 없음 #### Impacted Area Delta - Docs: - docs/srs/index.md (Register Implemented → Approved) - Modules: - `trex_core/adapters/broker/paper.py`(optional seq store 주입 + `submit_order` seq 발번 경로) - `trex_core/adapters/broker/seq_store.py`(신규: `SeqStore` 포트 + `RedisSeqStore`(INCR 기반, best-effort) + `InMemorySeqStore` 폴백, token_cache 패턴 정합) - `trex_core/runtime/config.py`(`PaperBrokerConfig.redis_url` 추가) - `trex_core/runtime/daemon.py`(`_build_broker` paper 경로 seq store wiring) - Tests: - 재시작 시뮬레이션(seq store 공유) 후 매도 correlation_id 비충돌 + 폴백 동작 단위 테스트 #### Delivery Trace Delta - Batches: - BAT-039 (예정, issue #4) - Releases: - none #### Revalidation Impact - Reverification Needed: yes (BAT-039 에서 신규 AC-4 + AC-1~3 회귀) - Existing Implementation Invalidated: no (기존 비동기 계약/도메인 순수성 불변, 발번 경로에 optional 영속화만 추가). 단 신규 AC-4 미구현으로 Implemented 유지 불가 → Approved. - Status Recommendation: Implemented → **Approved** (구현·검증 후 confirm-req-implemented 로 복귀) - Follow-up Action: confirm-req → draft-batch(BAT-039) → 구현·검증 → confirm-req-implemented → issue #4 close #### Validation Plan - BAT-039: (a) 같은 seq store 를 공유한 두 PaperBroker 인스턴스(재시작 모사)에서 두 번째 인스턴스의 첫 order_id 가 첫 인스턴스 이후로 단조 증가, (b) 매수 후 재시작 매도 시 correlation_id 비충돌(원장 dedup 미발생), (c) seq store 미주입 시 기존 `PAPER-000001` 부터 in-memory 동작 폴백, (d) AC-1~3 기존 paper 테스트 회귀 없음. `pytest` 전체 + `ruff check` clean. ### CHG-20260612-02 - Date: 2026-06-12 - Author: Justin Ko #### Change Summary - Status 변경: Approved → **Implemented** (confirm-req-implemented, 근거 batch BAT-039 release-candidate). #### Intent - BAT-039 verification.md 의 acceptance mapping + evidence(434 passed / seq store 재시작 단조·correlation_id 비충돌·in-memory 폴백 / fake redis INCR 단조)로 AC-1~4 충족 → 구현 완료 동기화. #### Acceptance Criteria Delta - Added/Updated/Removed: 없음 (상태 전이만) #### Impacted Area Delta - Docs/Modules/Tests: 없음 (상태 전이만) #### Delivery Trace Delta - Batches: - BAT-039 (release-candidate) - Releases: - none (release 편성은 별도 진행) #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: Implemented - Follow-up Action: draft-release 로 release 편성(BAT-039 포함) + issue #4 close #### Validation Plan - BAT-039 verification evidence 재참조로 충분. - AC-4: `test_shared_seq_store_is_monotonic_across_restart`, `test_post_restart_sell_does_not_collide_with_prior_buy`, `test_in_memory_fallback_starts_at_one`, `test_redis_seq_store_incr_is_monotonic_and_shared`. - AC-1~3: 전체 회귀 434 passed(기존 paper 더블 시나리오 + 도메인 순수성 회귀 없음).