iop/agent-contract/inner/edge-config-runtime-refresh.md
toki 0ffcb88db0 feat: provider-resource-admission-ownership alignment
- Archive provider-resource-admission-ownership milestone/SDD
- Align contract: CP-edge wire, runtime refresh, node runtime, OpenAI surface
- Update roadmap: phase state, priority queue
- Update specs: control-plane ops, OpenAI surface, edge execution, provider pool refresh
- Add node runtime supervisor bootstrapping and unit tests
- Fix control-plane edge registry handler and http_views
- Fix edge model queue admission and long context queue tests
2026-07-22 20:45:04 +09:00

9.2 KiB

Edge Config And Runtime Refresh Contract

계약 메타

  • id: iop.edge-config-runtime-refresh
  • boundary: inner
  • status: active
  • 원본 경로:
    • packages/go/config/edge_types.go
    • packages/go/config/provider_types.go
    • packages/go/config/load.go
    • configs/edge.yaml
    • apps/edge/internal/configrefresh/request.go
    • apps/edge/internal/configrefresh/result.go
    • apps/edge/internal/configrefresh/classify.go
    • proto/iop/runtime.proto
    • apps/edge/internal/node/mapper.go
    • apps/node/internal/adapters/config_set.go
  • human docs: apps/edge/README.md

읽는 조건

  • configs/edge.yaml, packages/go/config, provider pool, openai.model_routes, models[], nodes[].providers[], adapter instance 설정을 바꿀 때
  • iop-edge config refresh의 dry-run/apply 결과 schema나 restart/applied 분류를 바꿀 때
  • Edge가 Node에 전달하는 NodeConfigPayload 또는 NodeConfigRefresh* payload를 바꿀 때

범위

이 계약은 Edge 설정 YAML, Go config struct, config refresh 결과, Edge-to-Node runtime config payload의 연결 규칙이다. tracked config에는 public 예시와 기본 구조만 두고, 실제 endpoint/credential/private host 값은 환경별 private 설정으로 주입한다.

핵심 규칙

  • openai.principal_tokens[]는 raw token을 저장하지 않고 hash/reference로 principal 매핑을 관리한다. 각 entry는 token_ref (non-empty, unique), token_hash_sha256 (64-char hex, duplicate hash rejection), principal_ref (non-empty), optional principal_alias 필드를 갖는다. 여러 entry가 같은 principal_refprincipal_alias를 공유할 수 있으며, 이때 token_ref가 앱/통합/용도별 사용량 분해 기준이 된다. tracked config에는 raw token을 저장하지 않고 hash/reference만 둔다.
  • openai.provider_auth는 request-time raw provider token forwarding rule이다. enabled=false가 기본이며 raw token 값은 저장하지 않는다. enabled=true이고 header fields가 생략되면 from_header=X-IOP-Provider-Authorization, target_header=Authorization, scheme=Bearer, required=true로 해석한다.
  • openai deep diff는 restart-required로 분류한다. openai.principal_tokens[] 변경은 credential/hash 변경으로 restart-required classifier에 포함된다.
  • openai.model_routes[]는 외부 OpenAI-compatible model id를 내부 adapter + target route로 매핑하는 compatibility catalog다.
  • long_context_threshold_tokens는 Edge root의 입력 토큰 추정 기준 long-context 분류 threshold다. 기본값은 100000이며 0 이하 값은 config load에서 거부한다.
  • provider_pool.max_queueprovider_pool.queue_timeout_ms는 모든 model group과 provider candidate에 공통인 Edge provider-pool queue policy의 canonical owner다. max_queue는 Edge provider-pool 전체 pending 상한이며 0/생략은 기본값 16으로 정규화된다. queue_timeout_ms는 각 pending request의 최대 대기 시간이며 명시적 0은 timeout 없음, 생략은 기본값 30000이다.
  • canonical provider_pool key가 없을 때만 legacy nodes[].providers[].max_queue/queue_timeout_ms를 compatibility 입력으로 읽는다. 참여 provider의 유효 pair가 모두 같으면 root policy로 승격하고, 하나라도 다르면 first-candidate 값을 택하지 않고 load를 거부한다. canonical root key가 있으면 legacy provider queue 값은 effective policy와 refresh diff에 영향을 주지 않는다.
  • models[]는 provider pool 방향의 canonical routing key이며 nodes[].providers[].id를 참조한다. context_window_tokens는 해당 model group의 provider 공통 단일 요청 최대 context 계약이다. default_max_tokens, min_max_tokens, default_thinking_token_budget은 OpenAI-compatible 요청을 내부 실행으로 넘기기 전에 적용하는 모델 단위 generation policy다.
  • 하나의 models[] entry는 OpenAI-compatible provider와 normalized-only provider를 함께 참조할 수 있다. 선택된 provider가 OpenAI-compatible 호출 방식을 지원하면 passthrough 실행 경로를 사용하고, ollama/cli 같은 normalized-only provider면 normalized 실행 경로를 사용한다. Ollama 후보는 model group에서 제거하지 않고 capacitypriority로 낮은 동시성/선호도를 표현한다.
  • nodes[].providers[]는 Node 아래 resource/provider catalog다. categoryapi, cli, local_inference resource kind를 나타낸다.
  • nodes[].providers[].typeseulgivibe_claudeseulgivibe_openai는 runtime type을 openai_compat로 정규화한다. Edge가 Node adapter payload를 만들 때 명시 provider label이 없으면 원래 Seulgivibe type alias를 OpenAICompatAdapterConfig.provider로 보존한다.
  • nodes[].providers[].id는 전체 Edge config 안에서 중복되면 안 된다.
  • nodes[].providers[].adapter는 같은 Node 안의 enabled adapter instance key를 참조해야 한다. Exact instance key를 우선하고, legacy type-name route는 같은 type의 enabled instance가 정확히 하나일 때만 허용한다. category: cli resource는 enabled CLI adapter가 필요하다.
  • nodes[].providers[].enabled: 생략 또는 true → provider pool dispatch 후보에 포함. false → dispatch pool에서 제외. 비활성화된 provider는 status snapshot에 status=disabled, health=disabled, capacity=0으로 표시된다. adapter process lifecycle 변경 없음. config refresh 시 enabled 토글은 live-apply(restart 불필요)로 분류된다. disabled provider의 adapter reference check는 skip되지만 structural validation(type, category, models, numeric bounds)은 수행된다.
  • nodes[].providers[].capacitylong_context_capacitynode_id + provider_id resource가 소유한다. 같은 provider를 참조하는 여러 models[].id는 일반·long slot을 합산 공유한다. total_context_tokens는 runtime counter가 아니라 context_window_tokens * long_context_capacity 이상이어야 하는 정적 load/refresh validation 값이다.
  • nodes[].providers[].priority: provider-pool dispatch tie-breaker다. 기본값은 0이고 음수는 validation error다. dispatch는 in_flight < capacity 후보 중 가장 낮은 in_flight를 먼저 선택하며, in_flight가 같은 후보에서만 낮은 숫자의 priority를 우선한다. in_flightpriority가 모두 같으면 기존 순환을 유지한다. priority 변경은 live-apply(restart 불필요)로 분류된다.
  • legacy single-instance adapter 설정은 load 시 named instance slice로 normalize된다.
  • NodeConfigPayload는 Edge가 Node에 내려주는 실행 adapter/runtime payload다.
  • refresh 결과는 applied, restart_required, rejected를 구분하고, changed node/provider/model/report slice는 안정적으로 non-nil이어야 한다.

refresh 분류 기준

  • live apply 가능: Edge root long_context_threshold_tokens, provider_pool.max_queue, provider_pool.queue_timeout_ms, provider capacity, provider long-context capacity, provider total-context validation budget, provider priority, provider enabled toggle, models[] display/context window/provider/generation policy mapping, legacy node runtime concurrency metadata. 기존 lease는 유지하며 새 admission과 모든 pending item은 새 policy/candidate 상태로 재평가한다.
  • restart required: Edge identity/listen/bootstrap/logging/metrics/console/control-plane/openai/a2a listener config, node 추가/삭제, node token/alias/agent kind, adapter 설정, provider type/category/adapter/models/health/lifecycle capability, provider-first execution fields(provider, endpoint, base_url, headers, command, args, env, mode, resume_args, output_format, context_size, request_timeout_ms) 변경.
  • rejected: candidate config load/validate 실패, invalid refresh mode, apply failure.

금지 사항

  • 설정 파일만 바꾸고 packages/go/config loading/default/validation과 불일치하게 두지 않는다.
  • provider id, model id, route id의 의미를 섞지 않는다. 외부 model은 OpenAI-compatible 경계의 route key이고, 내부 실행은 adapter + target이다.
  • credential, bearer token, private endpoint 원문을 tracked docs/roadmap/contract에 기록하지 않는다.
  • provider auth raw token 원문을 config, docs, task artifact, metric label에 기록하지 않는다.
  • Node bootstrap 기본 경로에서 사용자가 직접 node config를 작성하거나 adapter/provider 값을 명령줄로 넣어야 하는 계약을 만들지 않는다.

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

  • packages/go/config/edge_openai_config_test.go
  • packages/go/config/edge_runtime_config_test.go
  • packages/go/config/node_config_test.go
  • packages/go/config/provider_catalog_config_test.go
  • packages/go/config/provider_catalog_validation_config_test.go
  • apps/edge/internal/configrefresh/node_runtime_classify_test.go
  • apps/edge/internal/configrefresh/path_refresh_test.go
  • apps/edge/internal/configrefresh/provider_classify_test.go
  • apps/edge/internal/edgecmd/edgecmd_test.go
  • apps/edge/internal/node/mapper_test.go
  • apps/node/internal/adapters/config_set_test.go
  • agent-test/local/platform-common-smoke.md
  • agent-test/local/edge-smoke.md