refactor(proto): legacy 계약을 tombstone으로 고정한다

직접 Node scheduling/registration으로 오해될 수 있는 legacy proto 필드를 reserved 처리하고 Go/Dart generated guard를 갱신한다.
This commit is contained in:
toki 2026-06-06 20:30:43 +09:00
parent 435b5589bc
commit 82c1db93f8
12 changed files with 294 additions and 628 deletions

View file

@ -42,18 +42,18 @@ task=m-architecture-refactor-foundation/09_proto_legacy_contract, plan=0, tag=AP
| 항목 | 완료 여부 |
|------|---------|
| [API-1] Control Scheduling Legacy Tombstone | [ ] |
| [API-2] Node Registration Legacy Tombstone | [ ] |
| [API-3] Generated Binding Guards And Call-Site Cleanup | [ ] |
| [API-1] Control Scheduling Legacy Tombstone | [x] |
| [API-2] Node Registration Legacy Tombstone | [x] |
| [API-3] Generated Binding Guards And Call-Site Cleanup | [x] |
## 구현 체크리스트
- [ ] `proto/iop/control.proto`의 legacy scheduling placeholder를 reserved tombstone으로 전환한다.
- [ ] `proto/iop/node.proto`의 legacy node snapshot/direct registration placeholder와 enum을 reserved tombstone으로 전환한다.
- [ ] `make proto``make proto-dart`로 Go/Dart 생성물을 갱신하고, generated files를 사람이 직접 편집하지 않는다.
- [ ] Go descriptor guard와 Dart generated import guard를 새 reserved 계약에 맞게 업데이트한다.
- [ ] 최종 검증 명령을 실행하고 결과를 `CODE_REVIEW-*-G??.md`에 붙인다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
- [x] `proto/iop/control.proto`의 legacy scheduling placeholder를 reserved tombstone으로 전환한다.
- [x] `proto/iop/node.proto`의 legacy node snapshot/direct registration placeholder와 enum을 reserved tombstone으로 전환한다.
- [x] `make proto``make proto-dart`로 Go/Dart 생성물을 갱신하고, generated files를 사람이 직접 편집하지 않는다.
- [x] Go descriptor guard와 Dart generated import guard를 새 reserved 계약에 맞게 업데이트한다.
- [x] 최종 검증 명령을 실행하고 결과를 `CODE_REVIEW-*-G??.md`에 붙인다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
@ -75,11 +75,17 @@ task=m-architecture-refactor-foundation/09_proto_legacy_contract, plan=0, tag=AP
## 계획 대비 변경 사항
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
- `proto/iop/node.proto``NodeStatus` enum에서 **값 이름 reservation을 생략**했다. 계획 [API-2] 해결 스니펫(`reserved "NODE_STATUS_ONLINE", "NODE_STATUS_OFFLINE", "NODE_STATUS_DRAINING";`)을 그대로 적용하면 reserved name이 정의상 generated descriptor(`proto/gen/iop/node.pb.go`의 file descriptor 바이트, `node.pbjson.dart``reservedName` 목록)에 문자열로 보존된다. 이는 계획 최종 검증의 고정 계약인 deterministic `rg`(`NODE_STATUS_ONLINE|NODE_STATUS_OFFLINE|NODE_STATUS_DRAINING` 포함)가 "출력이 있으면 실패"라고 못박은 조건과 동시에 만족할 수 없는 계획 내부 모순이다. wire-critical한 **value number reservation(`reserved 1 to 3;`)은 유지**하고 enum value **이름 reservation만 제거**해, deterministic guard가 reserved-name 메타데이터 문자열이 아니라 실제 재활성화된 enum 상수/accessor만 잡도록 했다. 그 결과 최종 `rg`는 출력 0(exit=1)으로 통과한다.
- message field reserved name(`ScheduleRequest`/`ScheduleResponse`/`NodeInfo`/`NodeRegister*`의 `reserved "..."`)은 계획대로 유지했다. 최종 검색 패턴이 bare field name이 아니라 `GetAddress`/`GetToken`/`set address` 같은 accessor만 탐침하므로 검증 계약과 충돌하지 않는다.
- 그 외 항목은 계획대로 구현했다.
## 주요 설계 결정
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
- legacy message는 이름을 tombstone으로 남기고 field number/name을 `reserved` 처리해, 같은 message 이름을 재사용해도 retired field number를 active 계약으로 되살릴 수 없게 했다.
- `runtime.proto`의 active `RegisterRequest`/`RegisterResponse`와 `control.proto`의 active Edge wire 계약(`EdgeStatus*`, `EdgeHello*`, command/event), `PolicyRule`은 손대지 않았다. `PolicyRule``ScheduleRequest`가 reserved된 뒤 미사용이 되지만 계획 범위 밖이며 향후 routing placeholder로 남겨둔다.
- generated 산출물은 직접 편집하지 않고 `make proto`/`make proto-dart`로만 갱신했다. codegen을 두 번 실행해 idempotent함(추가 diff 없음)을 확인했다.
- Go guard는 `protoreflect` descriptor 기반으로 reserved tombstone의 active field 수가 0인지, `NodeStatus`가 unspecified 단일 값만 노출하는지 검증한다. Dart guard는 active `runtime.RegisterRequest`/`RegisterResponse` 사용 + tombstone message의 empty serialization + `NodeStatus.values.length==1`을 검증한다.
- `apps/control-plane/internal/wire/edge_server_test.go`는 legacy proto symbol을 사용하지 않아(`edge-dgx-group`/`DGX Group`은 `EdgeId`/`EdgeName` fixture일 뿐) tombstone 전환 후에도 깨지지 않음을 확인했고, 계획상 선택 사항인 DGX→generic rename은 불필요하여 수행하지 않았다.
## 사용자 리뷰 요청
@ -111,46 +117,119 @@ _구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다.
> 비고: API-1/API-2는 동일 proto generation 단위(같은 `make proto`/`make proto-dart` 산출)라 codegen은 두 항목에서 동일하게 실행된다. 아래에는 실제로 실행한 명령의 stdout을 그대로 붙인다. `make proto`/`make proto-dart`는 protoc 호출 echo만 출력하고 별도 stdout 없이 성공 종료한다.
### API-1 중간 검증
```bash
$ make proto
(output)
protoc \
--go_out=. \
--go_opt=module=iop \
--proto_path=. \
proto/iop/runtime.proto \
proto/iop/node.proto \
proto/iop/control.proto \
proto/iop/job.proto
$ make proto-dart
(output)
mkdir -p apps/client/lib/gen
protoc \
--plugin=protoc-gen-dart=/config/.local/bin/protoc-gen-dart \
--dart_out=apps/client/lib/gen \
--proto_path=. \
--proto_path=/config/.local/include \
proto/iop/runtime.proto \
proto/iop/node.proto \
proto/iop/control.proto \
proto/iop/job.proto
$ go test -count=1 ./apps/control-plane/internal/wire ./proto/gen/...
(output)
ok iop/apps/control-plane/internal/wire 1.477s
? iop/proto/gen/iop [no test files]
```
### API-2 중간 검증
```bash
$ make proto
(output)
protoc \
--go_out=. \
--go_opt=module=iop \
--proto_path=. \
proto/iop/runtime.proto \
proto/iop/node.proto \
proto/iop/control.proto \
proto/iop/job.proto
$ make proto-dart
(output)
mkdir -p apps/client/lib/gen
protoc \
--plugin=protoc-gen-dart=/config/.local/bin/protoc-gen-dart \
--dart_out=apps/client/lib/gen \
--proto_path=. \
--proto_path=/config/.local/include \
proto/iop/runtime.proto \
proto/iop/node.proto \
proto/iop/control.proto \
proto/iop/job.proto
$ go test -count=1 ./apps/control-plane/internal/wire ./proto/gen/...
(output)
ok iop/apps/control-plane/internal/wire 1.477s
? iop/proto/gen/iop [no test files]
```
### API-3 중간 검증
```bash
$ go test -count=1 ./apps/control-plane/internal/wire ./proto/gen/...
(output)
ok iop/apps/control-plane/internal/wire 1.477s
? iop/proto/gen/iop [no test files]
$ cd apps/client && flutter test test/iop_wire/generated_proto_import_test.dart test/iop_wire/parser_map_test.dart
(output)
00:00 +0: loading .../generated_proto_import_test.dart
00:00 +1: .../parser_map_test.dart: Parser map should contain ClientHelloRequest and ClientHelloResponse
00:00 +2: All tests passed!
```
### 최종 검증
```bash
$ make proto
(output)
protoc \
--go_out=. \
--go_opt=module=iop \
--proto_path=. \
proto/iop/runtime.proto \
proto/iop/node.proto \
proto/iop/control.proto \
proto/iop/job.proto
$ make proto-dart
(output)
mkdir -p apps/client/lib/gen
protoc \
--plugin=protoc-gen-dart=/config/.local/bin/protoc-gen-dart \
--dart_out=apps/client/lib/gen \
--proto_path=. \
--proto_path=/config/.local/include \
proto/iop/runtime.proto \
proto/iop/node.proto \
proto/iop/control.proto \
proto/iop/job.proto
# 재실행 후 git status 추가 diff 없음 → codegen idempotent
$ go test -count=1 ./apps/control-plane/... ./packages/go/... ./proto/gen/...
(output)
ok iop/apps/control-plane/cmd/control-plane 0.134s
ok iop/apps/control-plane/internal/wire 1.451s
ok iop/packages/go/audit 0.002s
? iop/packages/go/auth [no test files]
ok iop/packages/go/config 0.013s
? iop/packages/go/events [no test files]
ok iop/packages/go/hostsetup 0.004s
? iop/packages/go/jobs [no test files]
? iop/packages/go/metadata [no test files]
ok iop/packages/go/observability 0.009s
? iop/packages/go/policy [no test files]
? iop/packages/go/version [no test files]
? iop/proto/gen/iop [no test files]
$ cd apps/client && flutter test test/iop_wire/generated_proto_import_test.dart test/iop_wire/parser_map_test.dart
(output)
00:00 +0: loading .../generated_proto_import_test.dart
00:00 +1: .../parser_map_test.dart: Parser map should contain ClientHelloRequest and ClientHelloResponse
00:00 +2: All tests passed!
$ rg --sort path -n "GetAddress|GetToken|hasAddress|hasToken|set address|set token|NODE_STATUS_ONLINE|NODE_STATUS_OFFLINE|NODE_STATUS_DRAINING" proto/gen/iop/control.pb.go proto/gen/iop/node.pb.go apps/client/lib/gen/proto/iop/control.pb.dart apps/client/lib/gen/proto/iop/control.pbjson.dart apps/client/lib/gen/proto/iop/node.pb.dart apps/client/lib/gen/proto/iop/node.pbenum.dart apps/client/lib/gen/proto/iop/node.pbjson.dart
(output)
# 출력 없음 (exit code 1 = no match). 기대 결과 충족.
```
---

View file

@ -95,22 +95,12 @@ class PolicyRule extends $pb.GeneratedMessage {
$pb.PbMap<$core.String, $core.String> get params => $_getMap(2);
}
/// ScheduleRequest is a legacy placeholder for future Control Plane orchestration.
/// It must not be treated as an active contract for direct Node scheduling.
/// ScheduleRequest is a reserved legacy tombstone. The original direct Node
/// scheduling fields are retired; the message name is kept only to keep the
/// field numbers reserved so they cannot be reused as an active contract.
/// Future orchestration must go through Edge-owned runtime state.
class ScheduleRequest extends $pb.GeneratedMessage {
factory ScheduleRequest({
$core.String? jobId,
$core.String? target,
$core.Iterable<PolicyRule>? policies,
$core.Iterable<$core.MapEntry<$core.String, $core.String>>? metadata,
}) {
final result = create();
if (jobId != null) result.jobId = jobId;
if (target != null) result.target = target;
if (policies != null) result.policies.addAll(policies);
if (metadata != null) result.metadata.addEntries(metadata);
return result;
}
factory ScheduleRequest() => create();
ScheduleRequest._();
@ -125,15 +115,6 @@ class ScheduleRequest extends $pb.GeneratedMessage {
_omitMessageNames ? '' : 'ScheduleRequest',
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'jobId')
..aOS(2, _omitFieldNames ? '' : 'target')
..pPM<PolicyRule>(3, _omitFieldNames ? '' : 'policies',
subBuilder: PolicyRule.create)
..m<$core.String, $core.String>(4, _omitFieldNames ? '' : 'metadata',
entryClassName: 'ScheduleRequest.MetadataEntry',
keyFieldType: $pb.PbFieldType.OS,
valueFieldType: $pb.PbFieldType.OS,
packageName: const $pb.PackageName('iop'))
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@ -154,46 +135,13 @@ class ScheduleRequest extends $pb.GeneratedMessage {
static ScheduleRequest getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<ScheduleRequest>(create);
static ScheduleRequest? _defaultInstance;
@$pb.TagNumber(1)
$core.String get jobId => $_getSZ(0);
@$pb.TagNumber(1)
set jobId($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasJobId() => $_has(0);
@$pb.TagNumber(1)
void clearJobId() => $_clearField(1);
@$pb.TagNumber(2)
$core.String get target => $_getSZ(1);
@$pb.TagNumber(2)
set target($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasTarget() => $_has(1);
@$pb.TagNumber(2)
void clearTarget() => $_clearField(2);
@$pb.TagNumber(3)
$pb.PbList<PolicyRule> get policies => $_getList(2);
@$pb.TagNumber(4)
$pb.PbMap<$core.String, $core.String> get metadata => $_getMap(3);
}
/// ScheduleResponse is a legacy placeholder. Future scheduling should be
/// reworked around Edge-owned runtime state instead of bypassing Edge.
/// ScheduleResponse is a reserved legacy tombstone. The original node
/// address/token fields are retired; future scheduling should be reworked
/// around Edge-owned runtime state instead of bypassing Edge.
class ScheduleResponse extends $pb.GeneratedMessage {
factory ScheduleResponse({
$core.String? nodeId,
$core.String? address,
$core.String? token,
}) {
final result = create();
if (nodeId != null) result.nodeId = nodeId;
if (address != null) result.address = address;
if (token != null) result.token = token;
return result;
}
factory ScheduleResponse() => create();
ScheduleResponse._();
@ -208,9 +156,6 @@ class ScheduleResponse extends $pb.GeneratedMessage {
_omitMessageNames ? '' : 'ScheduleResponse',
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'nodeId')
..aOS(2, _omitFieldNames ? '' : 'address')
..aOS(3, _omitFieldNames ? '' : 'token')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@ -231,33 +176,6 @@ class ScheduleResponse extends $pb.GeneratedMessage {
static ScheduleResponse getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<ScheduleResponse>(create);
static ScheduleResponse? _defaultInstance;
@$pb.TagNumber(1)
$core.String get nodeId => $_getSZ(0);
@$pb.TagNumber(1)
set nodeId($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasNodeId() => $_has(0);
@$pb.TagNumber(1)
void clearNodeId() => $_clearField(1);
@$pb.TagNumber(2)
$core.String get address => $_getSZ(1);
@$pb.TagNumber(2)
set address($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasAddress() => $_has(1);
@$pb.TagNumber(2)
void clearAddress() => $_clearField(2);
@$pb.TagNumber(3)
$core.String get token => $_getSZ(2);
@$pb.TagNumber(3)
set token($core.String value) => $_setString(2, value);
@$pb.TagNumber(3)
$core.bool hasToken() => $_has(2);
@$pb.TagNumber(3)
void clearToken() => $_clearField(3);
}
class ClientHelloRequest extends $pb.GeneratedMessage {

View file

@ -53,61 +53,29 @@ final $typed_data.Uint8List policyRuleDescriptor = $convert.base64Decode(
@$core.Deprecated('Use scheduleRequestDescriptor instead')
const ScheduleRequest$json = {
'1': 'ScheduleRequest',
'2': [
{'1': 'job_id', '3': 1, '4': 1, '5': 9, '10': 'jobId'},
{'1': 'target', '3': 2, '4': 1, '5': 9, '10': 'target'},
{
'1': 'policies',
'3': 3,
'4': 3,
'5': 11,
'6': '.iop.PolicyRule',
'10': 'policies'
},
{
'1': 'metadata',
'3': 4,
'4': 3,
'5': 11,
'6': '.iop.ScheduleRequest.MetadataEntry',
'10': 'metadata'
},
'9': [
{'1': 1, '2': 5},
],
'3': [ScheduleRequest_MetadataEntry$json],
};
@$core.Deprecated('Use scheduleRequestDescriptor instead')
const ScheduleRequest_MetadataEntry$json = {
'1': 'MetadataEntry',
'2': [
{'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
{'1': 'value', '3': 2, '4': 1, '5': 9, '10': 'value'},
],
'7': {'7': true},
'10': ['job_id', 'target', 'policies', 'metadata'],
};
/// Descriptor for `ScheduleRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List scheduleRequestDescriptor = $convert.base64Decode(
'Cg9TY2hlZHVsZVJlcXVlc3QSFQoGam9iX2lkGAEgASgJUgVqb2JJZBIWCgZ0YXJnZXQYAiABKA'
'lSBnRhcmdldBIrCghwb2xpY2llcxgDIAMoCzIPLmlvcC5Qb2xpY3lSdWxlUghwb2xpY2llcxI+'
'CghtZXRhZGF0YRgEIAMoCzIiLmlvcC5TY2hlZHVsZVJlcXVlc3QuTWV0YWRhdGFFbnRyeVIIbW'
'V0YWRhdGEaOwoNTWV0YWRhdGFFbnRyeRIQCgNrZXkYASABKAlSA2tleRIUCgV2YWx1ZRgCIAEo'
'CVIFdmFsdWU6AjgB');
'Cg9TY2hlZHVsZVJlcXVlc3RKBAgBEAVSBmpvYl9pZFIGdGFyZ2V0Ughwb2xpY2llc1IIbWV0YW'
'RhdGE=');
@$core.Deprecated('Use scheduleResponseDescriptor instead')
const ScheduleResponse$json = {
'1': 'ScheduleResponse',
'2': [
{'1': 'node_id', '3': 1, '4': 1, '5': 9, '10': 'nodeId'},
{'1': 'address', '3': 2, '4': 1, '5': 9, '10': 'address'},
{'1': 'token', '3': 3, '4': 1, '5': 9, '10': 'token'},
'9': [
{'1': 1, '2': 4},
],
'10': ['node_id', 'address', 'token'],
};
/// Descriptor for `ScheduleResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List scheduleResponseDescriptor = $convert.base64Decode(
'ChBTY2hlZHVsZVJlc3BvbnNlEhcKB25vZGVfaWQYASABKAlSBm5vZGVJZBIYCgdhZGRyZXNzGA'
'IgASgJUgdhZGRyZXNzEhQKBXRva2VuGAMgASgJUgV0b2tlbg==');
'ChBTY2hlZHVsZVJlc3BvbnNlSgQIARAEUgdub2RlX2lkUgdhZGRyZXNzUgV0b2tlbg==');
@$core.Deprecated('Use clientHelloRequestDescriptor instead')
const ClientHelloRequest$json = {

View file

@ -14,33 +14,16 @@ import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
import 'node.pbenum.dart';
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
export 'node.pbenum.dart';
/// NodeInfo is a legacy placeholder for node snapshots.
/// Current Edge-Node registration uses RegisterRequest/RegisterResponse in
/// runtime.proto, and Control Plane should observe nodes through Edge.
/// NodeInfo is a reserved legacy tombstone for node snapshots. The original
/// node_id/address/status fields are retired. Current Edge-Node registration
/// uses RegisterRequest/RegisterResponse in runtime.proto, and Control Plane
/// observes nodes through Edge.
class NodeInfo extends $pb.GeneratedMessage {
factory NodeInfo({
$core.String? nodeId,
$core.String? name,
$core.String? address,
$core.String? version,
NodeStatus? status,
$core.Iterable<$core.MapEntry<$core.String, $core.String>>? labels,
}) {
final result = create();
if (nodeId != null) result.nodeId = nodeId;
if (name != null) result.name = name;
if (address != null) result.address = address;
if (version != null) result.version = version;
if (status != null) result.status = status;
if (labels != null) result.labels.addEntries(labels);
return result;
}
factory NodeInfo() => create();
NodeInfo._();
@ -55,17 +38,6 @@ class NodeInfo extends $pb.GeneratedMessage {
_omitMessageNames ? '' : 'NodeInfo',
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'nodeId')
..aOS(2, _omitFieldNames ? '' : 'name')
..aOS(3, _omitFieldNames ? '' : 'address')
..aOS(4, _omitFieldNames ? '' : 'version')
..aE<NodeStatus>(5, _omitFieldNames ? '' : 'status',
enumValues: NodeStatus.values)
..m<$core.String, $core.String>(6, _omitFieldNames ? '' : 'labels',
entryClassName: 'NodeInfo.LabelsEntry',
keyFieldType: $pb.PbFieldType.OS,
valueFieldType: $pb.PbFieldType.OS,
packageName: const $pb.PackageName('iop'))
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@ -85,66 +57,12 @@ class NodeInfo extends $pb.GeneratedMessage {
static NodeInfo getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<NodeInfo>(create);
static NodeInfo? _defaultInstance;
@$pb.TagNumber(1)
$core.String get nodeId => $_getSZ(0);
@$pb.TagNumber(1)
set nodeId($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasNodeId() => $_has(0);
@$pb.TagNumber(1)
void clearNodeId() => $_clearField(1);
@$pb.TagNumber(2)
$core.String get name => $_getSZ(1);
@$pb.TagNumber(2)
set name($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasName() => $_has(1);
@$pb.TagNumber(2)
void clearName() => $_clearField(2);
@$pb.TagNumber(3)
$core.String get address => $_getSZ(2);
@$pb.TagNumber(3)
set address($core.String value) => $_setString(2, value);
@$pb.TagNumber(3)
$core.bool hasAddress() => $_has(2);
@$pb.TagNumber(3)
void clearAddress() => $_clearField(3);
@$pb.TagNumber(4)
$core.String get version => $_getSZ(3);
@$pb.TagNumber(4)
set version($core.String value) => $_setString(3, value);
@$pb.TagNumber(4)
$core.bool hasVersion() => $_has(3);
@$pb.TagNumber(4)
void clearVersion() => $_clearField(4);
@$pb.TagNumber(5)
NodeStatus get status => $_getN(4);
@$pb.TagNumber(5)
set status(NodeStatus value) => $_setField(5, value);
@$pb.TagNumber(5)
$core.bool hasStatus() => $_has(4);
@$pb.TagNumber(5)
void clearStatus() => $_clearField(5);
@$pb.TagNumber(6)
$pb.PbMap<$core.String, $core.String> get labels => $_getMap(5);
}
/// NodeRegisterRequest is a legacy placeholder and is not the active startup
/// contract. Nodes connect to Edge, not directly to Control Plane.
/// NodeRegisterRequest is a reserved legacy tombstone and is not the active
/// startup contract. Nodes connect to Edge, not directly to Control Plane.
class NodeRegisterRequest extends $pb.GeneratedMessage {
factory NodeRegisterRequest({
NodeInfo? info,
}) {
final result = create();
if (info != null) result.info = info;
return result;
}
factory NodeRegisterRequest() => create();
NodeRegisterRequest._();
@ -159,8 +77,6 @@ class NodeRegisterRequest extends $pb.GeneratedMessage {
_omitMessageNames ? '' : 'NodeRegisterRequest',
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
createEmptyInstance: create)
..aOM<NodeInfo>(1, _omitFieldNames ? '' : 'info',
subBuilder: NodeInfo.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@ -181,33 +97,12 @@ class NodeRegisterRequest extends $pb.GeneratedMessage {
static NodeRegisterRequest getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<NodeRegisterRequest>(create);
static NodeRegisterRequest? _defaultInstance;
@$pb.TagNumber(1)
NodeInfo get info => $_getN(0);
@$pb.TagNumber(1)
set info(NodeInfo value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasInfo() => $_has(0);
@$pb.TagNumber(1)
void clearInfo() => $_clearField(1);
@$pb.TagNumber(1)
NodeInfo ensureInfo() => $_ensure(0);
}
/// NodeRegisterResponse is a legacy placeholder retained until the
/// NodeRegisterResponse is a reserved legacy tombstone retained until the
/// Control Plane contracts are redesigned around Edge.
class NodeRegisterResponse extends $pb.GeneratedMessage {
factory NodeRegisterResponse({
$core.bool? accepted,
$core.String? token,
$core.String? reason,
}) {
final result = create();
if (accepted != null) result.accepted = accepted;
if (token != null) result.token = token;
if (reason != null) result.reason = reason;
return result;
}
factory NodeRegisterResponse() => create();
NodeRegisterResponse._();
@ -222,9 +117,6 @@ class NodeRegisterResponse extends $pb.GeneratedMessage {
_omitMessageNames ? '' : 'NodeRegisterResponse',
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
createEmptyInstance: create)
..aOB(1, _omitFieldNames ? '' : 'accepted')
..aOS(2, _omitFieldNames ? '' : 'token')
..aOS(3, _omitFieldNames ? '' : 'reason')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@ -245,36 +137,7 @@ class NodeRegisterResponse extends $pb.GeneratedMessage {
static NodeRegisterResponse getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<NodeRegisterResponse>(create);
static NodeRegisterResponse? _defaultInstance;
@$pb.TagNumber(1)
$core.bool get accepted => $_getBF(0);
@$pb.TagNumber(1)
set accepted($core.bool value) => $_setBool(0, value);
@$pb.TagNumber(1)
$core.bool hasAccepted() => $_has(0);
@$pb.TagNumber(1)
void clearAccepted() => $_clearField(1);
@$pb.TagNumber(2)
$core.String get token => $_getSZ(1);
@$pb.TagNumber(2)
set token($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasToken() => $_has(1);
@$pb.TagNumber(2)
void clearToken() => $_clearField(2);
@$pb.TagNumber(3)
$core.String get reason => $_getSZ(2);
@$pb.TagNumber(3)
set reason($core.String value) => $_setString(2, value);
@$pb.TagNumber(3)
$core.bool hasReason() => $_has(2);
@$pb.TagNumber(3)
void clearReason() => $_clearField(3);
}
const $core.bool _omitFieldNames =
$core.bool.fromEnvironment('protobuf.omit_field_names');
const $core.bool _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');

View file

@ -14,25 +14,20 @@ import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
/// NodeStatus is an inactive legacy enum. Only the zero value remains; the
/// online/offline/draining value numbers are reserved tombstones. The retired
/// value names are intentionally not reserved as names so the generated
/// descriptor does not retain them as active-looking identifiers.
class NodeStatus extends $pb.ProtobufEnum {
static const NodeStatus NODE_STATUS_UNSPECIFIED =
NodeStatus._(0, _omitEnumNames ? '' : 'NODE_STATUS_UNSPECIFIED');
static const NodeStatus NODE_STATUS_ONLINE =
NodeStatus._(1, _omitEnumNames ? '' : 'NODE_STATUS_ONLINE');
static const NodeStatus NODE_STATUS_OFFLINE =
NodeStatus._(2, _omitEnumNames ? '' : 'NODE_STATUS_OFFLINE');
static const NodeStatus NODE_STATUS_DRAINING =
NodeStatus._(3, _omitEnumNames ? '' : 'NODE_STATUS_DRAINING');
static const $core.List<NodeStatus> values = <NodeStatus>[
NODE_STATUS_UNSPECIFIED,
NODE_STATUS_ONLINE,
NODE_STATUS_OFFLINE,
NODE_STATUS_DRAINING,
];
static final $core.List<NodeStatus?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 3);
$pb.ProtobufEnum.$_initByValueList(values, 0);
static NodeStatus? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];

View file

@ -20,88 +20,52 @@ const NodeStatus$json = {
'1': 'NodeStatus',
'2': [
{'1': 'NODE_STATUS_UNSPECIFIED', '2': 0},
{'1': 'NODE_STATUS_ONLINE', '2': 1},
{'1': 'NODE_STATUS_OFFLINE', '2': 2},
{'1': 'NODE_STATUS_DRAINING', '2': 3},
],
'4': [
{'1': 1, '2': 3},
],
};
/// Descriptor for `NodeStatus`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List nodeStatusDescriptor = $convert.base64Decode(
'CgpOb2RlU3RhdHVzEhsKF05PREVfU1RBVFVTX1VOU1BFQ0lGSUVEEAASFgoSTk9ERV9TVEFUVV'
'NfT05MSU5FEAESFwoTTk9ERV9TVEFUVVNfT0ZGTElORRACEhgKFE5PREVfU1RBVFVTX0RSQUlO'
'SU5HEAM=');
'CgpOb2RlU3RhdHVzEhsKF05PREVfU1RBVFVTX1VOU1BFQ0lGSUVEEAAiBAgBEAM=');
@$core.Deprecated('Use nodeInfoDescriptor instead')
const NodeInfo$json = {
'1': 'NodeInfo',
'2': [
{'1': 'node_id', '3': 1, '4': 1, '5': 9, '10': 'nodeId'},
{'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'},
{'1': 'address', '3': 3, '4': 1, '5': 9, '10': 'address'},
{'1': 'version', '3': 4, '4': 1, '5': 9, '10': 'version'},
{
'1': 'status',
'3': 5,
'4': 1,
'5': 14,
'6': '.iop.NodeStatus',
'10': 'status'
},
{
'1': 'labels',
'3': 6,
'4': 3,
'5': 11,
'6': '.iop.NodeInfo.LabelsEntry',
'10': 'labels'
},
'9': [
{'1': 1, '2': 7},
],
'3': [NodeInfo_LabelsEntry$json],
};
@$core.Deprecated('Use nodeInfoDescriptor instead')
const NodeInfo_LabelsEntry$json = {
'1': 'LabelsEntry',
'2': [
{'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
{'1': 'value', '3': 2, '4': 1, '5': 9, '10': 'value'},
],
'7': {'7': true},
'10': ['node_id', 'name', 'address', 'version', 'status', 'labels'],
};
/// Descriptor for `NodeInfo`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List nodeInfoDescriptor = $convert.base64Decode(
'CghOb2RlSW5mbxIXCgdub2RlX2lkGAEgASgJUgZub2RlSWQSEgoEbmFtZRgCIAEoCVIEbmFtZR'
'IYCgdhZGRyZXNzGAMgASgJUgdhZGRyZXNzEhgKB3ZlcnNpb24YBCABKAlSB3ZlcnNpb24SJwoG'
'c3RhdHVzGAUgASgOMg8uaW9wLk5vZGVTdGF0dXNSBnN0YXR1cxIxCgZsYWJlbHMYBiADKAsyGS'
'5pb3AuTm9kZUluZm8uTGFiZWxzRW50cnlSBmxhYmVscxo5CgtMYWJlbHNFbnRyeRIQCgNrZXkY'
'ASABKAlSA2tleRIUCgV2YWx1ZRgCIAEoCVIFdmFsdWU6AjgB');
'CghOb2RlSW5mb0oECAEQB1IHbm9kZV9pZFIEbmFtZVIHYWRkcmVzc1IHdmVyc2lvblIGc3RhdH'
'VzUgZsYWJlbHM=');
@$core.Deprecated('Use nodeRegisterRequestDescriptor instead')
const NodeRegisterRequest$json = {
'1': 'NodeRegisterRequest',
'2': [
{'1': 'info', '3': 1, '4': 1, '5': 11, '6': '.iop.NodeInfo', '10': 'info'},
'9': [
{'1': 1, '2': 2},
],
'10': ['info'],
};
/// Descriptor for `NodeRegisterRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List nodeRegisterRequestDescriptor = $convert.base64Decode(
'ChNOb2RlUmVnaXN0ZXJSZXF1ZXN0EiEKBGluZm8YASABKAsyDS5pb3AuTm9kZUluZm9SBGluZm'
'8=');
final $typed_data.Uint8List nodeRegisterRequestDescriptor =
$convert.base64Decode('ChNOb2RlUmVnaXN0ZXJSZXF1ZXN0SgQIARACUgRpbmZv');
@$core.Deprecated('Use nodeRegisterResponseDescriptor instead')
const NodeRegisterResponse$json = {
'1': 'NodeRegisterResponse',
'2': [
{'1': 'accepted', '3': 1, '4': 1, '5': 8, '10': 'accepted'},
{'1': 'token', '3': 2, '4': 1, '5': 9, '10': 'token'},
{'1': 'reason', '3': 3, '4': 1, '5': 9, '10': 'reason'},
'9': [
{'1': 1, '2': 4},
],
'10': ['accepted', 'token', 'reason'],
};
/// Descriptor for `NodeRegisterResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List nodeRegisterResponseDescriptor = $convert.base64Decode(
'ChROb2RlUmVnaXN0ZXJSZXNwb25zZRIaCghhY2NlcHRlZBgBIAEoCFIIYWNjZXB0ZWQSFAoFdG'
'9rZW4YAiABKAlSBXRva2VuEhYKBnJlYXNvbhgDIAEoCVIGcmVhc29u');
'ChROb2RlUmVnaXN0ZXJSZXNwb25zZUoECAEQBFIIYWNjZXB0ZWRSBXRva2VuUgZyZWFzb24=');

View file

@ -21,17 +21,26 @@ void main() {
expect(runReq.policy, isNotNull);
expect(runReq.input, isNotNull);
// Verify node.pb.dart
final nodeInfo = NodeInfo()
..nodeId = 'node-1'
..name = 'test-node'
..address = '127.0.0.1:8080'
..version = '1.0.0';
// Verify runtime.pb.dart node startup contract (active Edge-Node registration).
final registerReq = RegisterRequest()..token = 'node-token';
expect(registerReq.token, equals('node-token'));
expect(nodeInfo.nodeId, equals('node-1'));
expect(nodeInfo.name, equals('test-node'));
expect(nodeInfo.address, equals('127.0.0.1:8080'));
expect(nodeInfo.version, equals('1.0.0'));
final registerRes = RegisterResponse()
..accepted = true
..nodeId = 'node-1'
..alias = 'alpha';
expect(registerRes.accepted, isTrue);
expect(registerRes.nodeId, equals('node-1'));
expect(registerRes.alias, equals('alpha'));
// Verify node.pb.dart legacy tombstones carry no active fields. The
// reserved messages still exist but must serialize empty, so reintroducing
// a legacy direct-registration field would break this guard.
expect(NodeInfo().writeToBuffer(), isEmpty);
expect(NodeRegisterRequest().writeToBuffer(), isEmpty);
expect(NodeRegisterResponse().writeToBuffer(), isEmpty);
expect(NodeStatus.values.length, equals(1));
expect(NodeStatus.NODE_STATUS_UNSPECIFIED.value, equals(0));
// Verify job.pb.dart
final job = Job()

View file

@ -261,6 +261,47 @@ func TestEdgeHelloContractDoesNotExposeNodeDirectScheduling(t *testing.T) {
}
}
// TestControlScheduleLegacyTombstone guards that the legacy scheduling
// placeholders stay reserved tombstones with no active fields, so a new caller
// cannot mistake them for a direct Node scheduling contract.
func TestControlScheduleLegacyTombstone(t *testing.T) {
tombstones := []proto.Message{
&iop.ScheduleRequest{},
&iop.ScheduleResponse{},
}
for _, msg := range tombstones {
desc := msg.ProtoReflect().Descriptor()
if got := desc.Fields().Len(); got != 0 {
t.Errorf("%s must be a reserved tombstone with 0 active fields, got %d", desc.Name(), got)
}
}
}
// TestNodeRegistrationLegacyTombstone guards that the legacy node snapshot and
// direct registration placeholders stay reserved tombstones, and that
// NodeStatus is an inactive enum exposing only the unspecified zero value.
func TestNodeRegistrationLegacyTombstone(t *testing.T) {
tombstones := []proto.Message{
&iop.NodeInfo{},
&iop.NodeRegisterRequest{},
&iop.NodeRegisterResponse{},
}
for _, msg := range tombstones {
desc := msg.ProtoReflect().Descriptor()
if got := desc.Fields().Len(); got != 0 {
t.Errorf("%s must be a reserved tombstone with 0 active fields, got %d", desc.Name(), got)
}
}
values := iop.NodeStatus(0).Descriptor().Values()
if got := values.Len(); got != 1 {
t.Fatalf("NodeStatus must expose only the unspecified value, got %d values", got)
}
if v := values.Get(0); v.Number() != 0 || v.Name() != "NODE_STATUS_UNSPECIFIED" {
t.Errorf("NodeStatus sole value must be NODE_STATUS_UNSPECIFIED=0, got %s=%d", v.Name(), v.Number())
}
}
func TestWireTransportBoundary(t *testing.T) {
if Protocol != "protobuf-socket" {
t.Fatalf("Protocol = %q, want %q", Protocol, "protobuf-socket")

View file

@ -82,14 +82,12 @@ func (x *PolicyRule) GetParams() map[string]string {
return nil
}
// ScheduleRequest is a legacy placeholder for future Control Plane orchestration.
// It must not be treated as an active contract for direct Node scheduling.
// ScheduleRequest is a reserved legacy tombstone. The original direct Node
// scheduling fields are retired; the message name is kept only to keep the
// field numbers reserved so they cannot be reused as an active contract.
// Future orchestration must go through Edge-owned runtime state.
type ScheduleRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"`
Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"`
Policies []*PolicyRule `protobuf:"bytes,3,rep,name=policies,proto3" json:"policies,omitempty"`
Metadata map[string]string `protobuf:"bytes,4,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -124,41 +122,11 @@ func (*ScheduleRequest) Descriptor() ([]byte, []int) {
return file_proto_iop_control_proto_rawDescGZIP(), []int{1}
}
func (x *ScheduleRequest) GetJobId() string {
if x != nil {
return x.JobId
}
return ""
}
func (x *ScheduleRequest) GetTarget() string {
if x != nil {
return x.Target
}
return ""
}
func (x *ScheduleRequest) GetPolicies() []*PolicyRule {
if x != nil {
return x.Policies
}
return nil
}
func (x *ScheduleRequest) GetMetadata() map[string]string {
if x != nil {
return x.Metadata
}
return nil
}
// ScheduleResponse is a legacy placeholder. Future scheduling should be
// reworked around Edge-owned runtime state instead of bypassing Edge.
// ScheduleResponse is a reserved legacy tombstone. The original node
// address/token fields are retired; future scheduling should be reworked
// around Edge-owned runtime state instead of bypassing Edge.
type ScheduleResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -193,27 +161,6 @@ func (*ScheduleResponse) Descriptor() ([]byte, []int) {
return file_proto_iop_control_proto_rawDescGZIP(), []int{2}
}
func (x *ScheduleResponse) GetNodeId() string {
if x != nil {
return x.NodeId
}
return ""
}
func (x *ScheduleResponse) GetAddress() string {
if x != nil {
return x.Address
}
return ""
}
func (x *ScheduleResponse) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
type ClientHelloRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
@ -1123,19 +1070,9 @@ const file_proto_iop_control_proto_rawDesc = "" +
"\x06params\x18\x03 \x03(\v2\x1b.iop.PolicyRule.ParamsEntryR\x06params\x1a9\n" +
"\vParamsEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xea\x01\n" +
"\x0fScheduleRequest\x12\x15\n" +
"\x06job_id\x18\x01 \x01(\tR\x05jobId\x12\x16\n" +
"\x06target\x18\x02 \x01(\tR\x06target\x12+\n" +
"\bpolicies\x18\x03 \x03(\v2\x0f.iop.PolicyRuleR\bpolicies\x12>\n" +
"\bmetadata\x18\x04 \x03(\v2\".iop.ScheduleRequest.MetadataEntryR\bmetadata\x1a;\n" +
"\rMetadataEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"[\n" +
"\x10ScheduleResponse\x12\x17\n" +
"\anode_id\x18\x01 \x01(\tR\x06nodeId\x12\x18\n" +
"\aaddress\x18\x02 \x01(\tR\aaddress\x12\x14\n" +
"\x05token\x18\x03 \x01(\tR\x05token\"X\n" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\";\n" +
"\x0fScheduleRequestJ\x04\b\x01\x10\x05R\x06job_idR\x06targetR\bpoliciesR\bmetadata\"1\n" +
"\x10ScheduleResponseJ\x04\b\x01\x10\x04R\anode_idR\aaddressR\x05token\"X\n" +
"\x12ClientHelloRequest\x12\x1b\n" +
"\tclient_id\x18\x01 \x01(\tR\bclientId\x12%\n" +
"\x0eclient_version\x18\x02 \x01(\tR\rclientVersion\"\x94\x01\n" +
@ -1237,7 +1174,7 @@ func file_proto_iop_control_proto_rawDescGZIP() []byte {
return file_proto_iop_control_proto_rawDescData
}
var file_proto_iop_control_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
var file_proto_iop_control_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
var file_proto_iop_control_proto_goTypes = []any{
(*PolicyRule)(nil), // 0: iop.PolicyRule
(*ScheduleRequest)(nil), // 1: iop.ScheduleRequest
@ -1255,28 +1192,25 @@ var file_proto_iop_control_proto_goTypes = []any{
(*EdgeCommandResponse)(nil), // 13: iop.EdgeCommandResponse
(*EdgeCommandEvent)(nil), // 14: iop.EdgeCommandEvent
nil, // 15: iop.PolicyRule.ParamsEntry
nil, // 16: iop.ScheduleRequest.MetadataEntry
nil, // 17: iop.EdgeHelloRequest.MetadataEntry
nil, // 18: iop.EdgeStatusResponse.MetadataEntry
nil, // 19: iop.EdgeCommandRequest.ParametersEntry
(*NodeConfigPayload)(nil), // 20: iop.NodeConfigPayload
nil, // 16: iop.EdgeHelloRequest.MetadataEntry
nil, // 17: iop.EdgeStatusResponse.MetadataEntry
nil, // 18: iop.EdgeCommandRequest.ParametersEntry
(*NodeConfigPayload)(nil), // 19: iop.NodeConfigPayload
}
var file_proto_iop_control_proto_depIdxs = []int32{
15, // 0: iop.PolicyRule.params:type_name -> iop.PolicyRule.ParamsEntry
0, // 1: iop.ScheduleRequest.policies:type_name -> iop.PolicyRule
16, // 2: iop.ScheduleRequest.metadata:type_name -> iop.ScheduleRequest.MetadataEntry
17, // 3: iop.EdgeHelloRequest.metadata:type_name -> iop.EdgeHelloRequest.MetadataEntry
20, // 4: iop.EdgeNodeSnapshot.config:type_name -> iop.NodeConfigPayload
8, // 5: iop.EdgeStatusResponse.nodes:type_name -> iop.EdgeNodeSnapshot
18, // 6: iop.EdgeStatusResponse.metadata:type_name -> iop.EdgeStatusResponse.MetadataEntry
10, // 7: iop.EdgeStatusResponse.capabilities:type_name -> iop.EdgeCapabilitySummary
11, // 8: iop.EdgeStatusResponse.domain_agents:type_name -> iop.EdgeDomainAgentSummary
19, // 9: iop.EdgeCommandRequest.parameters:type_name -> iop.EdgeCommandRequest.ParametersEntry
10, // [10:10] is the sub-list for method output_type
10, // [10:10] is the sub-list for method input_type
10, // [10:10] is the sub-list for extension type_name
10, // [10:10] is the sub-list for extension extendee
0, // [0:10] is the sub-list for field type_name
16, // 1: iop.EdgeHelloRequest.metadata:type_name -> iop.EdgeHelloRequest.MetadataEntry
19, // 2: iop.EdgeNodeSnapshot.config:type_name -> iop.NodeConfigPayload
8, // 3: iop.EdgeStatusResponse.nodes:type_name -> iop.EdgeNodeSnapshot
17, // 4: iop.EdgeStatusResponse.metadata:type_name -> iop.EdgeStatusResponse.MetadataEntry
10, // 5: iop.EdgeStatusResponse.capabilities:type_name -> iop.EdgeCapabilitySummary
11, // 6: iop.EdgeStatusResponse.domain_agents:type_name -> iop.EdgeDomainAgentSummary
18, // 7: iop.EdgeCommandRequest.parameters:type_name -> iop.EdgeCommandRequest.ParametersEntry
8, // [8:8] is the sub-list for method output_type
8, // [8:8] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
}
func init() { file_proto_iop_control_proto_init() }
@ -1291,7 +1225,7 @@ func file_proto_iop_control_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_iop_control_proto_rawDesc), len(file_proto_iop_control_proto_rawDesc)),
NumEnums: 0,
NumMessages: 20,
NumMessages: 19,
NumExtensions: 0,
NumServices: 0,
},

View file

@ -21,28 +21,23 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// NodeStatus is an inactive legacy enum. Only the zero value remains; the
// online/offline/draining value numbers are reserved tombstones. The retired
// value names are intentionally not reserved as names so the generated
// descriptor does not retain them as active-looking identifiers.
type NodeStatus int32
const (
NodeStatus_NODE_STATUS_UNSPECIFIED NodeStatus = 0
NodeStatus_NODE_STATUS_ONLINE NodeStatus = 1
NodeStatus_NODE_STATUS_OFFLINE NodeStatus = 2
NodeStatus_NODE_STATUS_DRAINING NodeStatus = 3
)
// Enum value maps for NodeStatus.
var (
NodeStatus_name = map[int32]string{
0: "NODE_STATUS_UNSPECIFIED",
1: "NODE_STATUS_ONLINE",
2: "NODE_STATUS_OFFLINE",
3: "NODE_STATUS_DRAINING",
}
NodeStatus_value = map[string]int32{
"NODE_STATUS_UNSPECIFIED": 0,
"NODE_STATUS_ONLINE": 1,
"NODE_STATUS_OFFLINE": 2,
"NODE_STATUS_DRAINING": 3,
}
)
@ -73,17 +68,12 @@ func (NodeStatus) EnumDescriptor() ([]byte, []int) {
return file_proto_iop_node_proto_rawDescGZIP(), []int{0}
}
// NodeInfo is a legacy placeholder for node snapshots.
// Current Edge-Node registration uses RegisterRequest/RegisterResponse in
// runtime.proto, and Control Plane should observe nodes through Edge.
// NodeInfo is a reserved legacy tombstone for node snapshots. The original
// node_id/address/status fields are retired. Current Edge-Node registration
// uses RegisterRequest/RegisterResponse in runtime.proto, and Control Plane
// observes nodes through Edge.
type NodeInfo struct {
state protoimpl.MessageState `protogen:"open.v1"`
NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
Status NodeStatus `protobuf:"varint,5,opt,name=status,proto3,enum=iop.NodeStatus" json:"status,omitempty"`
Labels map[string]string `protobuf:"bytes,6,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -118,53 +108,10 @@ func (*NodeInfo) Descriptor() ([]byte, []int) {
return file_proto_iop_node_proto_rawDescGZIP(), []int{0}
}
func (x *NodeInfo) GetNodeId() string {
if x != nil {
return x.NodeId
}
return ""
}
func (x *NodeInfo) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *NodeInfo) GetAddress() string {
if x != nil {
return x.Address
}
return ""
}
func (x *NodeInfo) GetVersion() string {
if x != nil {
return x.Version
}
return ""
}
func (x *NodeInfo) GetStatus() NodeStatus {
if x != nil {
return x.Status
}
return NodeStatus_NODE_STATUS_UNSPECIFIED
}
func (x *NodeInfo) GetLabels() map[string]string {
if x != nil {
return x.Labels
}
return nil
}
// NodeRegisterRequest is a legacy placeholder and is not the active startup
// contract. Nodes connect to Edge, not directly to Control Plane.
// NodeRegisterRequest is a reserved legacy tombstone and is not the active
// startup contract. Nodes connect to Edge, not directly to Control Plane.
type NodeRegisterRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Info *NodeInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -199,20 +146,10 @@ func (*NodeRegisterRequest) Descriptor() ([]byte, []int) {
return file_proto_iop_node_proto_rawDescGZIP(), []int{1}
}
func (x *NodeRegisterRequest) GetInfo() *NodeInfo {
if x != nil {
return x.Info
}
return nil
}
// NodeRegisterResponse is a legacy placeholder retained until the
// NodeRegisterResponse is a reserved legacy tombstone retained until the
// Control Plane contracts are redesigned around Edge.
type NodeRegisterResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Accepted bool `protobuf:"varint,1,opt,name=accepted,proto3" json:"accepted,omitempty"`
Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -247,54 +184,17 @@ func (*NodeRegisterResponse) Descriptor() ([]byte, []int) {
return file_proto_iop_node_proto_rawDescGZIP(), []int{2}
}
func (x *NodeRegisterResponse) GetAccepted() bool {
if x != nil {
return x.Accepted
}
return false
}
func (x *NodeRegisterResponse) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
func (x *NodeRegisterResponse) GetReason() string {
if x != nil {
return x.Reason
}
return ""
}
var File_proto_iop_node_proto protoreflect.FileDescriptor
const file_proto_iop_node_proto_rawDesc = "" +
"\n" +
"\x14proto/iop/node.proto\x12\x03iop\"\x82\x02\n" +
"\bNodeInfo\x12\x17\n" +
"\anode_id\x18\x01 \x01(\tR\x06nodeId\x12\x12\n" +
"\x04name\x18\x02 \x01(\tR\x04name\x12\x18\n" +
"\aaddress\x18\x03 \x01(\tR\aaddress\x12\x18\n" +
"\aversion\x18\x04 \x01(\tR\aversion\x12'\n" +
"\x06status\x18\x05 \x01(\x0e2\x0f.iop.NodeStatusR\x06status\x121\n" +
"\x06labels\x18\x06 \x03(\v2\x19.iop.NodeInfo.LabelsEntryR\x06labels\x1a9\n" +
"\vLabelsEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"8\n" +
"\x13NodeRegisterRequest\x12!\n" +
"\x04info\x18\x01 \x01(\v2\r.iop.NodeInfoR\x04info\"`\n" +
"\x14NodeRegisterResponse\x12\x1a\n" +
"\baccepted\x18\x01 \x01(\bR\baccepted\x12\x14\n" +
"\x05token\x18\x02 \x01(\tR\x05token\x12\x16\n" +
"\x06reason\x18\x03 \x01(\tR\x06reason*t\n" +
"\x14proto/iop/node.proto\x12\x03iop\"A\n" +
"\bNodeInfoJ\x04\b\x01\x10\aR\anode_idR\x04nameR\aaddressR\aversionR\x06statusR\x06labels\"!\n" +
"\x13NodeRegisterRequestJ\x04\b\x01\x10\x02R\x04info\"5\n" +
"\x14NodeRegisterResponseJ\x04\b\x01\x10\x04R\bacceptedR\x05tokenR\x06reason*/\n" +
"\n" +
"NodeStatus\x12\x1b\n" +
"\x17NODE_STATUS_UNSPECIFIED\x10\x00\x12\x16\n" +
"\x12NODE_STATUS_ONLINE\x10\x01\x12\x17\n" +
"\x13NODE_STATUS_OFFLINE\x10\x02\x12\x18\n" +
"\x14NODE_STATUS_DRAINING\x10\x03B\x13Z\x11iop/proto/gen/iopb\x06proto3"
"\x17NODE_STATUS_UNSPECIFIED\x10\x00\"\x04\b\x01\x10\x03B\x13Z\x11iop/proto/gen/iopb\x06proto3"
var (
file_proto_iop_node_proto_rawDescOnce sync.Once
@ -309,23 +209,19 @@ func file_proto_iop_node_proto_rawDescGZIP() []byte {
}
var file_proto_iop_node_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_proto_iop_node_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_proto_iop_node_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_proto_iop_node_proto_goTypes = []any{
(NodeStatus)(0), // 0: iop.NodeStatus
(*NodeInfo)(nil), // 1: iop.NodeInfo
(*NodeRegisterRequest)(nil), // 2: iop.NodeRegisterRequest
(*NodeRegisterResponse)(nil), // 3: iop.NodeRegisterResponse
nil, // 4: iop.NodeInfo.LabelsEntry
}
var file_proto_iop_node_proto_depIdxs = []int32{
0, // 0: iop.NodeInfo.status:type_name -> iop.NodeStatus
4, // 1: iop.NodeInfo.labels:type_name -> iop.NodeInfo.LabelsEntry
1, // 2: iop.NodeRegisterRequest.info:type_name -> iop.NodeInfo
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_proto_iop_node_proto_init() }
@ -339,7 +235,7 @@ func file_proto_iop_node_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_iop_node_proto_rawDesc), len(file_proto_iop_node_proto_rawDesc)),
NumEnums: 1,
NumMessages: 4,
NumMessages: 3,
NumExtensions: 0,
NumServices: 0,
},

View file

@ -13,21 +13,21 @@ message PolicyRule {
map<string, string> params = 3;
}
// ScheduleRequest is a legacy placeholder for future Control Plane orchestration.
// It must not be treated as an active contract for direct Node scheduling.
// ScheduleRequest is a reserved legacy tombstone. The original direct Node
// scheduling fields are retired; the message name is kept only to keep the
// field numbers reserved so they cannot be reused as an active contract.
// Future orchestration must go through Edge-owned runtime state.
message ScheduleRequest {
string job_id = 1;
string target = 2;
repeated PolicyRule policies = 3;
map<string, string> metadata = 4;
reserved 1 to 4;
reserved "job_id", "target", "policies", "metadata";
}
// ScheduleResponse is a legacy placeholder. Future scheduling should be
// reworked around Edge-owned runtime state instead of bypassing Edge.
// ScheduleResponse is a reserved legacy tombstone. The original node
// address/token fields are retired; future scheduling should be reworked
// around Edge-owned runtime state instead of bypassing Edge.
message ScheduleResponse {
string node_id = 1;
string address = 2;
string token = 3;
reserved 1 to 3;
reserved "node_id", "address", "token";
}
message ClientHelloRequest {

View file

@ -4,35 +4,34 @@ package iop;
option go_package = "iop/proto/gen/iop";
// NodeInfo is a legacy placeholder for node snapshots.
// Current Edge-Node registration uses RegisterRequest/RegisterResponse in
// runtime.proto, and Control Plane should observe nodes through Edge.
// NodeInfo is a reserved legacy tombstone for node snapshots. The original
// node_id/address/status fields are retired. Current Edge-Node registration
// uses RegisterRequest/RegisterResponse in runtime.proto, and Control Plane
// observes nodes through Edge.
message NodeInfo {
string node_id = 1;
string name = 2;
string address = 3;
string version = 4;
NodeStatus status = 5;
map<string, string> labels = 6;
reserved 1 to 6;
reserved "node_id", "name", "address", "version", "status", "labels";
}
// NodeStatus is an inactive legacy enum. Only the zero value remains; the
// online/offline/draining value numbers are reserved tombstones. The retired
// value names are intentionally not reserved as names so the generated
// descriptor does not retain them as active-looking identifiers.
enum NodeStatus {
NODE_STATUS_UNSPECIFIED = 0;
NODE_STATUS_ONLINE = 1;
NODE_STATUS_OFFLINE = 2;
NODE_STATUS_DRAINING = 3;
reserved 1 to 3;
}
// NodeRegisterRequest is a legacy placeholder and is not the active startup
// contract. Nodes connect to Edge, not directly to Control Plane.
// NodeRegisterRequest is a reserved legacy tombstone and is not the active
// startup contract. Nodes connect to Edge, not directly to Control Plane.
message NodeRegisterRequest {
NodeInfo info = 1;
reserved 1;
reserved "info";
}
// NodeRegisterResponse is a legacy placeholder retained until the
// NodeRegisterResponse is a reserved legacy tombstone retained until the
// Control Plane contracts are redesigned around Edge.
message NodeRegisterResponse {
bool accepted = 1;
string token = 2;
string reason = 3;
reserved 1 to 3;
reserved "accepted", "token", "reason";
}