<!-- task=m-api-centered-proto-socket-rail/02+01_worker_socket_rail plan=0 tag=WORKER -->
# PLAN-cloud-G08: API to Worker Proto-Socket Rail

## 이 파일을 읽는 구현 에이전트에게
이 계획은 API를 기준으로 worker와 내부망을 연결하는 기반 작업이다. client가 worker를 직접 제어하지 않는다는 프로젝트 룰을 지키며, API가 worker에 명령/조회 요청을 보낼 수 있는 proto-socket rail을 만든다.

## 배경
현재 `services/worker/cmd/alt-worker/main.go:10`은 runner와 builtin job registration만 수행하며 socket server가 없다. worker config도 `services/worker/internal/config/config.go:5` 기준 DB/Redis/queue 중심이고 runtime socket address가 없다. API 역시 worker client가 없고, `services/api/internal/socket/server.go:32`에서 hello 외 요청을 처리하지 않는다. 이 작업은 API와 worker 사이의 내부 프로세스 경계를 proto-socket으로 여는 일이다.

## 사용자 리뷰 요청 흐름
worker를 API가 아닌 client에 직접 노출해야 한다는 요구가 발견되면 중단한다. 이는 현재 프로젝트 룰과 충돌하므로 `CODE_REVIEW-cloud-G08.md` 사용자 리뷰 요청 섹션에 사유를 적고 결정을 받아야 한다.

## 분석 결과
### 읽은 파일
- `services/worker/cmd/alt-worker/main.go`
- `services/worker/internal/config/config.go`
- `services/worker/internal/jobs/runner.go`
- `services/worker/internal/jobs/backtest_jobs.go`
- `services/worker/internal/storage/ports.go`
- `services/api/internal/socket/server.go`
- `services/api/internal/config/config.go`
- `services/api/cmd/alt-api/main.go`
- `services/api/go.mod`
- `services/worker/go.mod`
- `../proto-socket/go/ws_server.go`
- `../proto-socket/go/ws_client.go`
- `../proto-socket/go/communicator.go`

### 테스트 커버리지 공백
- worker에는 socket runtime 테스트가 없다.
- API에는 worker 연결 실패/timeout/retry behavior 테스트가 없다.
- 프로세스 간 smoke는 아직 문서 수준이며 로컬 실행은 금지되어 있다.

### 심볼 참조
- worker entrypoint: `services/worker/cmd/alt-worker/main.go:10`
- worker config: `services/worker/internal/config/config.go:5`
- job runner `Register`: `services/worker/internal/jobs/runner.go:27`
- job runner `Execute`: `services/worker/internal/jobs/runner.go:42`
- API config: `services/api/internal/config/config.go`
- proto-socket typed listener: `../proto-socket/go/communicator.go`
- proto-socket websocket server/client: `../proto-socket/go/ws_server.go`, `../proto-socket/go/ws_client.go`

### 분할 판단
이 작업은 worker socket server, API worker client, config, lifecycle만 구현한다. backtest와 market의 실제 business handler wiring은 각각 `04+02_backtest_rail`, `05+02_market_rail`에서 구현한다.

### 범위 결정 근거
- API가 control plane이고 worker가 execution plane이라는 결정이 이미 프로젝트 룰에 들어갔다.
- worker internal package는 API가 직접 import할 수 없고, import해서도 안 된다. 따라서 process boundary는 proto-socket이어야 한다.
- 초기 rail은 health/hello 또는 최소 ping 성격의 요청으로 연결성과 timeout을 검증하고, domain 요청은 후속 계획에 얹는다.

### 빌드 등급
- Build lane: `cloud-G08`
- Review lane: `cloud-G08`
- 근거: 두 Go service의 runtime boundary, config, lifecycle, network failure behavior를 함께 다룬다.

## 구현 체크리스트
### [WORKER-1] worker proto-socket server 추가
문제:
worker process가 proto-socket 요청을 받을 surface가 없다.

해결 방법:
`services/worker/internal/socket` 또는 기존 구조에 맞는 패키지를 만들고 proto-socket server를 시작한다. server는 worker-owned handlers만 등록하고, client-facing endpoint가 아님을 코드/테스트 구조로 드러낸다.

수정 파일 및 체크리스트:
- `services/worker/cmd/alt-worker/main.go`
- `services/worker/internal/config/config.go`
- `services/worker/internal/socket/**`
- `services/worker/go.mod`
- [ ] worker listen address/env가 추가된다.
- [ ] worker socket server lifecycle이 main에서 시작된다.
- [ ] shutdown/context 처리가 기존 runner 구조를 해치지 않는다.
- [ ] worker가 API/client package를 import하지 않는다.

테스트 작성:
- config env parsing test.
- worker socket handler registration test.
- 최소 hello/health request-response test.

중간 검증:
- 원격 검증 환경에서만 `go test ./services/worker/...` 실행.

### [WORKER-2] API worker proto-socket client 추가
문제:
API가 worker에 요청을 보낼 client abstraction이 없다.

해결 방법:
`services/api/internal/workerclient` 같은 패키지를 만들고 proto-socket Go client를 감싼다. 초기 메서드는 연결성 확인용으로 작게 시작하고, domain method는 후속 계획에서 추가한다. context timeout과 worker unavailable error mapping을 명확히 한다.

수정 파일 및 체크리스트:
- `services/api/internal/config/config.go`
- `services/api/cmd/alt-api/main.go`
- `services/api/internal/workerclient/**`
- `services/api/go.mod`
- [ ] API worker socket URL/env가 추가된다.
- [ ] request timeout 기본값이 있다.
- [ ] worker unavailable이 client-facing proto error로 변환될 자리만 만든다.
- [ ] API가 `services/worker/internal/**`를 import하지 않는다.

테스트 작성:
- API config env parsing test.
- fake proto-socket worker 또는 fake client 기반 unavailable/timeout test.
- workerclient request mapping unit test.

중간 검증:
- 원격 검증 환경에서만 `go test ./services/api/...` 실행.

### [WORKER-3] 양쪽 parser map 정렬
문제:
worker도 proto-socket request를 받으려면 contract parser가 필요하지만 현재 parser map은 API 내부에만 있다.

해결 방법:
가장 작은 안전한 선택을 한다. API 내부 parser map을 바로 공유하려고 internal 경계를 깨지 않는다. worker에 필요한 parser registration을 추가하거나, contracts module에 수동 helper를 둘 경우 generated artifact와 충돌하지 않는 위치인지 먼저 확인한다.

수정 파일 및 체크리스트:
- `services/worker/internal/contracts/**` 또는 안전한 shared contracts helper
- `services/api/internal/contracts/**` 필요 시 정렬
- [ ] worker에서 받을 request parser가 등록된다.
- [ ] API에서 worker response parser가 등록된다.
- [ ] API internal package를 worker가 import하지 않는다.

테스트 작성:
- worker parser map 필수 메시지 목록 테스트.
- API/worker parser 누락 테스트.

중간 검증:
- 원격 검증 환경에서만 `bin/contracts-check` 실행.
- 원격 검증 환경에서만 `go test ./services/api/... ./services/worker/...` 실행.

## 수정 파일 요약
- 예상 코드: `services/worker/internal/socket/**`, `services/worker/internal/config/config.go`, `services/worker/cmd/alt-worker/main.go`
- 예상 코드: `services/api/internal/workerclient/**`, `services/api/internal/config/config.go`, `services/api/cmd/alt-api/main.go`
- 예상 코드: API/worker parser map 관련 파일
- 예상 모듈: `services/worker/go.mod`, `services/api/go.mod`

## 최종 검증
- 원격 검증 환경에서만 `go test ./services/api/...`
- 원격 검증 환경에서만 `go test ./services/worker/...`
- 원격 검증 환경에서만 `bin/contracts-check`
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
