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

# Plan - Lock case-insensitive backing-adapter credential rejection

## For the Implementing Agent

Filling implementation-owned sections in `CODE_REVIEW-*-G??.md` is mandatory. Update only the two scoped regression fixture keys, run every verification command exactly as written, record actual notes plus each command's stdout/stderr and exit status 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 real exact-name and one-enabled type-fallback backing references are now present, and fresh reviewer verification passes. Both fixtures nevertheless use identical casing for the profile auth header and adapter map key, so they do not lock the case-insensitive comparison explicitly required by the prior plan and reviewer checkpoints.

## Archive Evidence Snapshot

- The closing pair will be `agent-task/m-principal-provider-credential-slot-routing/09+08_migration_attribution/plan_cloud_G04_4.log` and `agent-task/m-principal-provider-credential-slot-routing/09+08_migration_attribution/code_review_cloud_G04_4.log`; verdict `FAIL`, Required=1, Suggested=0, Nit=0, `review_rework_count=4`, and `evidence_integrity_failure=true`.
- Required finding: `packages/go/config/credential_plane_config_test.go:163` and `:189` use `X-Custom-Key` for both the profile header and referenced adapter map key, so neither fixture proves case-insensitive matching.
- Fresh reviewer execution passed the focused config suite, config/bootstrap/input, OpenAI/service, race, vet, diff, deterministic scan, and cleanup. The repository-local executable temporary directory was 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/credential_plane_config_test.go` and the active review evidence file; production source behavior is unchanged.

## Analysis

### Files Read

- `packages/go/config/validate.go`
- `packages/go/config/credential_plane_config_test.go`
- `apps/edge/internal/node/mapper.go`
- `agent-task/m-principal-provider-credential-slot-routing/09+08_migration_attribution/PLAN-cloud-G04.md`
- `agent-task/m-principal-provider-credential-slot-routing/09+08_migration_attribution/CODE_REVIEW-cloud-G04.md`

### 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 managed mode to reject every dual credential source while preserving disabled legacy behavior. S15 requires credential-slot attribution to remain distinct from inbound `token_ref` and secret-bearing labels.
- Evidence Map S14 requires migration/config rejection evidence; S15 requires dispatch/usage attribution and metric-label evidence. The case-variant real-reference fixtures complete S14's deterministic regression evidence, while unchanged OpenAI/service and race verification carries S15 evidence through this test-only correction.

### Verification Context

- Handoff: none supplied. Repository-native fallback used the active pair, current source/tests, selected Phase/Milestone and approved SDD, `agent-test/local/rules.md`, `agent-test/local/platform-common-smoke.md`, `agent-test/local/edge-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`, `agent-spec/input/openai-compatible-surface.md`, and the exact predecessor `complete.log` cited above.
- Reviewer evidence: Go resolved to `/config/.local/bin/go`, version `go1.26.2`, `GOROOT=/config/opt/go`; focused config, config/bootstrap/input, OpenAI/service, race, vet, diff, deterministic scan, and cleanup all passed fresh.
- Preconditions: the checkout is intentionally dirty with sibling Milestone work that must be preserved. `/tmp` is mounted `noexec`, so Go verification uses a newly created executable repository-local temporary directory and removes it afterward.
- External Verification Preflight: not applicable. This is deterministic regression-fixture and evidence work; no remote host, credential, live provider, port, or authorization is required.
- Gap: both committed real-reference fixtures use identical header casing despite claiming case-insensitive coverage. Confidence is high because the source locations are exact and production `matchesEffectiveProfileAuthHeader` already uses case folding.

### Test Coverage Gaps

- Exact named backing reference: covered, but its custom auth-header casing is identical and must become a case variant.
- One-enabled legacy type fallback: covered, but its custom auth-header casing is identical and must become a case variant.
- Safe-path/non-echo behavior: existing shared assertions cover both cases and must remain unchanged.
- Production behavior and slot attribution: fresh reviewer suites pass; no production change is required.

### Symbol References

None. No symbol is renamed or removed.

### Split Judgment

Keep one compact plan. The indivisible completion unit is the two real adapter-reference variants with the same case-insensitive credential-source invariant and one trustworthy verification packet. 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 `packages/go/config/validate.go`: fresh reviewer execution confirms production behavior is correct; only deterministic test coverage is missing.
- Exclude `apps/edge/internal/node/mapper.go`: it defines exact-name and type-fallback semantics but needs no change.
- Exclude contract, spec, roadmap, OpenAI/service, and metric source edits: their behavior and boundaries remain correct; those suites are regression evidence only.
- Exclude live provider, auxiliary E2E, and full-cycle runtime smoke because this is a test-fixture casing correction with no production or user execution path change.

### 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=0, evidence=2, verification=1, grade G04; base=`local-fit`, final route=`recovery-boundary`, lane=`cloud`, canonical file=`PLAN-cloud-G04.md`.
- Review closures are all true. Scores are scope=1, state=0, blast=0, evidence=2, verification=1, grade G04; route=`official-review`, lane=`cloud`, canonical file=`CODE_REVIEW-cloud-G04.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=4` and `evidence_integrity_failure=true`, so the recovery boundary applies. Capability gap: none.

## Implementation Checklist

- [ ] [REVIEW_REVIEW_REVIEW_REVIEW_API-1] Change both real backing-reference adapter map keys to a casing different from the uppercase profile auth header, preserve exact-name/type-fallback selection plus safe-path/non-echo assertions, and record every verification command's output and exit status independently.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_REVIEW_REVIEW_REVIEW_API-1] Lock case-insensitive real backing references

**Problem:** At `packages/go/config/credential_plane_config_test.go:153-163` and `:179-189`, each profile declares `Auth.Header: "X-Custom-Key"` and its referenced adapter map also uses `"X-Custom-Key"`. The cases exercise exact-name and one-enabled type fallback but do not prove `matchesEffectiveProfileAuthHeader` is case-insensitive.

**Solution:** Keep both uppercase profile declarations and change both referenced adapter map keys to lowercase `x-custom-key`. Retain the exact-name/type-fallback adapter selectors, enabled instances, safe config-path expectation, and credential-value non-echo assertion. Leave production validation unchanged.

Before (`packages/go/config/credential_plane_config_test.go:153-163` and `:179-189`):

```go
Auth: ProtocolAuthConf{Header: "X-Custom-Key"},
// ...
Headers: map[string]string{"X-Custom-Key": "redacted-fixture"},
```

After:

```go
Auth: ProtocolAuthConf{Header: "X-Custom-Key"},
// ...
Headers: map[string]string{"x-custom-key": "redacted-fixture"},
```

**Modified Files and Checklist:**

- [ ] `packages/go/config/credential_plane_config_test.go`: change both referenced adapter header keys to lowercase while preserving every backing-reference and safety assertion.
- [ ] `agent-task/m-principal-provider-credential-slot-routing/09+08_migration_attribution/CODE_REVIEW-cloud-G04.md`: record implementation notes and independent command outputs/statuses.

**Test Strategy:** Update the existing named and legacy-type subtests in `TestCredentialPlaneEnabledRejectsEveryCompetingSource`. Each must retain its real backing reference, reject the lowercase adapter key against uppercase `RuntimeProfile.Auth.Header`, return only the safe adapter-header path, and never echo `redacted-fixture`. No new production test file is needed because this correction strengthens the existing table cases.

**Verification:** Run every Final Verification command with `-count=1` and the repository-local executable temporary directory. Each result and exit status must be recorded separately; all commands must pass and cleanup must remove the directory.

## 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. Change both adapter map keys, then run and independently record the full verification packet.
3. Subtask `10+08,09_verification_contracts` continues to wait for this directory's `complete.log`.

## Modified Files Summary

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

## Final Verification

Run from `/config/workspace/iop-s0`. Cached test output is not acceptable. Record each command's stdout/stderr and exit status independently in the active review file.

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

Expected: tool discovery identifies the configured Go toolchain; the dirty worktree is preserved; both real backing-reference fixtures use lowercase adapter keys against uppercase profile auth headers; focused config, config/bootstrap/input, OpenAI/service, race, vet, diff, and deterministic scan commands each exit `0`; every result is recorded separately; and the temporary directory is absent afterward.

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