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

# 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`.
