feat(REQ-006): implement v1 assets endpoint with verification

- Add v1_assets.py API endpoint for asset list retrieval
- Add AssetResponse schema to v1.py
- Implement comprehensive test coverage in test_v1.py
- Update requirement verification with implementation evidence
- Update SRS index to mark REQ-006 as Implemented
- Document acceptance criteria validation results
This commit is contained in:
2026-05-03 13:36:27 +00:00
parent 222c66bb7f
commit 545d4da413
6 changed files with 62 additions and 8 deletions
@@ -1,8 +1,9 @@
# BAT-001 Verification
- Status: verified
- Status: re-verified
- Batch: BAT-001
- Last Updated (KST): 2026-05-01
- Last Updated (KST): 2026-05-03
- Re-verification Trigger: CHG-20260503-01 (REQ-006 strategy_type 필드 추가)
## Acceptance Mapping
@@ -40,13 +41,15 @@
|---|---|---|---|
| AC1 | service-token 인증 → 200 + portfolio 목록 | `tests/test_v1.py::test_v1_assets_returns_asset_list` PASS | PASS |
| AC2 | ?status=active 쿼리 파라미터 필터 | `tests/test_v1.py::test_v1_assets_status_filter` — ?status=active 필터 동작 확인 PASS | PASS |
| AC3 | 응답 필드: asset_id, symbol, market, status, cash, quantity, broker_type, strategy_id, strategy_params, updated_at | `test_v1_assets_returns_asset_list` — cash/quantity/broker_type/strategy_params 필드명 assert PASS | PASS |
| AC3 | 응답 필드: asset_id, symbol, market, status, cash, quantity, broker_type, strategy_id, strategy_type, strategy_params, updated_at | `test_v1_assets_returns_asset_list` — 필드명 assert PASS. `test_v1_assets_strategy_params` — strategy_type=="strategy" PASS. `test_v1_assets_returns_asset_list` — strategy_type is None PASS | PASS |
| AC4 | strategy_params → StrategySet.config 파생 JSON | `tests/test_v1.py::test_v1_assets_strategy_params` — config JSON 파싱 결과 반환 PASS | PASS |
| AC5 | strategy_params {} 폴백 | `tests/test_v1.py::test_v1_assets_strategy_params_fallback_on_error` — 조회 실패 시 {} 반환 PASS | PASS |
| AC6 | portfolios.market NULL → 응답 null | `AssetItem.market: str | None = None`, `Portfolio.market: str | None = None` — NULL 전파 구조 검토 PASS | PASS |
| AC7 | 미인증 401 | `tests/test_v1.py::test_v1_assets_requires_service_token` PASS | PASS |
| AC8 | active_strategy_id → strategy_type = StrategySet.name | `tests/test_v1.py::test_v1_assets_strategy_params` — `strategy_type == "strategy"` assert PASS | PASS |
| AC9 | active_strategy_id 없거나 조회 실패 → strategy_type = null | `tests/test_v1.py::test_v1_assets_returns_asset_list` — `strategy_type is None` PASS. `test_v1_assets_strategy_params_fallback_on_error` — `strategy_type is None` PASS | PASS |
**REQ-006 판정: PASS**
**REQ-006 판정: PASS** (CHG-20260503-01 strategy_type 추가 재검증 완료)
---
@@ -126,7 +129,7 @@
- `tests/test_v1.py` — 19개 전부 PASS
- `test_health_returns_full_response`, `test_auth_issue_service_token_returns_runtime_id`
- `test_v1_assets_requires_service_token`, `test_v1_assets_rejects_env_token`, `test_v1_assets_returns_asset_list`
- `test_v1_assets_status_filter`, `test_v1_assets_strategy_params`, `test_v1_assets_strategy_params_fallback_on_error`
- `test_v1_assets_status_filter`, `test_v1_assets_strategy_params`(`strategy_type` assert 포함), `test_v1_assets_strategy_params_fallback_on_error`(`strategy_type is None` assert 포함)
- `test_v1_user_info_404_when_no_runtime_id`, `test_v1_user_info_returns_user`, `test_v1_user_info_inactive_user_has_disabled_reason`
- `test_v1_user_info_returns_decrypted_broker_credentials`
- `test_v1_ledger_trade_created`, `test_v1_ledger_trade_idempotent_same_payload`, `test_v1_ledger_trade_conflict_different_payload`, `test_v1_ledger_trade_asset_not_found`
@@ -134,7 +137,7 @@
- `tests/test_app.py` — PASS (startup bootstrap 포함)
- `tests/test_auth.py`, `tests/test_cli.py`, `tests/test_domain_services.py` — PASS
- `tests/test_portfolio_comments.py`, `tests/test_portfolio_ownership.py`, `tests/test_portfolio_tags.py`, `tests/test_users.py` — PASS
- **전체 합계: 98 passed (2026-05-01)**
- **전체 합계: 115 passed (2026-05-03, CHG-20260503-01 재검증 포함)**
### Code Review