From aebba6508c848e33871f8d2b4bb6461ad789dce1 Mon Sep 17 00:00:00 2001 From: toki Date: Sat, 1 Aug 2026 13:28:16 +0900 Subject: [PATCH] =?UTF-8?q?chore(agent-task):=20dev=EC=97=90=20=EC=9C=A0?= =?UTF-8?q?=EC=9E=85=EB=90=9C=20=EC=9E=91=EC=97=85=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=EC=9D=84=20=EC=A0=9C=EA=B1=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 다른 브랜치에서만 유지해야 할 계획·리뷰 로그가 dev에 유입되어 삭제한다. --- .../CODE_REVIEW-cloud-G06.md | 142 -------- .../01_principal_store/PLAN-local-G06.md | 216 ------------- .../CODE_REVIEW-cloud-G07.md | 141 -------- .../PLAN-local-G07.md | 183 ----------- .../code_review_cloud_G07_0.log | 134 -------- .../plan_local_G07_0.log | 182 ----------- .../CODE_REVIEW-cloud-G09.md | 145 --------- .../PLAN-cloud-G09.md | 285 ---------------- .../code_review_cloud_G10_0.log | 148 --------- .../plan_cloud_G10_0.log | 304 ------------------ .../CODE_REVIEW-cloud-G08.md | 143 -------- .../04+03_principal_routes/PLAN-local-G07.md | 241 -------------- .../code_review_cloud_G09_0.log | 145 --------- .../plan_local_G08_0.log | 245 -------------- .../CODE_REVIEW-cloud-G06.md | 135 -------- .../PLAN-local-G06.md | 154 --------- .../code_review_cloud_G08_1.log | 143 -------- .../code_review_cloud_G10_0.log | 147 --------- .../plan_cloud_G10_0.log | 273 ---------------- .../plan_local_G07_1.log | 228 ------------- .../CODE_REVIEW-cloud-G06.md | 135 -------- .../PLAN-local-G06.md | 173 ---------- 22 files changed, 4042 deletions(-) delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/01_principal_store/CODE_REVIEW-cloud-G06.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/01_principal_store/PLAN-local-G06.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/CODE_REVIEW-cloud-G07.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/PLAN-local-G07.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/code_review_cloud_G07_0.log delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/plan_local_G07_0.log delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/CODE_REVIEW-cloud-G09.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/PLAN-cloud-G09.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/code_review_cloud_G10_0.log delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/plan_cloud_G10_0.log delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/CODE_REVIEW-cloud-G08.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/PLAN-local-G07.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/code_review_cloud_G09_0.log delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/plan_local_G08_0.log delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/CODE_REVIEW-cloud-G06.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/PLAN-local-G06.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G08_1.log delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G10_0.log delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_cloud_G10_0.log delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_local_G07_1.log delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/CODE_REVIEW-cloud-G06.md delete mode 100644 agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/PLAN-local-G06.md diff --git a/agent-task/m-principal-provider-credential-slot-routing/01_principal_store/CODE_REVIEW-cloud-G06.md b/agent-task/m-principal-provider-credential-slot-routing/01_principal_store/CODE_REVIEW-cloud-G06.md deleted file mode 100644 index 8b6508b..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/01_principal_store/CODE_REVIEW-cloud-G06.md +++ /dev/null @@ -1,142 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/01_principal_store, plan=0, tag=API - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `principal-store`: principal 및 IOP token hash 원장 -- Completion mode: check-on-pass - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G06.md` → `code_review_cloud_G06_0.log` and `PLAN-local-G06.md` → `plan_local_G06_0.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/01_principal_store/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-1 Open and migrate the credential store | [ ] | -| API-2 Enforce principal token lifecycle and secret hygiene | [ ] | -| API-3 Preserve startup compatibility and prove package integrity | [ ] | - -## Implementation Checklist - -- [ ] Add the Control Plane credential-store connection, schema migration, and clean shutdown boundary. -- [ ] Implement atomic principal/token issuance, lookup, disable, and irreversible revoke lifecycle with digest-only persistence. -- [ ] Wire the optional database-backed store into Control Plane startup while preserving database-unconfigured legacy startup. -- [ ] Run fresh repository, startup, vet, and diff verification with the declared executable Go cache paths. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G06_0.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_local_G06_0.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/01_principal_store/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/01_principal_store/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Confirm the configured PostgreSQL path never silently falls back and the empty URL preserves legacy startup. -- Inspect schema/transactions for digest-only storage, monotonic revision, and irreversible revoke. -- Confirm raw tokens are absent from DB queries, list/get types, captured logs, metrics labels, and errors. -- Re-run restart persistence and race evidence before PASS. - -## Verification Results - -Paste actual stdout/stderr beneath every command. Do not summarize reconstructed output; if output is too long, record the saved output path and exact capture command. - -### API-1 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore ./apps/control-plane/cmd/control-plane` - -_Pending._ - -### API-2 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore` - -_Pending._ - -### API-3 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -run '^$' ./apps/control-plane/...` - -_Pending._ - -### Final Verification - -1. `command -v go && go version && go env GOROOT` -2. `mkdir -p .cache/go-build .cache/go-cache` -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go mod tidy` -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/...` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore` -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` -7. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/01_principal_store/PLAN-local-G06.md b/agent-task/m-principal-provider-credential-slot-routing/01_principal_store/PLAN-local-G06.md deleted file mode 100644 index efbef27..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/01_principal_store/PLAN-local-G06.md +++ /dev/null @@ -1,216 +0,0 @@ - - -# Principal Store - -## For the Implementing Agent - -Filling the implementation-owned sections of `CODE_REVIEW-cloud-G06.md` is mandatory. Run every verification command, paste actual notes/output, keep both active files in place, and report ready for review; only the code-review skill may finalize, rename logs, write `complete.log`, or archive the task. If blocked, record only the exact blocker, attempted commands/output, and resume condition in the implementation-owned evidence fields; do not ask the user, call user-input tools, create control-plane stop files, or classify the next state. - -## Background - -Control Plane currently accepts `database.url` but only logs that it is configured; there is no durable credential-plane repository. Principal tokens are Edge config entries, so issuance, revocation, revision fencing, restart persistence, and one-time raw-token return cannot be enforced by Control Plane. - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `principal-store`: principal 및 IOP token hash 원장 -- Completion mode: check-on-pass - -## Analysis - -### Files Read - -- `go.mod` -- `go.sum` -- `docker-compose.yml` -- `configs/control-plane.yaml` -- `apps/control-plane/cmd/control-plane/main.go` -- `apps/control-plane/cmd/control-plane/server.go` -- `apps/control-plane/cmd/control-plane/config_test.go` -- `apps/edge/internal/openai/principal.go` -- `apps/node/internal/store/store.go` -- `apps/node/internal/store/store_test.go` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 구현 잠금 해제). -- Target: S01 / `principal-store`. -- Evidence Map row: S01-S03의 CP repository lifecycle 근거 중 S01 persistence/auth 결과. -- 따라서 checklist는 원문 token의 1회 반환, SHA-256 digest만 영속화, revision/status 전이, revoke 불가역성, process reopen persistence, DB/API/log/metric 비노출 검증을 한 저장소 경계에 묶는다. - -### Verification Context - -- 별도 handoff는 없었다. 저장소 근거는 `go.mod`, Control Plane config/server, `docker-compose.yml`, project/domain/test rules와 `agent-test/local`의 control-plane smoke profile에서 도출했다. -- Local runner: `/config/workspace/iop-s0`, branch `feature/multi-provider-protocol-profile-native-messages`, HEAD `f2306f4dc8cabd7ff3c2085c016897f0bb337cc6`, Linux aarch64. -- `go version go1.26.2 linux/arm64`; PostgreSQL URL은 compose의 `IOP_DATABASE_URL`, 테스트는 기존 `modernc.org/sqlite`로 process reopen을 재현한다. PostgreSQL runtime driver는 현재 manifest에 없어 `pgx/v5/stdlib` 추가가 필요하다. -- 현재 셸의 기본 `GOCACHE`는 권한이 없는 임시 경로이고 `/tmp`는 `noexec`이다. 저장소의 ignored `.cache/go-cache`와 `.cache/go-build`를 명시하면 관련 package compile preflight가 PASS했다. -- 외부 provider, 원격 runner, secret, port가 필요하지 않다. Confidence: high. - -### Test Coverage Gaps - -- 기존 Control Plane 테스트는 config redaction만 확인하고 DB open/migration을 다루지 않는다: 신규 startup wiring test 필요. -- 기존 Node SQLite store는 reopen 패턴만 제공하며 principal token의 one-time return/revoke/revision을 다루지 않는다: 신규 repository tests 필요. -- raw token의 log/metric 비노출 검사는 없다: logger observer를 사용하는 신규 test 필요. - -### Symbol References - -- Rename/remove 없음. `run` 호출은 `apps/control-plane/cmd/control-plane/main.go:82` 한 곳이며 signature를 유지한다. - -### Split Judgment - -- `01_principal_store`: DB 연결·migration·principal/token transaction을 제공하고 restart persistence tests로 독립 PASS한다. -- `02+01_credential_catalog`: 01의 FK/source-of-truth를 사용해 slot/route catalog를 독립 검증한다. -- `03+01,02_projection_auth`: 01/02 snapshot을 wire로 보내 Edge에서 인증한다. -- `04+03_principal_routes`: 적용된 projection만 읽어 discovery/selection을 검증한다. -- `05+01,02_management_core`: 01/02 service를 principal-scoped in-process operations로 노출한다. -- `06+01,02_host_local_bootstrap`: 01의 first-principal issuance를 host-local CLI로 노출한다. -- 본 packet은 predecessor가 없으며, principal과 최초 token 발급을 한 transaction으로 유지해야 raw-token one-time invariant가 독립 PASS하므로 더 나누지 않는다. - -### Scope Rationale - -- Edge projection, HTTP ingress, slot/route schema, management wire/CLI, provider secret delivery는 후속 packet 소유이므로 제외한다. -- `agent-ops/rules/common/**`, `agent-ops/skills/common/**`, roadmap/SDD/spec 문서는 수정하지 않는다. -- SQLite는 deterministic repository test dialect이고 production URL은 PostgreSQL이다; 별도 migration framework 도입은 하지 않는다. - -### Final Routing - -- `status=routed`, `evaluation_mode=first-pass`, finalizer=`finalize-task-policy.sh`, mode=`pair`. -- Build closures: scope/context/verification/evidence/ownership/decision 모두 true. Scores `2+1+1+1+1=G06`; base/route=`local-fit`, lane=`local`, canonical=`PLAN-local-G06.md`. -- Review closures 모두 true. Scores `2+1+1+1+1=G06`; route=`official-review`, lane=`cloud`, model=`gpt-5.6-sol` xhigh, canonical=`CODE_REVIEW-cloud-G06.md`. -- `large_indivisible_context=false`; matched loop risk=`temporal_state` (1); rework=0; evidence integrity failure=false; capability gap 없음. - -## Implementation Checklist - -- [ ] Add the Control Plane credential-store connection, schema migration, and clean shutdown boundary. -- [ ] Implement atomic principal/token issuance, lookup, disable, and irreversible revoke lifecycle with digest-only persistence. -- [ ] Wire the optional database-backed store into Control Plane startup while preserving database-unconfigured legacy startup. -- [ ] Run fresh repository, startup, vet, and diff verification with the declared executable Go cache paths. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-1] Open and migrate the credential store - -**Problem:** `apps/control-plane/cmd/control-plane/server.go:29-31` only logs `database.url`; no connection, migration, or close path exists. - -**Solution:** Add a `database/sql` store that selects PostgreSQL for `postgres://`/`postgresql://` and SQLite only for tests, pings before use, runs idempotent schema migrations, and closes with server lifetime. Add `github.com/jackc/pgx/v5/stdlib`; keep secrets out of connection logs. - -Before (`apps/control-plane/cmd/control-plane/server.go:29-31`): - -```go -if cfg.Database.URL != "" { - logger.Info("control-plane database configured", databaseLogFields(cfg.Database.URL)...) -} -``` - -After: - -```go -store, err := credentialstore.Open(ctx, cfg.Database.URL) -if err != nil { - return fmt.Errorf("open credential store: %w", err) -} -if store != nil { - defer store.Close() -} -``` - -**Modified Files and Checklist:** - -- [ ] `go.mod`: add the PostgreSQL stdlib driver. -- [ ] `go.sum`: record resolved driver checksums. -- [ ] `apps/control-plane/internal/credentialstore/store.go`: implement dialect selection, ping, transaction helper, and close. -- [ ] `apps/control-plane/internal/credentialstore/schema.go`: implement idempotent principal/token schema and constraints. -- [ ] `apps/control-plane/cmd/control-plane/server.go`: open/close the optional store. -- [ ] `apps/control-plane/cmd/control-plane/credential_store_test.go`: prove configured failure and unconfigured compatibility. - -**Test Strategy:** Write `TestOpenMigratesAndReopensCredentialStore`, `TestRunRejectsInvalidDatabaseURL`, and `TestRunAllowsUnconfiguredDatabase`. Use a temp SQLite file and ephemeral listener addresses; assert schema persists and invalid configured DB fails before serving. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore ./apps/control-plane/cmd/control-plane` must pass. - -### [API-2] Enforce principal token lifecycle and secret hygiene - -**Problem:** `apps/edge/internal/openai/principal.go:86-137` matches static config hashes, but Control Plane has no issuer, revision, durable status, or revocation source of truth. - -**Solution:** Generate 32 random bytes, encode only the one-time response, persist SHA-256 digest plus stable token reference, principal reference, status, revision, and timestamps in one transaction. List/get return metadata only. Disable/revoke use compare-and-swap revision; revoke is irreversible and no method reconstructs raw token. - -Before (`apps/control-plane/cmd/control-plane/server.go:15-18`): - -```go -func run(ctx context.Context, cfg controlPlaneConfig, logger *zap.Logger) error { - mux := newHTTPMux() - - wireEndpoint := wire.Endpoint{Listen: cfg.Server.WireListen} -``` - -After domain boundary: - -```go -issued, err := store.CreatePrincipalWithToken(ctx, credentialstore.CreatePrincipalInput{Alias: alias}) -// issued.RawToken is returned once; stored TokenRecord contains Digest only. -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/internal/credentialstore/principal.go`: define records, status validation, issuance, lookup/list, disable, and revoke transactions. -- [ ] `apps/control-plane/internal/credentialstore/principal_test.go`: cover issuance, duplicate alias, CAS revision, disable/revoke, reopen, and raw-token absence. - -**Test Strategy:** Write `TestCreatePrincipalReturnsRawTokenOnce`, `TestPrincipalTokenLifecycleUsesRevisionCAS`, `TestRevokedTokenCannotBeReenabled`, and `TestPrincipalTokenPersistsAcrossReopen`. Inspect DB columns and captured zap entries to assert neither raw token nor a reversible form appears. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore` must pass with fresh execution. - -### [API-3] Preserve startup compatibility and prove package integrity - -**Problem:** `apps/control-plane/cmd/control-plane/main.go:87-97` defaults `database.url` to empty, so unconditional store construction would regress existing health/status use. - -**Solution:** Treat empty URL as credential plane unavailable while leaving legacy server startup unchanged; treat any non-empty invalid/unreachable URL as fatal. Do not silently fall back from configured PostgreSQL to SQLite. - -Before (`apps/control-plane/cmd/control-plane/main.go:92`): - -```go -cfg.Database.URL = "" -``` - -After: - -```go -// Empty URL preserves legacy startup; a configured URL must open successfully. -store, err := credentialstore.Open(ctx, cfg.Database.URL) -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/cmd/control-plane/server.go`: preserve nil-store compatibility and fail configured startup closed. -- [ ] `apps/control-plane/cmd/control-plane/credential_store_test.go`: assert both branches and redacted errors/logs. - -**Test Strategy:** Reuse the explicit startup tests from API-1; no external PostgreSQL test is required because SQL behavior is covered through SQLite and driver selection/config failure is unit-tested. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -run '^$' ./apps/control-plane/...` must compile all Control Plane packages. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `go.mod` | API-1 | -| `go.sum` | API-1 | -| `apps/control-plane/internal/credentialstore/store.go` | API-1 | -| `apps/control-plane/internal/credentialstore/schema.go` | API-1 | -| `apps/control-plane/internal/credentialstore/principal.go` | API-2 | -| `apps/control-plane/internal/credentialstore/principal_test.go` | API-2 | -| `apps/control-plane/cmd/control-plane/server.go` | API-1, API-3 | -| `apps/control-plane/cmd/control-plane/credential_store_test.go` | API-1, API-3 | -| `agent-task/m-principal-provider-credential-slot-routing/01_principal_store/CODE_REVIEW-cloud-G06.md` | API-1, API-2, API-3 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; fresh results are required and Go test cache output is not acceptable. - -1. `command -v go && go version && go env GOROOT` — Go resolves and reports the preflighted toolchain. -2. `mkdir -p .cache/go-build .cache/go-cache` — executable workspace-local temp/cache paths exist. -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go mod tidy` — dependency files are canonical with no unrelated dependency drift. -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/...` — no vet findings. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore` — lifecycle, restart, redaction, and race tests pass. -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` — all Control Plane tests pass. -7. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`. diff --git a/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/CODE_REVIEW-cloud-G07.md b/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/CODE_REVIEW-cloud-G07.md deleted file mode 100644 index 0d0a7c9..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/CODE_REVIEW-cloud-G07.md +++ /dev/null @@ -1,141 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/02+01_credential_catalog, plan=1, tag=API - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `slot-store`: principal별 provider credential slot 원장 - - `model-binding`: route와 slot/profile/upstream model의 단일 결합 -- Completion mode: check-on-pass - -## Archive Evidence Snapshot - -- Prior pair: `agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/plan_local_G07_0.log`, `agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/code_review_cloud_G07_0.log`. -- Verdict/evidence: implementation had not started and no verdict or verification output existed. -- Replan reason: predecessor verification assumed an active `complete.log` even though PASS archives the predecessor, and envelope validation did not prove that the referenced key exists. -- Roadmap carryover: S04 `slot-store` and S05 `model-binding` remain the completion targets. - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G07.md` → `code_review_cloud_G07_1.log` and `PLAN-local-G07.md` → `plan_local_G07_1.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/02+01_credential_catalog/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-1 Persist key-backed opaque credential slots | [ ] | -| API-2 Bind every route to one compatible slot/profile/model | [ ] | - -## Implementation Checklist - -- [ ] Persist opaque encrypted-secret revisions and slot lifecycle only when the envelope key id is registered, while enforcing principal-scoped aliases and S04 lifecycle fixtures. -- [ ] Persist route bindings that converge to exactly one principal, slot, compatible protocol profile, and upstream model, with S05 ambiguity and cross-principal fixtures. -- [ ] Run fresh repository race, restart, Control Plane regression, archive-predecessor, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G07_1.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_local_G07_1.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/02+01_credential_catalog/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Verify the archived 01 predecessor completion before implementation evidence. -- Confirm unknown key ids fail before transaction commit and no plaintext/decrypt API exists. -- Inspect composite ownership FKs, alias uniqueness, profile compatibility, and revision CAS. -- Re-run multi-slot, multi-route, restart, and cross-principal fixtures before PASS. - -## Verification Results - -Paste actual stdout/stderr beneath every command; do not summarize or reconstruct it. - -### API-1 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore -run 'CredentialSlot|EnvelopeKey'` - -_Pending._ - -### API-2 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore -run 'Route|Binding'` - -_Pending._ - -### Final Verification - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/01_principal_store/complete.log' -print | wc -l)" -eq 1` -2. `mkdir -p .cache/go-build .cache/go-cache` -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialstore` -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` -6. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/PLAN-local-G07.md b/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/PLAN-local-G07.md deleted file mode 100644 index 7d1106d..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/PLAN-local-G07.md +++ /dev/null @@ -1,183 +0,0 @@ - - -# Credential Slot and Route Catalog - -## For the Implementing Agent - -Filling implementation-owned sections of `CODE_REVIEW-cloud-G07.md` is mandatory. Run every verification command, paste actual output, keep the active pair in place, and report ready for review; only code-review may finalize, rename logs, write `complete.log`, or archive. If blocked, record only exact blocker evidence and the resume condition in implementation-owned fields; do not ask the user, call user-input tools, create stop files, or classify the next state. - -## Background - -Provider credentials need a principal-scoped durable slot independent of protocol profiles, and every client route must converge to one slot/profile/model tuple. The store boundary must accept only encrypted envelopes whose key id is recognized; accepting a merely non-empty key id would let an unusable or fabricated envelope become active. - -## Archive Evidence Snapshot - -- Prior pair: `agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/plan_local_G07_0.log`, `agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/code_review_cloud_G07_0.log`. -- Verdict/evidence: implementation had not started and no verdict or verification output existed. -- Replan reason: predecessor verification assumed an active `complete.log` even though PASS archives the predecessor, and envelope validation did not prove that the referenced key exists. -- Roadmap carryover: S04 `slot-store` and S05 `model-binding` remain the completion targets. - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `slot-store`: principal별 provider credential slot 원장 - - `model-binding`: route와 slot/profile/upstream model의 단일 결합 -- Completion mode: check-on-pass - -## Analysis - -### Files Read - -- `apps/control-plane/cmd/control-plane/server.go` -- `apps/node/internal/store/store.go` -- `apps/node/internal/store/store_test.go` -- `packages/go/config/config.go` -- `packages/go/config/protocol_profile.go` -- `packages/go/config/protocol_profile_test.go` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 잠금 해제). -- Targets: S04 / `slot-store`, S05 / `model-binding`; Evidence Map S04-S08 중 multi-slot, alias collision, multi-model binding. -- Checklist와 verification은 동일 principal/vendor 복수 slot, registered key의 opaque ciphertext envelope, alias uniqueness, 한 slot의 compatible multi-profile/model route, cross-principal/incompatible/ambiguous binding 거부를 직접 증명한다. - -### Verification Context - -- handoff 없음. manifest, protocol-profile resolver/tests, local Control Plane test rules에서 검증을 도출했다. -- Go 1.26.2 linux/arm64. `/tmp`는 noexec이고 기본 Go cache는 접근 불가하므로 ignored `.cache/go-build`와 `.cache/go-cache`를 명시한다. -- Predecessor 01은 현재 미완료다. 구현 시 runtime scheduler가 active 또는 archived completion을 해결하며, verification은 허용된 동일 task-group archive 후보를 정확히 한 건 확인한다. -- External provider, raw secret, production key manager는 필요 없다. Tests use a deterministic fake key registry and opaque ciphertext. Confidence: high. - -### Test Coverage Gaps - -- 기존 protocol profile tests는 credential kind/vendor compatibility와 slot ownership을 다루지 않는다. -- multi-slot, registered/missing key, alias collision, route ownership, restart persistence tests가 없다. - -### Symbol References - -- Rename/remove 없음. Existing `config.ResolveProtocolProfile`은 validation dependency로만 추가 호출한다. - -### Split Judgment - -- Slot envelope/key registration, principal ownership, route FK/compatibility는 활성화 transaction의 한 invariant이므로 S04/S05를 같은 packet으로 유지한다. -- Predecessor 01 `01_principal_store`: active/archived `complete.log` missing, ambiguity 없음. -- 03, 05, 06은 이 packet의 immutable slot/route store API를 소비한다. - -### Scope Rationale - -- Encryption/decryption, deployment key loading/rotation, secure management transport는 Epic 3이다. 이 packet은 `EnvelopeKeyRegistry`로 key id 존재만 확인하고 plaintext/decrypt API를 만들지 않는다. -- Edge projection/route resolution과 management adapters는 후속 packets이다. - -### Final Routing - -- `status=routed`, `evaluation_mode=isolated-reassessment`, finalizer=`finalize-task-policy.sh`, pair mode. -- Build closures all true; scores `2+2+1+1+1=G07`; base/route=`local-fit`, local, `PLAN-local-G07.md`. -- Review closures all true; scores `2+2+1+1+1=G07`; `official-review`, cloud, `gpt-5.6-sol` xhigh, `CODE_REVIEW-cloud-G07.md`. -- `large_indivisible_context=false`; risks=`temporal_state`, `boundary_contract`, `variant_product` (3); rework=0; integrity failure=false; capability gap 없음. - -## Dependencies and Execution Order - -1. `01_principal_store` must complete first; runtime accepts its active or archived `complete.log`. -2. Implement envelope/key registry and slot lifecycle before route bindings. -3. No dependency absent from `02+01_credential_catalog` may be introduced. - -## Implementation Checklist - -- [ ] Persist opaque encrypted-secret revisions and slot lifecycle only when the envelope key id is registered, while enforcing principal-scoped aliases and S04 lifecycle fixtures. -- [ ] Persist route bindings that converge to exactly one principal, slot, compatible protocol profile, and upstream model, with S05 ambiguity and cross-principal fixtures. -- [ ] Run fresh repository race, restart, Control Plane regression, archive-predecessor, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-1] Persist key-backed opaque credential slots - -**Problem:** no Control Plane slot store exists, and checking only a non-empty `key_id` cannot satisfy S04's missing-envelope-key rejection. - -**Solution:** Add constrained slot and immutable secret-revision tables. Add a source-compatible store option for `EnvelopeKeyRegistry`; the existing `Open` path installs an unavailable registry so production slot secret mutations fail closed until Epic-3 key wiring exists. Creation/rotation/activation rejects unknown key ids before transaction commit. Persist only algorithm, key id/version, nonce, ciphertext, AAD metadata, lifecycle, and revision. - -Before (`apps/control-plane/cmd/control-plane/server.go:29-31`): - -```go -if cfg.Database.URL != "" { - logger.Info("control-plane database configured", databaseLogFields(cfg.Database.URL)...) -} -``` - -After domain contract: - -```go -import "context" - -type EnvelopeKeyRegistry interface { - HasEnvelopeKey(context.Context, string, uint64) (bool, error) -} -if !known { return CredentialSlot{}, ErrEnvelopeKeyUnavailable } -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/internal/credentialstore/schema.go`: add slot/secret revision tables and constraints. -- [ ] `apps/control-plane/internal/credentialstore/store.go`: add source-compatible key-registry option and unavailable-by-default implementation. -- [ ] `apps/control-plane/internal/credentialstore/secret_envelope.go`: define opaque envelope and key-registry boundary. -- [ ] `apps/control-plane/internal/credentialstore/slot.go`: implement create/list/rotate/disable/enable/revoke with revision CAS and registered-key validation. -- [ ] `apps/control-plane/internal/credentialstore/slot_test.go`: cover same-vendor slots, registered/missing key, alias collision, lifecycle, ciphertext inspection, and reopen. - -**Test Strategy:** Write `TestCredentialSlotsAllowSameVendorMultipleSlots`, `TestCredentialSlotRejectsUnknownEnvelopeKey`, `TestCredentialSlotRotationRequiresRegisteredKey`, `TestCredentialSlotAliasUniqueWithinPrincipal`, and `TestCredentialSlotLifecyclePersists` using fake key registry and opaque bytes. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore -run 'CredentialSlot|EnvelopeKey'` passes. - -### [API-2] Bind every route to one compatible slot/profile/model - -**Problem:** the global model catalog has no durable principal route id and cannot fail closed on cross-principal or ambiguous alias selection. - -**Solution:** Add route records with principal+slot composite ownership, canonical route id, optional normalized alias, profile id, upstream model, resource selector, status, and revision. Resolve profiles through `config.ResolveProtocolProfile`, validate vendor/auth compatibility, and enforce uniqueness transactionally. - -Before (`packages/go/config/protocol_profile.go`, resolver contract): - -```go -func ResolveProtocolProfile(selector, legacyType string, catalog map[string]ProtocolProfileConf) (ConcreteProtocolProfile, error) -``` - -After usage: - -```go -profile, err := config.ResolveProtocolProfile(input.ProfileID, input.Vendor, config.BuiltInProtocolProfiles) -if err != nil { return RouteBinding{}, ErrIncompatibleProfile } -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/internal/credentialstore/schema.go`: add composite FKs and principal-scoped uniqueness constraints. -- [ ] `apps/control-plane/internal/credentialstore/route.go`: implement create/list/update/disable/revoke and strict lookup. -- [ ] `apps/control-plane/internal/credentialstore/route_test.go`: cover same upstream model/two slots, one slot/multiple routes, incompatible profile, ambiguous alias, and cross-principal rejection. - -**Test Strategy:** Write `TestRoutesDisambiguateSameUpstreamModelBySlot`, `TestSlotSupportsMultipleCompatibleRoutes`, `TestRouteRejectsCrossPrincipalSlot`, `TestRouteRejectsIncompatibleProfile`, and `TestRouteAliasCollisionFailsClosed`. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore -run 'Route|Binding'` passes. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `apps/control-plane/internal/credentialstore/schema.go` | API-1, API-2 | -| `apps/control-plane/internal/credentialstore/store.go` | API-1 | -| `apps/control-plane/internal/credentialstore/secret_envelope.go` | API-1 | -| `apps/control-plane/internal/credentialstore/slot.go` | API-1 | -| `apps/control-plane/internal/credentialstore/slot_test.go` | API-1 | -| `apps/control-plane/internal/credentialstore/route.go` | API-2 | -| `apps/control-plane/internal/credentialstore/route_test.go` | API-2 | -| `agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/CODE_REVIEW-cloud-G07.md` | API-1, API-2 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; cached Go results are not acceptable. - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/01_principal_store/complete.log' -print | wc -l)" -eq 1` — exactly one archived predecessor completion exists. -2. `mkdir -p .cache/go-build .cache/go-cache` — executable Go paths exist. -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialstore` — no vet findings. -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore` — S04/S05 lifecycle, isolation, restart, and race tests pass. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` — Control Plane regression suite passes. -6. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`. diff --git a/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/code_review_cloud_G07_0.log b/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/code_review_cloud_G07_0.log deleted file mode 100644 index 2227910..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/code_review_cloud_G07_0.log +++ /dev/null @@ -1,134 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/02+01_credential_catalog, plan=0, tag=API - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `slot-store`: principal별 provider credential slot 원장 - - `model-binding`: route와 slot/profile/upstream model의 단일 결합 -- Completion mode: check-on-pass - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G07.md` → `code_review_cloud_G07_0.log` and `PLAN-local-G07.md` → `plan_local_G07_0.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/02+01_credential_catalog/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-1 Persist opaque credential slots independently of profiles | [ ] | -| API-2 Bind each client route to one slot/profile/model | [ ] | - -## Implementation Checklist - -- [ ] Add opaque encrypted-secret revisions and principal-scoped credential-slot lifecycle with strict alias constraints. -- [ ] Add route bindings that converge to exactly one principal, slot, compatible protocol profile, and upstream model. -- [ ] Prove multi-slot, multi-profile/model, collision, cross-principal, lifecycle, and restart behavior with fresh repository tests. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G07_0.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_local_G07_0.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/02+01_credential_catalog/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Verify the 01 predecessor complete log before evaluating implementation evidence. -- Confirm the repository accepts only opaque encrypted envelopes and has no plaintext/decrypt API. -- Inspect composite FKs/unique constraints and application checks for principal ownership, alias normalization, and profile compatibility. -- Re-run same-vendor multi-slot, same-upstream multi-route, restart, CAS, and cross-principal failure fixtures. - -## Verification Results - -Paste actual stdout/stderr beneath every command; do not summarize or reconstruct it. - -### API-1 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore -run 'CredentialSlot|EncryptedSecret'` - -_Pending._ - -### API-2 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore -run 'Route|Binding'` - -_Pending._ - -### Final Verification - -1. `test -f agent-task/m-principal-provider-credential-slot-routing/01_principal_store/complete.log` -2. `mkdir -p .cache/go-build .cache/go-cache` -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialstore` -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` -6. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/plan_local_G07_0.log b/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/plan_local_G07_0.log deleted file mode 100644 index 69ea3db..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/plan_local_G07_0.log +++ /dev/null @@ -1,182 +0,0 @@ - - -# Credential Slot and Route Catalog - -## For the Implementing Agent - -Filling the implementation-owned sections of `CODE_REVIEW-cloud-G07.md` is mandatory. Run every verification command, paste actual notes/output, keep the active pair in place, and report ready for review; finalization belongs only to the code-review skill. If blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields; do not ask the user, call user-input tools, create stop files, classify state, rename logs, write `complete.log`, or archive. - -## Background - -Provider credentials are currently coupled to static Edge provider configuration. The milestone needs a Control Plane source of truth where multiple credential slots per principal are independent from protocol profiles and client-facing routes resolve unambiguously to one slot/profile/upstream-model tuple. - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `slot-store`: principal별 provider credential slot 원장 - - `model-binding`: route와 slot/profile/upstream model의 단일 결합 -- Completion mode: check-on-pass - -## Analysis - -### Files Read - -- `go.mod` -- `apps/control-plane/cmd/control-plane/server.go` -- `apps/node/internal/store/store.go` -- `apps/node/internal/store/store_test.go` -- `packages/go/config/config.go` -- `packages/go/config/protocol_profile.go` -- `packages/go/config/protocol_profile_test.go` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 잠금 해제). -- Targets: S04 / `slot-store`, S05 / `model-binding`. -- Evidence Map row: S04-S08의 multi-slot, alias collision, multi-model binding 근거 중 S04-S05. -- Checklist/verification은 동일 principal/vendor 복수 slot, ciphertext envelope 필수, principal-scoped alias uniqueness, 한 slot의 compatible multi-profile/model route, cross-principal/incompatible/ambiguous route fail-closed를 직접 증명한다. - -### Verification Context - -- handoff 없음. 저장소 manifest, protocol profile resolver/tests, Control Plane store plan contract, project/domain/local test rules로 명령을 도출했다. -- Local runner `/config/workspace/iop-s0`, Go 1.26.2 linux/arm64. 기본 Go temp/cache 권한 문제 때문에 ignored `.cache/go-build`와 `.cache/go-cache`를 명시한다. -- Precondition: sibling `01_principal_store/complete.log`가 필요하다. 현재 active/archived completion은 없어 implementation을 시작할 수 없지만 계획 작성과 routing에는 ambiguity가 없다. -- 외부 provider/DB/secret 없이 temp SQLite와 deterministic opaque envelopes로 검증 가능하다. Confidence: high. - -### Test Coverage Gaps - -- 기존 config protocol profile tests는 built-in profile resolution만 다루며 credential slot compatibility/lifecycle을 다루지 않는다. -- multi-slot, alias collision, route ownership, route ID uniqueness, encrypted envelope validation을 다루는 Control Plane test가 전무하므로 신규 repository tests가 필요하다. - -### Symbol References - -- Rename/remove 없음. 기존 `config.ResolveProtocolProfile`은 validation dependency로 호출만 추가한다. - -### Split Judgment - -- Stable contract: slot row는 opaque encrypted revision을 보존하고 route row는 정확히 한 principal/slot/profile/model을 참조한다. 두 테이블의 FK와 활성화 transaction이 하나의 invariant이므로 S04/S05를 같은 packet으로 유지한다. -- Predecessor 01 = `01_principal_store`; active `complete.log` missing, archived candidate 없음. `agent-task/m-principal-provider-credential-slot-routing/01_principal_store/complete.log` 생성 전 구현 금지. -- Consumers: 03은 projection snapshot을, 05는 management mutation API를 사용한다. - -### Scope Rationale - -- raw provider credential 암호화 구현과 실행 시 secret delivery는 Epic 3 소유이다. 이 packet은 non-empty key id/nonce/ciphertext를 가진 opaque envelope만 수락하고 plaintext를 받지 않는다. -- Edge cache, discovery/dispatch, management transport는 후속 packet으로 제외한다. -- built-in protocol profile 정의는 변경하지 않고 resolver 결과를 compatibility oracle로 사용한다. - -### Final Routing - -- `status=routed`, `evaluation_mode=first-pass`, finalizer=`finalize-task-policy.sh`, pair mode. -- Build closures 모두 true; scores `2+2+1+1+1=G07`; base/route=`local-fit`, lane=`local`, canonical=`PLAN-local-G07.md`. -- Review closures 모두 true; scores `2+2+1+1+1=G07`; `official-review`, cloud, `gpt-5.6-sol` xhigh, canonical=`CODE_REVIEW-cloud-G07.md`. -- `large_indivisible_context=false`; risks=`temporal_state`, `boundary_contract`, `variant_product` (3); rework=0; integrity failure=false; capability gap 없음. - -## Dependencies and Execution Order - -1. `01_principal_store` must produce `agent-task/m-principal-provider-credential-slot-routing/01_principal_store/complete.log`. -2. Implement schema/envelope/slot lifecycle, then route bindings against that stable contract. -3. Do not add dependencies absent from directory name `02+01_credential_catalog`. - -## Implementation Checklist - -- [ ] Add opaque encrypted-secret revisions and principal-scoped credential-slot lifecycle with strict alias constraints. -- [ ] Add route bindings that converge to exactly one principal, slot, compatible protocol profile, and upstream model. -- [ ] Prove multi-slot, multi-profile/model, collision, cross-principal, lifecycle, and restart behavior with fresh repository tests. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-1] Persist opaque credential slots independently of profiles - -**Problem:** the repository has no Control Plane credential tables; Edge provider auth config couples secret material and provider protocol selection. - -**Solution:** Extend the credential-store migration with `credential_slots` and immutable `credential_secret_revisions`. Define stable UUID `slot_id`, principal FK, vendor, credential kind, optional normalized alias, lifecycle status/revision, and current secret revision. Accept only an `EncryptedSecretEnvelope` containing key id, nonce, ciphertext, and algorithm; never accept plaintext in this package. - -Before (`apps/control-plane/cmd/control-plane/server.go:29-31`): - -```go -if cfg.Database.URL != "" { - logger.Info("control-plane database configured", databaseLogFields(cfg.Database.URL)...) -} -``` - -After domain shape: - -```go -type EncryptedSecretEnvelope struct { - KeyID, Algorithm string - Nonce, Ciphertext []byte -} -type CredentialSlot struct { - SlotID, PrincipalID, Vendor, CredentialKind string - Alias, Status string - Revision, SecretRevision uint64 -} -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/internal/credentialstore/schema.go`: add constrained slot/secret revision tables and indexes. -- [ ] `apps/control-plane/internal/credentialstore/secret_envelope.go`: define opaque validated envelope without decrypt/plaintext API. -- [ ] `apps/control-plane/internal/credentialstore/slot.go`: create/list/rotate/disable/revoke with revision CAS and principal-scoped alias normalization. -- [ ] `apps/control-plane/internal/credentialstore/slot_test.go`: test two same-vendor slots, alias collision, envelope rejection, rotate, disable/revoke, reopen. - -**Test Strategy:** Write `TestCredentialSlotsAllowSameVendorMultipleSlots`, `TestCredentialSlotRejectsMissingEnvelopeFields`, `TestCredentialSlotAliasUniqueWithinPrincipal`, `TestCredentialSlotRotationCreatesRevision`, and `TestCredentialSlotLifecyclePersists`. Fixtures use distinct opaque ciphertext bytes and never raw API tokens. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore -run 'CredentialSlot|EncryptedSecret'` passes. - -### [API-2] Bind each client route to one slot/profile/model - -**Problem:** no durable `route_id` exists; config model catalogs can map a model group to several providers and cannot express principal-scoped explicit slot selection. - -**Solution:** Add route records with principal FK, slot FK, client-facing stable `route_id`, optional display alias, protocol profile id, upstream model, status/revision. Resolve the profile via `config.ResolveProtocolProfile`; validate vendor/credential-kind compatibility; enforce route and alias uniqueness within a principal and transactionally reject cross-principal slot references. - -Before (`packages/go/config/protocol_profile.go`, existing resolver contract): - -```go -func ResolveProtocolProfile(profileID, providerType string, catalog map[string]ConcreteProtocolProfile) (ConcreteProtocolProfile, error) -``` - -After usage: - -```go -profile, err := config.ResolveProtocolProfile(input.ProfileID, input.Vendor, config.BuiltInProtocolProfiles) -if err != nil { - return RouteBinding{}, ErrIncompatibleProfile -} -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/internal/credentialstore/schema.go`: add route binding table, principal/slot composite FK, and uniqueness constraints. -- [ ] `apps/control-plane/internal/credentialstore/route.go`: create/list/update/disable/revoke and strict lookup by principal+route id. -- [ ] `apps/control-plane/internal/credentialstore/route_test.go`: cover same upstream model on two slots, one slot on multiple compatible routes, invalid profile, alias ambiguity, and cross-principal rejection. - -**Test Strategy:** Write `TestRoutesDisambiguateSameUpstreamModelBySlot`, `TestSlotSupportsMultipleCompatibleProfileModelRoutes`, `TestRouteRejectsCrossPrincipalSlot`, `TestRouteRejectsIncompatibleProfile`, and `TestRouteAliasCollisionFailsClosed`. Assert each lookup returns one tuple and never guesses. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore -run 'Route|Binding'` passes. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `apps/control-plane/internal/credentialstore/schema.go` | API-1, API-2 | -| `apps/control-plane/internal/credentialstore/secret_envelope.go` | API-1 | -| `apps/control-plane/internal/credentialstore/slot.go` | API-1 | -| `apps/control-plane/internal/credentialstore/slot_test.go` | API-1 | -| `apps/control-plane/internal/credentialstore/route.go` | API-2 | -| `apps/control-plane/internal/credentialstore/route_test.go` | API-2 | -| `agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/CODE_REVIEW-cloud-G07.md` | API-1, API-2 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; cached test results are not acceptable. - -1. `test -f agent-task/m-principal-provider-credential-slot-routing/01_principal_store/complete.log` — predecessor is complete. -2. `mkdir -p .cache/go-build .cache/go-cache` — executable Go temp/cache paths exist. -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialstore` — no vet findings. -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore` — all lifecycle, compatibility, isolation, reopen, and race tests pass. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` — Control Plane suite passes. -6. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`. diff --git a/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/CODE_REVIEW-cloud-G09.md b/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/CODE_REVIEW-cloud-G09.md deleted file mode 100644 index 7616b2e..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/CODE_REVIEW-cloud-G09.md +++ /dev/null @@ -1,145 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/03+01,02_projection_auth, plan=1, tag=API - -## Archive Evidence Snapshot - -- Prior pair: `agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/plan_cloud_G10_0.log`, `agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/code_review_cloud_G10_0.log`. -- Verdict/evidence: implementation had not started; no verdict or verification output. -- Replan reason: the previous plan pushed authorization state over the current unauthenticated plain TCP connector and incorrectly claimed S02/S03 completion before S10 `secure-transport`. -- Roadmap carryover: this is foundation-only. PASS must not check `auth-projection` or `surface-auth`; authenticated CP–Edge activation remains required. - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G09.md` → `code_review_cloud_G09_1.log` and `PLAN-cloud-G09.md` → `plan_cloud_G09_1.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-1 Define durable secret-free projection snapshots | [ ] | -| API-2 Add a shared bounded Edge cache | [ ] | -| API-3 Add dormant managed-mode surface authentication | [ ] | - -## Implementation Checklist - -- [ ] Build durable, secret-free projection snapshots with monotonic generation and additive generated message types, covering the S02 data/state fixtures without transport activation. -- [ ] Build a bounded immutable Edge cache that applies only higher fresh generations and remains managed fail-closed after expiry/revocation under race tests. -- [ ] Make OpenAI bearer and Anthropic bearer/x-api-key authentication consume the shared cache only when a verified snapshot is installed, with S03 mismatch and zero-handler-call fixtures. -- [ ] Document and test that the current unauthenticated CP–Edge connector cannot install or receive the projection; leave S02/S03 Roadmap completion for secure-transport rollout. -- [ ] Run fresh generation, race, Edge/client regression, dormant-activation search, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G09_1.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_cloud_G09_1.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Confirm no Roadmap Targets section exists and PASS cannot check S02/S03. -- Verify generation commits with mutations and the cache bounds/deep-copy/atomic higher-generation fence under `-race`. -- Confirm managed expiry/revocation rejects before handlers while unmanaged config behavior remains unchanged. -- Prove Connector, EdgeServer, and Runtime have no projection listener/push/wiring on current plain transport. -- Check contracts describe reserved/gated behavior rather than active production rollout. - -## Verification Results - -Paste actual stdout/stderr beneath every command; do not summarize or reconstruct it. - -### API-1 - -`make proto && make proto-dart && GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore` - -_Pending._ - -### API-2 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/edge/internal/authprojection ./apps/edge/internal/input` - -_Pending._ - -### API-3 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Managed|Principal|Anthropic.*Auth'` - -_Pending._ - -### Final Verification - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/01_principal_store/complete.log' -print | wc -l)" -eq 1 && test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log' -print | wc -l)" -eq 1` -2. `command -v go && go version && command -v protoc && protoc --version && command -v protoc-gen-go && command -v protoc-gen-dart && command -v flutter && flutter --version` -3. `mkdir -p .cache/go-build .cache/go-cache` -4. `make proto && make proto-dart` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialstore ./apps/edge/internal/authprojection ./apps/edge/internal/input ./apps/edge/internal/openai` -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore ./apps/edge/internal/authprojection ./apps/edge/internal/input ./apps/edge/internal/openai` -7. `make client-test` -8. `if rg --sort path -n 'PrincipalProjection' apps/control-plane/internal/wire/edge_server.go apps/edge/internal/controlplane/connector.go apps/edge/internal/bootstrap/runtime.go; then exit 1; else exit 0; fi` -9. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/PLAN-cloud-G09.md b/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/PLAN-cloud-G09.md deleted file mode 100644 index 5df503a..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/PLAN-cloud-G09.md +++ /dev/null @@ -1,285 +0,0 @@ - - -# Auth Projection and Surface-Auth Foundation - -## For the Implementing Agent - -Filling implementation-owned sections of `CODE_REVIEW-cloud-G09.md` is mandatory. Run every verification command, paste actual output, keep active files in place, and report ready for review; only code-review may finalize, rename logs, write `complete.log`, or archive. If blocked, record exact blocker evidence and resume conditions only in implementation-owned fields; do not ask the user, call user-input tools, create stop files, or classify next state. - -## Background - -The Edge needs a bounded immutable principal projection cache and common OpenAI/Anthropic authentication logic. The current CP–Edge TCP connection has no authenticated peer or transport integrity, so wiring an authorization projection over it would allow an untrusted source to replace token verifiers and routes; this packet deliberately builds but does not activate that transport path. - -## Archive Evidence Snapshot - -- Prior pair: `agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/plan_cloud_G10_0.log`, `agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/code_review_cloud_G10_0.log`. -- Verdict/evidence: implementation had not started; no verdict or verification output. -- Replan reason: the previous plan pushed authorization state over the current unauthenticated plain TCP connector and incorrectly claimed S02/S03 completion before S10 `secure-transport`. -- Roadmap carryover: this is foundation-only. PASS must not check `auth-projection` or `surface-auth`; authenticated CP–Edge activation remains required. - -## Analysis - -### Files Read - -- `proto/iop/control.proto` -- `proto/gen/iop/control.pb.go` -- `apps/client/lib/gen/proto/iop/control.pb.dart` -- `apps/client/lib/gen/proto/iop/control.pbenum.dart` -- `apps/client/lib/gen/proto/iop/control.pbjson.dart` -- `apps/client/lib/gen/proto/iop/control.pbserver.dart` -- `apps/control-plane/internal/wire/edge.go` -- `apps/control-plane/internal/wire/edge_server.go` -- `apps/edge/internal/controlplane/connector.go` -- `apps/edge/internal/controlplane/connector_test.go` -- `apps/edge/internal/input/manager.go` -- `apps/edge/internal/input/manager_test.go` -- `apps/edge/internal/openai/server.go` -- `apps/edge/internal/openai/principal.go` -- `apps/edge/internal/openai/anthropic_types.go` -- `apps/edge/internal/openai/routes.go` -- `apps/edge/internal/openai/identity_metering_test.go` -- `apps/edge/internal/openai/anthropic_surface_test.go` -- `apps/edge/internal/openai/openai_auth_routes_models_test.go` -- `agent-contract/inner/control-plane-edge-wire.md` -- `agent-contract/outer/openai-compatible-api.md` -- `agent-contract/outer/anthropic-compatible-api.md` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 잠금 해제). -- Foundation maps to S02 / `auth-projection` and S03 / `surface-auth`, Evidence Map S01-S03, but intentionally does not satisfy their production synchronization/authorization evidence. -- Checklist covers durable generation, bounded atomic cache, fresh/stale/revoked/out-of-order fixtures, and dual-header zero-handler-call behavior. Final verification also proves no current Connector/EdgeServer call site activates projection messages. - -### Verification Context - -- handoff 없음. SDD secure-delivery clause explicitly states current plain TCP/WS cannot carry credential-bearing operations; current CP–Edge contract has hello but no peer authentication. -- Go 1.26.2, protoc 29.3, Go/Dart generators present, Flutter 3.41.5. Workspace ignored Go temp/cache paths are required because `/tmp` is noexec. -- Preconditions 01 and 02 are currently incomplete; runtime resolves their archived completions before implementation. -- No external provider or TLS runner is required because this packet is dormant foundation. Confidence: high. -- The current dirty baseline already contains user-owned authentication fixes in `principal.go`, `anthropic_types.go`, `anthropic_surface_test.go`, and `openai_auth_routes_models_test.go`; preserve and integrate those semantics instead of replacing or reverting them. - -### Test Coverage Gaps - -- Static Edge auth tests cover header normalization but not generation/expiry/revocation or concurrent apply/read. -- No durable projection snapshot builder or bounded cache exists. -- No test currently proves projection activation is absent on the unauthenticated connector. - -### Symbol References - -- Rename/remove 없음. `openai.NewServer` signature remains unchanged; many tests rely on it. -- `input.NewManager` is called by `bootstrap.NewRuntime`; preserve its signature and expose the shared cache on Manager. -- No `NewConnector`/`NewEdgeServer` call site is changed in this packet. - -### Split Judgment - -- Durable snapshot format and Edge cache/header semantics form a stable dormant contract with deterministic tests. -- Predecessors 01 and 02: active/archived completion missing, ambiguity 없음. -- Authenticated transport activation is excluded and must be planned with S10; therefore no Roadmap Targets section is present. -- Packet 04 may consume only the dormant cache contract and likewise cannot claim public rollout. - -### Scope Rationale - -- Do not register projection listeners, push from `EdgeServer`, or wire `bootstrap.Runtime.ControlPlane` to the cache on the current plain transport. -- Do not carry ciphertext/plaintext, add TLS, or implement credential leases. -- Preserve the existing user changes that scope Anthropic `x-api-key`/version handling away from ordinary OpenAI routes; managed-mode additions must extend that baseline without reverting it. -- Contracts must mark messages/cache as reserved/gated foundation, not active production behavior. - -### Final Routing - -- `status=routed`, `evaluation_mode=isolated-reassessment`, finalizer=`finalize-task-policy.sh`, pair mode. -- Build closures all true for dormant foundation; scores `2+2+1+2+2=G09`; base/route=`grade-boundary`, cloud, `PLAN-cloud-G09.md`. -- Review closures all true; scores `2+2+1+2+2=G09`; `official-review`, cloud, `gpt-5.6-sol` xhigh, `CODE_REVIEW-cloud-G09.md`. -- `large_indivisible_context=false`; risks=`temporal_state`, `concurrent_consistency`, `boundary_contract`, `variant_product` (4); rework=0; integrity failure=false; no capability gap. - -## Dependencies and Execution Order - -1. `01_principal_store` and `02+01_credential_catalog` must complete; runtime accepts their archived `complete.log` files. -2. Add durable snapshot generation and additive message schema, then the shared Edge cache, then dormant HTTP managed-mode logic. -3. Do not add dependencies absent from `03+01,02_projection_auth`. - -## Implementation Checklist - -- [ ] Build durable, secret-free projection snapshots with monotonic generation and additive generated message types, covering the S02 data/state fixtures without transport activation. -- [ ] Build a bounded immutable Edge cache that applies only higher fresh generations and remains managed fail-closed after expiry/revocation under race tests. -- [ ] Make OpenAI bearer and Anthropic bearer/x-api-key authentication consume the shared cache only when a verified snapshot is installed, with S03 mismatch and zero-handler-call fixtures. -- [ ] Document and test that the current unauthenticated CP–Edge connector cannot install or receive the projection; leave S02/S03 Roadmap completion for secure-transport rollout. -- [ ] Run fresh generation, race, Edge/client regression, dormant-activation search, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-1] Define durable secret-free projection snapshots - -**Problem:** `proto/iop/control.proto` and the Control Plane store have no generation/expiry token+route snapshot contract. - -**Solution:** Add additive projection value messages, but no live request listener. Add a DB singleton generation bumped transactionally by token/slot/route mutations and a bounded snapshot builder containing active digests and route metadata only. - -Before (`apps/control-plane/internal/wire/edge.go:12-18`): - -```go -return proto_socket.ParserMap{ - proto_socket.TypeNameOf(&iop.EdgeHelloRequest{}): func(b []byte) (proto.Message, error) { - req := &iop.EdgeHelloRequest{} - return req, proto.Unmarshal(b, req) - }, -``` - -After schema boundary: - -```protobuf -message PrincipalProjection { - uint64 generation = 1; - int64 issued_at_unix_nano = 2; - int64 expires_at_unix_nano = 3; - repeated ProjectedPrincipalToken tokens = 4; - repeated ProjectedPrincipalRoute routes = 5; -} -``` - -**Modified Files and Checklist:** - -- [ ] `proto/iop/control.proto`: add value/apply types additively; do not register an active wire operation. -- [ ] `proto/gen/iop/control.pb.go`: regenerate Go. -- [ ] `apps/client/lib/gen/proto/iop/control.pb.dart`: regenerate Dart. -- [ ] `apps/client/lib/gen/proto/iop/control.pbenum.dart`: regenerate Dart enums. -- [ ] `apps/client/lib/gen/proto/iop/control.pbjson.dart`: regenerate Dart metadata. -- [ ] `apps/client/lib/gen/proto/iop/control.pbserver.dart`: regenerate Dart helpers. -- [ ] `apps/control-plane/internal/credentialstore/schema.go`: add durable projection generation. -- [ ] `apps/control-plane/internal/credentialstore/principal.go`: bump generation with token mutations. -- [ ] `apps/control-plane/internal/credentialstore/slot.go`: bump generation with slot mutations. -- [ ] `apps/control-plane/internal/credentialstore/route.go`: bump generation with route mutations. -- [ ] `apps/control-plane/internal/credentialstore/projection.go`: build bounded immutable snapshots. -- [ ] `apps/control-plane/internal/credentialstore/projection_test.go`: verify durability/filtering/bounds. - -**Test Strategy:** Write `TestProjectionGenerationCommitsWithMutation`, `TestProjectionGenerationPersistsAcrossReopen`, and `TestProjectionSnapshotOmitsInactiveRecords` with temp SQLite and injected clocks. - -**Verification:** `make proto && make proto-dart && GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore` passes. - -### [API-2] Add a shared bounded Edge cache - -**Problem:** `apps/edge/internal/openai/server.go:50-68` owns mutable config/catalog state but has no fenced principal projection snapshot. - -**Solution:** Add `apps/edge/internal/authprojection` with injected clock, hard entry/byte limits, deep-copy validation, atomic snapshot swap, digest lookup, and explicit unmanaged/fresh/expired states. `input.Manager` constructs one cache and gives it to OpenAI; it remains unmanaged because Runtime/Connector receives no apply handle. - -Required imports for the new cache boundary: - -```go -import ( - "crypto/subtle" - "errors" - "sync/atomic" - "time" - - iop "iop/proto/gen/iop" -) -``` - -Before (`apps/edge/internal/input/manager.go:20-29`): - -```go -func NewManager(cfg config.EdgeConfig, svc *edgeservice.Service, logger *zap.Logger) *Manager { - openaiServer := edgeopenai.NewServer(cfg.OpenAI, svc, logger.Named("openai")) - openaiServer.SetEdgeID(cfg.Edge.ID) -``` - -After: - -```go -projection := authprojection.NewCache(authprojection.DefaultLimits(), time.Now) -openaiServer := edgeopenai.NewServer(cfg.OpenAI, svc, logger.Named("openai")) -openaiServer.SetPrincipalProjection(projection) -``` - -**Modified Files and Checklist:** - -- [ ] `apps/edge/internal/authprojection/cache.go`: implement validated atomic cache and states. -- [ ] `apps/edge/internal/authprojection/cache_test.go`: cover fresh/stale/expired/revoked/out-of-order/bounds/concurrency. -- [ ] `apps/edge/internal/openai/server.go`: read the cache through a narrow interface without changing constructor. -- [ ] `apps/edge/internal/input/manager.go`: create and expose the dormant shared cache. -- [ ] `apps/edge/internal/input/manager_test.go`: prove shared instance and unmanaged default. - -**Test Strategy:** Write `TestCacheAppliesOnlyHigherFreshGeneration`, `TestCacheExpiryKeepsManagedFailClosed`, `TestCacheRejectsOversizedSnapshot`, and `TestCacheConcurrentLookupAndApply`; run with `-race`. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/edge/internal/authprojection ./apps/edge/internal/input` passes. - -### [API-3] Add dormant managed-mode surface authentication - -**Problem:** `apps/edge/internal/openai/routes.go:30-43` reads only static config, so no shared cache behavior can be tested; directly wiring the cache to current connector would be unsafe. - -**Solution:** When the cache is explicitly in managed state, authenticate constant-time token digests and surface-specific headers from it; unmanaged state preserves existing config behavior. Expired/revoked managed state returns 401 before handler. Do not add any production cache writer. - -Before (`apps/edge/internal/openai/routes.go:30-33`): - -```go -func (s *Server) withAuth(next http.HandlerFunc) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - principal, ok := principalFromRequest(r, s.cfg) -``` - -After: - -```go -principal, state := s.authenticatePrincipal(r) -if state != principalAuthenticated { - s.writeAuthenticationFailure(w, r) - return -} -``` - -**Modified Files and Checklist:** - -- [ ] `apps/edge/internal/openai/principal.go`: share header normalization and projected digest lookup. -- [ ] `apps/edge/internal/openai/routes.go`: enforce managed error precedence before handlers. -- [ ] `apps/edge/internal/openai/identity_metering_test.go`: cover managed principal metadata and static compatibility. -- [ ] `apps/edge/internal/openai/anthropic_surface_test.go`: cover same/mismatch/unregistered/revoked/expired dual headers and zero dispatch. -- [ ] `agent-contract/inner/control-plane-edge-wire.md`: mark projection types reserved until authenticated transport, with no current listener. -- [ ] `agent-contract/outer/openai-compatible-api.md`: document dormant managed-mode gate and unchanged legacy production mode. -- [ ] `agent-contract/outer/anthropic-compatible-api.md`: document the same gated header semantics. - -**Test Strategy:** Write `TestManagedOpenAIAuthRejectsBeforeHandler`, `TestManagedAnthropicDualHeadersSameToken`, `TestManagedAnthropicDualHeadersMismatch`, and `TestManagedProjectionExpiryRejectsBeforeDispatch` using direct cache fixture installation inside tests. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Managed|Principal|Anthropic.*Auth'` passes. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `proto/iop/control.proto` | API-1 | -| `proto/gen/iop/control.pb.go` | API-1 | -| `apps/client/lib/gen/proto/iop/control.pb.dart` | API-1 | -| `apps/client/lib/gen/proto/iop/control.pbenum.dart` | API-1 | -| `apps/client/lib/gen/proto/iop/control.pbjson.dart` | API-1 | -| `apps/client/lib/gen/proto/iop/control.pbserver.dart` | API-1 | -| `apps/control-plane/internal/credentialstore/schema.go` | API-1 | -| `apps/control-plane/internal/credentialstore/principal.go` | API-1 | -| `apps/control-plane/internal/credentialstore/slot.go` | API-1 | -| `apps/control-plane/internal/credentialstore/route.go` | API-1 | -| `apps/control-plane/internal/credentialstore/projection.go` | API-1 | -| `apps/control-plane/internal/credentialstore/projection_test.go` | API-1 | -| `apps/edge/internal/authprojection/cache.go` | API-2 | -| `apps/edge/internal/authprojection/cache_test.go` | API-2 | -| `apps/edge/internal/openai/server.go` | API-2 | -| `apps/edge/internal/input/manager.go` | API-2 | -| `apps/edge/internal/input/manager_test.go` | API-2 | -| `apps/edge/internal/openai/principal.go` | API-3 | -| `apps/edge/internal/openai/routes.go` | API-3 | -| `apps/edge/internal/openai/identity_metering_test.go` | API-3 | -| `apps/edge/internal/openai/anthropic_surface_test.go` | API-3 | -| `agent-contract/inner/control-plane-edge-wire.md` | API-3 | -| `agent-contract/outer/openai-compatible-api.md` | API-3 | -| `agent-contract/outer/anthropic-compatible-api.md` | API-3 | -| `agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/CODE_REVIEW-cloud-G09.md` | API-1, API-2, API-3 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; fresh results are required. - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/01_principal_store/complete.log' -print | wc -l)" -eq 1 && test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log' -print | wc -l)" -eq 1` — both archived predecessors exist exactly once. -2. `command -v go && go version && command -v protoc && protoc --version && command -v protoc-gen-go && command -v protoc-gen-dart && command -v flutter && flutter --version` — toolchains resolve. -3. `mkdir -p .cache/go-build .cache/go-cache` — executable Go paths exist. -4. `make proto && make proto-dart` — generated outputs are current. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialstore ./apps/edge/internal/authprojection ./apps/edge/internal/input ./apps/edge/internal/openai` — no vet findings. -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore ./apps/edge/internal/authprojection ./apps/edge/internal/input ./apps/edge/internal/openai` — foundation lifecycle and race tests pass. -7. `make client-test` — generated Dart compatibility passes. -8. `if rg --sort path -n 'PrincipalProjection' apps/control-plane/internal/wire/edge_server.go apps/edge/internal/controlplane/connector.go apps/edge/internal/bootstrap/runtime.go; then exit 1; else exit 0; fi` — current unauthenticated runtime has no projection activation. -9. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`. diff --git a/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/code_review_cloud_G10_0.log b/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/code_review_cloud_G10_0.log deleted file mode 100644 index ae960f3..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/code_review_cloud_G10_0.log +++ /dev/null @@ -1,148 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/03+01,02_projection_auth, plan=0, tag=API - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `auth-projection`: generation/expiry principal projection과 bounded Edge cache - - `surface-auth`: OpenAI/Anthropic 동일 principal 인증 -- Completion mode: check-on-pass - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G10.md` → `code_review_cloud_G10_0.log` and `PLAN-cloud-G10.md` → `plan_cloud_G10_0.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-1 Produce and synchronize durable projections | [ ] | -| API-2 Apply a fenced bounded Edge cache | [ ] | -| API-3 Authenticate both HTTP surfaces from the same snapshot | [ ] | - -## Implementation Checklist - -- [ ] Add durable monotonic principal projection snapshots and the CP-to-Edge protobuf request/acknowledgment contract. -- [ ] Apply only higher, unexpired generations to a bounded atomic Edge cache and retain managed fail-closed state after expiry or revocation. -- [ ] Authenticate OpenAI bearer and Anthropic bearer/x-api-key through the shared cache, rejecting mismatch or invalid tokens before model/dispatch handlers. -- [ ] Update generated Go/Dart code and inner/outer contracts without exposing raw secrets. -- [ ] Run fresh race, wire, client-generation, full-cycle ingress, vet, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G10_0.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_cloud_G10_0.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Verify both predecessor complete logs and additive protobuf compatibility. -- Inspect transaction boundaries so each auth-affecting mutation and durable generation commit together. -- Confirm cache validation, size bounds, deep copy, atomic swap, higher-generation fence, fake-clock expiry, and `-race` evidence. -- Confirm managed expiry/revocation never falls back to static config and 401 occurs before model/dispatch handler invocation. -- Search generated/contracts/logging paths for raw token/provider secret exposure. - -## Verification Results - -Paste actual stdout/stderr beneath every command; do not summarize or reconstruct it. - -### API-1 - -`make proto && make proto-dart && GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore ./apps/control-plane/internal/wire` - -_Pending._ - -### API-2 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/edge/internal/controlplane ./apps/edge/internal/openai ./apps/edge/internal/input ./apps/edge/internal/bootstrap` - -_Pending._ - -### API-3 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Principal|Anthropic.*Auth|Projection'` - -_Pending._ - -### Final Verification - -1. `test -f agent-task/m-principal-provider-credential-slot-routing/01_principal_store/complete.log && test -f agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log` -2. `command -v go && go version && command -v protoc && protoc --version && command -v protoc-gen-go && command -v protoc-gen-dart && command -v flutter && flutter --version` -3. `mkdir -p .cache/go-build .cache/go-cache` -4. `make proto && make proto-dart` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/... ./apps/edge/internal/controlplane ./apps/edge/internal/openai ./apps/edge/internal/input ./apps/edge/internal/bootstrap` -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore ./apps/control-plane/internal/wire ./apps/edge/internal/controlplane ./apps/edge/internal/openai ./apps/edge/internal/input ./apps/edge/internal/bootstrap` -7. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache make test-control-plane-edge-wire` -8. `make client-test` -9. `cd apps/client && flutter analyze` -10. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/plan_cloud_G10_0.log b/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/plan_cloud_G10_0.log deleted file mode 100644 index d03b39a..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/plan_cloud_G10_0.log +++ /dev/null @@ -1,304 +0,0 @@ - - -# Principal Projection and Surface Authentication - -## For the Implementing Agent - -Filling the implementation-owned sections of `CODE_REVIEW-cloud-G10.md` is mandatory. Execute every verification command, paste actual notes/output, leave active files in place, and report ready for review; only code-review may finalize, rename logs, create `complete.log`, or archive. If blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence; do not ask the user, invoke user-input tools, create stop files, or classify next state. - -## Background - -Edge authenticates static config hashes and already normalizes Anthropic bearer/`x-api-key`, but it has no Control Plane generation, expiry, revocation, or bounded cache. This packet establishes the CP→Edge projection contract and makes both compatible HTTP surfaces use the same fresh principal snapshot before model lookup or provider dispatch. - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `auth-projection`: generation/expiry principal projection과 bounded Edge cache - - `surface-auth`: OpenAI/Anthropic 동일 principal 인증 -- Completion mode: check-on-pass - -## Analysis - -### Files Read - -- `proto/iop/control.proto` -- `proto/gen/iop/control.pb.go` -- `apps/client/lib/gen/proto/iop/control.pb.dart` -- `apps/client/lib/gen/proto/iop/control.pbenum.dart` -- `apps/client/lib/gen/proto/iop/control.pbjson.dart` -- `apps/client/lib/gen/proto/iop/control.pbserver.dart` -- `apps/control-plane/cmd/control-plane/server.go` -- `apps/control-plane/internal/wire/edge.go` -- `apps/control-plane/internal/wire/edge_server.go` -- `apps/control-plane/internal/wire/edge_test.go` -- `apps/control-plane/internal/wire/edge_server_test.go` -- `apps/edge/internal/controlplane/connector.go` -- `apps/edge/internal/controlplane/connector_test.go` -- `apps/edge/internal/bootstrap/runtime.go` -- `apps/edge/internal/bootstrap/runtime_connector_test.go` -- `apps/edge/internal/input/manager.go` -- `apps/edge/internal/input/manager_test.go` -- `apps/edge/internal/openai/server.go` -- `apps/edge/internal/openai/principal.go` -- `apps/edge/internal/openai/routes.go` -- `apps/edge/internal/openai/identity_metering_test.go` -- `apps/edge/internal/openai/anthropic_surface_test.go` -- `apps/client/test/iop_wire/generated_proto_import_test.dart` -- `agent-contract/inner/control-plane-edge-wire.md` -- `agent-contract/outer/openai-compatible-api.md` -- `agent-contract/outer/anthropic-compatible-api.md` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 잠금 해제). -- Targets: S02 / `auth-projection`, S03 / `surface-auth`. -- Evidence Map row: S01-S03의 projection generation/expiry 및 dual-header ingress tests 중 S02-S03. -- Checklist는 durable monotonic generation, atomic higher-generation apply, fresh/stale/expired/revoked/out-of-order fixtures, bounded cache, same-token dual header success, mismatched/unregistered/revoked 401-before-handler를 직접 연결한다. - -### Verification Context - -- handoff 없음. wire/proto generators, CP/Edge tests, outer/inner contracts, domain rules와 local control-plane/edge/client smoke profiles에서 검증을 구성했다. -- Tools: Go 1.26.2, `protoc` 29.3, `protoc-gen-go` v1.36.11, `protoc-gen-dart` present, Flutter 3.41.5/Dart 3.11.3. `make -n proto proto-dart`가 canonical outputs를 확인했다. -- Local preflight compile and focused legacy principal/Anthropic tests pass only with `GOTMPDIR`/`GOCACHE` under ignored workspace `.cache`; `/tmp` is noexec and default cache is inaccessible. -- Preconditions: `01_principal_store` and `02+01_credential_catalog` complete logs. 현재 둘 다 missing이며 ambiguity 없음. -- Full cycle is local CP→Edge TCP plus Edge HTTP; no real provider credential or external host is required because rejection must occur before fake dispatch. Confidence: high. - -### Test Coverage Gaps - -- Existing Edge auth tests cover static hashes and dual-header mismatch, but not projection generation/expiry/revocation or fail-closed managed mode. -- CP-Edge tests cover hello/status/command only; no projection parser/request/apply acknowledgment exists. -- Runtime/input tests do not prove a shared cache is wired from Connector into OpenAI server. -- Generated Dart import test does not reference projection messages yet. - -### Symbol References - -- No rename/remove. -- `wire.NewEdgeServer` call sites: `apps/control-plane/cmd/control-plane/server.go:51`, `apps/control-plane/internal/wire/edge_server_test.go:22`; preserve constructor compatibility through an option. -- `controlplane.NewConnector` call site: `apps/edge/internal/bootstrap/runtime.go:83`; existing tests call it directly and remain source-compatible through an option. -- `openai.NewServer` has many tests; do not change its signature. Add setter/sink methods. - -### Split Judgment - -- Projection and ingress authentication remain one packet because “higher fresh generation atomically replaces token lookup, then middleware authenticates from that exact snapshot” is one correctness invariant. Splitting would allow an invalid state where wire reports success while HTTP still reads static config. -- Predecessor 01 `01_principal_store`: missing active `complete.log`, no archived candidate. -- Predecessor 02 `02+01_credential_catalog`: missing active `complete.log`, no archived candidate. -- Consumer 04 depends only on this packet's complete projection snapshot contract. - -### Scope Rationale - -- Principal-specific model listing/dispatch is packet 04. Management mutations are packet 05. -- Provider ciphertext delivery/decrypt/header injection is Epic 3 and excluded; projection contains IDs, hashes, route metadata, never raw provider or IOP secrets. -- Legacy config auth remains available only when Edge has never entered CP-managed projection mode; once managed, expiry is fail-closed rather than fallback. - -### Final Routing - -- `status=routed`, `evaluation_mode=first-pass`, finalizer=`finalize-task-policy.sh`, pair mode. -- Build closures all true; scores `2+2+2+2+2=G10`; base/route=`grade-boundary`, cloud, canonical=`PLAN-cloud-G10.md`. -- Review closures all true; scores `2+2+2+2+2=G10`; `official-review`, cloud, `gpt-5.6-sol` xhigh, canonical=`CODE_REVIEW-cloud-G10.md`. -- `large_indivisible_context=false`; risks=`temporal_state`, `concurrent_consistency`, `boundary_contract`, `variant_product` (4), risk boundary matched but grade basis retained; rework=0; integrity failure=false; no capability gap. - -## Dependencies and Execution Order - -1. `01_principal_store` must provide `agent-task/m-principal-provider-credential-slot-routing/01_principal_store/complete.log`. -2. `02+01_credential_catalog` must provide `agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log`. -3. Add durable projection generation/snapshot, then wire apply, then switch ingress authentication to the shared cache. -4. No dependency beyond indices `01,02` may be introduced. - -## Implementation Checklist - -- [ ] Add durable monotonic principal projection snapshots and the CP-to-Edge protobuf request/acknowledgment contract. -- [ ] Apply only higher, unexpired generations to a bounded atomic Edge cache and retain managed fail-closed state after expiry or revocation. -- [ ] Authenticate OpenAI bearer and Anthropic bearer/x-api-key through the shared cache, rejecting mismatch or invalid tokens before model/dispatch handlers. -- [ ] Update generated Go/Dart code and inner/outer contracts without exposing raw secrets. -- [ ] Run fresh race, wire, client-generation, full-cycle ingress, vet, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-1] Produce and synchronize durable projections - -**Problem:** `apps/control-plane/internal/wire/edge.go:12-46` knows only hello/status/events/commands, and store mutations have no durable projection generation. - -**Solution:** Add a singleton projection generation incremented in the same DB transaction as principal/token/slot/route mutations. Build immutable snapshots of active token digests and route metadata with `generation`, `issued_at`, and `expires_at`. Add CP→Edge `PrincipalProjectionApplyRequest/Response`; push after accepted hello and on newer store generation, with retry safe through generation fencing. - -Before (`apps/control-plane/internal/wire/edge.go:12-18`): - -```go -return proto_socket.ParserMap{ - proto_socket.TypeNameOf(&iop.EdgeHelloRequest{}): func(b []byte) (proto.Message, error) { - req := &iop.EdgeHelloRequest{} - return req, proto.Unmarshal(b, req) - }, -``` - -After: - -```go -proto_socket.TypeNameOf(&iop.PrincipalProjectionApplyRequest{}): func(b []byte) (proto.Message, error) { - req := &iop.PrincipalProjectionApplyRequest{} - return req, proto.Unmarshal(b, req) -}, -``` - -**Modified Files and Checklist:** - -- [ ] `proto/iop/control.proto`: add projection token/route/snapshot/apply/ack messages with additive field numbers. -- [ ] `proto/gen/iop/control.pb.go`: regenerate Go messages. -- [ ] `apps/client/lib/gen/proto/iop/control.pb.dart`: regenerate Dart messages. -- [ ] `apps/client/lib/gen/proto/iop/control.pbenum.dart`: regenerate Dart enum output. -- [ ] `apps/client/lib/gen/proto/iop/control.pbjson.dart`: regenerate Dart JSON metadata. -- [ ] `apps/client/lib/gen/proto/iop/control.pbserver.dart`: regenerate Dart server helpers. -- [ ] `apps/control-plane/internal/credentialstore/schema.go`: add durable projection generation state. -- [ ] `apps/control-plane/internal/credentialstore/principal.go`: bump generation transactionally on token lifecycle mutations. -- [ ] `apps/control-plane/internal/credentialstore/slot.go`: bump generation transactionally on slot lifecycle mutations. -- [ ] `apps/control-plane/internal/credentialstore/route.go`: bump generation transactionally on route lifecycle mutations. -- [ ] `apps/control-plane/internal/credentialstore/projection.go`: build bounded immutable active snapshots. -- [ ] `apps/control-plane/internal/credentialstore/projection_test.go`: test generation durability and filtered snapshots. -- [ ] `apps/control-plane/internal/wire/edge.go`: register projection parsers. -- [ ] `apps/control-plane/internal/wire/edge_server.go`: accept projection source option and push fresh snapshot to live Edge connections. -- [ ] `apps/control-plane/internal/wire/projection_sync.go`: implement generation-aware publish/retry without blocking hello. -- [ ] `apps/control-plane/internal/wire/edge_test.go`: assert parser round trips. -- [ ] `apps/control-plane/internal/wire/edge_server_test.go`: assert connect/push/ack and reconnect behavior. -- [ ] `apps/control-plane/cmd/control-plane/server.go`: supply store projection source to EdgeServer. - -**Test Strategy:** Write `TestProjectionGenerationCommitsWithMutation`, `TestProjectionSnapshotOmitsDisabledRevokedExpiredRecords`, `TestEdgeServerPushesProjectionAfterHello`, and `TestProjectionRetryKeepsGeneration`. Use temp SQLite and loopback TCP; timestamps use injected clocks. - -**Verification:** `make proto && make proto-dart && GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/credentialstore ./apps/control-plane/internal/wire` passes. - -### [API-2] Apply a fenced bounded Edge cache - -**Problem:** `apps/edge/internal/controlplane/connector.go:229-238` registers only status/command listeners, and OpenAI server state has no CP projection cache. - -**Solution:** Define a `PrincipalProjectionSink` connector option. Register the apply listener before hello, validate sizes/digests/times, deep-copy and atomically swap only when generation is higher and snapshot is fresh. Once the first managed generation is accepted, expiry/revocation remains managed fail-closed and never falls back to static config. - -Before (`apps/edge/internal/controlplane/connector.go:229-238`): - -```go -toki.AddRequestListenerTyped(&cl.Communicator, func(req *iop.EdgeStatusRequest) (*iop.EdgeStatusResponse, error) { - return c.buildStatusResponse(req), nil -}) - -toki.AddRequestListenerTyped(&cl.Communicator, func(req *iop.EdgeCommandRequest) (*iop.EdgeCommandResponse, error) { - return c.handleEdgeCommand(ctx, req) -}) -``` - -After: - -```go -toki.AddRequestListenerTyped(&cl.Communicator, func(req *iop.PrincipalProjectionApplyRequest) (*iop.PrincipalProjectionApplyResponse, error) { - return c.applyPrincipalProjection(req), nil -}) -``` - -**Modified Files and Checklist:** - -- [ ] `apps/edge/internal/controlplane/connector.go`: add sink option/listener and stable apply responses. -- [ ] `apps/edge/internal/controlplane/connector_test.go`: test listener ordering, invalid/out-of-order application, reconnect. -- [ ] `apps/edge/internal/openai/principal_projection.go`: implement limits, injected clock, atomic immutable snapshot, lookup, expiry state. -- [ ] `apps/edge/internal/openai/principal_projection_test.go`: cover fresh/stale/expired/revoked/out-of-order/concurrent reads. -- [ ] `apps/edge/internal/openai/server.go`: own the projection cache and expose sink/setter without changing `NewServer` signature. -- [ ] `apps/edge/internal/input/manager.go`: expose the OpenAI projection sink. -- [ ] `apps/edge/internal/input/manager_test.go`: assert the shared cache exists. -- [ ] `apps/edge/internal/bootstrap/runtime.go`: wire connector sink to `Input.OpenAI`. -- [ ] `apps/edge/internal/bootstrap/runtime_connector_test.go`: assert projection sink wiring. - -**Test Strategy:** Write `TestProjectionAppliesOnlyHigherFreshGeneration`, `TestProjectionExpiryKeepsManagedFailClosed`, `TestProjectionBoundsRejectOversizedSnapshot`, and `TestProjectionConcurrentLookupAndApply`. Run `-race` with a deterministic fake clock. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/edge/internal/controlplane ./apps/edge/internal/openai ./apps/edge/internal/input ./apps/edge/internal/bootstrap` passes. - -### [API-3] Authenticate both HTTP surfaces from the same snapshot - -**Problem:** `apps/edge/internal/openai/routes.go:30-43` always calls static `principalFromRequest(r, s.cfg)`. Static dual-header logic cannot observe Control Plane revocation or expiry. - -**Solution:** Make middleware resolve from the cache when managed; use constant-time digest lookup, require equal bearer and `x-api-key` values when both exist, and return surface-correct 401 before invoking the handler. Keep current static behavior only in never-managed compatibility mode. - -Before (`apps/edge/internal/openai/routes.go:30-33`): - -```go -func (s *Server) withAuth(next http.HandlerFunc) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - principal, ok := principalFromRequest(r, s.cfg) - if !ok { -``` - -After: - -```go -principal, authState := s.authenticatePrincipal(r) -if authState != principalAuthenticated { - s.writeAuthenticationFailure(w, r) - return -} -``` - -**Modified Files and Checklist:** - -- [ ] `apps/edge/internal/openai/principal.go`: share header normalization and digest matching between static and projected sources. -- [ ] `apps/edge/internal/openai/routes.go`: fail before handler invocation with OpenAI/Anthropic 401 envelopes. -- [ ] `apps/edge/internal/openai/identity_metering_test.go`: retain static compatibility and projected principal metadata assertions. -- [ ] `apps/edge/internal/openai/anthropic_surface_test.go`: add bearer/x-api-key same/mismatch/unregistered/revoked/expired cases and zero-dispatch assertions. -- [ ] `agent-contract/inner/control-plane-edge-wire.md`: document projection fields, generation, expiry, size and ack rules. -- [ ] `agent-contract/outer/openai-compatible-api.md`: document CP-managed bearer behavior. -- [ ] `agent-contract/outer/anthropic-compatible-api.md`: document bearer/x-api-key equivalence and 401 precedence. - -**Test Strategy:** Add `TestProjectedOpenAIAuthRejectsBeforeHandler`, `TestAnthropicProjectedDualHeadersSameToken`, `TestAnthropicProjectedDualHeadersMismatch`, and `TestRevokedOrExpiredProjectionRejectsBeforeDispatch`. Use a counting handler/fake service to assert zero calls. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Principal|Anthropic.*Auth|Projection'` passes. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `proto/iop/control.proto` | API-1 | -| `proto/gen/iop/control.pb.go` | API-1 | -| `apps/client/lib/gen/proto/iop/control.pb.dart` | API-1 | -| `apps/client/lib/gen/proto/iop/control.pbenum.dart` | API-1 | -| `apps/client/lib/gen/proto/iop/control.pbjson.dart` | API-1 | -| `apps/client/lib/gen/proto/iop/control.pbserver.dart` | API-1 | -| `apps/control-plane/internal/credentialstore/schema.go` | API-1 | -| `apps/control-plane/internal/credentialstore/principal.go` | API-1 | -| `apps/control-plane/internal/credentialstore/slot.go` | API-1 | -| `apps/control-plane/internal/credentialstore/route.go` | API-1 | -| `apps/control-plane/internal/credentialstore/projection.go` | API-1 | -| `apps/control-plane/internal/credentialstore/projection_test.go` | API-1 | -| `apps/control-plane/internal/wire/edge.go` | API-1 | -| `apps/control-plane/internal/wire/edge_server.go` | API-1 | -| `apps/control-plane/internal/wire/projection_sync.go` | API-1 | -| `apps/control-plane/internal/wire/edge_test.go` | API-1 | -| `apps/control-plane/internal/wire/edge_server_test.go` | API-1 | -| `apps/control-plane/cmd/control-plane/server.go` | API-1 | -| `apps/edge/internal/controlplane/connector.go` | API-2 | -| `apps/edge/internal/controlplane/connector_test.go` | API-2 | -| `apps/edge/internal/openai/principal_projection.go` | API-2 | -| `apps/edge/internal/openai/principal_projection_test.go` | API-2 | -| `apps/edge/internal/openai/server.go` | API-2 | -| `apps/edge/internal/input/manager.go` | API-2 | -| `apps/edge/internal/input/manager_test.go` | API-2 | -| `apps/edge/internal/bootstrap/runtime.go` | API-2 | -| `apps/edge/internal/bootstrap/runtime_connector_test.go` | API-2 | -| `apps/edge/internal/openai/principal.go` | API-3 | -| `apps/edge/internal/openai/routes.go` | API-3 | -| `apps/edge/internal/openai/identity_metering_test.go` | API-3 | -| `apps/edge/internal/openai/anthropic_surface_test.go` | API-3 | -| `agent-contract/inner/control-plane-edge-wire.md` | API-3 | -| `agent-contract/outer/openai-compatible-api.md` | API-3 | -| `agent-contract/outer/anthropic-compatible-api.md` | API-3 | -| `agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/CODE_REVIEW-cloud-G10.md` | API-1, API-2, API-3 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; fresh Go tests are required. - -1. `test -f agent-task/m-principal-provider-credential-slot-routing/01_principal_store/complete.log && test -f agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log` — both predecessors complete. -2. `command -v go && go version && command -v protoc && protoc --version && command -v protoc-gen-go && command -v protoc-gen-dart && command -v flutter && flutter --version` — required generators/toolchains resolve. -3. `mkdir -p .cache/go-build .cache/go-cache` — executable Go temp/cache paths exist. -4. `make proto && make proto-dart` — generated Go/Dart artifacts are current. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/... ./apps/edge/internal/controlplane ./apps/edge/internal/openai ./apps/edge/internal/input ./apps/edge/internal/bootstrap` — no vet findings. -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialstore ./apps/control-plane/internal/wire ./apps/edge/internal/controlplane ./apps/edge/internal/openai ./apps/edge/internal/input ./apps/edge/internal/bootstrap` — projection/auth lifecycle and races pass. -7. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache make test-control-plane-edge-wire` — CP↔Edge wire compatibility passes. -8. `make client-test` — generated Dart messages/imports remain valid. -9. `cd apps/client && flutter analyze` — client analysis has no findings. -10. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`. diff --git a/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/CODE_REVIEW-cloud-G08.md b/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/CODE_REVIEW-cloud-G08.md deleted file mode 100644 index f62f338..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/CODE_REVIEW-cloud-G08.md +++ /dev/null @@ -1,143 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/04+03_principal_routes, plan=1, tag=API - -## Archive Evidence Snapshot - -- Prior pair: `agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/plan_local_G08_0.log`, `agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/code_review_cloud_G09_0.log`. -- Verdict/evidence: implementation had not started; no verdict or verification output. -- Replan reason: prior plan claimed principal discovery/selection rollout while its authorization projection would traverse an unauthenticated transport. -- Roadmap carryover: PASS is foundation-only and must not check `model-discovery` or `explicit-selection`. - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G08.md` → `code_review_cloud_G08_1.log` and `PLAN-local-G07.md` → `plan_local_G07_1.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/04+03_principal_routes/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-1 Add principal-scoped dormant discovery | [ ] | -| API-2 Fix managed requests to one projected route | [ ] | -| API-3 Keep gated contracts honest | [ ] | - -## Implementation Checklist - -- [ ] Return only a verified-cache principal's active projected route IDs from OpenAI and Anthropic model-list variants, covering the S06 isolation fixtures without production activation. -- [ ] Resolve request model to one projected route and compose fixed provider/profile/upstream-model predicates plus stable slot metadata across initial and recovery dispatch, covering S07 no-fallback fixtures. -- [ ] Preserve unmanaged global/legacy behavior and prove managed unknown/inactive/cross-principal routes never fall back or dispatch. -- [ ] Keep contracts explicitly gated and run fresh focused/full Edge, dormant-activation, vet, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G08_1.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_local_G07_1.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/04+03_principal_routes/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Confirm no Roadmap Targets section exists and PASS cannot check S06/S07. -- Verify managed discovery and dispatch read one immutable principal route view. -- Confirm route predicates compose with stream/profile predicates and survive recovery re-resolution. -- Prove managed failures never enter global/legacy fallback while unmanaged behavior remains unchanged. -- Confirm no Connector/Runtime activation or secret-delivery logic entered this packet. - -## Verification Results - -Paste actual stdout/stderr beneath every command; do not summarize or reconstruct it. - -### API-1 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Managed.*Models|PrincipalRoute|UnmanagedModels'` - -_Pending._ - -### API-2 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'ManagedRoute|ExplicitSlot|NoFallback'` - -_Pending._ - -### API-3 - -`rg --sort path -n 'verified|managed|route_id|slot_id|fallback' agent-contract/outer/openai-compatible-api.md agent-contract/outer/anthropic-compatible-api.md` - -_Pending._ - -### Final Verification - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/complete.log' -print | wc -l)" -eq 1` -2. `mkdir -p .cache/go-build .cache/go-cache` -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/edge/internal/authprojection ./apps/edge/internal/openai ./apps/edge/internal/service` -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Managed|PrincipalRoute|ExplicitSlot|NoFallback|Anthropic'` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/authprojection ./apps/edge/internal/openai ./apps/edge/internal/service` -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/...` -7. `if rg --sort path -n 'PrincipalProjection' apps/control-plane/internal/wire/edge_server.go apps/edge/internal/controlplane/connector.go apps/edge/internal/bootstrap/runtime.go; then exit 1; else exit 0; fi` -8. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/PLAN-local-G07.md b/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/PLAN-local-G07.md deleted file mode 100644 index 9cc508b..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/PLAN-local-G07.md +++ /dev/null @@ -1,241 +0,0 @@ - - -# Principal Route Resolution Foundation - -## For the Implementing Agent - -Filling implementation-owned sections of `CODE_REVIEW-cloud-G08.md` is mandatory. Run every verification command, paste actual output, leave active files in place, and report ready for review; only code-review may finalize, rename logs, write `complete.log`, or archive. If blocked, record exact blocker evidence and resume conditions only in implementation-owned fields; do not ask the user, call user-input tools, create stop files, or classify next state. - -## Background - -Managed model discovery and explicit route selection should consume one immutable principal projection view. Because packet 03 intentionally leaves projection transport dormant until authenticated CP–Edge transport exists, this packet builds and tests the managed route behavior without enabling it in production or claiming S06/S07 completion. - -## Archive Evidence Snapshot - -- Prior pair: `agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/plan_local_G08_0.log`, `agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/code_review_cloud_G09_0.log`. -- Verdict/evidence: implementation had not started; no verdict or verification output. -- Replan reason: prior plan claimed principal discovery/selection rollout while its authorization projection would traverse an unauthenticated transport. -- Roadmap carryover: PASS is foundation-only and must not check `model-discovery` or `explicit-selection`. - -## Analysis - -### Files Read - -- `apps/edge/internal/openai/routes.go` -- `apps/edge/internal/openai/route_resolution.go` -- `apps/edge/internal/openai/chat_handler.go` -- `apps/edge/internal/openai/responses_handler.go` -- `apps/edge/internal/openai/anthropic_handler.go` -- `apps/edge/internal/openai/server.go` -- `apps/edge/internal/openai/openai_auth_routes_models_test.go` -- `apps/edge/internal/openai/provider_selection_test.go` -- `apps/edge/internal/openai/anthropic_surface_test.go` -- `apps/edge/internal/service/provider_pool.go` -- `apps/edge/internal/service/protocol_profile_test.go` -- `agent-contract/outer/openai-compatible-api.md` -- `agent-contract/outer/anthropic-compatible-api.md` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 잠금 해제). -- Foundation maps to S06 / `model-discovery` and S07 / `explicit-selection`, Evidence Map S04-S08, but lacks authenticated projection rollout evidence and therefore has no Roadmap Targets. -- Checklist covers principal list isolation, inactive omission, exact provider/profile/model candidate predicate, stable slot metadata, recovery predicate retention, and no legacy/alternate-slot fallback in a directly installed verified-cache fixture. - -### Verification Context - -- handoff 없음. Existing provider-pool `AcceptCandidate` is reapplied during queued/recovery resolution and is the deterministic no-fallback oracle. -- Local Go-only tests use a counting fake service; no provider credential or network runner is required. Workspace-local Go temp/cache paths are mandatory. -- Predecessor 03 is incomplete and will be archived on PASS; verification checks the narrow archived candidate. -- Confidence: high for dormant foundation, not for production rollout. - -### Test Coverage Gaps - -- Existing model tests use global catalogs and do not isolate principals. -- Existing selection tests allow provider-pool fallback and do not retain slot/route binding metadata. -- No test proves managed lookup refuses legacy fallback while unmanaged behavior remains unchanged. - -### Symbol References - -- Rename/remove 없음. -- Production `resolveRouteDispatch` calls: `chat_handler.go:40`, `responses_handler.go:40`, `anthropic_handler.go:49,98`; preserve legacy function and add a context-aware wrapper. -- `advertisedModels` is called at `routes.go:60`; only internal managed branch changes. -- Existing handler `AcceptCandidate` assignments must compose, not overwrite, the route predicate. - -### Split Judgment - -- Discovery and dispatch resolution share the same route-view invariant and stay atomic. -- Predecessor 03 `03+01,02_projection_auth`: active/archived completion missing, ambiguity 없음. -- Authenticated transport activation remains a separate secure-transport rollout; no Roadmap Targets section is present. - -### Scope Rationale - -- Do not modify CP store/wire, Connector/Runtime, provider queue accounting, secret delivery, or provider auth header injection. -- Managed behavior is reachable only through packet-03 verified-cache state; current production stays unmanaged/legacy. -- Contracts describe gated semantics, not an active CP-managed deployment mode. - -### Final Routing - -- `status=routed`, `evaluation_mode=isolated-reassessment`, finalizer=`finalize-task-policy.sh`, pair mode. -- Build closures all true for dormant route foundation; scores `2+1+1+1+2=G07`; base/route=`local-fit`, local, `PLAN-local-G07.md`. -- Review closures all true; scores `2+1+1+2+2=G08`; `official-review`, cloud, `gpt-5.6-sol` xhigh, `CODE_REVIEW-cloud-G08.md`. -- `large_indivisible_context=false`; risks=`boundary_contract`, `structured_interpretation`, `variant_product` (3); rework=0; integrity failure=false; no capability gap. - -## Dependencies and Execution Order - -1. `03+01,02_projection_auth` must complete; runtime accepts its archived `complete.log`. -2. Implement principal route list/lookup, then compose its fixed predicate in all three handlers. -3. No dependency absent from `04+03_principal_routes` may be introduced. - -## Implementation Checklist - -- [ ] Return only a verified-cache principal's active projected route IDs from OpenAI and Anthropic model-list variants, covering the S06 isolation fixtures without production activation. -- [ ] Resolve request model to one projected route and compose fixed provider/profile/upstream-model predicates plus stable slot metadata across initial and recovery dispatch, covering S07 no-fallback fixtures. -- [ ] Preserve unmanaged global/legacy behavior and prove managed unknown/inactive/cross-principal routes never fall back or dispatch. -- [ ] Keep contracts explicitly gated and run fresh focused/full Edge, dormant-activation, vet, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-1] Add principal-scoped dormant discovery - -**Problem:** `apps/edge/internal/openai/routes.go:60` always lists the global catalog and ignores authenticated principal context. - -**Solution:** When the packet-03 cache is managed, list only active routes for the request principal from one snapshot, sort by canonical route id, and use the same list for OpenAI and Anthropic shapes. Unmanaged mode retains current behavior. - -Before (`apps/edge/internal/openai/routes.go:60-66`): - -```go -models := s.advertisedModels() -if anthropic { - if err := validateAnthropicHeaders(r, false); err != nil { - writeAnthropicError(w, http.StatusBadRequest, "invalid_request_error", err.Error()) - return - } - writeAnthropicModels(w, models) -``` - -After: - -```go -models, err := s.advertisedModelsForPrincipal(r.Context()) -if err != nil { s.writeManagedRouteError(w, r, err); return } -``` - -**Modified Files and Checklist:** - -- [ ] `apps/edge/internal/authprojection/cache.go`: expose active route snapshots for exactly one principal. -- [ ] `apps/edge/internal/openai/principal_routes.go`: implement managed list/normalization/sorting/errors. -- [ ] `apps/edge/internal/openai/routes.go`: use managed list for both variants. -- [ ] `apps/edge/internal/openai/principal_routes_test.go`: cover two-principal isolation, inactive/ambiguous omission, ordering, aliases, and unmanaged compatibility. - -**Test Strategy:** Write `TestManagedModelsListIsPrincipalScoped`, `TestManagedAnthropicModelsListUsesRouteIDs`, `TestManagedModelsOmitInactiveRoutes`, and `TestUnmanagedModelsRetainGlobalCatalog`. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Managed.*Models|PrincipalRoute|UnmanagedModels'` passes. - -### [API-2] Fix managed requests to one projected route - -**Problem:** `apps/edge/internal/openai/route_resolution.go:103-115` resolves global model groups, and handlers may overwrite request-local candidate predicates. - -**Solution:** Add a context-aware wrapper. Managed mode resolves one principal route and returns route id, slot id, provider id, profile id, and upstream model; unmanaged mode calls the legacy resolver. Compose its predicate with stream/profile predicates so initial and recovery candidate resolution cannot change the binding. - -Required standard-library import: - -```go -import "context" -``` - -Before (`apps/edge/internal/openai/route_resolution.go:103-108`): - -```go -// resolveRouteDispatch returns fully-resolved dispatch params for model. -// Priority: provider-pool catalog → legacy model_routes → single-target fallback. -// Returns (dispatch, true) on success; (zero, false) when no target can be resolved. -func (s *Server) resolveRouteDispatch(model string) (routeDispatch, bool) { - // Provider-pool catalog takes highest priority. - if catalogEntry := s.findProviderPoolEntry(model); catalogEntry != nil { -``` - -After: - -```go -func (s *Server) resolveRouteDispatchForPrincipal(ctx context.Context, model string) (routeDispatch, error) { - if s.principalProjection.Managed() { return s.resolveProjectedRoute(ctx, model) } - dispatch, ok := s.resolveRouteDispatch(model) - if !ok { return routeDispatch{}, ErrRouteNotFound } - return dispatch, nil -} -``` - -**Modified Files and Checklist:** - -- [ ] `apps/edge/internal/openai/route_resolution.go`: add managed wrapper and route/slot facts while preserving legacy resolver. -- [ ] `apps/edge/internal/openai/principal_routes.go`: resolve one route, compose predicates, and attach trusted metadata. -- [ ] `apps/edge/internal/openai/chat_handler.go`: use wrapper and composed route/stream predicate. -- [ ] `apps/edge/internal/openai/responses_handler.go`: use wrapper and composed route/stream predicate. -- [ ] `apps/edge/internal/openai/anthropic_handler.go`: use wrapper and composed route/capability predicate. -- [ ] `apps/edge/internal/openai/principal_routes_test.go`: test exact candidate filtering, recovery retention, zero fallback, and all surfaces. - -**Test Strategy:** Write `TestManagedRouteSelectsOnlyBoundSlot`, `TestManagedRoutePredicateSurvivesRecovery`, `TestManagedRouteFailureDoesNotFallback`, and table cases for Chat/Responses/Messages/count_tokens. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'ManagedRoute|ExplicitSlot|NoFallback'` passes. - -### [API-3] Keep gated contracts honest - -**Problem:** contracts cannot describe principal-managed routing as available while no authenticated projection writer is wired. - -**Solution:** Document route-id selection and no-fallback semantics under an explicit “verified managed projection only” gate, and state that current deployments remain legacy until secure transport activation. - -Before (`apps/edge/internal/openai/anthropic_handler.go:49-54`): - -```go -dispatch, ok := s.resolveRouteDispatch(envelope.Model) -if !ok || !dispatch.ProviderPool { - writeAnthropicError(w, http.StatusBadRequest, "not_supported_error", "model does not resolve to a protocol profile") - return -} -``` - -After: - -```go -dispatch, err := s.resolveRouteDispatchForPrincipal(r.Context(), envelope.Model) -if err != nil || !dispatch.ProviderPool { s.writeAnthropicRouteError(w, err); return } -``` - -**Modified Files and Checklist:** - -- [ ] `agent-contract/outer/openai-compatible-api.md`: document verified-cache gate, route ids, and no fallback. -- [ ] `agent-contract/outer/anthropic-compatible-api.md`: document the same gated model-list/selection semantics. - -**Test Strategy:** No docs-only test; API-1/API-2 tests are executable contract evidence. - -**Verification:** `rg --sort path -n 'verified|managed|route_id|slot_id|fallback' agent-contract/outer/openai-compatible-api.md agent-contract/outer/anthropic-compatible-api.md` shows gated clauses. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `apps/edge/internal/authprojection/cache.go` | API-1 | -| `apps/edge/internal/openai/principal_routes.go` | API-1, API-2 | -| `apps/edge/internal/openai/routes.go` | API-1 | -| `apps/edge/internal/openai/route_resolution.go` | API-2 | -| `apps/edge/internal/openai/chat_handler.go` | API-2 | -| `apps/edge/internal/openai/responses_handler.go` | API-2 | -| `apps/edge/internal/openai/anthropic_handler.go` | API-2 | -| `apps/edge/internal/openai/principal_routes_test.go` | API-1, API-2 | -| `agent-contract/outer/openai-compatible-api.md` | API-3 | -| `agent-contract/outer/anthropic-compatible-api.md` | API-3 | -| `agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/CODE_REVIEW-cloud-G08.md` | API-1, API-2, API-3 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; fresh Go results are required. - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/complete.log' -print | wc -l)" -eq 1` — exactly one archived predecessor completion exists. -2. `mkdir -p .cache/go-build .cache/go-cache` — executable Go paths exist. -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/edge/internal/authprojection ./apps/edge/internal/openai ./apps/edge/internal/service` — no vet findings. -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Managed|PrincipalRoute|ExplicitSlot|NoFallback|Anthropic'` — focused fixtures pass. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/authprojection ./apps/edge/internal/openai ./apps/edge/internal/service` — affected suites pass. -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/...` — Edge regression suite passes. -7. `if rg --sort path -n 'PrincipalProjection' apps/control-plane/internal/wire/edge_server.go apps/edge/internal/controlplane/connector.go apps/edge/internal/bootstrap/runtime.go; then exit 1; else exit 0; fi` — unauthenticated runtime still has no activation. -8. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`. diff --git a/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/code_review_cloud_G09_0.log b/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/code_review_cloud_G09_0.log deleted file mode 100644 index 58fdb1e..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/code_review_cloud_G09_0.log +++ /dev/null @@ -1,145 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/04+03_principal_routes, plan=0, tag=API - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `model-discovery`: principal별 active route model list - - `explicit-selection`: request model의 단일 slot route 선택 및 no fallback -- Completion mode: check-on-pass - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G09.md` → `code_review_cloud_G09_0.log` and `PLAN-local-G08.md` → `plan_local_G08_0.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/04+03_principal_routes/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-1 Make model discovery principal-scoped | [ ] | -| API-2 Fix each request to one route and credential slot | [ ] | -| API-3 Keep public contracts aligned | [ ] | - -## Implementation Checklist - -- [ ] Return only the authenticated principal's active projected route IDs from OpenAI and Anthropic model-list variants. -- [ ] Resolve request model to one projected route and compose a fixed provider/profile/upstream-model candidate predicate plus stable slot metadata across initial and recovery dispatch. -- [ ] Reject unknown, ambiguous, disabled, revoked, expired, cross-principal, and failed-slot routes without legacy or alternate-slot fallback in managed mode. -- [ ] Update OpenAI/Anthropic contracts and run fresh isolated/full Edge tests, vet, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G09_0.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_local_G08_0.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/04+03_principal_routes/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Verify predecessor 03 completion and that managed discovery/selection read the same immutable projection view. -- Confirm managed-mode unknown/inactive/ambiguous routes never enter global catalog, legacy routes, or fallback target resolution. -- Inspect predicate composition so stream/profile predicates cannot overwrite provider/profile/upstream route fencing. -- Prove recovery re-resolution carries the same predicate and trusted `route_id`/`slot_id` metadata. -- Confirm no secret delivery/decrypt logic was pulled forward from Epic 3. - -## Verification Results - -Paste actual stdout/stderr beneath every command; do not summarize or reconstruct it. - -### API-1 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Managed.*Models|PrincipalRoute'` - -_Pending._ - -### API-2 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'ManagedRoute|ExplicitSlot|NoFallback'` - -_Pending._ - -### API-3 - -`rg --sort path -n "principal|route_id|slot_id|fallback" agent-contract/outer/openai-compatible-api.md agent-contract/outer/anthropic-compatible-api.md` - -_Pending._ - -### Final Verification - -1. `test -f agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/complete.log` -2. `mkdir -p .cache/go-build .cache/go-cache` -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/edge/internal/openai ./apps/edge/internal/service` -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Managed|PrincipalRoute|ExplicitSlot|NoFallback|Anthropic'` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai ./apps/edge/internal/service` -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/...` -7. `rg --sort path -n "principal|route_id|slot_id|fallback" agent-contract/outer/openai-compatible-api.md agent-contract/outer/anthropic-compatible-api.md` -8. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/plan_local_G08_0.log b/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/plan_local_G08_0.log deleted file mode 100644 index f917302..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/plan_local_G08_0.log +++ /dev/null @@ -1,245 +0,0 @@ - - -# Principal Model Discovery and Explicit Route Selection - -## For the Implementing Agent - -Filling the implementation-owned sections of `CODE_REVIEW-cloud-G09.md` is mandatory. Run every verification command, paste actual output/notes, keep the active pair, and report ready for review; only code-review finalizes, renames, writes `complete.log`, or archives. If blocked, record exact blocker evidence and resume condition only in implementation-owned fields; do not ask the user, invoke user-input tools, create stop files, or classify next state. - -## Background - -`/v1/models` currently lists the global provider catalog, and route resolution prioritizes global catalog then legacy routes/fallback. A projected principal can therefore neither discover only its authorized client route IDs nor force a request to remain on the one credential slot/profile/model binding selected by `model`. - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `model-discovery`: principal별 active route model list - - `explicit-selection`: request model의 단일 slot route 선택 및 no fallback -- Completion mode: check-on-pass - -## Analysis - -### Files Read - -- `apps/edge/internal/openai/routes.go` -- `apps/edge/internal/openai/route_resolution.go` -- `apps/edge/internal/openai/chat_handler.go` -- `apps/edge/internal/openai/responses_handler.go` -- `apps/edge/internal/openai/anthropic_handler.go` -- `apps/edge/internal/openai/server.go` -- `apps/edge/internal/openai/openai_auth_routes_models_test.go` -- `apps/edge/internal/openai/provider_selection_test.go` -- `apps/edge/internal/openai/anthropic_surface_test.go` -- `apps/edge/internal/service/provider_pool.go` -- `apps/edge/internal/service/protocol_profile_test.go` -- `agent-contract/outer/openai-compatible-api.md` -- `agent-contract/outer/anthropic-compatible-api.md` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 잠금 해제). -- Targets: S06 / `model-discovery`, S07 / `explicit-selection`. -- Evidence Map row: S04-S08의 principal discovery/no-fallback 근거 중 S06-S07. -- Checklist는 two-principal list isolation, disabled/revoked/expired omission, Claude-compatible route IDs, same-upstream/two-slot disambiguation, provider/profile/model predicate, recovery re-resolution에서도 fixed slot metadata 유지, failure 시 다른 slot/vendor 미선택을 직접 검증한다. - -### Verification Context - -- handoff 없음. OpenAI/Anthropic handlers, provider-pool predicate/re-resolution contract, outer contracts, Edge local smoke rules에서 명령을 도출했다. -- Local Go runner only; no real provider. Counting fake service evaluates `AcceptCandidate` and records metadata, including recovery re-entry. -- Go temp/cache is pinned to ignored workspace `.cache` because default cache is inaccessible and `/tmp` noexec. -- Precondition: `03+01,02_projection_auth/complete.log`; current active/archived completion missing, no ambiguity. Confidence: high. - -### Test Coverage Gaps - -- Existing model tests assert global catalog ordering/refresh, not principal filtering. -- Existing provider selection tests allow provider-pool fallback and do not carry credential slot/route IDs. -- Existing Anthropic tests route global models; no isolated model list or fixed-slot predicate tests. - -### Symbol References - -- No rename/remove. -- `resolveRouteDispatch` direct production call sites: `chat_handler.go:40`, `responses_handler.go:40`, `anthropic_handler.go:49,98`; preserve the existing function for legacy/direct tests and add a context-aware wrapper. -- `advertisedModels` call site: `routes.go:60`; change only this internal call to pass authenticated principal context. -- Existing provider-pool `AcceptCandidate` writers in chat, responses, Anthropic must compose rather than overwrite principal route predicates. - -### Split Judgment - -- Discovery and selection share one immutable per-principal route view: listing an ID that dispatch cannot resolve, or resolving an ID hidden from listing, is invalid. Keep S06/S07 atomic. -- Predecessor 03 = `03+01,02_projection_auth`; active `complete.log` missing, archived candidate 없음. Implementation waits for its exact complete log. -- Secret decryption/injection remains downstream; fixed `slot_id` is carried as dispatch metadata so Epic 3 can consume it without reselecting. - -### Scope Rationale - -- Do not modify provider queue scheduling/resource accounting. Existing request-local candidate predicates already reapply on initial and recovery resolution. -- Do not inject/decrypt credentials or remove legacy caller provider-auth forwarding; Epic 3 owns that cutover. -- CP store/projection wire and management mutations are predecessor/parallel packet responsibilities. - -### Final Routing - -- `status=routed`, `evaluation_mode=first-pass`, finalizer=`finalize-task-policy.sh`, pair mode. -- Build closures all true; scores `2+1+2+1+2=G08`; base/route=`local-fit`, local, canonical=`PLAN-local-G08.md`. -- Review closures all true; scores `2+1+2+2+2=G09`; `official-review`, cloud, `gpt-5.6-sol` xhigh, canonical=`CODE_REVIEW-cloud-G09.md`. -- `large_indivisible_context=false`; risks=`boundary_contract`, `structured_interpretation`, `variant_product` (3); rework=0; integrity failure=false; no capability gap. - -## Dependencies and Execution Order - -1. `03+01,02_projection_auth` must create `agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/complete.log`. -2. Add route-view lookup/listing, then use the same resolved record to construct candidate predicates and metadata on all three handlers. -3. Directory name `04+03_principal_routes` is the complete dependency declaration. - -## Implementation Checklist - -- [ ] Return only the authenticated principal's active projected route IDs from OpenAI and Anthropic model-list variants. -- [ ] Resolve request model to one projected route and compose a fixed provider/profile/upstream-model candidate predicate plus stable slot metadata across initial and recovery dispatch. -- [ ] Reject unknown, ambiguous, disabled, revoked, expired, cross-principal, and failed-slot routes without legacy or alternate-slot fallback in managed mode. -- [ ] Update OpenAI/Anthropic contracts and run fresh isolated/full Edge tests, vet, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-1] Make model discovery principal-scoped - -**Problem:** `apps/edge/internal/openai/routes.go:60` calls `s.advertisedModels()`, which reads the global catalog and ignores authenticated principal context. - -**Solution:** In managed mode, read the request principal and the exact current projection snapshot, filter active route records by principal and lifecycle/expiry, sort by stable route ID, and emit those IDs for both OpenAI and Anthropic shapes. Never merge legacy/global entries into a managed response. - -Before (`apps/edge/internal/openai/routes.go:60-66`): - -```go -models := s.advertisedModels() -if anthropic { - if err := validateAnthropicHeaders(r, false); err != nil { - writeAnthropicError(w, http.StatusBadRequest, "invalid_request_error", err.Error()) - return - } - writeAnthropicModels(w, models) -``` - -After: - -```go -models, err := s.advertisedModelsForPrincipal(r.Context()) -if err != nil { - s.writeManagedRouteError(w, r, err) - return -} -``` - -**Modified Files and Checklist:** - -- [ ] `apps/edge/internal/openai/principal_projection.go`: expose immutable active routes for one principal without leaking other principals. -- [ ] `apps/edge/internal/openai/principal_routes.go`: implement principal route list, normalization, deterministic sorting, and managed errors. -- [ ] `apps/edge/internal/openai/routes.go`: use principal-scoped discovery for both response variants. -- [ ] `apps/edge/internal/openai/principal_routes_test.go`: test two-principal isolation, lifecycle omission, aliases, ordering, and Claude-compatible IDs. - -**Test Strategy:** Write `TestManagedModelsListIsPrincipalScoped`, `TestManagedAnthropicModelsListUsesRouteIDs`, and `TestManagedModelsOmitInactiveOrAmbiguousRoutes`. Fixtures install one fresh snapshot with two principals and conflicting upstream model names. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Managed.*Models|PrincipalRoute'` passes. - -### [API-2] Fix each request to one route and credential slot - -**Problem:** `apps/edge/internal/openai/route_resolution.go:103-115` resolves a global model group and lets provider-pool admission choose any matching candidate; handlers can overwrite `AcceptCandidate` with surface/runtime predicates. - -**Solution:** Add `resolveRouteDispatchForPrincipal(ctx, model)` that, in managed mode, resolves exactly one projected route and returns `route_id`, `slot_id`, provider id, profile id, upstream model, and pool dispatch facts. Compose its candidate predicate with stream/profile predicates; attach route/slot IDs to trusted metadata. Managed lookup failures return an error and never call legacy resolution. Because `AcceptCandidate` is copied into recovery requests, the fixed predicate applies on every re-resolution. - -Before (`apps/edge/internal/openai/route_resolution.go:103-108`): - -```go -// resolveRouteDispatch returns fully-resolved dispatch params for model. -// Priority: provider-pool catalog → legacy model_routes → single-target fallback. -func (s *Server) resolveRouteDispatch(model string) (routeDispatch, bool) { - // Provider-pool catalog takes highest priority. - if catalogEntry := s.findProviderPoolEntry(model); catalogEntry != nil { -``` - -After managed wrapper: - -```go -func (s *Server) resolveRouteDispatchForPrincipal(ctx context.Context, model string) (routeDispatch, error) { - if s.principalProjection.Managed() { - return s.resolveProjectedRoute(ctx, model) - } - dispatch, ok := s.resolveRouteDispatch(model) - if !ok { return routeDispatch{}, ErrRouteNotFound } - return dispatch, nil -} -``` - -**Modified Files and Checklist:** - -- [ ] `apps/edge/internal/openai/route_resolution.go`: extend dispatch facts and add context-aware managed wrapper while preserving legacy resolver. -- [ ] `apps/edge/internal/openai/principal_routes.go`: resolve one principal route, construct fixed candidate predicate, compose predicates, and attach trusted metadata. -- [ ] `apps/edge/internal/openai/chat_handler.go`: use managed wrapper and compose route predicate with stream-gate predicate. -- [ ] `apps/edge/internal/openai/responses_handler.go`: use managed wrapper and compose route predicate with stream-gate predicate. -- [ ] `apps/edge/internal/openai/anthropic_handler.go`: use managed wrapper and compose route predicate with Messages capability predicate. -- [ ] `apps/edge/internal/openai/principal_routes_test.go`: assert exact provider/profile/model predicate, slot metadata, and no alternate selection on errors/recovery. - -**Test Strategy:** Write `TestManagedRouteSelectsOnlyBoundSlot`, `TestManagedRouteCandidatePredicateSurvivesRecovery`, `TestManagedRouteFailureDoesNotFallback`, and table tests for Chat, Responses, Anthropic Messages/count_tokens. Use two routes sharing upstream model but different slot IDs and a fake provider pool with candidates in adverse order. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'ManagedRoute|ExplicitSlot|NoFallback'` passes. - -### [API-3] Keep public contracts aligned - -**Problem:** outer contracts describe global models/legacy route behavior and do not state managed principal isolation or exact slot no-fallback semantics. - -**Solution:** Document route IDs as the `model` selector, principal-scoped listing, managed-mode error precedence, and the invariant that retry/recovery may re-resolve execution capacity but may not change credential slot/profile/model binding. - -Before (`apps/edge/internal/openai/anthropic_handler.go:49-54`): - -```go -dispatch, ok := s.resolveRouteDispatch(envelope.Model) -if !ok || !dispatch.ProviderPool { - writeAnthropicError(w, http.StatusBadRequest, "not_supported_error", "model does not resolve to a protocol profile") - return -} -``` - -After: - -```go -dispatch, err := s.resolveRouteDispatchForPrincipal(r.Context(), envelope.Model) -if err != nil || !dispatch.ProviderPool { - s.writeAnthropicRouteError(w, err) - return -} -``` - -**Modified Files and Checklist:** - -- [ ] `agent-contract/outer/openai-compatible-api.md`: document managed `/v1/models` and explicit route selection. -- [ ] `agent-contract/outer/anthropic-compatible-api.md`: document Anthropic model-list variant and fixed route semantics. - -**Test Strategy:** No docs-only test. API-1/API-2 tests are executable evidence for every documented behavior. - -**Verification:** `rg --sort path -n "principal|route_id|slot_id|fallback" agent-contract/outer/openai-compatible-api.md agent-contract/outer/anthropic-compatible-api.md` shows the new contract clauses in stable path order. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `apps/edge/internal/openai/principal_projection.go` | API-1 | -| `apps/edge/internal/openai/principal_routes.go` | API-1, API-2 | -| `apps/edge/internal/openai/routes.go` | API-1 | -| `apps/edge/internal/openai/route_resolution.go` | API-2 | -| `apps/edge/internal/openai/chat_handler.go` | API-2 | -| `apps/edge/internal/openai/responses_handler.go` | API-2 | -| `apps/edge/internal/openai/anthropic_handler.go` | API-2 | -| `apps/edge/internal/openai/principal_routes_test.go` | API-1, API-2 | -| `agent-contract/outer/openai-compatible-api.md` | API-3 | -| `agent-contract/outer/anthropic-compatible-api.md` | API-3 | -| `agent-task/m-principal-provider-credential-slot-routing/04+03_principal_routes/CODE_REVIEW-cloud-G09.md` | API-1, API-2, API-3 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; Go results must be fresh. - -1. `test -f agent-task/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/complete.log` — predecessor complete. -2. `mkdir -p .cache/go-build .cache/go-cache` — executable temp/cache paths exist. -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/edge/internal/openai ./apps/edge/internal/service` — no vet findings. -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai -run 'Managed|PrincipalRoute|ExplicitSlot|NoFallback|Anthropic'` — focused isolation/selection suite passes. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/internal/openai ./apps/edge/internal/service` — full affected suites pass. -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/edge/...` — Edge regression suite passes. -7. `rg --sort path -n "principal|route_id|slot_id|fallback" agent-contract/outer/openai-compatible-api.md agent-contract/outer/anthropic-compatible-api.md` — contract clauses are present. -8. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`. diff --git a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/CODE_REVIEW-cloud-G06.md b/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/CODE_REVIEW-cloud-G06.md deleted file mode 100644 index cb55990..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/CODE_REVIEW-cloud-G06.md +++ /dev/null @@ -1,135 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/05+01,02_management_core, plan=2, tag=API - -## Archive Evidence Snapshot - -- Parent pair: `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_local_G07_1.log`, `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G08_1.log`. -- Verdict/evidence: implementation had not started; no verdict or verification output. -- Refinement reason: the in-process service and host-local first-principal bootstrap are independently implementable and verifiable; bootstrap moved to sibling `06+01,02_host_local_bootstrap`. -- Roadmap carryover: this remains a preparatory packet. PASS must not check `credential-management`; S08 requires S09 at-rest sealer and S10 confidential Client transport rollout. - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G06.md` → `code_review_cloud_G06_2.log` and `PLAN-local-G06.md` → `plan_local_G06_2.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/05+01,02_management_core/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-1 Add the in-process management core | [ ] | -| API-3 Keep the service dormant on the plaintext boundary | [ ] | - -## Implementation Checklist - -- [ ] Add an in-process principal-authenticated management service with revision authorization, secret-blind records, and an injected-but-unimplemented `SecretSealer` boundary. -- [ ] Prove own-principal lifecycle, cross-principal denial, stale revision conflict, missing-sealer failure, and raw-secret redaction with deterministic tests. -- [ ] Prove service construction has no network registration side effect and leaves the plaintext ClientServer contract unchanged. -- [ ] Run fresh race, Control Plane regression, archive-predecessor, structural absence, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G06_2.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_local_G06_2.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/05+01,02_management_core/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Confirm no Roadmap Targets section exists and PASS cannot check S08. -- Verify service authorization, revision CAS, missing-sealer fail-closed behavior, and secret-blind DTOs. -- Confirm service construction has no ClientServer or protobuf registration side effect. -- Prove raw IOP/provider secrets are absent from response DTOs, logs, errors, and persisted service inputs. -- Confirm no concrete key loading/encryption or network credential transport entered this packet. - -## Verification Results - -Paste actual stdout/stderr beneath every command; do not summarize or reconstruct it. - -### API-1 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops` - -_Pending._ - -### API-3 - -`if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` - -_Pending._ - -### Final Verification - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/01_principal_store/complete.log' -print | wc -l)" -eq 1 && test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log' -print | wc -l)" -eq 1` -2. `mkdir -p .cache/go-build .cache/go-cache` -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialops` -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` -6. `if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` -7. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/PLAN-local-G06.md b/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/PLAN-local-G06.md deleted file mode 100644 index 41236e3..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/PLAN-local-G06.md +++ /dev/null @@ -1,154 +0,0 @@ - - -# Credential Management Core - -## For the Implementing Agent - -Filling implementation-owned sections of `CODE_REVIEW-cloud-G06.md` is mandatory. Run every verification command, paste actual output, keep active files in place, and report ready for review; only code-review may finalize, rename logs, write `complete.log`, or archive. If blocked, record exact blocker evidence and resume conditions only in implementation-owned fields; do not ask the user, call user-input tools, create stop files, or classify next state. - -## Background - -Control Plane needs a principal-scoped in-process management service. The current `/client` WebSocket is plaintext and unauthenticated, so this packet keeps the service dormant, defines an injected `SecretSealer` boundary, and does not expose a remote management operation or claim S08 completion. - -## Archive Evidence Snapshot - -- Parent pair: `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_local_G07_1.log`, `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G08_1.log`. -- Verdict/evidence: implementation had not started; no verdict or verification output. -- Refinement reason: the in-process service and host-local first-principal bootstrap are independently implementable and verifiable; bootstrap moved to sibling `06+01,02_host_local_bootstrap`. -- Roadmap carryover: this remains a preparatory packet. PASS must not check `credential-management`; S08 requires S09 at-rest sealer and S10 confidential Client transport rollout. - -## Analysis - -### Files Read - -- `apps/control-plane/internal/wire/client.go` -- `apps/control-plane/internal/wire/client_test.go` -- `proto/iop/control.proto` -- `apps/client/lib/iop_wire/client_wire_client.dart` -- `apps/client/lib/iop_wire/parser_map.dart` -- `agent-contract/inner/client-control-plane-wire.md` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 잠금 해제). -- This foundation maps to S08 / `credential-management`, but intentionally lacks the confidential remote operation required for full S08. -- Checklist covers principal/revision authorization, secret-blind records, fail-closed missing sealer behavior, lifecycle isolation, and proof that creating the service does not register a plaintext network operation. - -### Verification Context - -- No handoff exists. The SDD requires principal clients to authenticate over TLS and forbids credential-bearing operations on the current plain WebSocket. -- Go 1.26.2 linux/arm64. Tests use a temp SQLite store, fake sealer, injected logger/random reader, and workspace-local Go temp/cache paths. -- Preconditions 01 and 02 are incomplete; runtime resolves their archived completion artifacts before implementation. -- No external key manager, TLS runner, Flutter change, or provider is required. Confidence: high. - -### Test Coverage Gaps - -- No principal/revision authorization service exists. -- Current tests do not cover own-principal lifecycle, cross-principal denial, stale revision conflicts, missing sealer failure, or secret-blind responses. -- Existing ClientServer tests cover hello only; the new service must have no network registration side effect. - -### Symbol References - -- Rename/remove 없음. -- `wire.NewClientServer`, Dart client/parser call sites, and Control Plane server wiring remain unchanged. - -### Split Judgment - -- This child owns the reusable authorization/CAS service and its dormant secure-boundary guard. -- Sibling `06+01,02_host_local_bootstrap` independently owns the host-local first-principal CLI and structural absence check. -- Further separation would split service behavior from the tests and fail-closed sealer rule required for its PASS. - -### Scope Rationale - -- Do not modify `proto/iop/control.proto`, ClientServer, Dart client/parser, configs, CLI registration, or Control Plane server wiring. -- Define a `SecretSealer` interface only; tests use a fake. Do not add AES/key-file/deployment-key implementation. -- Do not add remote bootstrap, credential reveal, or plaintext network payloads. - -### Final Routing - -- `status=routed`, `evaluation_mode=isolated-reassessment`, finalizer=`finalize-task-policy.sh`, pair mode. -- Build closures all true; scores `1+2+1+1+1=G06`; base/route=`local-fit`, lane=`local`, canonical=`PLAN-local-G06.md`. -- Review closures all true; scores `1+2+1+1+1=G06`; route=`official-review`, lane=`cloud`, model=`gpt-5.6-sol` xhigh, canonical=`CODE_REVIEW-cloud-G06.md`. -- `large_indivisible_context=false`; risks=`temporal_state`, `concurrent_consistency`, `boundary_contract` (3); rework=0; integrity failure=false; capability gap 없음. - -## Dependencies and Execution Order - -1. `01_principal_store` and `02+01_credential_catalog` must complete; runtime accepts their archived `complete.log` files. -2. Implement authentication/ownership/CAS mapping, then the injected sealer boundary and secret-blind responses. -3. No dependency absent from `05+01,02_management_core` may be introduced. - -## Implementation Checklist - -- [ ] Add an in-process principal-authenticated management service with revision authorization, secret-blind records, and an injected-but-unimplemented `SecretSealer` boundary. -- [ ] Prove own-principal lifecycle, cross-principal denial, stale revision conflict, missing-sealer failure, and raw-secret redaction with deterministic tests. -- [ ] Prove service construction has no network registration side effect and leaves the plaintext ClientServer contract unchanged. -- [ ] Run fresh race, Control Plane regression, archive-predecessor, structural absence, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-1] Add the in-process management core - -**Problem:** `apps/control-plane/internal/wire/client.go:62-73` has only hello, and there is no reusable service enforcing principal identity, target ownership, expected revision, or secret-blind response types. - -**Solution:** Add `credentialops.Service` over the store. It hashes the presented IOP token in process, resolves the principal, authorizes target equality, maps CAS/lifecycle errors, and exposes token/slot/route operations. Provider create/rotate receives plaintext only at the method boundary, requires an injected `SecretSealer`, clears the local byte slice on return, and passes only an opaque envelope to the store. The production packet supplies no sealer or network adapter. - -Before (`apps/control-plane/internal/wire/client.go:62-73`): - -```go -proto_socket.AddRequestListenerTyped(&client.Communicator, func(req *iop.ClientHelloRequest) (*iop.ClientHelloResponse, error) { - return &iop.ClientHelloResponse{Ready: true, Protocol: Protocol}, nil -}) -``` - -After service-only boundary: - -```go -type SecretSealer interface { - Seal(context.Context, []byte, SecretContext) (credentialstore.EncryptedSecretEnvelope, error) -} -func (s *Service) RotateSlot(ctx context.Context, rawIOPToken []byte, input RotateSlotInput) (SlotRecord, error) -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/internal/credentialops/service.go`: implement authentication, ownership, CAS, lifecycle mapping, secret-blind DTOs, and sealer interface. -- [ ] `apps/control-plane/internal/credentialops/service_test.go`: cover own/cross-principal operations, stale revision, lifecycle, missing sealer, fake-sealer ciphertext handoff, captured-log redaction, and absence of network side effects. - -**Test Strategy:** Write `TestServiceScopesOperationsToAuthenticatedPrincipal`, `TestServiceRejectsCrossPrincipalTargets`, `TestServiceRejectsStaleRevision`, `TestServiceRequiresSealerForSecretMutation`, and `TestServiceResponsesAreSecretBlind` using the temp store and deterministic fake sealer. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops` passes. - -### [API-3] Keep the service dormant on the plaintext boundary - -**Problem:** a future service constructor could register credential operations on the current unauthenticated ClientServer as a side effect. - -**Solution:** Keep `credentialops.Service` transport-neutral and add a deterministic test that constructing it does not mutate or register against the ClientServer. Missing sealer behavior remains fail-closed. - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/internal/credentialops/service_test.go`: prove no network registration side effect and missing sealer failure. - -**Test Strategy:** Exercise the service directly without a wire server and verify no listener or generated credential message is required. - -**Verification:** `if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` passes with no matches. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `apps/control-plane/internal/credentialops/service.go` | API-1 | -| `apps/control-plane/internal/credentialops/service_test.go` | API-1, API-3 | -| `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/CODE_REVIEW-cloud-G06.md` | API-1, API-3 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; fresh Go results are required. - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/01_principal_store/complete.log' -print | wc -l)" -eq 1 && test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log' -print | wc -l)" -eq 1` — both archived predecessors exist exactly once. -2. `mkdir -p .cache/go-build .cache/go-cache` — executable Go paths exist. -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialops` — no vet findings. -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops` — service lifecycle and race tests pass. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` — Control Plane regression suite passes. -6. `if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` — no plaintext management wire was added. -7. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`. diff --git a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G08_1.log b/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G08_1.log deleted file mode 100644 index af7e159..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G08_1.log +++ /dev/null @@ -1,143 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/05+01,02_management_ops, plan=1, tag=API - -## Archive Evidence Snapshot - -- Prior pair: `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_ops/plan_cloud_G10_0.log`, `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_ops/code_review_cloud_G10_0.log`. -- Verdict/evidence: implementation had not started; no verdict or verification output. -- Replan reason: the previous plan sent raw IOP/provider credentials on the current plaintext Client WebSocket and implemented part of Epic-3 at-rest protection while claiming only S08. -- Roadmap carryover: this is a preparatory service/CLI packet. PASS must not check `credential-management`; S08 requires S09 at-rest sealer and S10 confidential Client transport rollout. - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G08.md` → `code_review_cloud_G08_1.log` and `PLAN-local-G07.md` → `plan_local_G07_1.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/05+01,02_management_ops/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-1 Add the in-process management core | [ ] | -| API-2 Add host-local first-principal bootstrap | [ ] | -| API-3 Guard the secure-transport boundary | [ ] | - -## Implementation Checklist - -- [ ] Add an in-process principal-authenticated management service with revision authorization, secret-blind records, and an injected-but-unimplemented `SecretSealer` boundary. -- [ ] Add a host-local-only first-principal/bootstrap CLI that emits the initial raw IOP token exactly once and never logs or persists it. -- [ ] Prove own-principal lifecycle, cross-principal denial, stale revision conflict, one-time output, restart persistence, and raw-secret redaction with deterministic tests. -- [ ] Prove no management/bootstrap protobuf, ClientServer listener, Dart method, or plaintext network activation was added; leave S08 completion for S09/S10 rollout. -- [ ] Run fresh race, Control Plane regression, archive-predecessor, structural absence, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G08_1.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_local_G07_1.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_ops/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/05+01,02_management_ops/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Confirm no Roadmap Targets section exists and PASS cannot check S08. -- Verify service authorization, revision CAS, missing-sealer fail-closed, and secret-blind DTOs. -- Confirm bootstrap is direct host CLI, refuses an existing principal, and emits/logs raw token only as specified. -- Prove proto, ClientServer, Dart client/parser, and server wiring remain unchanged. -- Confirm no concrete key loading/encryption or network credential transport was pulled into this packet. - -## Verification Results - -Paste actual stdout/stderr beneath every command; do not summarize or reconstruct it. - -### API-1 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops` - -_Pending._ - -### API-2 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/cmd/control-plane -run 'PrincipalBootstrap|Credential'` - -_Pending._ - -### API-3 - -`if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` - -_Pending._ - -### Final Verification - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/01_principal_store/complete.log' -print | wc -l)" -eq 1 && test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log' -print | wc -l)" -eq 1` -2. `mkdir -p .cache/go-build .cache/go-cache` -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialops ./apps/control-plane/cmd/control-plane` -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops ./apps/control-plane/cmd/control-plane` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` -6. `if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` -7. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G10_0.log b/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G10_0.log deleted file mode 100644 index 305874b..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G10_0.log +++ /dev/null @@ -1,147 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/05+01,02_management_ops, plan=0, tag=API - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `credential-management`: host-local bootstrap 및 principal-scoped management operations -- Completion mode: check-on-pass - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G10.md` → `code_review_cloud_G10_0.log` and `PLAN-cloud-G10.md` → `plan_cloud_G10_0.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/05+01,02_management_ops/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-1 Centralize authorization and sealing | [ ] | -| API-2 Expose typed authenticated wire operations | [ ] | -| API-3 Add host-local bootstrap only | [ ] | - -## Implementation Checklist - -- [ ] Add a principal-authenticated credential-operation service and host-local key-file sealer that never gives plaintext to the repository. -- [ ] Add typed Client-Control Plane management requests/responses for create/list/update/rotate/disable/revoke with principal and revision authorization. -- [ ] Add a host-local-only bootstrap CLI that emits the first raw IOP token once and has no remote wire equivalent. -- [ ] Update generated Go/Dart code, Dart client/parser methods, config, and the inner wire contract. -- [ ] Prove bootstrap and every operation, cross-principal denial, CAS conflict, ciphertext persistence, and secret non-disclosure with fresh Go/Dart tests. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G10_0.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_cloud_G10_0.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_ops/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/05+01,02_management_ops/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Verify both predecessor complete logs and confirm management auth reads the durable token store directly. -- Inspect every operation for principal equality, expected revision, stable error mapping, and no cross-principal existence leak. -- Confirm plaintext provider credentials cross only the service→sealer boundary and repository input is ciphertext envelope only. -- Confirm first-principal bootstrap is direct host CLI with no protobuf request equivalent and one-time stdout token behavior. -- Re-run Go race and Dart parser/client evidence; inspect logs/errors/list records for raw secrets. - -## Verification Results - -Paste actual stdout/stderr beneath every command; do not summarize or reconstruct it. - -### API-1 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops` - -_Pending._ - -### API-2 - -`make proto && make proto-dart && GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/wire ./apps/control-plane/cmd/control-plane && make client-test` - -_Pending._ - -### API-3 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/cmd/control-plane -run 'Bootstrap|Credential|Config'` - -_Pending._ - -### Final Verification - -1. `test -f agent-task/m-principal-provider-credential-slot-routing/01_principal_store/complete.log && test -f agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log` -2. `command -v go && go version && command -v protoc && protoc --version && command -v protoc-gen-go && command -v protoc-gen-dart && command -v flutter && flutter --version` -3. `mkdir -p .cache/go-build .cache/go-cache` -4. `make proto && make proto-dart` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/...` -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops ./apps/control-plane/internal/credentialstore ./apps/control-plane/internal/wire ./apps/control-plane/cmd/control-plane` -7. `make client-test` -8. `cd apps/client && flutter analyze` -9. `if rg --sort path -n 'Bootstrap.*Request|bootstrap.*request' proto/iop/control.proto agent-contract/inner/client-control-plane-wire.md; then exit 1; else exit 0; fi` -10. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_cloud_G10_0.log b/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_cloud_G10_0.log deleted file mode 100644 index 0880c06..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_cloud_G10_0.log +++ /dev/null @@ -1,273 +0,0 @@ - - -# Credential Management Operations - -## For the Implementing Agent - -Filling the implementation-owned sections of `CODE_REVIEW-cloud-G10.md` is mandatory. Run every verification command, paste actual output/notes, keep the active pair in place, and report ready for review; only code-review may finalize, rename logs, write `complete.log`, or archive. If blocked, record exact blocker evidence, attempted commands/output, and resume condition only in implementation-owned fields; do not ask the user, invoke user-input tools, create stop files, or classify next state. - -## Background - -Control Plane currently exposes only hello/status wire behavior and a `serve` CLI command. The approved design requires a host-local bootstrap path plus authenticated principal-scoped create/list/update/rotate/disable/revoke operations, with raw IOP/provider secrets accepted or emitted only at the relevant one-time boundary. - -## Roadmap Targets - -- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md` -- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md) -- Task ids: - - `credential-management`: host-local bootstrap 및 principal-scoped management operations -- Completion mode: check-on-pass - -## Analysis - -### Files Read - -- `proto/iop/control.proto` -- `proto/gen/iop/control.pb.go` -- `apps/client/lib/gen/proto/iop/control.pb.dart` -- `apps/client/lib/gen/proto/iop/control.pbenum.dart` -- `apps/client/lib/gen/proto/iop/control.pbjson.dart` -- `apps/client/lib/gen/proto/iop/control.pbserver.dart` -- `apps/control-plane/cmd/control-plane/main.go` -- `apps/control-plane/cmd/control-plane/server.go` -- `apps/control-plane/cmd/control-plane/config_test.go` -- `apps/control-plane/internal/wire/client.go` -- `apps/control-plane/internal/wire/client_test.go` -- `apps/client/lib/iop_wire/client_wire_client.dart` -- `apps/client/lib/iop_wire/parser_map.dart` -- `apps/client/test/iop_wire/client_wire_client_test.dart` -- `apps/client/test/iop_wire/parser_map_test.dart` -- `apps/client/test/iop_wire/generated_proto_import_test.dart` -- `configs/control-plane.yaml` -- `agent-contract/inner/client-control-plane-wire.md` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 잠금 해제). -- Target: S08 / `credential-management`. -- Evidence Map row: S04-S08의 management authorization 근거 중 S08. -- Checklist는 remote bootstrap 부재, host-local first principal/token issuance, authenticated principal-only token/slot/route mutations, optimistic revision, bootstrap/create/list/update/rotate/disable/revoke, cross-principal rejection, raw secret input/one-time output 및 list/log 비노출을 검증한다. - -### Verification Context - -- handoff 없음. existing Cobra/config, client WS parser, protobuf generation, client-control-plane contract, local CP/client test profiles에서 검증을 도출했다. -- Tools: Go 1.26.2, protoc 29.3, Go/Dart generators present, Flutter 3.41.5/Dart 3.11.3. `make -n proto proto-dart` confirms canonical generation commands. -- Preconditions: 01 and 02 complete logs. No external provider or running shared service is required; loopback WS and temp SQLite/key files suffice. -- Default Go temp/cache is unusable and `/tmp` noexec, so ignored workspace `.cache` paths are mandatory. Confidence: high. - -### Test Coverage Gaps - -- ClientServer parser map recognizes only hello request/response; no authenticated management message or authorization test exists. -- CLI has only `serve`; no host-local bootstrap or stdout/log secret hygiene test exists. -- Client Dart parser/method tests know only hello. -- No encryption ingress boundary exists between plaintext provider credential input and opaque store envelope. - -### Symbol References - -- No rename/remove. -- `rootCmd` adds commands at `main.go:61` and existing `serveCmd` remains. -- `wire.NewClientServer` call sites: `server.go:42` and `client_test.go`; preserve constructor compatibility through options. -- Dart `ClientWireClient` public hello method remains source-compatible; management methods are additive. - -### Split Judgment - -- Host CLI and authenticated wire operations share the same authorization/service/sealing boundary; splitting would duplicate or temporarily bypass the raw-secret invariant. Keep them atomic. -- Predecessor 01 `01_principal_store`: missing active `complete.log`, no archived candidate. -- Predecessor 02 `02+01_credential_catalog`: missing active `complete.log`, no archived candidate. -- This packet can PASS without projection/auth packet 03 because it authenticates management requests directly against the durable token store; later projection observes the transactionally bumped generation. - -### Scope Rationale - -- Implement only the sealing ingress needed to hand ciphertext envelopes to the packet-02 store: AES-256-GCM with a host-local external key file and non-secret key id. Do not claim or check Epic-3 `secret-at-rest`; key rotation policy, restart delivery, Edge decrypt, execution-time header injection, and plaintext zeroization evidence remain Epic 3. -- No remote bootstrap operation is added. Bootstrap opens DB/key locally from the Control Plane process command. -- No UI screens are added; Dart wire support is the typed client contract only. -- Roadmap/spec/SDD and central Agent-Ops files remain untouched. - -### Final Routing - -- `status=routed`, `evaluation_mode=first-pass`, finalizer=`finalize-task-policy.sh`, pair mode. -- Build closures all true; scores `2+2+2+2+2=G10`; base/route=`grade-boundary`, cloud, canonical=`PLAN-cloud-G10.md`. -- Review closures all true; scores `2+2+2+2+2=G10`; `official-review`, cloud, `gpt-5.6-sol` xhigh, canonical=`CODE_REVIEW-cloud-G10.md`. -- `large_indivisible_context=false`; risks=`temporal_state`, `concurrent_consistency`, `boundary_contract`, `variant_product` (4), risk boundary matched but grade basis retained; rework=0; integrity failure=false; no capability gap. - -## Dependencies and Execution Order - -1. `01_principal_store` must create `agent-task/m-principal-provider-credential-slot-routing/01_principal_store/complete.log`. -2. `02+01_credential_catalog` must create `agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log`. -3. Implement service/sealer, then WS operations/client, then host-local CLI on the same service. -4. No dependency absent from `05+01,02_management_ops` may be added. - -## Implementation Checklist - -- [ ] Add a principal-authenticated credential-operation service and host-local key-file sealer that never gives plaintext to the repository. -- [ ] Add typed Client-Control Plane management requests/responses for create/list/update/rotate/disable/revoke with principal and revision authorization. -- [ ] Add a host-local-only bootstrap CLI that emits the first raw IOP token once and has no remote wire equivalent. -- [ ] Update generated Go/Dart code, Dart client/parser methods, config, and the inner wire contract. -- [ ] Prove bootstrap and every operation, cross-principal denial, CAS conflict, ciphertext persistence, and secret non-disclosure with fresh Go/Dart tests. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-1] Centralize authorization and sealing - -**Problem:** `apps/control-plane/internal/wire/client.go:37-46` parses only hello messages, and there is no service that authenticates a durable principal token or seals provider input before storage. - -**Solution:** Add `credentialops.Service` over the credential store. Authenticate raw IOP tokens by SHA-256 lookup, authorize every target principal against that identity, require expected revision for mutations, and return typed stable errors. Add an AES-256-GCM `Sealer` loaded from a base64 32-byte host-local key file; key id/nonce/ciphertext only cross into `credentialstore`. - -Before (`apps/control-plane/internal/wire/client.go:37-46`): - -```go -parserMap := proto_socket.ParserMap{ - proto_socket.TypeNameOf(&iop.ClientHelloRequest{}): func(b []byte) (proto.Message, error) { - req := &iop.ClientHelloRequest{} - return req, proto.Unmarshal(b, req) - }, -``` - -After service boundary: - -```go -principal, err := svc.Authenticate(ctx, rawIOPToken) -if err != nil { return ErrUnauthenticated } -if principal.ID != input.PrincipalID { return ErrForbidden } -envelope, err := svc.Sealer.Seal(input.ProviderSecret) -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/internal/credentialops/sealer.go`: load/validate key file and seal with random nonce/AAD; never log key/plaintext. -- [ ] `apps/control-plane/internal/credentialops/sealer_test.go`: assert round-trip only in test helper, nonce uniqueness, missing/invalid key failures, ciphertext-only store input. -- [ ] `apps/control-plane/internal/credentialops/service.go`: authenticate, authorize, map lifecycle/CAS errors, and expose typed token/slot/route operations. -- [ ] `apps/control-plane/internal/credentialops/service_test.go`: cover own-principal success, cross-principal denial, lifecycle, CAS, one-time outputs, and captured log redaction. - -**Test Strategy:** Write `TestServiceAuthenticatesDigestAndScopesPrincipal`, `TestServiceRejectsCrossPrincipalOperations`, `TestServiceCASConflicts`, `TestSealerRejectsMissingKey`, and `TestProviderSecretIsStoredOnlyAsCiphertext`. Use temp key/SQLite files and injected logger/random reader. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops` passes. - -### [API-2] Expose typed authenticated wire operations - -**Problem:** `apps/control-plane/internal/wire/client.go:62-73` only handles hello and reports ready without an authenticated management surface. - -**Solution:** Add additive protobuf messages for typed token/slot/route operations and stable status/error fields. Each management request includes the caller IOP token as input-only auth material; the server passes it directly to `credentialops.Service`, never logs it, and response/list types omit secrets. Only create-token returns a one-time token field. Extend Go/Dart parser maps and Dart client methods. - -Before (`apps/control-plane/internal/wire/client.go:62-73`): - -```go -proto_socket.AddRequestListenerTyped(&client.Communicator, func(req *iop.ClientHelloRequest) (*iop.ClientHelloResponse, error) { - logger.Info("client hello request received", - zap.String("client_id", req.ClientId), - zap.String("client_version", req.ClientVersion), - ) - return &iop.ClientHelloResponse{Ready: true, Protocol: Protocol}, nil -}) -``` - -After: - -```go -proto_socket.AddRequestListenerTyped(&client.Communicator, func(req *iop.CredentialOperationRequest) (*iop.CredentialOperationResponse, error) { - return handleCredentialOperation(context.Background(), operations, req), nil -}) -``` - -**Modified Files and Checklist:** - -- [ ] `proto/iop/control.proto`: add additive management operation/request/response/record messages and oneofs. -- [ ] `proto/gen/iop/control.pb.go`: regenerate Go output. -- [ ] `apps/client/lib/gen/proto/iop/control.pb.dart`: regenerate Dart messages. -- [ ] `apps/client/lib/gen/proto/iop/control.pbenum.dart`: regenerate Dart enums. -- [ ] `apps/client/lib/gen/proto/iop/control.pbjson.dart`: regenerate Dart JSON metadata. -- [ ] `apps/client/lib/gen/proto/iop/control.pbserver.dart`: regenerate Dart server helpers. -- [ ] `apps/control-plane/internal/wire/client.go`: add parser/listener/option and error mapping without auth-token logging. -- [ ] `apps/control-plane/internal/wire/client_test.go`: test every operation class, missing/invalid/cross-principal auth, one-time token, and response secrecy. -- [ ] `apps/control-plane/cmd/control-plane/server.go`: construct credentialops service and inject into ClientServer when store is configured. -- [ ] `apps/client/lib/iop_wire/parser_map.dart`: register all management responses. -- [ ] `apps/client/lib/iop_wire/client_wire_client.dart`: add typed management methods while keeping hello behavior. -- [ ] `apps/client/test/iop_wire/parser_map_test.dart`: prove message parsing. -- [ ] `apps/client/test/iop_wire/client_wire_client_test.dart`: prove request/response typing, status errors, and no secret fields on list records. -- [ ] `apps/client/test/iop_wire/generated_proto_import_test.dart`: import/construct new generated messages. - -**Test Strategy:** Add Go table test `TestCredentialOperationAuthorizationAndLifecycle` for bootstrap absence plus create/list/update/rotate/disable/revoke. Add Dart tests for each oneof and parser type. Assert malformed/unknown operations fail closed and list responses have no raw secret/token field. - -**Verification:** `make proto && make proto-dart && GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/internal/wire ./apps/control-plane/cmd/control-plane && make client-test` passes. - -### [API-3] Add host-local bootstrap only - -**Problem:** `apps/control-plane/cmd/control-plane/main.go:49-62` registers only `serve`, so there is no safe first-principal bootstrap path. - -**Solution:** Add `principal bootstrap --alias ...` as a local command that loads config, opens the DB directly, refuses when any principal already exists unless an explicit idempotent lookup proves the same request, issues the first raw IOP token once to command stdout, and writes no token through zap/errors. Add key-file path config for slot operations; the tracked YAML stores only an empty path/key id, never key bytes. - -Before (`apps/control-plane/cmd/control-plane/main.go:59-62`): - -```go -} -root.PersistentFlags().StringVarP(&cfgFile, "config", "c", "configs/control-plane.yaml", "config file path") -root.AddCommand(serveCmd()) -return root -``` - -After: - -```go -root.PersistentFlags().StringVarP(&cfgFile, "config", "c", "configs/control-plane.yaml", "config file path") -root.AddCommand(serveCmd(), principalCmd()) -return root -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/cmd/control-plane/main.go`: add credential key-file config/env override and register principal CLI. -- [ ] `apps/control-plane/cmd/control-plane/credential_commands.go`: implement direct host-local bootstrap with explicit stdout writer. -- [ ] `apps/control-plane/cmd/control-plane/credential_commands_test.go`: test first bootstrap, second refusal, reopen, stdout one-time token, stderr/log redaction, and absence of remote bootstrap. -- [ ] `apps/control-plane/cmd/control-plane/config_test.go`: test key-file path override without reading/logging contents. -- [ ] `configs/control-plane.yaml`: document empty non-secret credential key file/key id settings. -- [ ] `agent-contract/inner/client-control-plane-wire.md`: document management authentication, operations, revision/status/errors, secret fields, and explicit no-remote-bootstrap rule. - -**Test Strategy:** Write `TestPrincipalBootstrapEmitsTokenOnce`, `TestPrincipalBootstrapRefusesSecondRoot`, `TestBootstrapLogsNeverContainToken`, and verify protobuf has no bootstrap request via deterministic `rg` command. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/cmd/control-plane -run 'Bootstrap|Credential|Config'` passes. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `apps/control-plane/internal/credentialops/sealer.go` | API-1 | -| `apps/control-plane/internal/credentialops/sealer_test.go` | API-1 | -| `apps/control-plane/internal/credentialops/service.go` | API-1 | -| `apps/control-plane/internal/credentialops/service_test.go` | API-1 | -| `proto/iop/control.proto` | API-2 | -| `proto/gen/iop/control.pb.go` | API-2 | -| `apps/client/lib/gen/proto/iop/control.pb.dart` | API-2 | -| `apps/client/lib/gen/proto/iop/control.pbenum.dart` | API-2 | -| `apps/client/lib/gen/proto/iop/control.pbjson.dart` | API-2 | -| `apps/client/lib/gen/proto/iop/control.pbserver.dart` | API-2 | -| `apps/control-plane/internal/wire/client.go` | API-2 | -| `apps/control-plane/internal/wire/client_test.go` | API-2 | -| `apps/control-plane/cmd/control-plane/server.go` | API-2 | -| `apps/client/lib/iop_wire/parser_map.dart` | API-2 | -| `apps/client/lib/iop_wire/client_wire_client.dart` | API-2 | -| `apps/client/test/iop_wire/parser_map_test.dart` | API-2 | -| `apps/client/test/iop_wire/client_wire_client_test.dart` | API-2 | -| `apps/client/test/iop_wire/generated_proto_import_test.dart` | API-2 | -| `apps/control-plane/cmd/control-plane/main.go` | API-3 | -| `apps/control-plane/cmd/control-plane/credential_commands.go` | API-3 | -| `apps/control-plane/cmd/control-plane/credential_commands_test.go` | API-3 | -| `apps/control-plane/cmd/control-plane/config_test.go` | API-3 | -| `configs/control-plane.yaml` | API-3 | -| `agent-contract/inner/client-control-plane-wire.md` | API-3 | -| `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_ops/CODE_REVIEW-cloud-G10.md` | API-1, API-2, API-3 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; fresh Go/Dart results are required. - -1. `test -f agent-task/m-principal-provider-credential-slot-routing/01_principal_store/complete.log && test -f agent-task/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log` — both predecessors complete. -2. `command -v go && go version && command -v protoc && protoc --version && command -v protoc-gen-go && command -v protoc-gen-dart && command -v flutter && flutter --version` — toolchains resolve. -3. `mkdir -p .cache/go-build .cache/go-cache` — executable Go temp/cache paths exist. -4. `make proto && make proto-dart` — generated sources are current. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/...` — no vet findings. -6. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops ./apps/control-plane/internal/credentialstore ./apps/control-plane/internal/wire ./apps/control-plane/cmd/control-plane` — service/store/wire/CLI lifecycle and race tests pass. -7. `make client-test` — Dart wire/parser tests pass. -8. `cd apps/client && flutter analyze` — client analysis has no findings. -9. `if rg --sort path -n 'Bootstrap.*Request|bootstrap.*request' proto/iop/control.proto agent-contract/inner/client-control-plane-wire.md; then exit 1; else exit 0; fi` — no remote bootstrap request contract exists. -10. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`. diff --git a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_local_G07_1.log b/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_local_G07_1.log deleted file mode 100644 index 5645db4..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_local_G07_1.log +++ /dev/null @@ -1,228 +0,0 @@ - - -# Credential Management Core Foundation - -## For the Implementing Agent - -Filling implementation-owned sections of `CODE_REVIEW-cloud-G08.md` is mandatory. Run every verification command, paste actual output, keep active files in place, and report ready for review; only code-review may finalize, rename logs, write `complete.log`, or archive. If blocked, record exact blocker evidence and resume conditions only in implementation-owned fields; do not ask the user, call user-input tools, create stop files, or classify next state. - -## Background - -Control Plane needs a principal-scoped management service and a host-local first-principal bootstrap command. The current `/client` WebSocket is plaintext and unauthenticated, while the SDD explicitly forbids credential-bearing operations on it; this packet builds the service/CLI core but does not expose a remote management operation or claim S08 completion. - -## Archive Evidence Snapshot - -- Prior pair: `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_ops/plan_cloud_G10_0.log`, `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_ops/code_review_cloud_G10_0.log`. -- Verdict/evidence: implementation had not started; no verdict or verification output. -- Replan reason: the previous plan sent raw IOP/provider credentials on the current plaintext Client WebSocket and implemented part of Epic-3 at-rest protection while claiming only S08. -- Roadmap carryover: this is a preparatory service/CLI packet. PASS must not check `credential-management`; S08 requires S09 at-rest sealer and S10 confidential Client transport rollout. - -## Analysis - -### Files Read - -- `apps/control-plane/cmd/control-plane/main.go` -- `apps/control-plane/cmd/control-plane/server.go` -- `apps/control-plane/cmd/control-plane/config_test.go` -- `apps/control-plane/internal/wire/client.go` -- `apps/control-plane/internal/wire/client_test.go` -- `proto/iop/control.proto` -- `apps/client/lib/iop_wire/client_wire_client.dart` -- `apps/client/lib/iop_wire/parser_map.dart` -- `apps/client/test/iop_wire/client_wire_client_test.dart` -- `apps/client/test/iop_wire/parser_map_test.dart` -- `agent-contract/inner/client-control-plane-wire.md` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 잠금 해제). -- Foundation maps to S08 / `credential-management`, Evidence Map S04-S08, but intentionally lacks the confidential remote operation required for full S08. -- Checklist covers host-local-only bootstrap, one-time raw token output, principal/revision authorization service fixtures, secret-blind list responses, and structural proof that no bootstrap/management protobuf or ClientServer listener is introduced. - -### Verification Context - -- handoff 없음. SDD says principal clients authenticate with IOP token over TLS and current plain WS cannot carry credential-bearing operations. -- Go 1.26.2 linux/arm64. Tests use temp SQLite, fake sealer, injected logger/random reader, and workspace-local Go temp/cache paths. -- Preconditions 01 and 02 are currently incomplete; runtime resolves their archived completion artifacts. -- No external key manager, TLS runner, Flutter change, or provider is required. Confidence: high for core foundation. - -### Test Coverage Gaps - -- CLI exposes only `serve`; no bootstrap/idempotency/one-time-output test exists. -- No principal/revision authorization service exists. -- Existing ClientServer tests cover hello only; no test currently protects the intentional absence of credential-bearing listeners. - -### Symbol References - -- Rename/remove 없음. -- `rootCmd` adds commands at `main.go:61`; `serveCmd` remains unchanged. -- `wire.NewClientServer` and Dart client/parser call sites are intentionally unchanged. - -### Split Judgment - -- The service authorization/CAS contract and host-local bootstrap are a stable useful foundation that preserves current network behavior and independently PASSes. -- Predecessors 01 and 02: active/archived completion missing, ambiguity 없음. -- Remote Client operation and concrete `SecretSealer` are excluded and must be planned with S09/S10; no Roadmap Targets section is present. - -### Scope Rationale - -- Do not modify `proto/iop/control.proto`, ClientServer, Dart client/parser, configs, or Control Plane server wiring. -- Define a `SecretSealer` interface only; tests use a fake. Do not add AES/key-file/deployment-key implementation in this packet. -- Do not add remote bootstrap, credential reveal, or plaintext network payloads. - -### Final Routing - -- `status=routed`, `evaluation_mode=isolated-reassessment`, finalizer=`finalize-task-policy.sh`, pair mode. -- Build closures all true for core foundation; scores `2+2+1+1+1=G07`; base/route=`local-fit`, local, `PLAN-local-G07.md`. -- Review closures all true; scores `2+2+1+1+2=G08`; `official-review`, cloud, `gpt-5.6-sol` xhigh, `CODE_REVIEW-cloud-G08.md`. -- `large_indivisible_context=false`; risks=`temporal_state`, `concurrent_consistency`, `boundary_contract` (3); rework=0; integrity failure=false; no capability gap. - -## Dependencies and Execution Order - -1. `01_principal_store` and `02+01_credential_catalog` must complete; runtime accepts their archived `complete.log` files. -2. Implement authorization/CAS service, then host-local bootstrap and absence guards. -3. No dependency absent from `05+01,02_management_ops` may be introduced. - -## Implementation Checklist - -- [ ] Add an in-process principal-authenticated management service with revision authorization, secret-blind records, and an injected-but-unimplemented `SecretSealer` boundary. -- [ ] Add a host-local-only first-principal/bootstrap CLI that emits the initial raw IOP token exactly once and never logs or persists it. -- [ ] Prove own-principal lifecycle, cross-principal denial, stale revision conflict, one-time output, restart persistence, and raw-secret redaction with deterministic tests. -- [ ] Prove no management/bootstrap protobuf, ClientServer listener, Dart method, or plaintext network activation was added; leave S08 completion for S09/S10 rollout. -- [ ] Run fresh race, Control Plane regression, archive-predecessor, structural absence, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-1] Add the in-process management core - -**Problem:** `apps/control-plane/internal/wire/client.go:62-73` has only hello, and there is no reusable service enforcing principal identity, target ownership, expected revision, or secret-blind response types. - -**Solution:** Add `credentialops.Service` over the store. It hashes the presented IOP token in process, resolves the principal, authorizes target equality, maps CAS/lifecycle errors, and exposes token/slot/route operations. Provider create/rotate receives plaintext only at the method boundary, requires an injected `SecretSealer`, clears the local byte slice on return, and passes only an opaque envelope to the store. The production packet supplies no sealer or network adapter. - -Before (`apps/control-plane/internal/wire/client.go:62-73`): - -```go -proto_socket.AddRequestListenerTyped(&client.Communicator, func(req *iop.ClientHelloRequest) (*iop.ClientHelloResponse, error) { - logger.Info("client hello request received", - zap.String("client_id", req.ClientId), - zap.String("client_version", req.ClientVersion), - ) - return &iop.ClientHelloResponse{ - Ready: true, - Protocol: Protocol, - ServerTimeUnixNano: time.Now().UnixNano(), - Message: "Hello from IOP Control Plane", - }, nil -}) -``` - -After service-only boundary: - -```go -import ( - "context" - - "iop/apps/control-plane/internal/credentialstore" -) - -type SecretSealer interface { - Seal(context.Context, []byte, SecretContext) (credentialstore.EncryptedSecretEnvelope, error) -} -func (s *Service) RotateSlot(ctx context.Context, rawIOPToken []byte, input RotateSlotInput) (SlotRecord, error) -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/internal/credentialops/service.go`: implement authentication, ownership, CAS, lifecycle mapping, secret-blind DTOs, and sealer interface. -- [ ] `apps/control-plane/internal/credentialops/service_test.go`: cover own/cross-principal operations, stale revision, lifecycle, missing sealer, fake-sealer ciphertext handoff, and captured-log redaction. - -**Test Strategy:** Write `TestServiceScopesOperationsToAuthenticatedPrincipal`, `TestServiceRejectsCrossPrincipalTargets`, `TestServiceRejectsStaleRevision`, `TestServiceRequiresSealerForSecretMutation`, and `TestServiceResponsesAreSecretBlind` using temp store and deterministic fake sealer. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops` passes. - -### [API-2] Add host-local first-principal bootstrap - -**Problem:** `apps/control-plane/cmd/control-plane/main.go:59-62` registers only `serve`, leaving no deployment-admin bootstrap path. - -**Solution:** Add `principal bootstrap --alias` that loads config, opens the DB directly, refuses when any principal already exists, issues the first token through packet-01 store, and writes the raw token once to command stdout without zap/error inclusion. No remote operation is added. - -Before (`apps/control-plane/cmd/control-plane/main.go:59-62`): - -```go -} -root.PersistentFlags().StringVarP(&cfgFile, "config", "c", "configs/control-plane.yaml", "config file path") -root.AddCommand(serveCmd()) -return root -``` - -After: - -```go -root.PersistentFlags().StringVarP(&cfgFile, "config", "c", "configs/control-plane.yaml", "config file path") -root.AddCommand(serveCmd(), principalCmd()) -return root -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/cmd/control-plane/main.go`: register the host-local principal command. -- [ ] `apps/control-plane/cmd/control-plane/credential_commands.go`: implement direct DB bootstrap with explicit stdout/stderr writers. -- [ ] `apps/control-plane/cmd/control-plane/credential_commands_test.go`: test first bootstrap, second refusal, restart, one-time stdout, and log/error redaction. - -**Test Strategy:** Write `TestPrincipalBootstrapEmitsTokenOnce`, `TestPrincipalBootstrapRefusesExistingPrincipal`, `TestPrincipalBootstrapPersistsAcrossReopen`, and `TestBootstrapLogsNeverContainToken`. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/cmd/control-plane -run 'PrincipalBootstrap|Credential'` passes. - -### [API-3] Guard the secure-transport boundary - -**Problem:** a future implementer could expose the service on current plaintext ClientServer and accidentally create the SDD-forbidden credential path. - -**Solution:** Add source-level absence tests that fail if bootstrap/credential protobuf messages or ClientServer credential listeners appear in this packet. Document the deferred adapter in service comments and tests, not the active wire contract. - -Before (`proto/iop/control.proto`, current client baseline): - -```protobuf -message ClientHelloRequest { - string client_id = 1; - string client_version = 2; -} -``` - -After: - -```text -unchanged: no BootstrapRequest, CredentialOperationRequest, or raw token field -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/internal/credentialops/service_test.go`: assert the service has no network registration side effect and missing sealer fails closed. -- [ ] `apps/control-plane/cmd/control-plane/credential_commands_test.go`: inspect root commands and prove bootstrap is CLI-only. - -**Test Strategy:** Use deterministic `rg` final verification plus Go tests; no wire/Dart tests are changed because their contract remains untouched. - -**Verification:** `if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` passes with no matches. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `apps/control-plane/internal/credentialops/service.go` | API-1 | -| `apps/control-plane/internal/credentialops/service_test.go` | API-1, API-3 | -| `apps/control-plane/cmd/control-plane/main.go` | API-2 | -| `apps/control-plane/cmd/control-plane/credential_commands.go` | API-2 | -| `apps/control-plane/cmd/control-plane/credential_commands_test.go` | API-2, API-3 | -| `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_ops/CODE_REVIEW-cloud-G08.md` | API-1, API-2, API-3 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; fresh Go results are required. - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/01_principal_store/complete.log' -print | wc -l)" -eq 1 && test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log' -print | wc -l)" -eq 1` — both archived predecessors exist exactly once. -2. `mkdir -p .cache/go-build .cache/go-cache` — executable Go paths exist. -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialops ./apps/control-plane/cmd/control-plane` — no vet findings. -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 -race ./apps/control-plane/internal/credentialops ./apps/control-plane/cmd/control-plane` — service/CLI tests and races pass. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` — Control Plane regression suite passes. -6. `if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` — no plaintext management wire was added. -7. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`. diff --git a/agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/CODE_REVIEW-cloud-G06.md b/agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/CODE_REVIEW-cloud-G06.md deleted file mode 100644 index dca64f5..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/CODE_REVIEW-cloud-G06.md +++ /dev/null @@ -1,135 +0,0 @@ - - -# Code Review Reference - API - -> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** -> The task is NOT complete until every implementation-owned section below is filled in. -> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving. -> Fill implementation-owned sections, then stop with active files in place and report ready for review. -> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. -> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state. -> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume. -> Follow the ownership table at the bottom of this file for which sections you own. - -## Overview - -date=2026-08-01 -task=m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap, plan=0, tag=API - -## Archive Evidence Snapshot - -- Parent pair: `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_local_G07_1.log`, `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G08_1.log`. -- Verdict/evidence: implementation had not started; no verdict or verification output. -- Refinement reason: host-local bootstrap is independently implementable and verifiable from the in-process management service retained in sibling `05+01,02_management_core`. -- Roadmap carryover: this remains preparatory. PASS must not check `credential-management`; S08 still requires S09 at-rest sealer and S10 confidential Client transport rollout. - -## For the Review Agent - -> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section. - -Compare implementation of each item against source files and verify that output in `Verification Results` matches code. -Review completion means the following steps are finished: - -1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals. -2. Archive `CODE_REVIEW-cloud-G06.md` → `code_review_cloud_G06_0.log` and `PLAN-local-G06.md` → `plan_local_G06_0.log`. -3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill. -4. If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata. Roadmap state check and `update-roadmap` calls are runtime responsibilities. -5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting. - ---- - -## Implementation Item Completion - -| Item | Status | -|------|---------| -| API-2 Add host-local first-principal bootstrap | [ ] | -| API-3 Guard the secure-transport boundary | [ ] | - -## Implementation Checklist - -- [ ] Add a host-local-only first-principal/bootstrap CLI that emits the initial raw IOP token exactly once and never logs or persists it. -- [ ] Prove first bootstrap, existing-principal refusal, one-time output, restart persistence, and raw-token redaction with deterministic tests. -- [ ] Prove no management/bootstrap protobuf, ClientServer listener, Dart method, or plaintext network activation was added; leave S08 completion for S09/S10 rollout. -- [ ] Run fresh CLI, Control Plane regression, archive-predecessor, structural absence, vet, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -## Review-Only Checklist - -> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent. -> Implementing agents must not modify or check this section. - -- [ ] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`. -- [ ] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match. -- [ ] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G06_0.log`. -- [ ] Archive active `PLAN-*-G??.md` to `plan_local_G06_0.log`. -- [ ] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`. -- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files. -- [ ] If PASS, move active task directory `agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/` to `agent-task/archive/YYYY/MM/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/` and update this checklist at the final archive path. -- [ ] If PASS and task group is `m-principal-provider-credential-slot-routing`, report completion event metadata for runtime, without modifying roadmap or directly calling `update-roadmap`. -- [ ] If PASS for split work, remove empty active parent `agent-task/m-principal-provider-credential-slot-routing/` or verify it was kept due to remaining siblings/files. -- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`. - -## Deviations from Plan - -_Record any deviations from the plan and the rationale here._ - -## Key Design Decisions - -_Record key design decisions here._ - -## Reviewer Checkpoints - -- Confirm no Roadmap Targets section exists and PASS cannot check S08. -- Verify bootstrap is a direct host-local CLI, refuses an existing principal, and emits the raw token exactly once. -- Confirm raw token bytes are absent from logs, errors, and persisted reversible fields. -- Prove proto, ClientServer, Dart client/parser, and server wiring remain unchanged. -- Confirm no concrete key loading/encryption or network credential transport entered this packet. - -## Verification Results - -Paste actual stdout/stderr beneath every command; do not summarize or reconstruct it. - -### API-2 - -`GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/cmd/control-plane -run 'PrincipalBootstrap|Credential'` - -_Pending._ - -### API-3 - -`if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` - -_Pending._ - -### Final Verification - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/01_principal_store/complete.log' -print | wc -l)" -eq 1 && test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log' -print | wc -l)" -eq 1` -2. `mkdir -p .cache/go-build .cache/go-cache` -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/cmd/control-plane` -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/cmd/control-plane -run 'PrincipalBootstrap|Credential'` -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` -6. `if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` -7. `git diff --check` - -_Pending actual output for each command._ - ---- - -> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?** -> If anything is blank, go back and fill it in before saving this file. -> Leave review-agent-only sections unchanged. - -## Section Ownership - -| Section | Owner | Note | -|---------|-------|------| -| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) | -| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS | -| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required | -| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only | -| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only | -| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section | -| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content | -| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan | -| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry | -| Code Review Result | Review agent appends | Not included in stub | diff --git a/agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/PLAN-local-G06.md b/agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/PLAN-local-G06.md deleted file mode 100644 index 6eb1bda..0000000 --- a/agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/PLAN-local-G06.md +++ /dev/null @@ -1,173 +0,0 @@ - - -# Host-Local Principal Bootstrap - -## For the Implementing Agent - -Filling implementation-owned sections of `CODE_REVIEW-cloud-G06.md` is mandatory. Run every verification command, paste actual output, keep active files in place, and report ready for review; only code-review may finalize, rename logs, write `complete.log`, or archive. If blocked, record exact blocker evidence and resume conditions only in implementation-owned fields; do not ask the user, call user-input tools, create stop files, or classify next state. - -## Background - -Control Plane needs a host-local way to create the first principal and return its raw IOP token once. The command must open the configured store directly and must not add any credential-bearing operation to the current plaintext Client WebSocket. - -## Archive Evidence Snapshot - -- Parent pair: `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_local_G07_1.log`, `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G08_1.log`. -- Verdict/evidence: implementation had not started; no verdict or verification output. -- Refinement reason: host-local bootstrap is independently implementable and verifiable from the in-process management service retained in sibling `05+01,02_management_core`. -- Roadmap carryover: this remains preparatory. PASS must not check `credential-management`; S08 still requires S09 at-rest sealer and S10 confidential Client transport rollout. - -## Analysis - -### Files Read - -- `apps/control-plane/cmd/control-plane/main.go` -- `apps/control-plane/cmd/control-plane/server.go` -- `apps/control-plane/cmd/control-plane/config_test.go` -- `apps/control-plane/internal/wire/client.go` -- `apps/control-plane/internal/wire/client_test.go` -- `proto/iop/control.proto` -- `apps/client/lib/iop_wire/client_wire_client.dart` -- `apps/client/lib/iop_wire/parser_map.dart` -- `agent-contract/inner/client-control-plane-wire.md` - -### SDD Criteria - -- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md` (`승인`, 잠금 해제). -- This foundation maps to S08 / `credential-management`, but the confidential remote operation required for full S08 remains excluded. -- Checklist covers host-local-only bootstrap, one-time raw token output, restart persistence, redaction, and structural proof that no bootstrap/management protobuf or ClientServer listener is introduced. - -### Verification Context - -- No handoff exists. The SDD forbids credential-bearing operations on the current plain WebSocket. -- Go 1.26.2 linux/arm64. Tests use temp SQLite, injected logger/random reader, explicit stdout/stderr writers, and workspace-local Go temp/cache paths. -- Preconditions 01 and 02 are incomplete; runtime resolves their archived completion artifacts before implementation. -- No external key manager, TLS runner, Flutter change, or provider is required. Confidence: high. - -### Test Coverage Gaps - -- CLI exposes only `serve`; no first-principal bootstrap, idempotency, restart, or one-time-output test exists. -- No structural test protects the intentional absence of credential-bearing ClientServer listeners and protobuf messages. - -### Symbol References - -- Rename/remove 없음. -- `rootCmd` adds commands at `main.go:61`; `serveCmd` remains unchanged. -- `wire.NewClientServer` and Dart client/parser call sites remain unchanged. - -### Split Judgment - -- This child owns the direct host-local command, one-time stdout contract, and plaintext-network absence guard. -- Sibling `05+01,02_management_core` independently owns the reusable authorization/CAS service. -- The bootstrap command and its CLI-only/absence tests stay together because those tests define its safe exposure boundary. - -### Scope Rationale - -- Do not modify `proto/iop/control.proto`, ClientServer, Dart client/parser, configs, or Control Plane server wiring. -- Do not depend on sibling 05; open the packet-01 store directly. -- Do not add remote bootstrap, credential reveal, concrete sealer/key loading, or plaintext network payloads. - -### Final Routing - -- `status=routed`, `evaluation_mode=isolated-reassessment`, finalizer=`finalize-task-policy.sh`, pair mode. -- Build closures all true; scores `1+1+2+1+1=G06`; base/route=`local-fit`, lane=`local`, canonical=`PLAN-local-G06.md`. -- Review closures all true; scores `1+1+2+1+1=G06`; route=`official-review`, lane=`cloud`, model=`gpt-5.6-sol` xhigh, canonical=`CODE_REVIEW-cloud-G06.md`. -- `large_indivisible_context=false`; risks=`temporal_state`, `boundary_contract` (2); rework=0; integrity failure=false; capability gap 없음. - -## Dependencies and Execution Order - -1. `01_principal_store` and `02+01_credential_catalog` must complete; runtime accepts their archived `complete.log` files. -2. Implement direct DB bootstrap, then one-time output/restart tests and structural absence guards. -3. No dependency absent from `06+01,02_host_local_bootstrap` may be introduced. - -## Implementation Checklist - -- [ ] Add a host-local-only first-principal/bootstrap CLI that emits the initial raw IOP token exactly once and never logs or persists it. -- [ ] Prove first bootstrap, existing-principal refusal, one-time output, restart persistence, and raw-token redaction with deterministic tests. -- [ ] Prove no management/bootstrap protobuf, ClientServer listener, Dart method, or plaintext network activation was added; leave S08 completion for S09/S10 rollout. -- [ ] Run fresh CLI, Control Plane regression, archive-predecessor, structural absence, vet, and diff verification. -- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output. - -### [API-2] Add host-local first-principal bootstrap - -**Problem:** `apps/control-plane/cmd/control-plane/main.go:59-62` registers only `serve`, leaving no deployment-admin bootstrap path. - -**Solution:** Add `principal bootstrap --alias` that loads config, opens the DB directly, refuses when any principal already exists, issues the first token through packet-01 store, and writes the raw token once to command stdout without zap/error inclusion. No remote operation is added. - -Before (`apps/control-plane/cmd/control-plane/main.go:59-62`): - -```go -root.PersistentFlags().StringVarP(&cfgFile, "config", "c", "configs/control-plane.yaml", "config file path") -root.AddCommand(serveCmd()) -return root -``` - -After: - -```go -root.PersistentFlags().StringVarP(&cfgFile, "config", "c", "configs/control-plane.yaml", "config file path") -root.AddCommand(serveCmd(), principalCmd()) -return root -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/cmd/control-plane/main.go`: register the host-local principal command. -- [ ] `apps/control-plane/cmd/control-plane/credential_commands.go`: implement direct DB bootstrap with explicit stdout/stderr writers. -- [ ] `apps/control-plane/cmd/control-plane/credential_commands_test.go`: test first bootstrap, second refusal, restart, one-time stdout, log/error redaction, and CLI-only exposure. - -**Test Strategy:** Write `TestPrincipalBootstrapEmitsTokenOnce`, `TestPrincipalBootstrapRefusesExistingPrincipal`, `TestPrincipalBootstrapPersistsAcrossReopen`, and `TestBootstrapLogsNeverContainToken`. - -**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/cmd/control-plane -run 'PrincipalBootstrap|Credential'` passes. - -### [API-3] Guard the secure-transport boundary - -**Problem:** a future implementer could expose bootstrap on the current plaintext ClientServer and create the SDD-forbidden credential path. - -**Solution:** Keep bootstrap registered only as a host-local Cobra command. Add source-level absence tests that fail if bootstrap/credential protobuf messages or ClientServer credential listeners appear. - -Before (`proto/iop/control.proto`, current client baseline): - -```protobuf -message ClientHelloRequest { - string client_id = 1; - string client_version = 2; -} -``` - -After: - -```text -unchanged: no BootstrapRequest, CredentialOperationRequest, or raw token field -``` - -**Modified Files and Checklist:** - -- [ ] `apps/control-plane/cmd/control-plane/credential_commands_test.go`: inspect root commands and prove bootstrap is CLI-only. - -**Test Strategy:** Use deterministic `rg` final verification plus command tests; no wire/Dart test changes are required because their contract remains untouched. - -**Verification:** `if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` passes with no matches. - -## Modified Files Summary - -| File | Items | -|------|-------| -| `apps/control-plane/cmd/control-plane/main.go` | API-2 | -| `apps/control-plane/cmd/control-plane/credential_commands.go` | API-2 | -| `apps/control-plane/cmd/control-plane/credential_commands_test.go` | API-2, API-3 | -| `agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/CODE_REVIEW-cloud-G06.md` | API-2, API-3 | - -## Final Verification - -Run from `/config/workspace/iop-s0`; fresh Go results are required. - -1. `test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/01_principal_store/complete.log' -print | wc -l)" -eq 1 && test "$(find agent-task/archive -type f -path '*/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log' -print | wc -l)" -eq 1` — both archived predecessors exist exactly once. -2. `mkdir -p .cache/go-build .cache/go-cache` — executable Go paths exist. -3. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/cmd/control-plane` — no vet findings. -4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/cmd/control-plane -run 'PrincipalBootstrap|Credential'` — focused bootstrap tests pass. -5. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/...` — Control Plane regression suite passes. -6. `if rg --sort path -n 'message[[:space:]]+.*(Bootstrap|CredentialOperation)|AddRequestListenerTyped.*Credential' proto/iop/control.proto apps/control-plane/internal/wire/client.go; then exit 1; else exit 0; fi` — no plaintext management wire was added. -7. `git diff --check` — no whitespace errors. - -After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`.