<!-- task=m-principal-provider-credential-slot-routing/09+08_migration_attribution plan=3 tag=REVIEW_REVIEW_API milestone-task=compat-migration,slot-attribution -->

# Plan - Close backing-adapter credential validation and restore trusted evidence

## For the Implementing Agent

Filling implementation-owned sections in `CODE_REVIEW-*-G??.md` is mandatory. Implement the scoped change, run every verification command exactly as written, record actual notes plus stdout/stderr and exit statuses in the active review file, keep the active PLAN/review pair in place, and report ready for review. If blocked, record only the exact blocker, attempted commands/output, and resume condition in implementation-owned evidence fields. Do not ask the user, call user-input tools, create control-plane stop files, classify the next state, archive logs, or write `complete.log`; finalization belongs to the code-review skill.

## Background

The second follow-up review found that managed credential-plane validation still accepts a custom profile auth credential inherited from a referenced OpenAI-compatible backing adapter. It also found that the submitted bootstrap output cannot belong to the displayed repository-local `TMPDIR` command. This follow-up closes the remaining effective-source path and replaces stale verification evidence with fresh per-command results.

## Archive Evidence Snapshot

- The closing pair will be `agent-task/m-principal-provider-credential-slot-routing/09+08_migration_attribution/plan_local_G05_2.log` and `agent-task/m-principal-provider-credential-slot-routing/09+08_migration_attribution/code_review_cloud_G05_2.log`; verdict `FAIL`, Required=2, Suggested=0, Nit=0, `review_rework_count=2`, and `evidence_integrity_failure=true`.
- Required finding 1: provider-local headers are correlated with `RuntimeProfile.Auth.Header`, but legacy and named OpenAI-compatible adapter header maps still use heuristic names only even though `apps/edge/internal/node/mapper.go` copies those headers into profile-backed provider adapter configs. A temporary reviewer reproducer returned `nil` for an inherited `X-Custom-Key` credential.
- Required finding 2: the submitted bootstrap output names `/tmp/TestActualNodeReconnectReadyPumpsQueuedWaiterExactlyOnce.../iop-node` despite the displayed repository-local `TMPDIR`. The reviewer reran the exact package packet with an executable repository-local temporary directory and all config/bootstrap/input packages passed.
- Fresh reviewer OpenAI/service focused and race tests, `go vet`, `git diff --check`, and the deterministic source scan passed. The temporary reproducer and review temporary directory were removed.
- Predecessor `08` remains satisfied by `agent-task/archive/2026/08/m-principal-provider-credential-slot-routing/08+03,04,07_secure_delivery/complete.log` with verdict `PASS`. Do not search sibling archives.
- Follow-up writes are limited to `packages/go/config/validate.go`, `packages/go/config/credential_plane_config_test.go`, and the active review evidence file.

## Analysis

### Files Read

- `packages/go/config/validate.go`
- `packages/go/config/credential_plane_config_test.go`
- `packages/go/config/load.go`
- `packages/go/config/protocol_profile.go`
- `packages/go/config/adapter_types.go`
- `packages/go/config/provider_types.go`
- `apps/edge/internal/node/mapper.go`

### SDD Criteria

- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md`; status `[Approved]`, lock released, no user review.
- Generation scope remains `milestone-task=compat-migration,slot-attribution`.
- S14 requires disabled legacy behavior and enabled Control-Plane-only ownership with every dual-source conflict rejected. S15 requires slot attribution to remain distinct from inbound `token_ref` and secret-bearing labels.
- Evidence Map S14 requires migration/config table rejection and Responses regression evidence; S15 requires dispatch/usage attribution and metric-label evidence. The backing-adapter regression closes the remaining S14 source variant, and the unchanged OpenAI/service focused plus race packet carries the existing S15 evidence through this fix.

### Verification Context

- Handoff: none supplied. Repository-native fallback used the active pair, the exact prior review logs, the exact predecessor `complete.log`, the selected Milestone/SDD, `agent-test/local/rules.md`, `agent-test/local/edge-smoke.md`, `agent-test/local/platform-common-smoke.md`, `agent-contract/inner/edge-config-runtime-refresh.md`, `agent-contract/outer/openai-compatible-api.md`, `agent-spec/runtime/provider-pool-config-refresh.md`, and `agent-spec/input/openai-compatible-surface.md`.
- Reviewer commands: fresh config credential-plane tests; config/bootstrap/input package tests; OpenAI/service focused and race tests; `go vet ./apps/edge/... ./packages/go/...`; `git diff --check`; deterministic profile-source scan; and one temporary focused backing-adapter reproducer.
- Preconditions: Go resolves to `/config/.local/bin/go`, version `go1.26.2`, with `GOROOT=/config/opt/go`. The checkout is intentionally dirty with sibling Milestone work that must be preserved.
- Constraint: `/tmp` is mounted `noexec`; every Go command uses the exact executable repository-local temporary directory created in Final Verification, and that directory is removed afterward.
- External Verification Preflight: not applicable. This is load-time config validation with repository-native deterministic tests; no remote host, credential, port, or live provider is required.
- Gap: exact named and legacy-type backing-adapter references with a non-heuristic profile auth header lack regression coverage. Confidence is high because the mapper inheritance path is explicit and the focused reproducer failed on the current validator.

### Test Coverage Gaps

- Provider-local custom auth header, profile base URL user-info, absolute operation URL user-info, and unrelated provider-local custom headers are covered.
- A custom profile auth header inherited from a named OpenAI-compatible backing adapter is not covered and is accepted.
- The supported legacy-type `adapter: openai_compat` fallback to one enabled instance is not covered for the same custom auth-header invariant.
- Submitted verification evidence does not faithfully match its displayed `TMPDIR` command; the next review artifact must contain fresh per-command output and exit statuses.

### Symbol References

None. No symbol is renamed or removed.

### Split Judgment

Keep one compact plan. The indivisible invariant is that enabled managed mode rejects every static header that becomes the effective profile auth credential, whether declared on the provider or inherited from its backing adapter, and proves that behavior with trustworthy fresh output. Subtask predecessor `08` is satisfied by `agent-task/archive/2026/08/m-principal-provider-credential-slot-routing/08+03,04,07_secure_delivery/complete.log`.

### Scope Rationale

- Exclude `apps/edge/internal/node/mapper.go`: it proves the inheritance path but requires no behavior change; config validation can reject the source before payload compilation.
- Exclude OpenAI/service runtime and metric code: the defect is static source validation, and the existing suites remain regression evidence only.
- Exclude protocol-profile resolution, contracts, specs, and roadmap edits: their effective auth-header and Control-Plane-only rules are already correct.
- Exclude live provider and external smoke: no credential or network dependency is needed for this deterministic startup-validation fix.

### Final Routing

- `evaluation_mode=isolated-reassessment`; finalizer=`finalize-task-policy.sh`, mode=`pair`.
- Build closures are all true (`scope`, `context`, `verification`, `evidence`, `ownership`, `decision`). Scores are scope=1, state=0, blast=2, evidence=2, verification=1, grade G06; base=`local-fit`, final route=`recovery-boundary`, lane=`cloud`, canonical file=`PLAN-cloud-G06.md`.
- Review closures are all true. Scores are scope=1, state=0, blast=2, evidence=2, verification=1, grade G06; route=`official-review`, lane=`cloud`, canonical file=`CODE_REVIEW-cloud-G06.md`.
- `large_indivisible_context=false`. Positive loop risks are `boundary_contract`, `structured_interpretation`, and `variant_product` (3), so no risk boundary. Recovery signals are `review_rework_count=2` and `evidence_integrity_failure=true`, so the recovery boundary applies. Capability gap: none.

## Implementation Checklist

- [ ] [REVIEW_REVIEW_API-1] Reject custom effective profile auth credentials inherited from exact named and legacy-type OpenAI-compatible backing adapters, preserve unrelated custom headers, and add focused regressions.
- [ ] [REVIEW_REVIEW_API-2] Run the repository-local temporary-directory verification packet and record fresh per-command stdout/stderr and exit statuses without stale `/tmp` evidence.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_REVIEW_API-1] Reject profile auth credentials inherited from backing adapters

**Problem:** `packages/go/config/validate.go:88-95` correlates only `provider.Headers` with that provider's `RuntimeProfile.Auth.Header`. The adapter scans at `packages/go/config/validate.go:125-134` use generic header-name heuristics only. `apps/edge/internal/node/mapper.go:208-213` and `apps/edge/internal/node/mapper.go:267-295` copy headers from a referenced OpenAI-compatible adapter into the compiled profile-backed provider, so a non-heuristic custom auth header remains a managed-mode credential source.

**Solution:** Derive a case-insensitive set of effective profile auth headers for each node before scanning its adapter header maps. Preserve the existing provider-local comparison, and reject legacy or named OpenAI-compatible adapter headers when they are heuristic credential names or match any effective profile auth header used by that node. Keep error strings path-only and preserve the disabled-mode early return.

Before (`packages/go/config/validate.go:125-134`):

```go
for header := range node.Adapters.OpenAICompat.Headers {
	if isCredentialHeaderName(header) {
		return fmt.Sprintf("nodes[%d].adapters.openai_compat.headers[%q]", nodeIndex, header)
	}
}
for instanceIndex := range node.Adapters.OpenAICompatInstances {
	instance := &node.Adapters.OpenAICompatInstances[instanceIndex]
	for header := range instance.Headers {
		if isCredentialHeaderName(header) {
			return fmt.Sprintf("nodes[%d].adapters.openai_compat_instances[%d].headers[%q]", nodeIndex, instanceIndex, header)
		}
	}
}
```

After:

```go
effectiveProfileAuthHeaders := collectEffectiveProfileAuthHeaders(node.Providers)
for header := range node.Adapters.OpenAICompat.Headers {
	if isCredentialHeaderName(header) || matchesEffectiveProfileAuthHeader(header, effectiveProfileAuthHeaders) {
		return fmt.Sprintf("nodes[%d].adapters.openai_compat.headers[%q]", nodeIndex, header)
	}
}
for instanceIndex := range node.Adapters.OpenAICompatInstances {
	instance := &node.Adapters.OpenAICompatInstances[instanceIndex]
	for header := range instance.Headers {
		if isCredentialHeaderName(header) || matchesEffectiveProfileAuthHeader(header, effectiveProfileAuthHeaders) {
			return fmt.Sprintf("nodes[%d].adapters.openai_compat_instances[%d].headers[%q]", nodeIndex, instanceIndex, header)
		}
	}
}
```

**Modified Files and Checklist:**

- [ ] `packages/go/config/validate.go`: correlate adapter header maps with node effective profile auth headers and retain path-only errors.
- [ ] `packages/go/config/credential_plane_config_test.go`: add exact named and legacy-type backing-adapter custom auth-header rejection cases, safe-value non-echo assertions, and an unrelated adapter custom-header acceptance case.
- [ ] `agent-task/m-principal-provider-credential-slot-routing/09+08_migration_attribution/CODE_REVIEW-cloud-G06.md`: record the implementation and focused regression evidence.

**Test Strategy:** Extend `TestCredentialPlaneEnabledRejectsEveryCompetingSource` with a `RuntimeProfile.Auth.Header="X-Custom-Key"` provider backed by a named `OpenAICompatInstanceConf` carrying that header, plus the one-enabled-instance `adapter="openai_compat"` fallback variant. Extend acceptance coverage with an adapter custom header that differs from every effective profile auth header. Assert the returned error includes only the safe adapter path and never the fixture value.

**Verification:** `TMPDIR="$IOP_MIGRATION_ATTRIBUTION_TMPDIR" go test -count=1 ./packages/go/config -run 'TestCredentialPlane'` must pass and exercise the new backing-adapter variants.

### [REVIEW_REVIEW_API-2] Restore trustworthy final verification evidence

**Problem:** The archived review evidence at `CODE_REVIEW-cloud-G05.md:118-141` displays a repository-local `TMPDIR` command but records a `/tmp/.../iop-node` execution failure. That output is contradicted by a fresh reviewer run of the displayed package packet, which passed with the repository-local temporary directory.

**Solution:** Create the exact task temporary directory only after proving it is absent, apply it to every Go verification command, and record each command's actual stdout/stderr and exit status independently in the active review artifact. Do not reuse the archived `/tmp` failure text.

Before (`CODE_REVIEW-cloud-G05.md:128-141`):

```text
--- FAIL: TestActualNodeReconnectReadyPumpsQueuedWaiterExactlyOnce
    start actual iop-node: fork/exec /tmp/.../iop-node: permission denied
```

After:

```text
Record only the fresh output produced by each Final Verification command with
TMPDIR=/config/workspace/iop-s0/.agent-migration-attribution-review-tmp,
followed by that command's exact exit status.
```

**Modified Files and Checklist:**

- [ ] `agent-task/m-principal-provider-credential-slot-routing/09+08_migration_attribution/CODE_REVIEW-cloud-G06.md`: paste fresh per-command output and exit statuses, explain any real deviation, and confirm cleanup.

**Test Strategy:** No separate test file is needed; this item is the evidence-integrity gate for the exact repository-native command packet. The reviewer will rerun the same commands and compare results.

**Verification:** Run every command in Final Verification exactly once against the newly created repository-local temporary directory; all tests, race tests, vet, diff, scan, and cleanup checks must exit `0`.

## Dependencies and Execution Order

1. Predecessor `08` is satisfied by `agent-task/archive/2026/08/m-principal-provider-credential-slot-routing/08+03,04,07_secure_delivery/complete.log`.
2. Implement REVIEW_REVIEW_API-1, then run and record REVIEW_REVIEW_API-2.
3. Subtask `10+08,09_verification_contracts` continues to wait for this directory's `complete.log`.

## Modified Files Summary

| File | Items |
|------|-------|
| `packages/go/config/validate.go` | REVIEW_REVIEW_API-1 |
| `packages/go/config/credential_plane_config_test.go` | REVIEW_REVIEW_API-1 |
| `agent-task/m-principal-provider-credential-slot-routing/09+08_migration_attribution/CODE_REVIEW-cloud-G06.md` | REVIEW_REVIEW_API-1, REVIEW_REVIEW_API-2 evidence |

## Final Verification

Run from `/config/workspace/iop-s0`. Cached test output is not acceptable; every Go test uses `-count=1`.

```bash
command -v go
go version
go env GOROOT
git status --short --branch
export IOP_MIGRATION_ATTRIBUTION_TMPDIR=/config/workspace/iop-s0/.agent-migration-attribution-review-tmp
test ! -e "$IOP_MIGRATION_ATTRIBUTION_TMPDIR"
mkdir "$IOP_MIGRATION_ATTRIBUTION_TMPDIR"
TMPDIR="$IOP_MIGRATION_ATTRIBUTION_TMPDIR" go test -count=1 ./packages/go/config -run 'TestCredentialPlane'
TMPDIR="$IOP_MIGRATION_ATTRIBUTION_TMPDIR" go test -count=1 ./packages/go/config ./apps/edge/internal/bootstrap ./apps/edge/internal/input
TMPDIR="$IOP_MIGRATION_ATTRIBUTION_TMPDIR" go test -count=1 ./apps/edge/internal/openai ./apps/edge/internal/service
TMPDIR="$IOP_MIGRATION_ATTRIBUTION_TMPDIR" go test -count=1 -race ./apps/edge/internal/openai ./apps/edge/internal/service
TMPDIR="$IOP_MIGRATION_ATTRIBUTION_TMPDIR" go vet ./apps/edge/... ./packages/go/...
git diff --check
rg --sort path -n 'X-Custom-Key|effectiveProfileAuthHeaders|profile.*base_url|profile.*operations|openai_compat(_instances)?' packages/go/config/validate.go packages/go/config/credential_plane_config_test.go
rmdir "$IOP_MIGRATION_ATTRIBUTION_TMPDIR"
test ! -e "$IOP_MIGRATION_ATTRIBUTION_TMPDIR"
```

Expected: tool discovery identifies the configured Go toolchain; the dirty worktree is preserved; managed mode rejects provider-local and backing-adapter effective auth credentials while accepting unrelated custom headers; config/bootstrap/input, OpenAI/service, race, and vet commands all exit `0`; diff and deterministic scans are clean and intentional; the temporary directory is absent afterward.

After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`.
