feat: implement portfolio UUID migration and v1 API finalization (BAT-006, BAT-001 re-verified)

Core Changes:
- Migrate portfolio_id from string to UUID in schema and repository layer
- Update portfolio CLI commands to use name+user combination for identification
- Update HTTP API to accept portfolio_id as UUID path parameter
- Implement portfolio ownership validation in repository queries

Requirements Completed (REQ-016 to REQ-019):
- REQ-016: portfolios table UUID schema migration with data migration script
- REQ-017: CLI portfolio commands with name+user identification
- REQ-018: HTTP API portfolio path parameters and v1 asset_id UUID returns
- REQ-019: Portfolio UUID baseline documentation updates

BAT-001 Re-verification:
- REQ-004~010 marked as Implemented after verification evidence validation
- All v1 API endpoints verified with comprehensive test coverage

Documentation Updates:
- Update data-model.md with portfolio UUID structure
- Update interface-contract.md with UUID path parameters
- Update runtime-flows.md with ownership-based resolution flows
- Update project-structure.md with database layer changes
- Add migration script for portfolio UUID transition

Testing:
- Add test_portfolio_uuid.py for migration validation
- Update test_cli.py and test_portfolio_ownership.py for ownership checks
This commit is contained in:
2026-05-11 09:27:57 +00:00
parent 9ed307555a
commit 829629fa8f
46 changed files with 3260 additions and 220 deletions
+88
View File
@@ -175,6 +175,94 @@ pfhub_DB_ENABLED=true pfhub portfolio list
This repository now uses Alembic for versioned schema migrations. Future schema changes should be added under `migrations/versions`.
## Local DB Validation Runbook
이 섹션은 로컬 docker compose 환경에서 DB 초기화, 마이그레이션, health-check, smoke flow를 반복 검증하기 위한 절차를 정의한다.
### 준비 — 컨테이너 시작
```bash
docker compose -f docker-compose.local-test.yml up -d
docker compose -f docker-compose.local-test.yml ps
# portfolio-hub-timescaledb 상태가 (healthy) 인지 확인
```
기본 접속 정보 (`.env` 설정 기준):
- TimescaleDB: `127.0.0.1:5432`
- DB: `portfolio_hub`, User: `portfolio_hub_user`
### Scenario A — Fresh DB (DB 미존재 상태)
```bash
# 1. DB 생성 + Alembic upgrade head
pfhub_DB_ENABLED=true pfhub init-db
# 기대: database: portfolio_hub / created: True / schema_initialized: True / migration_applied: head
# 2. DB 연결 health 확인
pfhub_DB_ENABLED=true pfhub health-check
# 기대: db_enabled: True / repository: PostgresPortfolioRepository
# 3. Smoke flow — 사용자 생성 + portfolio 생성 + 목록 확인
pfhub_DB_ENABLED=true pfhub user create --username alice --password password123 --force
pfhub_DB_ENABLED=true pfhub portfolio create my-portfolio --symbol 005930 --user alice --cash-balance 1000000 --force
pfhub_DB_ENABLED=true pfhub portfolio list --user alice
# 기대: my-portfolio가 목록에 포함
```
**pass 기준**: 각 명령 exit code 0 / 기대 필드 출력 확인
**fail 기준**: connection refused / Alembic revision 오류 / exit code ≠ 0
### Scenario B — runtime-precreated schema (App 선행 기동)
```bash
# 1. App 먼저 기동 (ensure_schema() 실행)
pfhub_DB_ENABLED=true uvicorn app.main:app &
# 2. migrate-db로 Alembic 관리 상태로 전환
pfhub_DB_ENABLED=true pfhub migrate-db
# 기대: migration_applied: head
# 3. health-check 재확인
pfhub_DB_ENABLED=true pfhub health-check
```
**동작 원리**: `bootstrap_or_upgrade_to_head()`가 `alembic_version` 테이블 없음 → 기존 핵심 테이블 존재 → legacy stamp → head upgrade 순서로 실행한다.
### 반복 실행 (재현성 확인)
```bash
# 컨테이너 + 볼륨 초기화
docker compose -f docker-compose.local-test.yml down -v
# 위 Scenario A 또는 B 재실행
```
출력이 이전 실행과 동일한지 비교한다. JSON 출력 수집:
```bash
pfhub_DB_ENABLED=true pfhub init-db --output json
pfhub_DB_ENABLED=true pfhub health-check --output json
```
로그 수집 위치: `docker compose -f docker-compose.local-test.yml logs portfolio-hub-timescaledb`
### Rollback / 재시도 판단 기준
| 증상 | 판단 | 조치 |
|------|------|------|
| `init-db`: `connection refused` | DB 컨테이너 미준비 | `docker compose ps` → `(healthy)` 대기 후 재시도 |
| `migrate-db`: `Alembic revision 오류` | revision 파일 손상 또는 순서 오류 | `migrations/versions/` revision 확인 |
| `migrate-db` 후 v1 API 오류 | ensure_schema() 선행 후 Alembic 미실행 | `migrate-db` 재실행 |
| 데이터 오염으로 스키마 불일치 | 심각한 데이터 오류 | 볼륨 초기화(`down -v`) + Scenario A 재시작 |
### Release Gate Criteria
다음 조건을 모두 만족해야 로컬 검증 완료로 간주한다:
1. Scenario A: `init-db` exit code 0 + `health-check` exit code 0 + smoke flow 정상 완료
2. `migrate-db` 반복 실행 시 오류 없음 (멱등성 확인)
3. `docker compose logs`에 ERROR 레벨 로그 없음
## Docs Sync Guardrail
To keep implementation and specification documents in sync, this repository provides an automated check.