# Milestone: Provider 기준 Usage Attribution Hot Path

## 위치

- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
- Phase: [PHASE.md](../PHASE.md)

## 목표

OpenAI-compatible hot path의 provider-reported token usage를 가상 요청 모델명이 아니라 실제 호출된 provider와 served model에 귀속한다. 가상 `model_group` 집계는 명시적으로 동일 논리 모델로 승인된 group에서만 허용하고, 단독·하이브리드·재시도/fallback 경로는 각 실제 호출 시도의 provider usage를 분리해 기록한다.

## 상태

[완료]

## 승격 조건

- 없음

## 구현 잠금

- 상태: 해제
- SDD: 필요
- SDD 문서: [SDD.md](../../../sdd/operational-observability-provider-management/provider-usage-attribution-hot-path/SDD.md)
- SDD 사유: OpenAI usage metric의 attribution contract, direct route provider identity, provider-pool retry/fallback의 시도별 관측과 Grafana query 기준을 함께 바꾼다.
- 잠금 해제 조건:
  - [x] SDD 잠금이 해제되어 있다.
  - [x] SDD 사용자 리뷰가 없거나 승인/해결되었다.
  - [x] Acceptance Scenario가 Milestone 기능 Task와 연결되어 있다.
  - [x] Evidence Map이 완료 시 `Roadmap Completion`과 최종 검증 evidence로 검증 가능하게 연결되어 있다.
- 결정 필요: 없음

## 범위

- provider-reported input/output/reasoning/cached-input token을 실제 `provider_id`와 served model에 귀속하는 OpenAI metric attribution contract
- `models[].usage_attribution=model_group`으로 명시 승인된 동일 논리 모델 group만 가상 model-group rollup을 허용하고, 기본값 `provider`를 적용하는 config/validation 기준
- direct/legacy route와 provider-pool hybrid route 모두에서 실제 provider identity를 dispatch 결과로 보존하는 경로
- retry/fallback을 포함한 각 실제 provider 호출 시도별 usage emission 및 저-cardinality label guard
- Grafana usage query와 운영 가이드의 provider 기준 migration

## 기능

### Epic: [attribution] Actual Provider Usage Attribution

단일·하이브리드 실행에서 token 사용량을 실제 provider 호출에 정확히 귀속하는 hot-path capability를 묶는다.

- [x] [group-policy] `models[].usage_attribution=model_group`으로 명시 승인된 동일 논리 모델 group만 가상 rollup query를 허용하고, 기본값 및 그 밖의 route에는 provider 기준 attribution을 강제한다. 검증: group·direct·hybrid config/route test에서 attribution basis가 기대값과 일치하고 별도 group counter가 중복 emit되지 않는다.
- [x] [dispatch-binding] direct/legacy의 `openai.model_routes[].provider_id`와 top-level fallback `openai.provider_id`, provider-pool의 normalized/tunnel dispatch가 실제 `provider_id`, served model, node identity를 metric emitter까지 전달한다. 검증: adapter 이름만으로 provider를 대체하지 않고 각 dispatch binding을 검증한다.
- [x] [attempt-usage] hybrid selection, retry, fallback에서 provider-reported token 및 reasoning observation usage를 실제 호출 시도별 provider binding으로 emit한다. 검증: provider가 바뀌는 deterministic test에서 token series가 각 provider에 분리되어 증가하고 request terminal counter는 한 번만 증가한다.

### Epic: [operations] Usage Metric Migration

provider 기준 운영 조회를 기존 OpenAI usage metric과 Grafana 가이드에 정착시킨다.

- [x] [metric-contract] metric label allowlist와 OpenAI-compatible 관측 계약을 provider attribution 기준으로 갱신하고 기존 `model_group`은 `route_model` trace와 승인된 rollup query로 migration한다. 검증: secret/high-cardinality label guard와 metric contract test가 통과한다.
- [x] [grafana-migration] Grafana query와 usage 운영 가이드를 provider 기준 집계 및 승인된 model-group rollup 기준으로 갱신한다. 검증: 대표 provider·group query가 metric label schema와 일치한다.

## 완료 리뷰

- 상태: 통과
- 요청일: 2026-07-31
- 완료 근거: `group-policy`, `dispatch-binding`, `attempt-usage`, `metric-contract`의 현재 코드·계약·검증 evidence와 `grafana-migration`의 [Grafana query guide](../../../../docs/openai-usage-grafana.md) actual-provider/승인-group PromQL schema 검증이 충족되었다. 종료 감사에서 provider-pool Stream Gate 준비 실패의 request terminal 누락을 Chat/Responses 양쪽에서 보완하고, direct-route `provider_id` 필수 계약을 기존 성공 fixture·E2E 설정·운영 가이드에 동기화했다. `go test -count=1 ./packages/go/streamgate ./apps/edge/internal/openai`, `go test -count=1 ./packages/go/config ./apps/edge/internal/service`, `go test -count=1 ./apps/edge/cmd/edge ./apps/edge/internal/bootstrap ./apps/edge/internal/configrefresh`, `go test -race -count=1 ./packages/go/streamgate ./packages/go/config ./apps/edge/internal/openai`가 통과했다.
- Spec sync: [OpenAI-compatible 입력 표면](../../../../agent-spec/input/openai-compatible-surface.md)과 [Edge-Node 실행 경로](../../../../agent-spec/runtime/edge-node-execution.md)가 actual-provider dispatch binding, attempt usage, exactly-once terminal 및 Grafana migration 상태와 일치한다. 결과: Spec updated.
- 남은 차단 항목: 없음
- 검토 항목: 기능 Task의 deterministic attribution 검증, Grafana query migration, SDD Evidence Map 충족과 구현 잠금 해제를 함께 확인한다.
- 리뷰 코멘트: 전체 `go test ./...` 보조 실행의 잔여 실패는 다음 `IOP Agent CLI Runtime` 범위의 fake-owner Unix socket/권한 fixture와 taskloop 규칙 검사에 한정되며, 현재 마일스톤의 Edge·Node·config·OpenAI 범위에는 실패가 없다.

## 범위 제외

- request ledger storage, 장기 retention, export API, billing/chargeback
- provider routing 알고리즘, capacity/queue timeout 정책 변경
- provider가 보고하지 않은 token의 추정 또는 billing-grade 복원
- Control Plane/Flutter client의 신규 usage 화면

## 작업 컨텍스트

- 관련 경로: `apps/edge/internal/openai`, `apps/edge/internal/service`, `packages/go/config`, `configs/edge.yaml`, `docs/openai-usage-grafana.md`, `agent-contract/outer/openai-compatible-api.md`
- 표준선(선택): canonical token attribution은 실제 dispatch provider binding이며, `model_group`은 `models[].usage_attribution=model_group`으로 명시 승인된 동일 논리 모델의 query-time rollup에만 사용한다. 기본 attribution은 `provider`다.
- 표준선(선택): provider-pool 재시도/fallback은 client 응답이 하나여도 provider-reported usage가 있는 각 실제 호출 시도를 독립 provider series로 기록한다.
- 선행 작업: [Provider Resource Admission Ownership 정합화](../../../../archive/phase/operational-observability-provider-management/milestones/provider-resource-admission-ownership-alignment.md)
- 후속 작업: [Provider 부하 메트릭과 Live Queue Dashboard](provider-load-metrics-queue-dashboard.md), [요청 실행 로그와 Usage Ledger 기반](request-execution-log-usage-ledger-foundation.md)
- 확인 필요: 없음
