# BAT-019 Verification - Status: confirmed - Batch: BAT-019 - Confirmed: 2026-06-27 - PR: #16 (main 머지, HEAD `7f15c6b`) - QC: PASS (독립 qc-reviewer) ## Acceptance Mapping ### REQ-044: GET /v1/assets 권한 완화 - AC: read 토큰 GET /v1/assets → 200 - Evidence: `test_v1_daemons.py::test_assets_read_token_200_regression` PASSED - Evidence: `test_v1.py::test_v1_assets_returns_asset_list` PASSED (200, total=0) - Evidence: `test_v1.py::test_v1_assets_env_read_token_returns_200` PASSED - Evidence: `test_v1.py::test_v1_assets_user_token` PASSED (200, total=0) - Evidence: `test_asset_catalog.py::test_get_v1_assets_user_token_returns_200` PASSED - Evidence: `test_asset_catalog.py::test_get_v1_assets_service_token_returns_200` PASSED - AC: admin GET 200(회귀) - Evidence: `test_v1_daemons.py::test_assets_admin_get_200_regression` PASSED - Evidence: `test_v1.py::test_v1_assets_admin_token_default` PASSED - Evidence: `test_asset_catalog.py::test_get_v1_assets_admin_returns_catalog_response` PASSED - AC: status·market 필터 유지 - Evidence: `test_v1.py::test_v1_assets_market_filter` PASSED (read 토큰 + market=KRX → 1개 반환) - Evidence: `test_asset_catalog.py::test_get_v1_assets_market_filter` PASSED - Evidence: `test_asset_catalog.py::test_get_v1_assets_status_filter_all_includes_inactive` PASSED - Evidence: `test_asset_catalog.py::test_get_v1_assets_status_filter_inactive_only` PASSED - Evidence: `test_asset_catalog.py::test_get_v1_assets_status_filter_default_active_only` PASSED - AC: read 토큰 쓰기 403 - Evidence: `test_v1_daemons.py::test_assets_write_requires_admin_regression` PASSED (POST /v1/assets read → 403) - Evidence: `test_asset_catalog.py::test_asset_http_non_admin_403` PASSED (POST /v1/assets read → 403) - AC: 무토큰 401 - Evidence: `test_v1_daemons.py::test_assets_no_token_returns_401_regression` PASSED - Evidence: `test_v1.py::test_v1_assets_requires_service_token` PASSED - Evidence: `test_asset_catalog.py::test_get_v1_assets_no_token_returns_401` PASSED ### REQ-045: GET /v1/daemons 신규 엔드포인트 - AC: 사용자A(데몬2) → 자기 2개만 - Evidence: `test_v1_daemons.py::test_daemons_returns_caller_owned_daemons` PASSED - AC: 필드 4개(id, daemon_slug, display_name, is_active) 포함 - Evidence: `test_v1_daemons.py::test_daemons_response_has_required_fields` PASSED - AC: 사용자B 데몬 비노출 - Evidence: `test_v1_daemons.py::test_daemons_does_not_expose_other_user_daemons` PASSED (list_daemons_for_user("user-1") 호출 검증) - AC: 데몬 없으면 빈 목록 200 - Evidence: `test_v1_daemons.py::test_daemons_empty_list_returns_200` PASSED - AC: 무토큰 401 - Evidence: `test_v1_daemons.py::test_daemons_no_token_returns_401` PASSED - AC: admin도 caller 스코프 - Evidence: `test_v1_daemons.py::test_daemons_admin_token_with_user_id_returns_caller_daemons` PASSED (admin user_id="admin-1" → admin-1 소유만) - Evidence: `test_v1_daemons.py::test_daemons_admin_token_with_user_id_none_returns_empty` PASSED (env admin 토큰 user_id=None → 빈 목록) ### Design 결정 AC 검증 - OQ-2 경로: GET /v1/daemons 사용 확인 (라우터 prefix="/v1", path="/daemons") - OQ-3 스키마: DaemonListResponse{daemons: [...], total: int} 사용 확인 - env토큰 처리: user_id=None → 빈 목록 200 (`test_daemons_admin_token_with_user_id_none_returns_empty` PASSED) - active 필터: 소유 전체 반환, is_active로 구분 (`test_daemons_includes_inactive_daemons` PASSED) ## Evidence - Test: - 전체 실행: `pytest tests/ -v` - 결과: **472 passed, 0 failed, 11 warnings** (2026-06-27) - 신규 테스트: `tests/test_v1_daemons.py` 13개 전부 PASSED - 업데이트된 테스트: `test_v1.py` 5개, `test_asset_catalog.py` 2→3개, `test_daemon_assignment.py` 2개, `test_tags_master.py` 3개 - 기존 v1_assets 회귀: 0 (모두 PASSED) - 기존 auth 회귀: 0 (모두 PASSED) ``` pytest 실행 원문 마지막 줄: ====================================================== 472 passed, 11 warnings in 24.83s ====================================================== ``` - Manual: - 없음 (DB 연결 없는 환경에서 mock 기반 단위 테스트로 모든 AC 커버) - Logs: - 없음 ## Result - Ready for Release: true - Blocking Issues: 없음 - Verification Outcome: PASS - 모든 AC 충족, 472 passed / 0 failed (2026-06-27) - QC 독립 검증 PASS - PR #16 main 머지 완료 (HEAD `7f15c6b`) - DB 통합 테스트는 로컬 인프라 필요(비활성 환경) — mock 기반 커버로 대체 (비차단)