09883d0358
- migrations 138~142: source TEXT DEFAULT 'document_server' + eval_case_id TEXT
추가, 인덱스 2개, backfill, 1주 관찰 후 NOT NULL (140 적용 분리)
- app/models/ask_event.py: source / eval_case_id ORM 필드 (138~141 단계 nullable)
- app/services/search_telemetry.py: record_ask_event 시그니처에 source / eval_case_id
- app/core/config.py: settings.eval_runner_token + EVAL_RUNNER_TOKEN env 로드
- app/api/search.py:
- X-Source / X-Eval-Case-Id / X-Eval-Token 헤더 수신
- _resolve_eval_identity(): hmac.compare_digest 로 token 검증, 실패 시 source
'document_server' 강등 + warning log + eval_case_id=None
- 두 record_ask_event 호출에 검증된 source/eval_case_id 전달
- credentials.env.example: EVAL_RUNNER_TOKEN= (empty default = 모든 eval claim 거부)
- tests/test_ask_eval_auth.py: 9 케이스 — token 없음/틀림/일치, env 미설정,
case_id only, non-eval source forces case_id None
trust boundary: 일반 client 의 X-Source=eval / X-Eval-Case-Id 시도는 무시되어
calibration telemetry 오염 불가. eval runner 만 EVAL_RUNNER_TOKEN 으로 인증.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>