<!-- task=m-cross-os-runner-bootstrap/01_core_command plan=1 tag=REVIEW_API -->

# PLAN: Windows PowerShell bootstrap command 인자 전달 수정

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

이 계획은 직전 코드리뷰 `code_review_cloud_G06_0.log`의 Required 이슈만 해결한다. 구현 중 사용자 결정이 필요하면 채팅으로 질문하지 말고 동반 `CODE_REVIEW-cloud-G07.md`의 `사용자 리뷰 요청` 섹션을 실제 내용으로 채운 뒤 중단한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/control-plane-product-surface/milestones/cross-os-runner-bootstrap.md`
- Epic: `[bootstrap-platforms] Cross-OS bootstrap contract`
- Task id: `[core-command]`
- Completion mode: check-on-pass

## 실패 원인

`services/core/internal/httpserver/runner_handlers.go`의 Windows command는 `powershell -ExecutionPolicy Bypass -Command "irm ... | iex" -- --server-url ...` 형태다. 이 형태는 다운로드한 script를 실행하더라도 `--server-url`, `--agent-id`, `--enrollment-token`, `--release-base-url` 인자를 script invocation에 넘기는 구조가 아니다. Windows bootstrap command 계약은 script URL과 필수 bootstrap 인자를 함께 전달해야 한다.

## 범위 결정 근거

이번 후속은 Core command template과 해당 Go 테스트만 수정한다. PowerShell bootstrap script asset 자체, `/bootstrap/oto-agent.ps1` serving route, OS별 binary install 구현은 후속 split 작업 범위로 둔다.

## 구현 체크리스트

- [ ] Windows bootstrap command가 다운로드한 PowerShell script를 scriptblock으로 실행하고 `--server-url`, `--agent-id`, `--enrollment-token`, `--release-base-url`을 같은 `-Command` 표현식 안에서 전달하도록 수정한다.
- [ ] PowerShell escaping helper/command template이 single quote, semicolon, `$()`가 포함된 runner_id/token을 실행하지 않고 인자로 보존하도록 테스트를 갱신한다.
- [ ] 기존 no-target/Linux/macOS shell command와 invalid target 400/token 비노출 계약이 유지되는지 확인한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_API-1] Windows command가 script 인자를 실제 invocation에 전달하도록 수정

문제: PowerShell command의 인자가 `-Command` 문자열 밖에 붙어 있어 다운로드된 script의 `$args` 또는 parameter binding으로 전달된다고 볼 수 없다.

해결 방법:

- `runner_handlers.go`의 Windows branch를 다운로드 script를 scriptblock으로 만든 뒤 그 scriptblock invocation에 bootstrap 인자를 붙이는 형태로 바꾼다.
- 예시는 `powershell -ExecutionPolicy Bypass -Command "& ([scriptblock]::Create((irm <script-url>))) -- --server-url <server-url> --agent-id <runner-id> --enrollment-token <token> --release-base-url <release-url>"` 같은 구조다. 실제 문법은 테스트 가능하고 quoting이 안전한 형태로 고정한다.
- `powershellEscape`가 이 command template에서 안전한지 다시 점검하고, single quote를 포함한 token이 PowerShell 코드로 실행되지 않고 literal argument로 남도록 한다.
- `server_test.go`의 Windows expected command와 malicious field 케이스를 새 구조로 갱신한다. 테스트는 인자들이 `-Command` 표현식 내부의 scriptblock invocation 뒤에 위치하는지 드러나야 한다.

수정 파일 및 체크리스트:

- `services/core/internal/httpserver/runner_handlers.go`
- `services/core/internal/httpserver/server_test.go`

테스트 작성:

- Windows target expected command를 새 scriptblock invocation 구조로 갱신한다.
- malicious runner_id/token 케이스가 literal quoting을 보존하는지 유지한다.
- no-target, linux, macos, invalid target 케이스는 회귀로 유지한다.

중간 검증:

- `cd services/core && go test ./...`

## 최종 검증

- `cd services/core && go test ./...`
- `cd apps/runner && dart analyze`

## 리뷰 포인트

- Windows command가 다운로드 script 실행과 bootstrap 인자 전달을 같은 PowerShell `-Command` 표현식 안에서 수행하는지 확인한다.
- runner id/token escaping이 PowerShell code injection으로 바뀌지 않는지 확인한다.
- 기존 Linux/macOS/default target 계약이 변하지 않았는지 확인한다.
