<!-- task=edge_config_mapper plan=0 tag=REFACTOR -->

# edge buildConfigPayload를 transport에서 edgenode 패키지로 이동

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

각 체크리스트 항목을 완료하고 중간 검증 명령을 실행한 뒤 출력을 `CODE_REVIEW-cloud-G03.md`의 검증 결과 섹션에 붙여 넣으세요.
`CODE_REVIEW-cloud-G03.md`의 "이 파일을 읽는 리뷰 에이전트에게" 섹션에 있는 아카이브·complete.log 생성 지시는 **리뷰 에이전트 전용**이므로 구현 에이전트는 실행하지 마세요.

## 배경

`apps/edge/internal/transport/server.go`에 `buildConfigPayload`와 `cliProfileToProto` 함수가 위치해 있다.
이 함수들은 `edgenode.NodeRecord`(도메인 타입)를 `*iop.NodeConfigPayload`(proto 타입)로 변환하는 mapper 역할이다.
transport 패키지는 연결 수락·메시지 송수신만 담당해야 하는데, 도메인 → proto 변환 책임을 함께 갖고 있어 경계가 흐리다.
`buildConfigPayload`를 `edgenode` 패키지(`apps/edge/internal/node/`)로 이동하면 transport는 변환 결과만 사용하고 도메인 변환 로직은 도메인 패키지 안에 남는다.

---

### [REFACTOR-1] `buildConfigPayload` 및 `cliProfileToProto`를 `edgenode` 패키지로 이동

**문제**

`apps/edge/internal/transport/server.go` (buildConfigPayload 정의 시작 라인 — 파일 내 `func buildConfigPayload` 위치 확인 후 정확한 라인 기재)

현재 `transport.Server.onNodeConnected` 안에서 `buildConfigPayload(rec)`를 직접 호출한다.
`buildConfigPayload`는 `config.CLIProfileConf` → `*iop.CLIProfileConfig` 변환(`cliProfileToProto`)도 포함하며,
`packages/config`와 `proto/gen/iop` 양쪽에 의존한다. 이 의존성은 transport가 아닌 edgenode 수준에서 갖는 게 적절하다.

**해결 방법**

1. `apps/edge/internal/node/` 패키지에 `mapper.go` 파일을 새로 만든다.
2. `buildConfigPayload`와 `cliProfileToProto`를 `mapper.go`로 이동한다. 함수명은 그대로 유지하되 패키지 외부에서 쓸 수 있도록 `BuildConfigPayload` / `CLIProfileToProto`로 export한다.
3. `transport/server.go`의 `onNodeConnected` 내 호출을 `edgenode.BuildConfigPayload(rec)`로 교체한다.
4. `transport/server.go`에서 더 이상 필요 없는 `packages/config` import와 proto mapper 관련 코드를 제거한다.

`mapper.go` 골격:

```go
package node

import (
    "fmt"

    "google.golang.org/protobuf/types/known/structpb"

    "iop/packages/config"
    iop "iop/proto/gen/iop"
)

// BuildConfigPayload converts a NodeRecord's adapter config to the proto payload
// sent to node during registration.
func BuildConfigPayload(rec *NodeRecord) (*iop.NodeConfigPayload, error) {
    // ... 기존 buildConfigPayload 로직 그대로 이동
}

func CLIProfileToProto(p config.CLIProfileConf) *iop.CLIProfileConfig {
    // ... 기존 cliProfileToProto 로직 그대로 이동
}
```

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

- [ ] `apps/edge/internal/node/mapper.go` — 신규 생성, `BuildConfigPayload` / `CLIProfileToProto` 정의
- [ ] `apps/edge/internal/transport/server.go` — `buildConfigPayload` / `cliProfileToProto` 삭제, `edgenode.BuildConfigPayload` 호출로 교체, 불필요 import 제거

**테스트 작성**: `apps/edge/internal/node/` 패키지에 `mapper_test.go` 추가.
- `TestBuildConfigPayload_OllamaEnabled`: Ollama 활성화된 NodeRecord 입력 시 payload에 ollama adapter 포함 확인.
- `TestBuildConfigPayload_CLIProfiles`: CLI 프로파일이 있는 NodeRecord 입력 시 payload에 cli adapter와 profile 매핑 확인.
- `TestBuildConfigPayload_MockAlwaysPresent`: 어떤 NodeRecord든 mock adapter가 항상 첫 번째로 포함되는지 확인.

**중간 검증**
```
go test ./apps/edge/internal/node/...
```
기대 결과: 신규 mapper 테스트 포함 PASS.

---

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `apps/edge/internal/node/mapper.go` (신규) | REFACTOR-1 |
| `apps/edge/internal/node/mapper_test.go` (신규) | REFACTOR-1 |
| `apps/edge/internal/transport/server.go` | REFACTOR-1 |

## 최종 검증

```
go build ./apps/edge/...
go test ./apps/edge/...
```
기대 결과: 빌드 성공, 모든 테스트 PASS, `transport/server.go`에 `buildConfigPayload` 정의 없음.
