<!-- task=m-command-first-operator-workflow/01_import_contract_worker_api plan=1 tag=REVIEW_API -->

# Plan - Review Follow-Up Import Date Range Validation

## 이 파일을 읽는 구현 에이전트에게

이 plan은 코드리뷰 FAIL 후속 구현 지시서다. 구현 완료 전 active `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 반드시 실제 내용과 검증 출력으로 채운다. 검증은 아래 명령을 실행하고 실제 stdout/stderr를 review stub에 붙인다. 최종 판정, archive 이동, `complete.log` 작성은 code-review-skill 전용이다. 사용자 결정, 사용자 소유 외부 환경/secret, 또는 범위 충돌 없이는 진행할 수 없을 때만 review stub의 `사용자 리뷰 요청`을 채우고 멈춘다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 증거 공백은 사용자 리뷰 요청이 아니다.

## 배경

첫 구현은 import command contract/API/worker rail을 추가했지만, date range를 API/worker handler에서 의미적으로 막지 못했다. 현재 live KIS importer는 `from/to` date range를 요구하고 `from <= to`를 기대하므로, operator command의 잘못된 날짜 입력은 API/worker boundary에서 typed `invalid_request`로 닫혀야 한다.

## 사용자 리뷰 요청 흐름

구현 중 사용자-only blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 이 섹션은 `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` 기준이며, code-review가 검증 후 실제 `USER_REVIEW.md` 작성 여부를 결정한다.

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/private/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-roadmap/current.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/code-review/SKILL.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`
- `agent-test/local/rules.md`
- `agent-test/local/contracts-smoke.md`
- `agent-test/local/api-smoke.md`
- `agent-test/local/worker-smoke.md`
- `agent-test/local/client-smoke.md`
- `agent-test/local/operations-smoke.md`
- `agent-ops/rules/project/domain/contracts/rules.md`
- `agent-ops/rules/project/domain/api/rules.md`
- `agent-ops/rules/project/domain/worker/rules.md`
- `agent-ops/rules/project/domain/client/rules.md`
- `agent-ops/rules/project/domain/operations/rules.md`
- `agent-task/m-command-first-operator-workflow/01_import_contract_worker_api/plan_cloud_G08_0.log`
- `agent-task/m-command-first-operator-workflow/01_import_contract_worker_api/code_review_cloud_G08_0.log`
- `packages/contracts/proto/alt/v1/market.proto`
- `packages/contracts/gen/go/alt/v1/market.pb.go`
- `apps/client/lib/src/generated/alt/v1/market.pb.dart`
- `apps/client/lib/src/generated/alt/v1/market.pbjson.dart`
- `services/api/internal/socket/market.go`
- `services/api/internal/socket/market_test.go`
- `services/api/internal/socket/backtest_test.go`
- `services/api/internal/socket/server_test.go`
- `services/api/internal/workerclient/client.go`
- `services/api/internal/workerclient/client_test.go`
- `services/worker/internal/socket/backtest.go`
- `services/worker/internal/socket/handlers.go`
- `services/worker/internal/socket/market.go`
- `services/worker/internal/socket/market_mapping.go`
- `services/worker/internal/socket/market_test.go`
- `services/worker/internal/socket/server_test.go`
- `services/worker/internal/jobs/marketdata_jobs.go`
- `services/worker/internal/jobs/marketdata_jobs_test.go`
- `services/worker/internal/marketdata/importer/importer.go`
- `services/worker/internal/providers/kis/live_client.go`
- `services/worker/internal/providers/kis/daily_itemchartprice_test.go`
- `services/worker/cmd/alt-worker/main.go`
- `packages/domain/market/types.go`

### 테스트 환경 규칙

- test_env: `local`.
- `agent-test/local/rules.md` present/read.
- Matched profiles read: `contracts-smoke`, `api-smoke`, `worker-smoke`, `client-smoke`, `operations-smoke`.
- Applied commands: focused `go test` for API/worker socket regressions, full `bin/contracts-check`, `go test ./packages/contracts/gen/go/... -count=1`, `go test ./services/api/... -count=1`, `go test ./services/worker/... -count=1`, `bin/lint`, `git diff --check`.
- Fallback: none. No `<확인 필요>` command values in matched profiles.

### 테스트 커버리지 공백

- API import validation tests cover malformed date strings, but not missing `from_yyyymmdd`, missing `to_yyyymmdd`, or `from > to`.
- Worker import validation tests cover malformed date strings, but not missing date endpoints or reversed date ranges.
- Existing KIS provider tests prove the live provider requires date range and validates ordering, but socket handlers currently let those user-input errors reach backend handling.

### 심볼 참조

- Renamed/removed symbols: none.
- New or touched symbols to audit after the fix: `handleImportDailyBars`, `validateImportDate`, `parseImportDate`, `validImportRequest`, `fakeWorkerClient.connectCount`, `fakeDailyBarImporter.called`.

### 분할 판단

- Split policy evaluated. This is a follow-up inside existing split subtask `01_import_contract_worker_api`.
- No new subtask is created because the fix is one narrow validation/test unit across API and worker handlers, and splitting would separate mirrored boundary tests from the same bug.

### 범위 결정 근거

- Include API/worker import date range validation and regression tests only.
- Exclude protobuf schema changes, CLI YAML action implementation, generated contract regeneration, Flutter UI, KIS live smoke, and roadmap updates.
- Keep provider default-date behavior unchanged. Current live KIS provider requires `from/to`, so the socket command should reject missing dates instead of inventing a default range.

### 빌드 등급

- build=`cloud-G08`, review=`cloud-G08`: follow-up is narrow but still closes a cross-domain protocol/API/worker validation failure from a cloud-routed contract task.

## 구현 체크리스트

- [ ] [REVIEW_API-1] Tighten `ImportDailyBars` date range validation in API and worker handlers, with regression tests for missing and reversed ranges.
- [ ] [REVIEW_API-2] Run focused and full verification, including generated-contract and client lint checks.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## [REVIEW_API-1] Date Range Validation

### 문제

[services/api/internal/socket/market.go](/config/workspace/alt/services/api/internal/socket/market.go:77) validates `from_yyyymmdd` and `to_yyyymmdd` independently, then opens the worker connection. [services/worker/internal/socket/market.go](/config/workspace/alt/services/worker/internal/socket/market.go:88) does the same before calling the importer. The live KIS provider requires both dates and validates `from <= to` only after worker/provider handling ([services/worker/internal/providers/kis/live_client.go](/config/workspace/alt/services/worker/internal/providers/kis/live_client.go:298), [services/worker/internal/providers/kis/live_client.go](/config/workspace/alt/services/worker/internal/providers/kis/live_client.go:223)), so bad user input becomes `internal` backend failure instead of typed `invalid_request`.

### 해결 방법

Add date range validation in both socket boundaries before worker/importer calls:

- Require `from_yyyymmdd` and `to_yyyymmdd` to be present for the current KIS import command surface.
- Parse both as YYYYMMDD.
- Reject `from > to` with `invalid_request`.
- In API tests, assert the fake worker is not connected or called for missing/reversed ranges.
- In worker tests, assert the fake importer is not called for missing/reversed ranges.

Before ([services/api/internal/socket/market.go](/config/workspace/alt/services/api/internal/socket/market.go:77)):

```go
if err := validateImportDate("from_yyyymmdd", req.GetFromYyyymmdd()); err != nil {
    return &altv1.ImportDailyBarsResponse{Error: marketInvalidRequest(err.Error())}, nil
}
if err := validateImportDate("to_yyyymmdd", req.GetToYyyymmdd()); err != nil {
    return &altv1.ImportDailyBarsResponse{Error: marketInvalidRequest(err.Error())}, nil
}
```

After:

```go
if err := validateImportDateRange(req.GetFromYyyymmdd(), req.GetToYyyymmdd()); err != nil {
    return &altv1.ImportDailyBarsResponse{Error: marketInvalidRequest(err.Error())}, nil
}
```

Use equivalent worker-side parsing that returns parsed `from` and `to` for the importer request.

### 수정 파일 및 체크리스트

- [ ] `services/api/internal/socket/market.go`: replace independent optional date validation with required range validation.
- [ ] `services/api/internal/socket/market_test.go`: add missing `from_yyyymmdd`, missing `to_yyyymmdd`, and reversed range validation cases; assert `connectCount == 0` and `importReq == nil`.
- [ ] `services/worker/internal/socket/market.go`: replace independent optional date parsing with required range parsing and `from <= to` validation.
- [ ] `services/worker/internal/socket/market_test.go`: add missing date and reversed range cases; assert fake importer is not called.

### 테스트 작성

- Add API regression coverage to `TestHandleImportDailyBarsValidation`.
- Add worker regression coverage to `TestHandleImportDailyBarsValidation`.
- No provider test changes are needed; KIS provider already covers malformed date/order behavior.

### 중간 검증

```bash
go test ./services/api/internal/socket -run TestHandleImportDailyBars -count=1
go test ./services/worker/internal/socket -run TestHandleImportDailyBars -count=1
```

Expected: both commands exit 0 and the new invalid range cases return `invalid_request`.

## [REVIEW_API-2] Verification

### 문제

The original task spans generated contracts, API, worker, and generated Dart client output. The follow-up must prove the validation fix does not leave contract drift or client generated analyzer fallout.

### 해결 방법

Run focused tests first, then rerun the full final command set. Use fresh Go tests with `-count=1`; cached output is not acceptable.

### 수정 파일 및 체크리스트

- [ ] No additional source files.

### 테스트 작성

No new test files beyond `REVIEW_API-1`.

### 중간 검증

```bash
bin/contracts-check
go test ./packages/contracts/gen/go/... -count=1
go test ./services/api/... -count=1
go test ./services/worker/... -count=1
bin/lint
git diff --check
```

Expected: all commands exit 0. If `bin/lint` reports pre-existing analyzer info but exits 0, paste the actual output and note whether it is unrelated to this generated contract change.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `services/api/internal/socket/market.go` | REVIEW_API-1 |
| `services/api/internal/socket/market_test.go` | REVIEW_API-1 |
| `services/worker/internal/socket/market.go` | REVIEW_API-1 |
| `services/worker/internal/socket/market_test.go` | REVIEW_API-1 |

## 최종 검증

```bash
go test ./services/api/internal/socket -run TestHandleImportDailyBars -count=1
go test ./services/worker/internal/socket -run TestHandleImportDailyBars -count=1
bin/contracts-check
go test ./packages/contracts/gen/go/... -count=1
go test ./services/api/... -count=1
go test ./services/worker/... -count=1
bin/lint
git diff --check
```

Expected: all commands exit 0. Fresh `go test -count=1` is required; cached output is not acceptable.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
