<!-- task=m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap plan=0 tag=API -->

# Host-Local Principal Bootstrap

## 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 host-local way to create the first principal and return its raw IOP token once. The command must open the configured store directly and must not add any credential-bearing operation to the current plaintext Client WebSocket.

## 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: host-local bootstrap is independently implementable and verifiable from the in-process management service retained in sibling `05+01,02_management_core`.
- Roadmap carryover: this remains preparatory. PASS must not check `credential-management`; S08 still requires S09 at-rest sealer and S10 confidential Client transport rollout.

## Analysis

### Files Read

- `apps/control-plane/cmd/control-plane/main.go`
- `apps/control-plane/cmd/control-plane/server.go`
- `apps/control-plane/cmd/control-plane/config_test.go`
- `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 the confidential remote operation required for full S08 remains excluded.
- Checklist covers host-local-only bootstrap, one-time raw token output, restart persistence, redaction, and structural proof that no bootstrap/management protobuf or ClientServer listener is introduced.

### Verification Context

- No handoff exists. The SDD forbids credential-bearing operations on the current plain WebSocket.
- Go 1.26.2 linux/arm64. Tests use temp SQLite, injected logger/random reader, explicit stdout/stderr writers, 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

- CLI exposes only `serve`; no first-principal bootstrap, idempotency, restart, or one-time-output test exists.
- No structural test protects the intentional absence of credential-bearing ClientServer listeners and protobuf messages.

### Symbol References

- Rename/remove 없음.
- `rootCmd` adds commands at `main.go:61`; `serveCmd` remains unchanged.
- `wire.NewClientServer` and Dart client/parser call sites remain unchanged.

### Split Judgment

- This child owns the direct host-local command, one-time stdout contract, and plaintext-network absence guard.
- Sibling `05+01,02_management_core` independently owns the reusable authorization/CAS service.
- The bootstrap command and its CLI-only/absence tests stay together because those tests define its safe exposure boundary.

### Scope Rationale

- Do not modify `proto/iop/control.proto`, ClientServer, Dart client/parser, configs, or Control Plane server wiring.
- Do not depend on sibling 05; open the packet-01 store directly.
- Do not add remote bootstrap, credential reveal, concrete sealer/key loading, 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+1+2+1+1=G06`; base/route=`local-fit`, lane=`local`, canonical=`PLAN-local-G06.md`.
- Review closures all true; scores `1+1+2+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`, `boundary_contract` (2); 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 direct DB bootstrap, then one-time output/restart tests and structural absence guards.
3. No dependency absent from `06+01,02_host_local_bootstrap` may be introduced.

## Implementation Checklist

- [ ] Add a host-local-only first-principal/bootstrap CLI that emits the initial raw IOP token exactly once and never logs or persists it.
- [ ] Prove first bootstrap, existing-principal refusal, one-time output, restart persistence, and raw-token redaction with deterministic tests.
- [ ] Prove no management/bootstrap protobuf, ClientServer listener, Dart method, or plaintext network activation was added; leave S08 completion for S09/S10 rollout.
- [ ] Run fresh CLI, Control Plane regression, archive-predecessor, structural absence, vet, and diff verification.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [API-2] Add host-local first-principal bootstrap

**Problem:** `apps/control-plane/cmd/control-plane/main.go:59-62` registers only `serve`, leaving no deployment-admin bootstrap path.

**Solution:** Add `principal bootstrap --alias` that loads config, opens the DB directly, refuses when any principal already exists, issues the first token through packet-01 store, and writes the raw token once to command stdout without zap/error inclusion. No remote operation is added.

Before (`apps/control-plane/cmd/control-plane/main.go:59-62`):

```go
root.PersistentFlags().StringVarP(&cfgFile, "config", "c", "configs/control-plane.yaml", "config file path")
root.AddCommand(serveCmd())
return root
```

After:

```go
root.PersistentFlags().StringVarP(&cfgFile, "config", "c", "configs/control-plane.yaml", "config file path")
root.AddCommand(serveCmd(), principalCmd())
return root
```

**Modified Files and Checklist:**

- [ ] `apps/control-plane/cmd/control-plane/main.go`: register the host-local principal command.
- [ ] `apps/control-plane/cmd/control-plane/credential_commands.go`: implement direct DB bootstrap with explicit stdout/stderr writers.
- [ ] `apps/control-plane/cmd/control-plane/credential_commands_test.go`: test first bootstrap, second refusal, restart, one-time stdout, log/error redaction, and CLI-only exposure.

**Test Strategy:** Write `TestPrincipalBootstrapEmitsTokenOnce`, `TestPrincipalBootstrapRefusesExistingPrincipal`, `TestPrincipalBootstrapPersistsAcrossReopen`, and `TestBootstrapLogsNeverContainToken`.

**Verification:** `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/cmd/control-plane -run 'PrincipalBootstrap|Bootstrap|Credential'` passes.

### [API-3] Guard the secure-transport boundary

**Problem:** a future implementer could expose bootstrap on the current plaintext ClientServer and create the SDD-forbidden credential path.

**Solution:** Keep bootstrap registered only as a host-local Cobra command. Add source-level absence tests that fail if bootstrap/credential protobuf messages or ClientServer credential listeners appear.

Before (`proto/iop/control.proto`, current client baseline):

```protobuf
message ClientHelloRequest {
  string client_id = 1;
  string client_version = 2;
}
```

After:

```text
unchanged: no BootstrapRequest, CredentialOperationRequest, or raw token field
```

**Modified Files and Checklist:**

- [ ] `apps/control-plane/cmd/control-plane/credential_commands_test.go`: inspect root commands and prove bootstrap is CLI-only.

**Test Strategy:** Use deterministic `rg` final verification plus command tests; no wire/Dart test changes are required because their contract remains untouched.

**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/cmd/control-plane/main.go` | API-2 |
| `apps/control-plane/cmd/control-plane/credential_commands.go` | API-2 |
| `apps/control-plane/cmd/control-plane/credential_commands_test.go` | API-2, API-3 |
| `agent-task/m-principal-provider-credential-slot-routing/06+01,02_host_local_bootstrap/CODE_REVIEW-cloud-G06.md` | API-2, 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/cmd/control-plane` — no vet findings.
4. `GOTMPDIR=/config/workspace/iop-s0/.cache/go-build GOCACHE=/config/workspace/iop-s0/.cache/go-cache go test -count=1 ./apps/control-plane/cmd/control-plane -run 'PrincipalBootstrap|Bootstrap|Credential'` — focused bootstrap 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`.
