<!-- task=m-principal-provider-credential-slot-routing/08+03,04,07_secure_delivery plan=0 tag=API -->

# 인증된 credential lease 전달과 adapter 주입 계획

## For the Implementing Agent

`CODE_REVIEW-*-G??.md`의 구현 담당 섹션 작성은 필수다. 모든 검증을 실행하고 실제 구현 메모와 stdout/stderr를 채운 뒤 active 파일을 그대로 두고 review 준비 완료를 보고한다. 막히면 정확한 blocker, 실행 명령과 출력, 재개 조건만 구현 evidence 필드에 기록한다. 사용자에게 묻거나 user-input 도구를 호출하거나 stop 파일을 만들거나 다음 상태를 분류하거나 archive/`complete.log`를 작성하지 않는다. 최종 판정은 code-review skill만 수행한다.

## Background

Edge에는 secret-free principal projection과 route binding이 있지만 Control Plane connector가 이를 적용하지 않고 모든 credential-bearing socket은 평문이다. 이 작업은 TLS identity가 검증된 CP-Edge/Edge-Node 경로에 bounded lease를 추가하고, 선택된 route/slot/revision/target에 맞는 raw secret을 dedicated sensitive protobuf field로 Node까지 운반한 뒤 provider adapter 직전에만 auth header로 주입한다.

## Archive Evidence Snapshot

- `agent-task/archive/2026/08/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/complete.log`: immutable generation/expiry cache와 managed auth foundation PASS; production transport activation은 제외됐다.
- `agent-task/archive/2026/08/m-principal-provider-credential-slot-routing/04+03_principal_routes/complete.log`: principal route/slot/profile/model binding과 no-fallback PASS; production delivery는 제외됐다.
- `agent-task/m-principal-provider-credential-slot-routing/07+01,02,05_secret_material/complete.log`: 현재 missing이다. 구현 전 반드시 이 exact path가 생겨 concrete decrypt/key-version contract가 완료되어야 한다.
- prior PASS에는 unresolved Required finding이 없었다. 03/04의 dormant contract를 보존하고 07의 keyring을 소비한다.

## 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:
  - `secure-transport`: credential-bearing peer 인증과 전송 기밀성
  - `credential-lease`: principal/slot/route/target/revision/expiry bounded lease
  - `adapter-injection`: request-local provider auth header 주입
  - `revocation`: rotation/revoke 이후 새 lease/dispatch/retry 차단
- Completion mode: check-on-pass

## Analysis

### Files Read

- `agent-roadmap/phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md`
- `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md`
- `agent-contract/inner/client-control-plane-wire.md`
- `agent-contract/inner/control-plane-edge-wire.md`
- `agent-contract/inner/edge-node-runtime-wire.md`
- `proto/iop/control.proto`
- `proto/iop/runtime.proto`
- `packages/go/auth/auth.go`
- `packages/go/config/edge_types.go`
- `packages/go/config/node_types.go`
- `packages/go/config/load.go`
- `packages/go/agentruntime/types.go`
- `apps/control-plane/cmd/control-plane/main.go`
- `apps/control-plane/cmd/control-plane/server.go`
- `apps/control-plane/internal/wire/edge_server.go`
- `apps/control-plane/internal/wire/edge_server_test.go`
- `apps/control-plane/internal/credentialstore/store.go`
- `apps/control-plane/internal/credentialstore/slot.go`
- `apps/control-plane/internal/credentialops/service.go`
- `apps/edge/internal/authprojection/cache.go`
- `apps/edge/internal/controlplane/connector.go`
- `apps/edge/internal/controlplane/connector_test.go`
- `apps/edge/internal/bootstrap/runtime.go`
- `apps/edge/internal/input/manager.go`
- `apps/edge/internal/openai/dispatch_context.go`
- `apps/edge/internal/openai/provider_tunnel.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/service/provider_tunnel.go`
- `apps/edge/internal/service/run_types.go`
- `apps/edge/internal/transport/server.go`
- `apps/node/internal/transport/client.go`
- `apps/node/internal/transport/session.go`
- `apps/node/internal/node/tunnel_handler.go`
- `apps/node/internal/adapters/openai_compat/provider_tunnel.go`
- `configs/control-plane.yaml`
- `configs/edge.yaml`
- `configs/node.yaml`
- `Makefile`
- `go.mod`
- `agent-test/local/rules.md`
- `agent-test/local/profiles/control-plane-smoke.md`
- `agent-test/local/profiles/edge-smoke.md`
- `agent-test/local/profiles/node-smoke.md`
- `agent-test/local/profiles/platform-common-smoke.md`

### SDD Criteria

- 승인 SDD S10~S13과 Evidence Map S09-S13을 대상으로 한다.
- S10: Client-CP server TLS와 CP-Edge/Edge-Node mTLS identity matrix에서 plaintext, no-cert, wrong-CA를 secret 전송 전에 거부한다.
- S11: lease를 principal/slot/route/profile/target/credential revision/expiry에 묶고 다른 scope, expired/revoked/tampered payload를 upstream 전에 거부한다.
- S12: adapter가 profile auth 규칙을 사용해 마지막 순간에 header를 만들고 raw secret을 generic headers/metadata/config/status/error/log/metric/response에 넣지 않는다.
- S13: 새 projection generation의 disable/revoke/rotation 뒤 미발급/대기/새 retry는 차단하고 이미 upstream으로 보낸 단일 attempt만 terminal까지 허용한다.
- 이 기준으로 transport matrix, lease deterministic clock, upstream header capture, revocation race, repository secret scan을 checklist/final verification에 고정했다.

### Verification Context

- handoff는 없었다. repository-native evidence는 transport constructors, dormant projection cache, provider tunnel flow, proto Make targets와 네 local profile에서 도출했다.
- `proto-socket` dependency는 이미 `NewTcpServerTLS`와 `DialTcpTLS`를 제공하므로 새 transport dependency는 추가하지 않는다. `go.mod`의 기존 `google/uuid`, protobuf, crypto 표준 라이브러리를 사용한다.
- 현재 host는 Linux/aarch64, Go `1.26.2`; `go`, `protoc`, `flutter`가 PATH에 있다. 18000/19080/19081에는 listener가 없었다.
- deterministic tests는 test-owned CA/server/client/wrong-peer certificates와 fake clock을 `/tmp` 또는 `t.TempDir()`에 생성한다. tracked fixture에 private key나 provider secret을 두지 않는다.
- external verification은 없다. live provider 호출은 10번 child가 소유한다. fresh Go tests와 race test가 필요하며 cache는 허용하지 않는다.
- confidence: medium-high. 세 프로세스와 두 wire schema를 동시에 바꾸므로 모든 exact regression command가 PASS해야 closure된다.

### Test Coverage Gaps

- 기존 CP-Edge, Edge-Node tests는 plain TCP success/reconnect만 검증한다: valid/no-cert/wrong-CA/server-name matrix가 없다.
- projection cache tests는 in-process `Apply`만 검증한다: authenticated connector 수신과 out-of-order apply가 없다.
- credential lease issuer/cache/validator가 없어 scope, expiry, tamper, unavailable CP, concurrent revoke race가 전부 gap이다.
- provider tunnel tests는 caller-supplied generic header를 전달한다: dedicated secret payload와 last-moment profile injection/zeroization을 검증하지 않는다.
- 기존 cancellation/queue recovery tests는 credential revision fence를 모른다: old lease retry가 없고 in-flight 1회만 terminal되는 ordering test가 필요하다.

### Symbol References

- rename/remove는 없다.
- additive schema/API call sites: `ProviderTunnelRequest` builders are `apps/edge/internal/service/provider_tunnel.go:371-406`; Node conversion is `apps/node/internal/node/tunnel_handler.go:24-38`; runtime consumer is `apps/node/internal/adapters/openai_compat/provider_tunnel.go:15-35`.
- constructor changes remain source-compatible through options: `wire.NewEdgeServer`, `controlplane.NewConnector`, `transport.NewServer`, and `transport.DialEdge` keep current call forms while accepting TLS/credential options.
- regenerated protobuf outputs are exact `proto/gen/iop/control.pb.go`, `proto/gen/iop/runtime.pb.go`, and the eight existing Dart control/runtime generated files.

### Split Judgment

- 이 child는 TLS trust, lease scope, projection/revocation fence와 request-local injection이 하나의 security invariant라 더 분리하면 raw secret이 평문 hop이나 unchecked retry에 노출되는 invalid intermediate가 된다.
- stable output은 default-off/dormant production composition과 constructor-level opt-in integration fixture다. 09가 config migration mode를 활성화하기 전 legacy behavior는 변하지 않지만, secure path 자체는 실제 three-process TLS/lease fixture로 독립 PASS한다.
- predecessor `03`은 `agent-task/archive/2026/08/m-principal-provider-credential-slot-routing/03+01,02_projection_auth/complete.log`로 충족됐다.
- predecessor `04`는 `agent-task/archive/2026/08/m-principal-provider-credential-slot-routing/04+03_principal_routes/complete.log`로 충족됐다.
- predecessor `07`은 `agent-task/m-principal-provider-credential-slot-routing/07+01,02,05_secret_material/complete.log`가 missing이므로 구현 시작이 차단된다.

### Scope Rationale

- legacy/CP mode startup policy와 caller provider-auth rejection은 09의 `compat-migration` 소유다. 이 packet은 secure path를 default-off로 조립하고 explicit test option에서만 활성화한다.
- usage metric label과 slot attribution 문서는 09가 소유한다. 이 packet은 immutable safe refs를 `RunDispatch`까지 보존하되 public metrics를 바꾸지 않는다.
- remote credential-management message 추가는 Epic 2에서 이미 완료된 operation의 별도 wire UX이며, 이번 요청 Epic 3/4 범위를 넘으므로 만들지 않는다. Client-CP는 credential-bearing HTTP/WS에 TLS server identity를 제공하고 평문 listener를 credential mode에서 열지 않는 것으로 S10 boundary를 충족한다.
- A2A/native normalized provider path, provider failover, lease persistence, auto-rotation은 milestone 범위 밖이다.

### Final Routing

- evaluation_mode `first-pass`; finalizer `finalize-task-policy.sh` pair.
- build closures 모두 true; scores `2,2,2,2,2` = G10, base/route `grade-boundary`; `large_indivisible_context=true`; positive risks `temporal_state`, `concurrent_consistency`, `boundary_contract`, `structured_interpretation`, `variant_product` (5); recovery 0/false; canonical `PLAN-cloud-G10.md`.
- review closures 모두 true; scores `2,2,2,2,2` = G10; `official-review`, `CODE_REVIEW-cloud-G10.md`, Codex `gpt-5.6-sol` xhigh.
- capability gap은 없다.

## Implementation Checklist

- [ ] Add fail-closed TLS configuration and peer-identity tests for credential-bearing Client-Control Plane, Control Plane-Edge, and Edge-Node connections.
- [ ] Add dedicated projection/credential-lease wire messages and a Control Plane issuer that validates active principal/route/slot/revision before decrypting.
- [ ] Bind Edge lease acquisition/cache to the selected candidate and projection generation, and fence expiry, revocation, rotation, retry, and Control Plane outage deterministically.
- [ ] Deliver the secret only in a dedicated sensitive payload and inject the profile auth header inside the Node adapter immediately before the upstream request.
- [ ] Add three-process TLS/lease/upstream-header, tamper/scope, revocation-race, and secret-leak regression verification.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [API-1] Credential-bearing TLS boundaries

**Problem:** Control Plane starts plain HTTP/WS/TCP at `apps/control-plane/cmd/control-plane/server.go:51-71`, Edge connects to CP with plain TCP, and Node `DialEdge` calls `net.Dialer.DialContext` at `apps/node/internal/transport/client.go:91-109`.

**Solution:** Define reusable server/client TLS config including CA, cert, key and expected server name. Credential mode must reject missing material; CP HTTP uses `ListenAndServeTLS`, CP-Edge and Edge-Node use the existing proto-socket TLS constructors, require TLS 1.3 and client cert verification, and never fall back to plaintext after a TLS failure. Token/hello registration remains the enrollment binding inside the verified peer channel.

Before (`packages/go/config/edge_types.go:85-92`):

```go
type EdgeControlPlaneConf struct {
	Enabled              bool   `mapstructure:"enabled" yaml:"enabled"`
	WireAddr             string `mapstructure:"wire_addr" yaml:"wire_addr"`
	ReconnectIntervalSec int    `mapstructure:"reconnect_interval_sec" yaml:"reconnect_interval_sec"`
}
```

After:

```go
type TLSClientConf struct {
	Enabled, RequireMTLS bool
	CAFile, CertFile, KeyFile, ServerName string
}
```

**Modified Files and Checklist:**

- [ ] Extend `packages/go/auth/auth.go`, `packages/go/config/edge_types.go`, `packages/go/config/node_types.go`, and `packages/go/config/load.go` with strict TLS client/server load and validation.
- [ ] Update `apps/control-plane/cmd/control-plane/main.go`, `apps/control-plane/cmd/control-plane/server.go`, and `configs/control-plane.yaml` for HTTP/client-wire/edge-wire TLS with no private-key content in tracked config.
- [ ] Update `apps/control-plane/internal/wire/edge_server.go` and add `apps/control-plane/internal/wire/credential_tls_test.go` for CP-Edge valid/no-cert/wrong-CA/plaintext cases.
- [ ] Update `apps/edge/internal/controlplane/connector.go`, `apps/edge/internal/transport/server.go`, `apps/edge/internal/bootstrap/runtime.go`, and `configs/edge.yaml` for CP client and Node server TLS.
- [ ] Update `apps/node/internal/transport/client.go` and `configs/node.yaml` for Edge server-name verification and client certificate.
- [ ] Add `apps/edge/internal/transport/credential_tls_test.go` and `apps/node/internal/transport/credential_tls_test.go` for wrong peer, plaintext, reconnect and valid registration.

**Test Strategy:** Generate an in-memory/test-temp root, server certs and two client identities. Named table tests assert failure before hello/register/lease parser invocation for plaintext/no-cert/wrong-CA/wrong-name and success only for the correct identity. No test key is tracked.

**Verification:** `go test -count=1 ./packages/go/auth ./packages/go/config ./apps/control-plane/internal/wire ./apps/edge/internal/controlplane ./apps/edge/internal/transport ./apps/node/internal/transport` must pass.

### [API-2] Projection activation and bounded lease issuer

**Problem:** `PrincipalProjectionApplyRequest` at `proto/iop/control.proto:104-115` is reserved but no parser/handler exists, and there is no credential lease contract. Edge therefore cannot securely acquire the concrete secret after resolving `CredentialSlotRef`.

**Solution:** Activate projection apply only on the authenticated CP-Edge communicator. Add request/response messages for a lease containing safe scope plus a `bytes secret` field explicitly marked sensitive. CP validates current active token principal, route, slot, profile, target and exact revisions from one store snapshot, decrypts with the 07 keyring, issues a random lease id and short expiry, and returns a copied secret. Public errors are typed and omit scope internals. Edge validates projection generation/scope and stores at most bounded, expiring entries keyed by all immutable dimensions.

Before (`proto/iop/control.proto:104-115`):

```proto
message PrincipalProjectionApplyRequest {
  PrincipalProjection projection = 1;
}
message PrincipalProjectionApplyResponse {
  bool applied = 1;
  uint64 accepted_generation = 2;
  string reason = 3;
}
```

After:

```proto
message CredentialLeaseRequest { /* principal, slot, route, profile, target, revisions */ }
message CredentialLeaseResponse { CredentialLeaseSensitive sensitive = 1; /* safe scope + expiry */ }
message CredentialLeaseSensitive { bytes secret = 1; }
```

**Modified Files and Checklist:**

- [ ] Extend `proto/iop/control.proto` with additive field numbers and explicit sensitive logging comments; regenerate `proto/gen/iop/control.pb.go`.
- [ ] Add `apps/control-plane/internal/credentiallease/service.go` and `apps/control-plane/internal/credentiallease/service_test.go` with current-row validation, decrypt, TTL bounds, copy/zero and non-leaking errors.
- [ ] Extend `apps/control-plane/internal/wire/edge_server.go` with option-injected projection publisher/lease handler available only on secure connections.
- [ ] Extend `apps/edge/internal/controlplane/connector.go` to apply fresh projections to the shared cache and request leases without debug-formatting sensitive messages.
- [ ] Add `apps/edge/internal/service/credential_lease.go` and `apps/edge/internal/service/credential_lease_test.go` for full-key bounded cache, clock, mutation-copy and unavailable-CP behavior.
- [ ] Wire `apps/edge/internal/bootstrap/runtime.go` and `apps/edge/internal/input/manager.go` so one cache is owned by ingress and the connector is the service lease provider.

**Test Strategy:** Add deterministic clock tables for wrong principal/slot/route/profile/target/revision, expired, revoked, rotated, tampered and out-of-order projection. Assert invalid cases never call keyring Open; unavailable CP can use only an unexpired exact cached lease.

**Verification:** `go test -count=1 -race ./apps/control-plane/internal/credentiallease ./apps/edge/internal/authprojection ./apps/edge/internal/service ./apps/edge/internal/controlplane` must pass.

### [API-3] Candidate-bound delivery and last-moment injection

**Problem:** `SubmitProviderTunnelRequest.Headers` at `apps/edge/internal/service/provider_tunnel.go:89-118` and `ProviderTunnelRequest.headers` at `proto/iop/runtime.proto:65-82` currently carry caller-supplied provider auth. Node forwards them directly at `apps/node/internal/adapters/openai_compat/provider_tunnel.go:24-35`, so there is no dedicated secret boundary.

**Solution:** Add a dedicated `CredentialLeaseSensitive` field to the Edge-local request, runtime protobuf and runtime DTO. Acquire the lease only after provider-pool candidate/profile/served target selection, validate it again before send and on Node receipt, and keep the credential out of generic maps. The adapter clones non-sensitive request headers, resolves the selected profile auth header/scheme, injects from request-local secret immediately before `client.Do`, rejects pre-existing collision, and zeros owned copies on terminal/cancel.

Before (`proto/iop/runtime.proto:65-83`):

```proto
message ProviderTunnelRequest {
  map<string, string> headers = 7;
  bytes body = 8;
  string operation = 13;
}
```

After:

```proto
message ProviderTunnelRequest {
  map<string, string> headers = 7;
  bytes body = 8;
  string operation = 13;
  CredentialLeaseSensitive credential = 14;
}
```

**Modified Files and Checklist:**

- [ ] Extend `proto/iop/runtime.proto`; regenerate `proto/gen/iop/runtime.pb.go` and all existing Dart control/runtime generated outputs under `apps/client/lib/gen/proto/iop/`.
- [ ] Extend `packages/go/agentruntime/types.go` with a private-by-convention request-local credential object and explicit zero method.
- [ ] Update `apps/edge/internal/openai/dispatch_context.go`, `apps/edge/internal/openai/chat_handler.go`, `apps/edge/internal/openai/responses_handler.go`, `apps/edge/internal/openai/anthropic_handler.go`, and `apps/edge/internal/openai/provider_tunnel.go` to pass trusted route scope and never caller provider auth for managed routes.
- [ ] Update `apps/edge/internal/service/provider_tunnel.go` and `apps/edge/internal/service/run_types.go` to acquire after candidate selection and preserve immutable slot/revision dispatch refs.
- [ ] Update `apps/node/internal/node/tunnel_handler.go` to validate expiry/scope/target/revision before adapter lookup/upstream work.
- [ ] Update `apps/node/internal/adapters/openai_compat/provider_tunnel.go` and add `apps/node/internal/adapters/openai_compat/credential_injection_test.go` for profile header injection, collision rejection and secret cleanup.
- [ ] Add `apps/edge/internal/service/credential_delivery_test.go` and `apps/node/internal/node/credential_lease_test.go` for dedicated field propagation and no generic-map copy.

**Test Strategy:** Use fake providers for OpenAI bearer and Anthropic `x-api-key` profiles. Assert exactly one correct upstream header, no credential bytes in headers/metadata/status/errors/proto-redacted formatting/response, and rejection before HTTP hit for every invalid scope.

**Verification:** Run `make proto && make proto-dart`, hash the exact generated control/runtime files, regenerate and compare a second hash manifest; the manifests must match. Then `go test -count=1 ./apps/edge/internal/openai ./apps/edge/internal/service ./apps/node/internal/node ./apps/node/internal/adapters/openai_compat` must pass.

### [API-4] Rotation/revocation ordering fence

**Problem:** projection apply currently changes route state atomically, but no lease cache or retry path compares its credential revision. A request admitted before revoke could otherwise reuse an old lease for a new attempt.

**Solution:** Capture projection generation and credential revision in the dispatch binding. On projection apply, evict mismatched cache entries; before every send/recovery attempt re-read the exact current binding and reject stale revisions. Mark a lease consumed when the upstream attempt starts so it is not reusable. Do not cancel/replay an attempt already sent upstream; only its existing terminal frame may finish.

Before (`apps/edge/internal/service/provider_tunnel.go:240-274`):

```go
if err := entry.Client.Send(tunnelReq); err != nil {
	unsubscribe()
	return nil, err
}
```

After:

```go
if err := leaseFence.ValidateForSend(binding); err != nil { return nil, err }
if err := entry.Client.Send(tunnelReq); err != nil { /* zero + release */ }
leaseFence.MarkAttemptStarted(binding)
```

**Modified Files and Checklist:**

- [ ] Complete eviction/generation observer in `apps/edge/internal/service/credential_lease.go`.
- [ ] Fence direct, queued and recovery sends in `apps/edge/internal/service/provider_tunnel.go`.
- [ ] Add deterministic concurrent cases to `apps/edge/internal/service/credential_lease_test.go` and `apps/edge/internal/service/credential_delivery_test.go`.
- [ ] Add `apps/control-plane/internal/credentiallease/revocation_test.go` for rotate/revoke versus issuance ordering.

**Test Strategy:** Fake clock/barrier tests cover revoke-before-issue, revoke-after-issue-before-send, rotate during queue, duplicate/out-of-order projection, CP outage with expired cache, and revoke after upstream send. Run with `-race`; assert at most one upstream call and no retry on old revision.

**Verification:** `go test -count=1 -race ./apps/control-plane/internal/credentiallease ./apps/edge/internal/service ./apps/node/internal/node` must pass.

## Dependencies and Execution Order

1. `03+01,02_projection_auth` and `04+03_principal_routes` are satisfied by their exact archived `complete.log` paths above.
2. `07+01,02,05_secret_material` is not satisfied. Do not implement until `agent-task/m-principal-provider-credential-slot-routing/07+01,02,05_secret_material/complete.log` exists.
3. Within this packet implement API-1 and API-2 before API-3; API-4 completes the cross-boundary ordering invariant.
4. 09 and 10 wait for this directory's `complete.log`.

## Modified Files Summary

| File | Items |
|------|-------|
| `packages/go/auth/auth.go` | API-1 |
| `packages/go/config/edge_types.go` | API-1 |
| `packages/go/config/node_types.go` | API-1 |
| `packages/go/config/load.go` | API-1 |
| `packages/go/agentruntime/types.go` | API-3 |
| `apps/control-plane/cmd/control-plane/main.go` | API-1 |
| `apps/control-plane/cmd/control-plane/server.go` | API-1, API-2 |
| `apps/control-plane/internal/wire/edge_server.go` | API-1, API-2 |
| `apps/control-plane/internal/wire/credential_tls_test.go` | API-1 |
| `apps/control-plane/internal/credentiallease/service.go` | API-2 |
| `apps/control-plane/internal/credentiallease/service_test.go` | API-2 |
| `apps/control-plane/internal/credentiallease/revocation_test.go` | API-4 |
| `apps/edge/internal/controlplane/connector.go` | API-1, API-2 |
| `apps/edge/internal/transport/server.go` | API-1 |
| `apps/edge/internal/transport/credential_tls_test.go` | API-1 |
| `apps/edge/internal/bootstrap/runtime.go` | API-1, API-2 |
| `apps/edge/internal/input/manager.go` | API-2 |
| `apps/edge/internal/openai/dispatch_context.go` | API-3 |
| `apps/edge/internal/openai/chat_handler.go` | API-3 |
| `apps/edge/internal/openai/responses_handler.go` | API-3 |
| `apps/edge/internal/openai/anthropic_handler.go` | API-3 |
| `apps/edge/internal/openai/provider_tunnel.go` | API-3 |
| `apps/edge/internal/service/credential_lease.go` | API-2, API-4 |
| `apps/edge/internal/service/credential_lease_test.go` | API-2, API-4 |
| `apps/edge/internal/service/credential_delivery_test.go` | API-3, API-4 |
| `apps/edge/internal/service/provider_tunnel.go` | API-3, API-4 |
| `apps/edge/internal/service/run_types.go` | API-3 |
| `apps/node/internal/transport/client.go` | API-1 |
| `apps/node/internal/transport/credential_tls_test.go` | API-1 |
| `apps/node/internal/node/tunnel_handler.go` | API-3 |
| `apps/node/internal/node/credential_lease_test.go` | API-3, API-4 |
| `apps/node/internal/adapters/openai_compat/provider_tunnel.go` | API-3 |
| `apps/node/internal/adapters/openai_compat/credential_injection_test.go` | API-3 |
| `proto/iop/control.proto` | API-2 |
| `proto/iop/runtime.proto` | API-3 |
| `proto/gen/iop/control.pb.go` | API-2 |
| `proto/gen/iop/runtime.pb.go` | API-3 |
| `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/client/lib/gen/proto/iop/runtime.pb.dart` | API-3 |
| `apps/client/lib/gen/proto/iop/runtime.pbenum.dart` | API-3 |
| `apps/client/lib/gen/proto/iop/runtime.pbjson.dart` | API-3 |
| `apps/client/lib/gen/proto/iop/runtime.pbserver.dart` | API-3 |
| `configs/control-plane.yaml` | API-1 |
| `configs/edge.yaml` | API-1 |
| `configs/node.yaml` | API-1 |
| `agent-task/m-principal-provider-credential-slot-routing/08+03,04,07_secure_delivery/CODE_REVIEW-cloud-G10.md` | API-1, API-2, API-3, API-4 |

## Final Verification

Run from `/config/workspace/iop-s0`; Go cache is not acceptable.

```bash
command -v go && go version && go env GOROOT
command -v protoc && command -v flutter
git status --short --branch
make proto
make proto-dart
sha256sum proto/gen/iop/control.pb.go proto/gen/iop/runtime.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/client/lib/gen/proto/iop/runtime.pb.dart apps/client/lib/gen/proto/iop/runtime.pbenum.dart apps/client/lib/gen/proto/iop/runtime.pbjson.dart apps/client/lib/gen/proto/iop/runtime.pbserver.dart > /tmp/iop-credential-proto-first.sha256
make proto
make proto-dart
sha256sum proto/gen/iop/control.pb.go proto/gen/iop/runtime.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/client/lib/gen/proto/iop/runtime.pb.dart apps/client/lib/gen/proto/iop/runtime.pbenum.dart apps/client/lib/gen/proto/iop/runtime.pbjson.dart apps/client/lib/gen/proto/iop/runtime.pbserver.dart > /tmp/iop-credential-proto-second.sha256
diff -u /tmp/iop-credential-proto-first.sha256 /tmp/iop-credential-proto-second.sha256
go test -count=1 ./packages/go/auth ./packages/go/config
go test -count=1 ./apps/control-plane/internal/wire ./apps/control-plane/internal/credentiallease ./apps/control-plane/cmd/control-plane
go test -count=1 ./apps/edge/internal/authprojection ./apps/edge/internal/controlplane ./apps/edge/internal/transport ./apps/edge/internal/openai ./apps/edge/internal/service
go test -count=1 ./apps/node/internal/transport ./apps/node/internal/node ./apps/node/internal/adapters/openai_compat
go test -count=1 -race ./apps/control-plane/internal/credentiallease ./apps/edge/internal/authprojection ./apps/edge/internal/service ./apps/node/internal/node
go vet ./apps/control-plane/... ./apps/edge/... ./apps/node/... ./packages/go/...
rg --sort path -n 'ProviderSecret|credential.*secret|Authorization' proto/iop/control.proto proto/iop/runtime.proto apps/edge/internal/service apps/node/internal/node
```

Expected: the two generated-file manifests are identical; tests/vet/race pass; the final audit shows secret bytes only in explicitly named sensitive structs and auth injection code, never generic `headers`/metadata/status/log paths. Record every intentional match in review evidence. After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`.
