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

# EdgeNode ID 생성 방식 개선 — alias 기반에서 명시적 ID로

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

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

## 배경

`apps/edge/internal/node/store.go:61`에서 NodeRecord ID를 `"node-" + d.Alias`로 만든다.
alias가 유일하므로 현재는 충돌이 없지만, alias 변경·재등록 시나리오나 control-plane 통합 시 예측 가능한 ID가 필요해진다.
`google/uuid`는 이미 go.mod indirect 의존성으로 존재하므로 추가 dep 없이 UUID를 사용할 수 있다.
설정 파일에 명시적 `id` 필드를 추가하고, 값이 없을 때만 UUID v4를 자동 생성하는 방식이 가장 유연하다.

---

### [REFACTOR-1] `config.NodeDefinition`에 `ID` 필드 추가

**문제**

`packages/config/` 내 NodeDefinition 구조체(정확한 파일·라인은 구현 전 확인)에 `ID` 필드가 없어서 edge 설정 파일에서 node ID를 지정할 수 없다.

**해결 방법**

```go
type NodeDefinition struct {
    ID       string            `yaml:"id" mapstructure:"id"`   // optional; UUID v4 auto-assigned if empty
    Alias    string            `yaml:"alias" mapstructure:"alias"`
    Token    string            `yaml:"token" mapstructure:"token"`
    Adapters AdaptersConf      `yaml:"adapters" mapstructure:"adapters"`
    Runtime  RuntimeConf       `yaml:"runtime" mapstructure:"runtime"`
}
```

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

- [ ] `packages/config/` 내 NodeDefinition 정의 파일 — `ID` 필드 추가
- [ ] `configs/edge.yaml` (예시 파일) — `id:` 필드 주석으로 추가

**테스트 작성**: 스킵 — struct 필드 추가만이므로 REFACTOR-2 테스트로 검증 가능.

**중간 검증**
```
go build ./packages/config/...
```
기대 결과: 빌드 성공.

---

### [REFACTOR-2] `LoadFromConfig`에서 UUID 자동 생성

**문제**

`apps/edge/internal/node/store.go:61`
```go
ID: "node-" + d.Alias,
```
alias 기반 ID는 alias 변경 시 ID가 바뀌고, 외부 시스템과 연동 시 예측 불가하다.

**해결 방법**

설정에 `d.ID`가 있으면 그대로 사용하고, 없으면 UUID v4를 생성한다.

```go
import "github.com/google/uuid"

nodeID := d.ID
if nodeID == "" {
    nodeID = uuid.NewString()
}
s.Add(&NodeRecord{
    ID:       nodeID,
    Alias:    d.Alias,
    Token:    d.Token,
    Adapters: d.Adapters,
    Runtime:  d.Runtime,
})
```

주의: `uuid.NewString()`은 매 호출마다 새 UUID를 반환한다. 따라서 ID 없는 노드는 edge 재시작마다 새 ID를 받는다. 이는 현재 단계에서 허용 가능하며, 지속적 ID가 필요해지면 설정 파일에 `id:` 필드를 명시한다.

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

- [ ] `apps/edge/internal/node/store.go` — `LoadFromConfig` 내 ID 생성 로직 교체, `github.com/google/uuid` import 추가
- [ ] `go.mod` — `github.com/google/uuid`를 indirect → direct로 승격 (`go mod tidy`)

**테스트 작성**: `apps/edge/internal/node/store_test.go`에 추가.
- `TestLoadFromConfig_ExplicitID`: `d.ID`가 설정된 경우 해당 ID가 그대로 사용되는지 확인.
- `TestLoadFromConfig_AutoID`: `d.ID`가 비어 있을 때 생성된 ID가 비어 있지 않고 유효한 UUID 형식인지 확인.
- `TestLoadFromConfig_AutoIDUnique`: 두 노드 모두 `id` 없이 정의 시 서로 다른 ID가 할당되는지 확인.

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

---

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `packages/config/` NodeDefinition 파일 | REFACTOR-1 |
| `configs/edge.yaml` | REFACTOR-1 |
| `apps/edge/internal/node/store.go` | REFACTOR-2 |
| `apps/edge/internal/node/store_test.go` | REFACTOR-2 |
| `go.mod` / `go.sum` | REFACTOR-2 |

## 의존 관계 및 구현 순서

REFACTOR-1 → REFACTOR-2 순서. config struct 변경 후 store 수정.

## 최종 검증

```
go mod tidy
go build ./...
go test ./apps/edge/... ./packages/config/...
```
기대 결과: 빌드 성공, 모든 테스트 PASS, `store.go`에 `"node-" + d.Alias` 패턴 없음.
