iop/agent-task/m-edge-local-dev-config-runtime/02+01_node_register_bootstrap/PLAN-cloud-G07.md
toki 5bb8a4bc85 feat: edge local dev config and observability improvements
- Add edge node bootstrap and runtime configuration
- Update observability with test coverage
- Add hostsetup test and template updates
- Add m-edge-local-dev-config-runtime task tracking
2026-05-28 05:44:43 +09:00

10 KiB

Plan - BOOTSTRAP

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

CODE_REVIEW-cloud-G07.md의 구현 에이전트 소유 섹션 작성은 필수다. 구현 후 검증을 실행하고 실제 출력과 구현 메모를 채운 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. finalization은 code-review-skill 전용이다.

배경

현재 Edge config의 nodes[]는 런타임 등록 source of truth지만 사용자가 직접 YAML을 편집해야 한다. Milestone은 iop-edge node register <node-id>가 node record를 생성/갱신하고, 바로 실행 가능한 one-line bootstrap command를 출력하는 UX를 요구한다. 이 작업은 config/env 기반이 완성된 뒤 진행해야 한다.

분석 결과

읽은 파일

  • agent-roadmap/current.md
  • agent-roadmap/phase/control-plane-portal-ops/PHASE.md
  • agent-roadmap/phase/control-plane-portal-ops/milestones/edge-local-dev-config-runtime.md
  • apps/edge/cmd/edge/main.go
  • apps/edge/cmd/edge/main_test.go
  • apps/edge/internal/node/store.go
  • apps/edge/internal/node/store_test.go
  • apps/edge/internal/bootstrap/runtime.go
  • apps/edge/internal/bootstrap/runtime_test.go
  • packages/config/config.go
  • packages/config/config_test.go
  • configs/edge.yaml
  • bin/build/field-binaries.sh
  • docs/field-bootstrap-user-test.md
  • docs/field-bootstrap-work-guide.md
  • docs/deploy-dev.md

테스트 커버리지 공백

  • config check loads YAML but does not exercise edgenode.LoadFromConfig from the CLI path.
  • edgenode.LoadFromConfig covers duplicate token/alias/id and empty token, but not adapter/runtime semantic validation.
  • No node or node register command exists.
  • Bootstrap scripts exist in bin/build/field-binaries.sh, but Edge CLI does not render the one-line command from config.

심볼 참조

  • none. No rename/remove is planned.

분할 판단

Split decision policy was evaluated before choosing plan files. Shared task group: agent-task/m-edge-local-dev-config-runtime/.

  • 01_config_runtime_env must finish first because this task needs resolved config path, advertise host, artifact URL, and Node transport address.
  • 02+01_node_register_bootstrap adds config validation and mutation.
  • 03+01,02_help_smoke_bundle_docs waits for this task because help and docs must describe the real register/bootstrap commands.

범위 결정 근거

Do not change the node transport handshake, bootstrap shell script internals, artifact build layout, Control Plane enrollment, or Node user-facing config commands here. The command may write an implementation detail config consumed by existing bootstrap scripts, but user-facing output must stay one-line and token-positional.

빌드 등급

build=cloud-G07, review=cloud-G07. This is CLI workflow, YAML mutation, token generation, bootstrap command rendering, and config validation with user-facing side effects.

구현 체크리스트

  • Verify agent-task/m-edge-local-dev-config-runtime/01_config_runtime_env/complete.log exists before implementation starts.
  • iop-edge config check validates nodes[] id/alias/token collisions and adapter/runtime errors through the same semantics used by runtime seed.
  • iop-edge node register <node-id> creates or updates one nodes[] record from flags/defaults without requiring manual YAML edits.
  • Register output ends with a single user-facing bootstrap command in curl -fsSL <complete-url> | bash -s <token> form and does not require named IOP_*= parameters.
  • Token generation/upsert behavior is deterministic in tests and does not leak full token in extra diagnostic output.
  • CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

의존 관계 및 구현 순서

Directory dependency is 02+01_node_register_bootstrap: wait for agent-task/m-edge-local-dev-config-runtime/01_config_runtime_env/complete.log. Do not add hidden dependencies beyond that.

[BOOTSTRAP-1] Config Check Uses Runtime Node Validation

문제

apps/edge/cmd/edge/main.go only calls config.LoadEdge, while apps/edge/internal/node/store.go is where duplicate token/alias/id and empty token are rejected for runtime.

Before:

// apps/edge/cmd/edge/main.go:153
if _, err := config.LoadEdge(cfgFile); err != nil {
    return fmt.Errorf("load config: %w", err)
}

해결 방법

After loading the resolved config, call an edge CLI validator that delegates node seed validation to edgenode.LoadFromConfig(cfg.Nodes) and adds adapter/runtime checks. Keep validation in apps/edge/cmd/edge or apps/edge/internal/node rather than packages/config to avoid importing app internals into common packages.

수정 파일 및 체크리스트

  • apps/edge/cmd/edge/main.go: add validateEdgeConfig call in config check.
  • apps/edge/cmd/edge/main_test.go: add CLI tests for duplicate token/id/alias and invalid adapter/runtime flags.
  • apps/edge/internal/node/store.go: add semantic validation only if it belongs to runtime seed; otherwise keep CLI-only validation in command package.
  • apps/edge/internal/node/store_test.go: extend only if store behavior changes.

테스트 작성

Write TestConfigCheckRejectsDuplicateNodeToken and at least one adapter/runtime invalid config test.

중간 검증

go test -count=1 ./apps/edge/cmd/edge ./apps/edge/internal/node

Expected: pass; cache output is not acceptable.

[BOOTSTRAP-2] Node Register Upserts Edge YAML

문제

docs/field-bootstrap-user-test.md says Node definitions are made with iop-edge node register, but apps/edge/cmd/edge/main.go has no node command.

Before:

// apps/edge/cmd/edge/main.go:35
root.AddCommand(serveCmd(), consoleCmd(), versionCmd(), configCmd(), setupCmd())

해결 방법

Add nodeCmd() with register subcommand. Load resolved edge config and YAML, upsert by id, default alias to id, generate token if not provided, and support initial flags:

iop-edge node register <node-id>
  --alias <alias>
  --token <token>
  --adapter ollama|cli
  --ollama-base-url <url>
  --ollama-context-size <n>
  --runtime-concurrency <n>
  --workspace-root <path>

Use gopkg.in/yaml.v3 already present in apps/edge/cmd/edge/main.go for writing. Keep output concise: write/update line plus final bootstrap command.

수정 파일 및 체크리스트

  • apps/edge/cmd/edge/main.go: add node/register command, token generator injection for tests, YAML upsert helpers.
  • apps/edge/cmd/edge/main_test.go: test create, update, generated token, explicit token, adapter flags, and no manual nodes[] edit path.
  • packages/config/config.go: add fields only if BOOTSTRAP-2 needs config surface not already added by CONFIG-2.
  • configs/edge.yaml: do not add field tokens or host-specific generated values.

테스트 작성

Write temp-file CLI tests that run config init --output, then node register, then config check. Assert exactly one node record after update and that generated token is present in YAML and bootstrap output.

중간 검증

go test -count=1 ./apps/edge/cmd/edge ./packages/config

Expected: pass; cache output is not acceptable.

[BOOTSTRAP-3] Bootstrap Command Rendering

문제

bin/build/field-binaries.sh generates target-specific bootstrap scripts, but docs/field-bootstrap-user-test.md expects Edge CLI to output the complete one-line command.

Before:

# docs/field-bootstrap-user-test.md:96
curl -fsSL http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh | bash -s <generated-token>

해결 방법

Render command from CONFIG-2 effective artifact base URL and default platform target. Provide flags on node register:

--target darwin-arm64
--artifact-base-url <url>

Default target can be current host GOOS-GOARCH for local dev, but tests should pass explicit --target darwin-arm64. The final visible command must be exactly one line with completed URL and token positional arg. Do not output IOP_ARTIFACT_BASE_URL=, IOP_EDGE_ADDR=, or IOP_NODE_TOKEN= in the default path.

수정 파일 및 체크리스트

  • apps/edge/cmd/edge/main.go: add bootstrap command renderer helper and register output.
  • apps/edge/cmd/edge/main_test.go: assert one-line command, complete URL, token positional arg, and absence of named env parameters.
  • docs/field-bootstrap-work-guide.md: no change in this subtask unless a field constant changes; defer broad docs to subtask 03.

테스트 작성

Write TestNodeRegisterPrintsOneLineBootstrapCommand and TestNodeRegisterUsesConfiguredArtifactBaseURL.

중간 검증

go test -count=1 ./apps/edge/cmd/edge

Expected: pass; cache output is not acceptable.

수정 파일 요약

파일 항목
apps/edge/cmd/edge/main.go BOOTSTRAP-1, BOOTSTRAP-2, BOOTSTRAP-3
apps/edge/cmd/edge/main_test.go BOOTSTRAP-1, BOOTSTRAP-2, BOOTSTRAP-3
apps/edge/internal/node/store.go BOOTSTRAP-1
apps/edge/internal/node/store_test.go BOOTSTRAP-1
packages/config/config.go BOOTSTRAP-2
packages/config/config_test.go BOOTSTRAP-2

최종 검증

test -f agent-task/m-edge-local-dev-config-runtime/01_config_runtime_env/complete.log
go test -count=1 ./apps/edge/cmd/edge ./apps/edge/internal/node ./packages/config
tmp="$(mktemp -d)" && go build -o "$tmp/iop-edge" ./apps/edge/cmd/edge && (cd "$tmp" && ./iop-edge config init --force && ./iop-edge node register node-silicon-ollama --adapter ollama --ollama-base-url http://127.0.0.1:11434 --target darwin-arm64 --artifact-base-url http://toki-labs.com:18080 && ./iop-edge config check)

Expected: predecessor exists; tests pass; temp command creates/updates edge.yaml, prints one final curl -fsSL http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh | bash -s <token> command, and config check passes.

모든 코드 변경 완료 후 반드시 CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.