# Milestone: KIS Live Data Collection Pipeline

## 위치

- Roadmap: `agent-roadmap/ROADMAP.md`
- Phase: `agent-roadmap/phase/operator-surface/PHASE.md`

## 목표

Flutter 실화면 구현 전에 한국투자증권(KIS) API를 실제 provider로 사용해 한국장 일봉 데이터를 수집하고, worker import/storage와 backtest 입력 조회 adapter 경계까지 검증한다. 기존 fixture/mock 기반 KIS adapter와 provider-neutral pipeline은 유지하되, live credential, token/auth, quota/error, sanitized smoke evidence를 별도 runtime 경계로 정리한다.

## 상태

[완료]

## 구현 잠금

- 상태: 해제
- 결정 필요: 아래 체크리스트
  - [x] KIS live smoke에 사용할 credential 주입 방식을 정한다. 원문 secret, secret-store 항목 이름, 계좌번호는 tracked 문서에 기록하지 않는다. 기준: SOPS + age 단일 원본, `bin/kis-sops-env` command-lifetime env 주입.
  - [x] live smoke 대상 범위를 정한다: 국내주식 일봉 `inquire-daily-itemchartprice` 단일 symbol/date range부터 시작한다. 기준: paper/real `005930`, `20240527~20240528`.
  - [x] live 호출 결과를 commit 가능한 sanitized fixture/evidence로 남기는 기준을 정한다. 기준: 데이터 적재가 아니라 테스트 evidence만 남기며, raw payload/header/token/key/account는 저장하지 않고 symbol/date/bar_count/msg_cd/result 같은 요약만 기록한다.

## 범위

- KIS REST auth/token 발급과 갱신 경계
- KIS 국내주식 일봉 조회 REST client
- runtime secret injection boundary
- quota/rate-limit, auth failure, unavailable, malformed response 상태 분류
- live response를 sanitized fixture/evidence로 남기는 절차
- worker market data importer와 실제 KIS provider 연결
- KIS live smoke/import/storage 결과가 `StorageBarSource` 입력 조회까지 이어지는 adapter 검증
- UI MVP가 의존할 market data availability/status evidence

## 기능

### Epic: [kis-live] KIS live market data collection

fixture/mock 기반 adapter를 실제 KIS provider 호출과 worker import pipeline으로 확장한다.

- [x] [credential-boundary] KIS credential은 command lifetime 동안만 주입하고, access token은 runtime에서 발급한다. 검증: SOPS + age 단일 원본과 `bin/kis-sops-env` command-lifetime env 주입을 사용하고, tracked 파일에 raw secret, secret-store 항목 이름, 계좌번호를 기록하지 않는다.
- [x] [auth-client] KIS auth/token client가 국내주식 일봉 호출에 필요한 access token을 얻고 만료/오류 상태를 분류한다. 검증: fake auth response unit test, credential 없는 unavailable test, SOPS 주입 live-gated paper/real smoke가 통과한다.
- [x] [daily-rest-client] KIS `inquire-daily-itemchartprice` REST client가 request parameter, response decode, error/quota/malformed 상태를 처리한다. 검증: 로컬 KIS 공식 샘플 cache, sanitized fixture 기반 test, quota/malformed/error-redaction test가 통과한다.
- [x] [live-provider] worker market data importer가 KIS live provider를 선택해 일봉 데이터를 fetch할 수 있다. 검증: fake HTTP test가 provider request, normalized bars, importer storage upsert를 확인하고, `alt-worker`가 KIS importer handler를 등록한다.
- [x] [live-smoke] credential이 준비된 환경에서 단일 symbol/date range KIS live smoke를 실행하고 sanitized evidence를 남긴다. 검증: 실제 KIS paper/real 호출 결과를 raw secret 없이 요약 evidence로 기록하고, 실패 시 auth/quota/unavailable 원인이 grep 가능한 상태로 남는다.
- [x] [backtest-input] KIS live로 수집한 normalized daily bars가 backtest 입력 조회 adapter 경계에서 사용 가능하다. 검증: `StorageBarSource`와 KIS fake HTTP -> importer -> store -> `StorageBarSource` query test가 통과한다.
- [x] [operator-handoff] Flutter Operator Console MVP로 넘길 provider readiness와 market data status key를 정리한다. 검증: 실행 명령, secret 주입 전제, sanitized evidence key, unavailable/auth/quota/malformed/provider 상태를 문서화한다.

## 완료 리뷰

- 상태: 승인됨
- 요청일: 2026-06-03
- 완료 근거: SOPS 주입 기반 KIS paper/real 일봉 smoke, worker KIS auth/daily/live-provider, import/storage/`StorageBarSource` 입력 조회 evidence가 준비됐다.
- 리뷰 필요:
  - [x] 사용자가 완료 결과를 확인했다
  - [x] archive 이동을 승인했다
- 리뷰 코멘트: 2026-06-03 사용자 요청에 따라 현재 마일스톤을 종료하고 archive로 이동했다.

## 범위 제외

- Flutter 실화면 구현
- 미국장 데이터 수집
- 분봉/틱/실시간 streaming
- 실거래 주문 API
- 계좌/잔고/주문 체결 조회
- production 자동 수집 스케줄링
- backtest start surface와 strategy runtime 운영 배선
- secret 원문, secret-store 항목 이름, 계좌번호의 tracked 문서 기록

## 작업 컨텍스트

- 관련 경로: `services/worker/`, `services/worker/internal/providers/kis/`, `services/worker/internal/marketdata/`, `services/worker/testdata/providers/kis/`, `packages/domain/market/`, `apps/client/`
- 표준선(선택): 기존 provider-neutral importer/storage/backtest 입력 조회 adapter 경계를 유지하고, KIS 특수성은 provider adapter와 runtime config에 격리한다.
- 표준선(선택): KIS 공식 샘플은 tracked source dependency가 아니라 local cache 참조로 사용한다. private rule의 `.agent-cache/koreainvestment/open-trading-api` 경계를 따른다.
- 표준선(선택): live smoke는 credential이 준비된 환경에서만 실행하며, credential 미설정 상태는 실패가 아니라 `unavailable` evidence로 남긴다.
- 표준선(선택): live smoke evidence는 데이터 적재 정책이 아니라 테스트 검증 기준이다. Commit 가능한 evidence에는 raw KIS payload/header/token/key/account를 남기지 않고, 실행 환경, symbol/date range, bar count, date span, message code, result 같은 요약만 둔다.
- 표준선(선택): 원격 field secret boundary는 SOPS + age를 agent runtime secret의 단일 원본으로 둔다. code-server 컨테이너에는 age private key나 평문 secret 파일을 두지 않고, SOPS 복호화 값을 command lifetime 동안만 환경변수로 주입해 smoke를 실행한다.
- 표준선(선택): SOPS/age key 위치와 host 경로 같은 환경 세부는 private testing rule에만 두고 tracked roadmap에는 raw secret, 계좌번호, secret-store 항목 이름을 기록하지 않는다.
- 최근 evidence: 2026-06-03 원격 host에서 `KIS_ACTIVE_ENV=paper`와 SOPS 주입으로 `bin/kis-paper-daily-smoke --symbol 005930 --start 20240527 --end 20240528` 실행 성공. Sanitized output: `KIS paper daily smoke ok`, `name=삼성전자`, `bar_count=2`, `first_date=20240527`, `last_date=20240528`, `msg_cd=MCA00000`.
- 최근 evidence: 2026-06-03 원격 host에서 `KIS_ACTIVE_ENV=real`와 SOPS 주입으로 `bin/kis-paper-daily-smoke --symbol 005930 --start 20240527 --end 20240528` 실행 성공. Sanitized output: `KIS real daily smoke ok`, `name=삼성전자`, `bar_count=2`, `first_date=20240527`, `last_date=20240528`, `msg_cd=MCA00000`.
- 최근 evidence: 2026-06-03 원격 host에서 `KIS_ACTIVE_ENV=paper`, `KIS_LIVE_SMOKE=1`, SOPS 주입으로 `go test ./services/worker/internal/providers/kis -run TestLiveProviderPaperSmoke -count=1 -v` 실행 성공. Sanitized output: `PASS`, `TestLiveProviderPaperSmoke`.
- 최근 evidence: 2026-06-03 원격 host에서 `KIS_ACTIVE_ENV=real`, `KIS_REAL_LIVE_SMOKE=1`, SOPS 주입으로 `go test ./services/worker/internal/providers/kis -run TestLiveProviderRealSmoke -count=1 -v` 실행 성공. Sanitized output: `PASS`, `TestLiveProviderRealSmoke`.
- 선행 작업: Korea Daily Data Foundation, Backtest Engine Baseline, Operator Client API/Core Integration Validation
- 후속 작업: Flutter Operator Console MVP
- 확인 필요: 없음
