# Client-Control Plane Wire Contract

## 계약 메타

- id: `iop.client-control-plane-wire`
- boundary: `inner`
- status: active-mvp
- 원본 경로:
  - `proto/iop/control.proto`
  - `apps/control-plane/internal/wire/wire.go`
  - `apps/control-plane/internal/wire/client.go`
  - `apps/client/lib/iop_wire/client_wire_client.dart`
  - `apps/client/lib/iop_wire/parser_map.dart`
- human docs:
  - `apps/control-plane/README.md`
  - `apps/client/README.md`

## 읽는 조건

- Client `/client` WebSocket proto-socket endpoint를 바꿀 때
- `ClientHelloRequest` 또는 `ClientHelloResponse`를 바꿀 때
- Client가 Control Plane을 통해 Edge/Node 운영 상태를 관찰하는 wire baseline을 검토할 때

## 범위

이 계약은 Flutter/Web/Desktop Client와 Control Plane 사이의 proto-socket WebSocket 경계다.
현재 MVP는 hello baseline이며, Client는 Edge나 Node TCP/protobuf transport에 직접 연결하지 않는다.

## 주요 흐름

- Client는 `/client` WebSocket으로 Control Plane에 연결한다.
- Client가 `ClientHelloRequest`를 보내면 Control Plane은 `ClientHelloResponse`로 readiness, protocol, server time, message를 응답한다.
- Control Plane listen 주소는 server config와 `IOP_WIRE_LISTEN`/compose port 기준으로 주입한다.

## 필드 의미

- `ClientHelloRequest.client_id`: client instance 식별자다.
- `ClientHelloRequest.client_version`: client build/version 관찰값이다.
- `ClientHelloResponse.ready`: Control Plane이 client 요청을 받을 수 있는지 나타낸다.
- `ClientHelloResponse.protocol`: 현재 `protobuf-socket` 값을 사용한다.
- `server_time_unix_nano`: client가 Control Plane time 기준을 관찰하는 값이다.

## 금지 사항

- Client가 Edge나 Node 내부 TCP/protobuf transport에 직접 연결하는 계약을 만들지 않는다.
- Client를 특정 외부 제품 shell 또는 navigation 계약으로 고정하지 않는다.
- Client wire에 실제 환경 endpoint, credential, private host 값을 tracked 문서로 기록하지 않는다.
- Dart protobuf 생성물을 proto 원본과 불일치하게 두지 않는다.

## 변경 시 확인할 코드/테스트

- `proto/iop/control.proto`
- `apps/control-plane/internal/wire/client_test.go`
- `apps/client/test/iop_wire/client_wire_client_test.dart`
- `apps/client/test/iop_wire/parser_map_test.dart`
- proto 변경 시 `make proto`와 `make proto-dart`
