---
domain: control-plane
last_rule_review_commit: 7ca329ac9e03bf7cfebfac4517559fc1e2f0bca8
last_rule_updated_at: 2026-07-14
---

# control-plane

## 목적 / 책임

여러 Edge를 연결하고 운영 제어할 제어면 영역이다. Control Plane은 Edge를 제어하기 쉽게 만드는 attachable layer이며, Edge의 실질 설정과 상태 원본을 소유하지 않는다. 현재는 health/readiness, Edge registry/status/event/operation HTTP view, fleet status/command fan-out, 환경별 설정 로딩, Client proto-socket WebSocket, Edge proto-socket TCP 연결 baseline을 제공하며, Node 직접 연결이나 직접 스케줄링은 책임으로 삼지 않는다.

## 포함 경로

- `apps/control-plane/cmd/control-plane/` — control-plane CLI 진입점, 설정 로딩, HTTP health/readiness와 Edge registry 조회 endpoint, wire server lifecycle
- `apps/control-plane/internal/wire/` — Control Plane wire protocol 상수, Client WebSocket endpoint, Edge TCP server와 in-memory Edge registry
- `apps/control-plane/README.md` — Control Plane 현재 상태와 계획된 운영 책임 설명
- `apps/control-plane/Dockerfile` — Control Plane 배포용 이미지 빌드 표면
- `apps/control-plane/Dockerfile.runtime` — Control Plane runtime 이미지 표면

## 제외 경로

- `apps/edge/` — Edge-local Node registry, routing, input surface, stream relay의 소유자
- `apps/client/` — Control Plane을 소비하는 Flutter client UI/UX 영역
- `apps/node/` — 실제 adapter execution과 runtime session의 소유자
- `apps/worker/` — 비동기 작업 처리 예정 영역
- `packages/go/` — 여러 앱이 공유하는 Go 공통 패키지
- `proto/` — 메시지 계약 원본과 생성물
- `configs/` — 앱별 설정 예시와 공통 설정 계약 확인 영역

## 주요 구성 요소

- `rootCmd()` / `serveCmd()` — `control-plane serve` command와 기본 config path 구성
- `controlPlaneConfig` — HTTP listen, Client wire listen, Edge wire listen, DB, Redis, logging 설정 구조
- `loadConfig()` / `applyEnvOverrides()` — YAML 설정 로딩과 `IOP_*` 환경 변수 override
- `run()` — health/readiness/Edge registry/fleet HTTP server, Client WS server, Edge TCP server lifecycle 조립
- `registerEdgeRegistryHandlers()` — `/edges`, `/edges/{edge_id}`, `/edges/{edge_id}/status`, `/edges/{edge_id}/events`, `/edges/{edge_id}/operations`, `/edges/{edge_id}/commands` JSON endpoint
- `registerFleetHandlers()` / `fleetService` — `/fleet/status`와 `/fleet/commands` fan-out, bounded concurrency, short status cache
- `edgeRegistryView` / `edgeStatusResponseView` / `fleetEdgeView` / `edgeCommandRecordView` — HTTP JSON 응답용 Control Plane view DTO
- `wire.Protocol` — Control Plane 통신 표준을 `protobuf-socket`으로 고정하는 상수
- `wire.Endpoint` — reserved wire endpoint 설정 타입
- `wire.ClientServer` — `/client` WebSocket proto-socket hello 요청을 처리하는 서버 구현
- `wire.EdgeServer` — Edge outbound TCP proto-socket 연결을 수락하고 hello/status/event 흐름을 처리하는 서버 구현
- `wire.EdgeRegistry` — Edge connection view, 최근 node lifecycle event relay, 최근 Edge command request/result/event를 보관하는 in-memory registry
- `wire.EdgeParserMap()` — Control Plane-Edge wire message parser map
- `wire.EdgeServer.RequestStatus()` — 연결된 Edge에 `EdgeStatusRequest`를 보내 Edge-owned node snapshot을 조회하는 helper
- `wire.EdgeServer.SendCommand()` — 연결된 Edge에 `EdgeCommandRequest`를 보내고 typed response를 받는 helper

## 유지할 패턴

- Control Plane은 Edge를 통해 시스템을 관찰/제어한다. Node를 직접 등록하거나 직접 스케줄링하는 active contract를 만들지 않는다.
- Control Plane은 Edge의 설정, Node registry, runtime/automation 상태의 canonical store가 아니다. Control Plane이 소유할 수 있는 것은 연결 view, 제어 요청/결과, audit에 필요한 최소 운영 기록으로 제한한다.
- Edge는 다른 Control Plane으로 연결 대상을 옮길 수 있어야 한다. Control Plane 교체나 이전이 Edge 실질 데이터 migration을 요구하는 구조를 만들지 않는다.
- Control Plane은 상시 운영, multi-edge 관찰/명령, 정책/감사 UX의 기본 운영면으로 확장한다. Edge-local bootstrap, config, 진단, 단일 Edge 유지보수 fallback을 대체하거나 제거하는 전제로 설계하지 않는다.
- Control Plane-Edge wire protocol은 Edge가 소유한 operation contract를 원격 운영면으로 소비하는 형태로 설계한다. Edge CLI와 같은 행위를 노출해야 하면 Edge 쪽 표면 중립 service/operation boundary로 수렴시킨다.
- `net/http`는 health/readiness와 단순 조회성 status endpoint에 우선 사용하고, IOP 고유 양방향 운영 통신은 proto-socket 기반 wire protocol로 확장한다.
- 브라우저/앱 경계는 WebSocket/WSS proto-socket을 사용할 수 있다. Edge-Node TCP transport 기준을 이 경계에 억지로 적용하지 않는다.
- Control Plane-Edge native wire는 Edge가 outbound로 연결하는 TCP proto-socket 경계로 둔다. Client WebSocket listener와 Edge TCP listener를 혼동하지 않는다.
- Control Plane-Edge wire 상세는 `agent-contract/inner/control-plane-edge-wire.md`, Client-Control Plane wire 상세는 `agent-contract/inner/client-control-plane-wire.md`를 기준으로 확인한다.
- Edge registry는 현재 in-memory connection/control view이다. 최근 node event와 command record/event는 운영 화면용 bounded view이며, durable history, audit, 정책 저장소를 이 registry에 섞지 않는다.
- Edge status 조회는 Edge가 보고한 `EdgeStatusResponse`를 관찰한다. Control Plane에서 Node address, token, transport internals, Edge 설정 원본을 직접 소유하지 않는다.
- Edge command와 fleet command는 Control Plane이 Edge-owned operation을 wire로 요청하는 표면이다. command semantics는 Edge service/operation boundary에 두고, Control Plane은 fan-out, timeout, view rendering, 최소 record만 담당한다.
- Fleet status fan-out은 bounded concurrency와 짧은 cache를 사용해 연결 Edge를 관찰한다. cache는 freshness 최적화일 뿐 source of truth가 아니며 disconnected view는 registry 상태를 즉시 반영한다.
- `ScheduleRequest`/`ScheduleResponse`는 legacy placeholder로만 취급하고, 새 orchestration 계약은 Edge-owned runtime state를 우회하지 않도록 다시 설계한다.
- Control Plane 설정에 실제 환경값, credential, private endpoint를 tracked 문서에 쓰지 않는다. 환경별 값은 private rule 라우팅을 따른다.
- proto 계약을 바꾸면 `proto/iop/*.proto`를 먼저 수정하고 Go 생성물을 명령으로 갱신한다.

## 다른 도메인과의 경계

- **edge**: Edge는 설정, 로컬 실행 그룹 상태와 Node registry 원본을 소유한다. Control Plane은 Edge를 통해 상태 조회, 설정 변경 요청, 명령 전달, 이벤트 수신을 확장한다. Control Plane 없는 bootstrap/local/field/진단 fallback은 `iop-edge` command 표면에 남긴다.
- **client**: Client는 Control Plane의 HTTP/WS 표면을 소비하는 UI/UX와 Dart wire wrapper를 소유한다. Control Plane은 server endpoint와 Edge connection/control view를 소유한다.
- **platform-common**: protobuf 원본, 생성물, 공통 설정/관측성 helper는 platform-common 계약을 따른다.
- **testing**: Control Plane command, wire endpoint, bootstrap/enrollment 사용자 흐름을 바꾸면 testing domain rule의 검증 기준을 따른다.

## 금지 사항

- Control Plane에서 Node를 직접 연결하거나 직접 스케줄링하는 경로를 제품 기본 계약으로 만들지 않는다.
- Edge 설정, Node registry, runtime/automation 상태의 원본 저장소를 Control Plane에 만들지 않는다.
- Edge-local registry, run dispatch, stream relay 구현을 Control Plane으로 복제하지 않는다.
- Edge가 보고하지 않은 Node address/token/scheduling 필드를 Control Plane status API에 만들지 않는다.
- Edge command/fleet command 구현에서 Node transport internals를 직접 조립하거나 Control Plane에서 Node command request를 직접 소유하지 않는다.
- `/fleet/status` cache나 Edge operation record를 durable state, audit 원장, Edge 설정 원본처럼 사용하지 않는다.
- Control Plane 도입만을 이유로 Edge-local CLI bootstrap/config/진단 fallback을 제품 기본 계약에서 제외하거나 제거하지 않는다. 축소는 별도 roadmap 결정과 대체 fallback 기준이 있을 때만 다룬다.
- gRPC를 Control Plane 기본 wire protocol로 도입하지 않는다.
- 실제 DB/Redis credential이나 환경별 endpoint를 tracked docs/rules에 기록하지 않는다.
