11 KiB
11 KiB
SDD: 요청 실행 로그와 Usage Ledger 기반
위치
- Milestone: request-execution-log-usage-ledger-foundation
- Phase: PHASE.md
상태
[초안]
SDD 잠금
- 상태: 잠금
- 사용자 리뷰: USER_REVIEW.md
- 잠금 항목:
- [D01] request ledger의 canonical 저장 책임을 Edge와 Control Plane 중 어디에 둘지 결정한다.
- [D02] provider-reported, estimated, mixed, unavailable usage source를 운영 UI와 export에서 어떻게 표시할지 결정한다.
- [D03] provider가 hidden think/reasoning token을 보고하지 않는 경우 표시 reasoning text 기반 추정치를 허용할지 결정한다.
- [D04] full prompt/response, preview, metadata, error detail의 redaction과 retention 기본값을 결정한다.
- [D05] 기존 runtime event 확장과 별도 request ledger/audit event schema 중 기본 구현 경계를 결정한다.
- [D06] tool-call argument, provider raw chunk, parser error detail을 preview/hash/raw capture 중 어떤 수준으로 보관하고 어떻게 redaction할지 결정한다.
문제 / 비목표
- 문제: 현재 IOP는 OpenAI-compatible 요청의 device/provider dispatch, 시작/종료 시간, queue wait, token breakdown, status/error를 요청 단위로 재구성하기 어렵다. 운영자는 provider 효율, 사용자별 사용량, 문제 요청의 원인, prompt/response 보관 범위를 한 기록에서 확인할 수 있어야 한다. provider/tool-call bridge에서 native tool call이 구조화되었는지, text fallback이 합성되었는지, raw
<tool_call>텍스트가 새어 나왔는지도 사후 판별할 수 있어야 한다. - 비목표:
- billing, chargeback, 조직 IAM, 장기 retention 정책 구현
- provider routing 알고리즘 변경
- provider가 보고하지 않는 hidden reasoning token의 완전 정확한 복원
- 품질 평가나 route recommendation 자동화
Source of Truth
| 영역 | 기준 | 메모 |
|---|---|---|
| Roadmap | request-execution-log-usage-ledger-foundation | Milestone 목표, 기능 Task, 잠금 항목 기준 |
| Code | apps/edge/internal/openai, apps/edge/internal/service, apps/node/internal/node, apps/node/internal/adapters/openai_compat, apps/node/internal/adapters/vllm, apps/node/internal/adapters/ollama, proto/iop/runtime.proto |
OpenAI-compatible input, dispatch, runtime event, usage/tool-call propagation 구현 기준 |
| External Provider | OpenAI-compatible provider usage chunk | provider-reported token usage가 있으면 우선 사용하고, 없으면 estimated/unavailable로 표시 |
| User Decision | D01-D06 | 저장 책임, usage source 표시, reasoning token 추정, redaction/retention, schema 분리, tool-call raw capture/redaction 결정 필요 |
State Machine
| 상태 | 진입 조건 | 다음 상태 | 근거 |
|---|---|---|---|
| accepted | Edge OpenAI-compatible 또는 native 실행 요청을 수신했다 | queued 또는 dispatched | request_id/run_id 생성, source metadata |
| queued | model group/provider capacity가 가득 차 요청이 대기한다 | admitted 또는 cancelled/error | queue admission event |
| admitted | scheduler가 provider slot을 예약했다 | dispatched 또는 error | provider_id/node_id/model selection |
| dispatched | Edge가 Node에 RunRequest를 보냈다 | provider_started 또는 error | RunRequest dispatch result |
| provider_started | Node adapter가 provider request를 시작했다 | first_token 또는 completed/error | Node runtime event 또는 adapter execution log |
| first_token | 첫 delta 또는 reasoning_delta가 관측되었다 | completed/error/cancelled | runtime stream event timestamp |
| tool_call_bridge_evaluated | provider stream 또는 CLI output에서 native tool_calls, text fallback, raw tool-call 후보를 관측했다 | completed/error/cancelled | tool-call source, synthesized/leaked flag, parser/fallback metadata |
| completed | provider/adapter가 complete event를 보냈다 | 없음 | complete event, usage, finish_reason |
| error | Edge, Node, provider, queue 중 하나가 실패했다 | 없음 | error event와 error detail |
| cancelled | 사용자 또는 runtime이 취소했다 | 없음 | cancel event |
Interface Contract
- 계약 원문: 없음
- 입력:
request_id: 외부 요청 또는 Edge-generated 요청 correlation idrun_id: Node runtime 실행 correlation idmetadata.user/session/workspace/source: 사용자, session, workspace, 호출 표면 식별model/served_model: 외부 model alias와 provider 실제 served modelprovider_id/node_id/device_id: 선택된 실행 위치 식별usage: input, cached input, think/reasoning, output, total token과 source 표시tool_call_trace: native tool_calls 수, text_tool_fallback, synthesized_tool_calls, raw_tool_call_leaked, parse failure/retry/fallback 시도, redacted preview/hash 후보
- 출력:
- 요청별 실행 ledger record
- provider/device/model별 usage와 latency rollup 후보
- provider/tool-call bridge 판정 summary
- 운영 UI/CLI/export에서 조회 가능한 redacted request summary
- 금지:
- provider가 보고하지 않은 token을 provider-reported처럼 표시하지 않는다.
- hidden reasoning token을 표시 reasoning text 추정치와 혼동하지 않는다.
- prompt/response 원문 보관 여부를 SDD 사용자 결정 없이 기본값으로 확정하지 않는다.
- tool-call argument와 provider raw chunk 원문을 redaction/capture 결정 없이 기본 저장하지 않는다.
Acceptance Scenarios
| ID | Milestone Task | Given | When | Then |
|---|---|---|---|---|
| S01 | event-lifecycle |
OpenAI-compatible 요청이 들어온다 | 요청이 queue, dispatch, provider, stream, complete 또는 error 경로를 지난다 | lifecycle별 timestamp 의미와 event source가 문서화되어 있다 |
| S02 | identity-correlation |
요청이 provider pool을 통해 특정 Node/provider/model로 라우팅된다 | 운영자가 run을 조회한다 | request_id, run_id, user/session/workspace/source, node/provider/device/model correlation 기준이 문서화되어 있다 |
| S03 | token-usage |
provider가 usage를 보고하거나 보고하지 않는다 | complete event 또는 response usage를 구성한다 | provider-reported/estimated/mixed/unavailable source 정책과 token breakdown 필드가 문서화되어 있다 |
| S04 | latency-metrics |
요청이 대기, 실행, streaming 단계를 지난다 | 운영자가 latency를 비교한다 | queue wait, TTFT, provider duration, stream duration, total duration 후보가 문서화되어 있다 |
| S05 | log-redaction |
요청/응답/metadata/error detail이 ledger에 남는다 | 운영 UI 또는 export가 기록을 표시한다 | preview/redaction/retention 기본값 후보와 사용자 결정 항목이 분리되어 있다 |
| S06 | storage-query |
Edge와 Control Plane이 모두 운영 기록 후보를 가질 수 있다 | 저장/조회 경계를 설계한다 | canonical owner와 조회/export 후보가 사용자 결정 항목으로 정리되어 있다 |
| S07 | migration-plan |
기존 zap log, runtime event, Control Plane operation history가 존재한다 | request ledger를 추가한다 | 병행 운용 또는 migration 전략 후보가 문서화되어 있다 |
| S08 | tool-call-trace |
provider 또는 CLI route가 tool call을 native tool_calls, text fallback, raw text 중 하나로 반환한다 | Edge가 OpenAI-compatible 응답을 구성하거나 parser/fallback 실패를 만난다 | native/text/synthesized/leaked/parse-failure 판정 필드와 redaction/capture 기준이 문서화되어 있다 |
Evidence Map
| Scenario | Required Evidence | agent-task 연결 |
완료 Evidence 기대 |
|---|---|---|---|
| S01 | Milestone 문서와 SDD에서 lifecycle 표와 event source 확인 | agent-task/m-request-execution-log-usage-ledger-foundation/... |
Roadmap Completion에 event-lifecycle와 S01 충족 근거 |
| S02 | correlation field 목록과 provider/device/model identity mapping 확인 | agent-task/m-request-execution-log-usage-ledger-foundation/... |
Roadmap Completion에 identity-correlation와 S02 충족 근거 |
| S03 | usage field/source 정책과 provider-reported/estimated 구분 확인 | agent-task/m-request-execution-log-usage-ledger-foundation/... |
Roadmap Completion에 token-usage와 S03 충족 근거 |
| S04 | latency metric 후보와 timestamp 계산 기준 확인 | agent-task/m-request-execution-log-usage-ledger-foundation/... |
Roadmap Completion에 latency-metrics와 S04 충족 근거 |
| S05 | redaction/retention 결정 항목과 기본 후보 확인 | agent-task/m-request-execution-log-usage-ledger-foundation/... |
Roadmap Completion에 log-redaction와 S05 충족 근거 |
| S06 | canonical owner 사용자 리뷰 해결 또는 결정 기록 확인 | agent-task/m-request-execution-log-usage-ledger-foundation/... |
Roadmap Completion에 storage-query와 S06 충족 근거 |
| S07 | 기존 로그/event와 새 ledger 병행 또는 migration 전략 확인 | agent-task/m-request-execution-log-usage-ledger-foundation/... |
Roadmap Completion에 migration-plan와 S07 충족 근거 |
| S08 | tool-call bridge 판정 필드, parser/fallback 실패 기록, redaction/capture 기준 확인 | agent-task/m-request-execution-log-usage-ledger-foundation/... |
Roadmap Completion에 tool-call-trace와 S08 충족 근거 |
Cross-repo Dependencies
- 없음
Drift Check
- Milestone 기능 Task와 Acceptance Scenario가 일치한다.
- Evidence Map이 code-review/complete.log에서 검증 가능하다.
- agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
- 사용자 리뷰가 필요한 항목은 USER_REVIEW.md에만 남겼다.
사용자 리뷰 이력
- 없음
작업 컨텍스트
- 표준선: Edge는 runtime execution과 provider routing의 원본 이벤트를 가장 먼저 알고, Control Plane은 연결 view와 운영 조회/export 표면을 제공한다.
- 표준선: usage는 provider-reported 값을 우선하고, provider가 주지 않는 값은 estimated 또는 unavailable로 명시해 정확도와 추정을 분리한다.
- 표준선: tool-call 추적은 기본적으로 raw 원문 저장보다
run_id기준 판정 필드, 길이, hash, 짧은 redacted preview를 우선하고, bounded raw capture는 명시적으로 켠 진단 모드로 제한한다. - 후속 SDD: 없음