<!-- task=m-principal-provider-credential-slot-routing/05+01,02_management_core plan=6 tag=REVIEW_REVIEW_REVIEW_REVIEW_API -->

# Credential Security Assertion Evidence Closure

## For the Implementing Agent

Filling implementation-owned sections of `CODE_REVIEW-cloud-G05.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, attempted commands/output, and resume conditions only in implementation-owned evidence fields; do not ask the user, call user-input tools, create stop files, classify the next state, archive logs, or write `complete.log`.

## Background

The management core source and all focused/regression commands pass, but the permanent tests still overstate two required security claims. The ordered token list omits revision verification, while the secret failure matrix does not prove complete envelope-metadata redaction or exact revision-history preservation. This test-only follow-up closes those assertion gaps without changing production behavior or claiming S08 completion.

## Archive Evidence Snapshot

- Current pair after archive: `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_cloud_G05_5.log`, `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G05_5.log`.
- Verdict: FAIL; Required 2, Suggested 0, Nit 0; `review_rework_count=4`, `evidence_integrity_failure=true`.
- Required repairs: assert revision metadata in the complete ordered token list; scan every failure error/log for unique plaintext, sealer-error, ciphertext, nonce, AAD, key-ID, and key-version sentinels; handle all snapshot read errors; compare complete slot and revision-history state.
- Fresh reviewer verification: both focused race suites, full credentialstore/credentialops race tests, Control Plane regression tests, predecessor checks, formatting, vet, structural absence, probe absence, and `git diff --check` exited zero. Source inspection proved the listed assertion gaps.
- Roadmap carryover: this remains preparatory S08 evidence. PASS must not check `credential-management`; concrete at-rest sealing and confidential Client transport remain later S09/S10 work.

## Analysis

### Files Read

- `apps/control-plane/internal/credentialstore/principal_test.go`
- `apps/control-plane/internal/credentialops/service_test.go`
- `apps/control-plane/internal/credentialstore/principal.go`
- `apps/control-plane/internal/credentialstore/projection.go`
- `apps/control-plane/internal/credentialstore/slot.go`
- `apps/control-plane/internal/credentialstore/secret_envelope.go`
- `apps/control-plane/internal/credentialops/service.go`
- `apps/control-plane/internal/wire/client.go`
- `proto/iop/control.proto`
- `agent-contract/index.md`
- `agent-contract/inner/client-control-plane-wire.md`
- `agent-spec/index.md`
- `agent-spec/control/control-plane-operations.md`
- `agent-ops/rules/project/domain/control-plane/rules.md`
- `agent-ops/rules/project/domain/platform-common/rules.md`
- `agent-ops/rules/project/domain/testing/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/control-plane-smoke.md`
- `agent-test/local/platform-common-smoke.md`
- `agent-roadmap/phase/operational-observability-provider-management/PHASE.md`
- `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-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/PLAN-cloud-G05.md`
- `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/CODE_REVIEW-cloud-G05.md`
- `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/plan_cloud_G06_4.log`
- `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/code_review_cloud_G06_4.log`

### SDD Criteria

- SDD: `agent-roadmap/sdd/operational-observability-provider-management/principal-provider-credential-slot-routing/SDD.md`; status approved, lock released, no user review.
- Targeted preparatory criterion: S08 / `credential-management`; Evidence Map row S04-S08 requires management authorization, principal isolation, lifecycle revisions, and secret-blind results.
- The checklist requires exact lifecycle metadata and secret-blind failure evidence because those are necessary to trust the current S08 foundation. `Roadmap Targets` remains omitted because the complete S08 operation and the S09/S10 sealing/transport gates are outside this packet.

### Verification Context

- No external verification handoff was supplied. Repository-native evidence came from the local test profiles, current Go module, target tests and source, approved SDD, Client wire contract, active pair, exact prior loop logs, and fresh reviewer commands.
- Preflight: `/config/.local/bin/go`, Go 1.26.2 linux/arm64, `GOROOT=/config/opt/go`, repository root `/config/workspace/iop-s0`, intentional dirty worktree preserved.
- Preconditions: archived `01_principal_store` and `02+01_credential_catalog` each have exactly one `complete.log`.
- Fresh results: both focused race suites, full credentialstore/credentialops race tests, Control Plane regression, formatting, vet, structural absence, probe absence, and diff checks exit zero.
- No remote runner, external provider, credential, TLS endpoint, UI, protobuf generation, or full-cycle user flow is required because this packet modifies deterministic package tests only. Confidence: high.

### Test Coverage Gaps

- `TestAdditionalTokenIssueAndList` covers issuance generation, digest-only persistence, ordering, status, and rejected-issuance count/generation, but does not assert revision on the returned ordered records.
- `TestServiceSecretHandlingFailureIsBlindAndDoesNotMutate` covers create/rotate and three failure classes, owned-buffer zeroization, caller preservation, and coarse state checks, but does not use or scan the complete envelope sentinel set and compares history only by length while ignoring snapshot read errors.

### Symbol References

- None. No production or test symbol needs renaming or removal.

### Split Judgment

- Keep one packet: the two compact test changes close one evidence-integrity boundary and share the same final package regression.
- Runtime predecessor `01_principal_store` is satisfied by `agent-task/archive/2026/08/m-principal-provider-credential-slot-routing/01_principal_store/complete.log`.
- Runtime predecessor `02+01_credential_catalog` is satisfied by `agent-task/archive/2026/08/m-principal-provider-credential-slot-routing/02+01_credential_catalog/complete.log`.

### Scope Rationale

- Modify only `principal_test.go` and `service_test.go`; current source and fresh tests do not justify a production change.
- Exclude service/store APIs, protobuf, ClientServer, Dart, CLI, config, server wiring, contracts, schema, concrete encryption/key loading, remote management, and roadmap state.
- If a strengthened assertion exposes a production defect, stop and record the exact failure instead of expanding this packet silently.

### Final Routing

- `status=routed`, `evaluation_mode=isolated-reassessment`, finalizer=`finalize-task-policy.sh`, pair mode.
- Build closures all true; scores `1+1+0+2+1=G05`; base=`local-fit`, route=`recovery-boundary`, lane=`cloud`, canonical=`PLAN-cloud-G05.md`.
- Review closures all true; scores `1+1+0+2+1=G05`; route=`official-review`, lane=`cloud`, model=`gpt-5.6-sol` xhigh, canonical=`CODE_REVIEW-cloud-G05.md`.
- `large_indivisible_context=false`; risks=`temporal_state`, `variant_product` (2); `review_rework_count=4`; `evidence_integrity_failure=true`; recovery boundary matched; capability gap none.

## Dependencies and Execution Order

1. Archived predecessors `01_principal_store` and `02+01_credential_catalog` remain complete.
2. Close ordered token metadata, then close the shared secret-failure assertion helper/matrix and run the combined regression.

## Implementation Checklist

- [ ] Assert exact revision metadata in every returned record from `TestAdditionalTokenIssueAndList` while preserving generation, digest-only persistence, ordering, and rejected-issuance checks.
- [ ] Make every create/rotate secret failure case prove complete sentinel redaction and exact before/after slot, revision-history, and projection state with checked snapshot errors.
- [ ] Run fresh focused race, full package race, Control Plane regression, predecessor, formatting, vet, structural-absence, probe-absence, and diff verification.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_REVIEW_REVIEW_REVIEW_API-1] Close ordered token revision evidence

**Problem:** `apps/control-plane/internal/credentialstore/principal_test.go:857-870` compares the ordered `ListTokens` records by ID, token ref, digest, and status but omits `Revision`, so the plan's stable lifecycle metadata claim is not proven.

**Solution:** Add expected status and revision to the shared expected-token records and use those values for both direct row inspection and `ListTokens` comparisons. Check `rows.Err()` after iteration so the persistence assertion cannot silently accept a terminal scan error.

Before (`apps/control-plane/internal/credentialstore/principal_test.go:857-870`):

```go
for i, exp := range expectedTokens {
    // ID, TokenRef, Digest, Status assertions.
}
```

After:

```go
for i, exp := range expectedTokens {
    // Existing exact assertions.
    if list[i].Revision != exp.revision {
        t.Errorf("list[%d] Revision mismatch: got %d want %d", i, list[i].Revision, exp.revision)
    }
}
```

**Modified Files and Checklist:**

- [ ] `apps/control-plane/internal/credentialstore/principal_test.go`: compare exact ordered status/revision metadata and surface row iteration errors.

**Test Strategy:** Strengthen the existing test only. Keep three one-time raw-token results, exact SHA-256 row identity, projection increments, stable ordering, and rejected-issuance atomicity in the same deterministic fixture.

**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 -run 'AdditionalTokenIssueAndList'` exits 0.

### [REVIEW_REVIEW_REVIEW_REVIEW_API-2] Make the secret failure matrix exact

**Problem:** `apps/control-plane/internal/credentialops/service_test.go:1001-1420` checks only plaintext/error/key subsets, gives nonce/ciphertext/AAD no unique failure sentinels, gives key version no searchable sentinel, omits returned-error redaction checks in invalid-envelope cases, ignores several store snapshot errors, and compares revision history only by length.

**Solution:** Define distinct plaintext, sealer-error, ciphertext, nonce, AAD, key-ID, and key-version sentinels; make every applicable failing-sealer, unknown-key, and invalid-envelope create/rotate fixture carry them; and scan both the returned error and captured logs against the complete applicable forbidden set. Use checked snapshot helpers for projection, slot list, slot record, and full revision-history records, then compare complete before/after values with `reflect.DeepEqual` for every failed operation.

Before (`apps/control-plane/internal/credentialops/service_test.go:1128-1146`):

```go
slotAfter, _ := store.GetSlot(ctx, issued.Principal.ID, validSlot.ID)
historyAfter, _ := store.ListSlotRevisions(ctx, issued.Principal.ID, validSlot.ID)
if len(historyAfter) != len(historyBefore) {
    t.Fatal("slot revision history mutated")
}
genAfter, _ := store.ProjectionGeneration(ctx)
```

After:

```go
slotAfter := mustGetSlot(t, store, issued.Principal.ID, validSlot.ID)
historyAfter := mustListSlotRevisions(t, store, issued.Principal.ID, validSlot.ID)
if !reflect.DeepEqual(slotAfter, slotBefore) || !reflect.DeepEqual(historyAfter, historyBefore) {
    t.Fatal("failed rotation mutated persisted slot state")
}
genAfter := mustProjectionGeneration(t, store)
```

**Modified Files and Checklist:**

- [ ] `apps/control-plane/internal/credentialops/service_test.go`: add complete redaction sentinel sets, checked snapshot helpers, and exact create/rotate no-mutation comparisons.

**Test Strategy:** Strengthen `TestServiceSecretHandlingFailureIsBlindAndDoesNotMutate` and reuse `retainingSealer`. Cover create and rotate for failing sealer, unknown key/version, and invalid envelope; each case must prove owned-buffer zeroization, caller-buffer preservation, stable `ErrSecretHandlingFailed`, full error/log redaction, and exact persisted-state preservation.

**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 -run 'ZeroizesOwnedProviderSecret|SecretHandlingFailureIsBlindAndDoesNotMutate'` exits 0.

## Modified Files Summary

| File | Items |
|------|-------|
| `apps/control-plane/internal/credentialstore/principal_test.go` | REVIEW_REVIEW_REVIEW_REVIEW_API-1 |
| `apps/control-plane/internal/credentialops/service_test.go` | REVIEW_REVIEW_REVIEW_REVIEW_API-2 |
| `agent-task/m-principal-provider-credential-slot-routing/05+01,02_management_core/CODE_REVIEW-cloud-G05.md` | REVIEW_REVIEW_REVIEW_REVIEW_API-1, REVIEW_REVIEW_REVIEW_REVIEW_API-2 |

## Final Verification

Run from `/config/workspace/iop-s0`; fresh Go results are required and cached output is 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 && 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 predecessors remain uniquely complete.
2. `mkdir -p .cache/go-build .cache/go-cache` — workspace-local Go temp/cache paths exist.
3. `test -z "$(gofmt -d apps/control-plane/internal/credentialstore/principal_test.go apps/control-plane/internal/credentialops/service_test.go)"` — no Go formatting drift.
4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go vet ./apps/control-plane/internal/credentialstore ./apps/control-plane/internal/credentialops` — 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 ./apps/control-plane/internal/credentialops` — all store/service lifecycle, security, 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/...` — the Control Plane regression suite passes.
7. `if sed -n '/func TestServiceSecretHandlingFailureIsBlindAndDoesNotMutate/,/^}/p' apps/control-plane/internal/credentialops/service_test.go | rg -n ', _ := store\.(ProjectionGeneration|GetSlot|ListSlotRevisions|ListSlots)'; then exit 1; else exit 0; fi` — the target matrix ignores no store snapshot error.
8. `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 Client management operation exists.
9. `test ! -e apps/control-plane/internal/credentialops/reviewer_probe_test.go` — no reviewer probe remains.
10. `git diff --check` — no whitespace errors.

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