<!-- task=m-node-provider-execution-liveness-recovery/12+08_health_overlay_observability plan=4 tag=REVIEW_REVIEW_REFACTOR milestone-task=ops-evidence -->

# Close the Remaining Provider-Health Leakage Oracle Gap

## For the Implementing Agent

Implement only the test-evidence repair selected below, run every verification command, and fill all implementation-owned sections of `CODE_REVIEW-cloud-G03.md` with actual notes and raw output. Keep the active files in place and report ready for review; finalization belongs to the code-review skill. 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`.

## Background

The normalized/tunnel state matrix, public snapshot assertions, and production `Capabilities` recovery path now satisfy the earlier R1 state-transition requirements. The remaining leakage oracle still fills only failure metadata while leaving several direct protobuf identity and raw payload fields empty, so it can pass even if those actual inputs leak. This follow-up closes that single SDD S06 evidence gap without changing production behavior.

## Archive Evidence Snapshot

- Prior pair: `agent-task/m-node-provider-execution-liveness-recovery/12+08_health_overlay_observability/plan_cloud_G04_3.log` and `agent-task/m-node-provider-execution-liveness-recovery/12+08_health_overlay_observability/code_review_cloud_G04_3.log`; verdict `FAIL` with Required R1.
- R1 evidence: `TestProviderHealthObservabilityDoesNotExposeSentinels` leaves direct `RunEvent.NodeId`, `RunEvent.SessionId`, `RunEvent.Message`, `RunEvent.Error`, `ProviderTunnelFrame.NodeId`, `ProviderTunnelFrame.Headers`, `ProviderTunnelFrame.Body`, and `ProviderTunnelFrame.Error` inputs empty and omits the authoritative/bound node, provider, adapter, and target values from its forbidden set.
- Reviewer verification: focused verbose, repeated, and race observability tests passed; `go vet` and `git diff --check` passed. The full service package still fails only in independently owned `apps/edge/internal/service/provider_recovery_selection_test.go:250`; do not modify that file.
- Carryover: preserve the corrected normalized/tunnel unavailable-stale-recovery matrix, public snapshots, production `Capabilities` recovery, production observer/overlay, contracts, specs, roadmap, and prior smoke evidence unchanged. SDD S06 remains the acceptance source.

## Finding Resolution Map

| Finding | Mode | Exact resolution | Changed precondition |
|---------|------|------------------|----------------------|
| Required R1 | `direct-fix` | Populate every available direct `RunEvent` and `ProviderTunnelFrame` identity/message/error/header/body input with distinct sentinels, include every authoritative and bound identity actually supplied to the handlers in the forbidden set, and scan all metric labels plus dedicated log messages/keys/values. | The leakage test will fail if either a direct protobuf raw input or an authoritative/bound node/provider/adapter/target value reaches the provider-health metrics or structured log. |

## Analysis

### Files Read

- `apps/edge/internal/service/provider_health_observability_test.go`
- `apps/edge/internal/service/provider_health_observability.go`
- `apps/edge/internal/service/service.go`
- `apps/edge/internal/service/provider_tunnel.go`
- `apps/edge/internal/service/node_command.go`
- `apps/edge/internal/service/model_queue_release.go`
- `apps/edge/internal/service/model_queue_snapshot.go`
- `proto/gen/iop/runtime.pb.go`
- `agent-contract/inner/edge-config-runtime-refresh.md`
- `agent-spec/runtime/provider-pool-config-refresh.md`
- `agent-roadmap/phase/operational-observability-provider-management/PHASE.md`
- `agent-roadmap/phase/operational-observability-provider-management/milestones/node-provider-execution-liveness-recovery.md`
- `agent-roadmap/sdd/operational-observability-provider-management/node-provider-execution-liveness-recovery/SDD.md`
- `agent-test/local/rules.md`
- `agent-test/local/edge-smoke.md`
- `agent-task/m-node-provider-execution-liveness-recovery/12+08_health_overlay_observability/plan_cloud_G04_3.log`
- `agent-task/m-node-provider-execution-liveness-recovery/12+08_health_overlay_observability/code_review_cloud_G04_3.log`

### SDD Criteria

- SDD: `agent-roadmap/sdd/operational-observability-provider-management/node-provider-execution-liveness-recovery/SDD.md`; status `[승인됨]`; `milestone-task=ops-evidence`.
- Acceptance Scenario S06 requires provider-health metric/log and snapshot evidence with no high-cardinality identity or raw content exposure.
- Evidence Map S06 requires metric label guards and structured-log capture. Those requirements make direct protobuf inputs and authoritative/bound identities part of the forbidden-value oracle and drive both the implementation checklist and focused verification.

### Verification Context

- No external handoff was supplied. Repository-native review used Go `1.26.2`, module `/config/workspace/iop-s1/go.mod`, the approved SDD, current protobuf fields, production reception/observation paths, and private Prometheus/zap fixtures.
- Fresh reviewer commands passed for focused verbose, count-20, race, vet, and diff checks. The full service package reproduced the unrelated active sibling panic at `apps/edge/internal/service/provider_recovery_selection_test.go:250`.
- No external runner, credential, smoke environment, or full-cycle runtime is required because this packet changes only a deterministic test oracle and preserves production behavior. The unrelated sibling file remains outside ownership.
- Confidence is high: the missing direct inputs are explicit in the protobuf types and the fix is confined to one test.

### Test Coverage Gaps

- Direct normalized inputs `NodeId`, `SessionId`, `Message`, and `Error` are not populated with leak-detection sentinels.
- Direct tunnel inputs `NodeId`, `Headers`, `Body`, and `Error` are not populated with leak-detection sentinels.
- The forbidden set does not contain the actual handler node id or bound provider/adapter/target identities.
- Existing matrix, public snapshot, recovery, duplicate-terminal, collector reuse, and post-lock assertions already cover their intended behavior and must remain unchanged.

### Symbol References

- None. No production symbol is renamed or removed.

### Split Judgment

- Keep one compact test-only packet. Direct field population and the forbidden-set scan are one leakage-oracle invariant and have one deterministic focused verification surface.
- The subtask predecessor remains satisfied by the existing `08+07_health_overlay` completion evidence already carried by the prior loop. Active sibling `09+08_retry_candidate_policy` is unordered and owns a different test file.

### Scope Rationale

- Modify only `apps/edge/internal/service/provider_health_observability_test.go` and implementation-owned evidence in the active review stub.
- Do not modify production Go files, protobuf sources/generated output, contracts, specs, roadmap files, smoke scripts, or sibling task artifacts.
- In particular, do not modify `apps/edge/internal/service/provider_recovery_selection_test.go` to make the full package command pass.

### Final Routing

- `evaluation_mode=isolated-reassessment`; finalizer=`finalize-task-policy.sh pair`.
- Build closures are all true; scores `(0,0,0,2,1)`, grade G03, base `local-fit`, escalated by `recovery-boundary` because `review_rework_count=2` and `evidence_integrity_failure=true`; canonical file `PLAN-cloud-G03.md`.
- Review closures are all true; scores `(0,0,0,2,1)`, grade G03, route `official-review`; canonical file `CODE_REVIEW-cloud-G03.md` (`codex`, `gpt-5.6-sol`, `xhigh`).
- `large_indivisible_context=false`; positive loop risks are `boundary_contract` and `variant_product` (2). `risk_boundary=false`; `recovery_boundary=true`; capability gap none.

## Implementation Checklist

- [ ] REVIEW_REVIEW_REFACTOR-1 injects distinct sentinels into every available direct `RunEvent` and `ProviderTunnelFrame` identity/message/error/header/body input, includes actual authoritative/bound identities in the forbidden set, and retains complete metric-label and structured-log scans.
- [ ] Run the focused, package, race, vet, and diff commands in Final Verification with fresh output; if the independently owned active sibling still fails, record its exact path and output without modifying it.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_REVIEW_REFACTOR-1] Exercise actual identity and raw protobuf inputs

**Problem:** `apps/edge/internal/service/provider_health_observability_test.go:258-315` creates synthetic forbidden strings but supplies them only through `ExecutionFailure.Message` and metadata. The direct normalized and tunnel fields stay empty, and the actual authoritative/bound identities are not scanned, leaving a false-negative path in the S06 leakage guard.

**Solution:** Preserve the current applied normalized terminal and tunnel terminal fixtures, but give each available direct event/frame identity and raw field its own sentinel. Add the handler's authoritative node id and the lease-bound provider, adapter, and target to the forbidden list even when the payload also carries untrusted sentinel identities. Scan every gathered metric label and every dedicated log message/key/value against that complete input-derived set.

Before (`apps/edge/internal/service/provider_health_observability_test.go:299`):

```go
event := &iop.RunEvent{
    RunId:    forbiddenValues[2],
    Type:     "error",
    Failure:  failure,
    Metadata: failure.Metadata,
}
```

After:

```go
event := &iop.RunEvent{
    RunId: forbiddenRunID, Type: "error", NodeId: forbiddenPayloadNodeID,
    SessionId: forbiddenSessionID, Message: forbiddenMessage, Error: forbiddenError,
    Failure: failure, Metadata: failure.Metadata,
}
frame := &iop.ProviderTunnelFrame{
    RunId: forbiddenFrameRunID, NodeId: forbiddenFrameNodeID,
    Headers: map[string]string{forbiddenHeaderName: forbiddenCredential},
    Body: []byte(forbiddenBody), Error: forbiddenFrameError,
    Kind: iop.ProviderTunnelFrameKind_PROVIDER_TUNNEL_FRAME_KIND_ERROR,
    Failure: frameFailure, Metadata: frameFailure.Metadata,
}
forbiddenValues = append(forbiddenValues, entry.NodeID, overlayProviderID, overlayAdapter, overlayTarget)
```

**Modified Files and Checklist:**

- [ ] `apps/edge/internal/service/provider_health_observability_test.go`: populate direct protobuf fields and complete the actual-input forbidden set.
- [ ] `agent-task/m-node-provider-execution-liveness-recovery/12+08_health_overlay_observability/CODE_REVIEW-cloud-G03.md`: record decisions and fresh command output.

**Test Strategy:** Strengthen `TestProviderHealthObservabilityDoesNotExposeSentinels` in the existing file. Assert absence for every actual direct protobuf input and authoritative/bound identity across every gathered label and dedicated log field; keep the production observer fixture and both reception handlers.

**Verification:** `go test -count=20 ./apps/edge/internal/service -run '^TestProviderHealthObservabilityDoesNotExposeSentinels$'` must pass every iteration after source inspection confirms the listed direct fields are populated.

## Modified Files Summary

| File | Item |
|------|------|
| `apps/edge/internal/service/provider_health_observability_test.go` | REVIEW_REVIEW_REFACTOR-1 |
| `agent-task/m-node-provider-execution-liveness-recovery/12+08_health_overlay_observability/CODE_REVIEW-cloud-G03.md` | REVIEW_REVIEW_REFACTOR-1 |

## Final Verification

Fresh Go output is required; cached output is not acceptable.

1. `go test -v -count=1 ./apps/edge/internal/service -run '^TestProviderHealthObservability'` — PASS and display normalized, tunnel, duplicate, default-collector, lock-safety, and forbidden-input rows.
2. `go test -count=20 ./apps/edge/internal/service -run '^TestProviderHealthObservabilityDoesNotExposeSentinels$'` — PASS every iteration for the strengthened leakage oracle.
3. `go test -count=20 ./apps/edge/internal/service -run '^TestProviderHealthObservability'` — PASS every iteration for the full observability set.
4. `go test -count=1 ./apps/edge/internal/service` — PASS after independently owned active sibling tests are valid; if the same out-of-scope sibling failure remains, record its exact path and output without modifying it.
5. `go test -race -count=3 ./apps/edge/internal/service -run '^TestProviderHealthObservability'` — PASS with no race report.
6. `go vet ./apps/edge/internal/service` — no diagnostics.
7. `git diff --check` — no whitespace errors.

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