<!-- task=m-core-server-boundary-cleanup/01_routes plan=3 tag=REVIEW_REVIEW_REVIEW_ROUTES -->

# Implementation Plan - REVIEW_REVIEW_REVIEW_ROUTES

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

구현 완료의 마지막 단계는 active `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채우는 것이다. 검증을 실행하고, active 파일은 그대로 둔 채 리뷰 준비 상태로 보고한다. 종결 처리, log archive, `complete.log` 작성, task directory archive 이동은 code-review 전용이다. 구현 중 사용자 결정, 사용자 소유 외부 환경, scope conflict 없이는 진행할 수 없으면 리뷰 stub의 `사용자 리뷰 요청`에 근거를 기록하고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다.

## 배경

이 후속 계획은 `code_review_local_G08_2.log`의 Required 이슈만 다룬다. G08 구현은 handler ownership을 대체로 회복했지만, 계획에서 제외한 handler body 변경이 섞였고 `handleRunnerBootstrapCommand`의 Host validation 조건이 보안상 잘못 바뀌었다. 이번 작업은 route/subrouter 파일 경계는 유지하면서 bootstrap command 관련 behavior를 원래 방어선으로 되돌리고, 범위 외 handler body rewrite를 줄인다.

## 사용자 리뷰 요청 흐름

구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 이 섹션은 `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` 기준이다. 구현 에이전트는 직접 사용자 prompt를 만들지 않으며, code-review가 사용자 리뷰 요청의 타당성 검증과 실제 `USER_REVIEW.md` 작성을 담당한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/independent-control-plane/milestones/core-server-boundary-cleanup.md`
- Task ids:
  - `routes`: route 등록과 subrouter 구성을 handler 구현에서 분리한다.
- Completion mode: check-on-pass

## 분석 결과

### 이전 리뷰 결과

- Archived plan: `agent-task/m-core-server-boundary-cleanup/01_routes/plan_local_G08_2.log`
- Archived review: `agent-task/m-core-server-boundary-cleanup/01_routes/code_review_local_G08_2.log`
- Verdict: `FAIL`
- Required issues:
  - Host validation upper-bound checks disappeared and invalid characters can pass.
  - Handler body rewrite/reformat churn exceeded the route boundary restoration scope.

### 범위 결정 근거

- 포함: Host validation 조건 복원, bootstrap Host regression test 추가, `server.go` handler body를 route extraction 전 의미/표현에 가깝게 되돌리기, `routes.go`의 route/subrouter boundary 유지.
- 제외: endpoint 추가/삭제, DTO helper 분리, handler 파일 분리, store/domain 동작 변경, unrelated cleanup.
- security-sensitive bootstrap command validation과 반복된 local FAIL이므로 follow-up route는 `cloud-G07`이다.

## 구현 체크리스트

- [ ] `handleRunnerBootstrapCommand`의 Host validation을 상한 포함 범위 검사로 복원하고, `shellEscape`는 기존 single-quote escaping 의미와 읽기 쉬운 표현을 유지한다.
- [ ] `TestHandleRunnerBootstrapCommand`에 공백 없는 invalid Host 예시(예: `localhost;rm`)가 `400 Bad Request`로 거부되는 assertion을 추가한다.
- [ ] `routes.go`는 `registerRoutes`, `apiPathSegments`, `handleRouter`만 보유하고, `server.go` handler body는 route extraction 전 의미와 표현을 최대한 유지하도록 범위 외 rewrite를 되돌린다.
- [ ] endpoint path 목록, `handleRouter(store, registry)` signature, HTTP method behavior를 변경하지 않고 `gofmt`를 실행한 뒤 `cd services/core && go test -count=1 ./internal/httpserver`를 통과시킨다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REVIEW_REVIEW_ROUTES-1] Restore Bootstrap Host Validation

#### 문제

- `server.go`의 Host validation 조건이 `char >= 'a' || char >= 'A' || char >= '0' || char >= '9'` 형태라 범위 상한이 없다.
- 기존 테스트의 malicious Host는 공백이 포함되어 있어 이 회귀를 잡지 못한다.

#### 해결 방법

- 허용 문자 검사를 소문자, 대문자, 숫자 범위 각각에 대해 `>=`와 `<=`를 모두 사용하는 조건으로 복원한다.
- `localhost;rm`처럼 공백 없는 shell metacharacter Host가 거부되는 테스트를 추가한다.
- `shellEscape`는 원래 single-quote escaping contract를 유지하고, 불필요하게 난해한 문자열 조합이나 빈 줄을 남기지 않는다.

#### 중간 검증

```bash
cd services/core && go test -count=1 ./internal/httpserver
```

### [REVIEW_REVIEW_REVIEW_ROUTES-2] Reduce Handler Body Scope Churn

#### 문제

- G08은 handler ownership 회복 과정에서 handler body reformat/rewrite를 함께 수행했다.
- 이번 task의 목표는 route registration/subrouter boundary이므로 handler body는 후속 handler/DTO split 작업 전까지 기존 의미와 표현을 최대한 유지해야 한다.

#### 해결 방법

- `routes.go`에는 route/subrouter helper만 남긴다.
- `server.go`의 handler body와 JSON/proto helper는 route 추출 전 원래 코드와 의미/표현이 최대한 같도록 되돌린다.
- Host validation 회복과 새 test 외의 behavior change를 만들지 않는다.

#### 중간 검증

```bash
cd services/core && go test -count=1 ./internal/httpserver
```

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `services/core/internal/httpserver/server.go` | REVIEW_REVIEW_REVIEW_ROUTES-1, REVIEW_REVIEW_REVIEW_ROUTES-2 |
| `services/core/internal/httpserver/server_test.go` | REVIEW_REVIEW_REVIEW_ROUTES-1 |
| `services/core/internal/httpserver/routes.go` | REVIEW_REVIEW_REVIEW_ROUTES-2 |

## 최종 검증

```bash
cd services/core && go test -count=1 ./...
```

기대 결과: 모든 `services/core` package test 통과. Go test cache output은 허용하지 않는다.

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