Files
portfolio-hub/docs/batches/bat-007_20260511_local-db-validation-and-operations-runbook/design.md
T
genichin 829629fa8f 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
2026-05-11 09:27:57 +00:00

7.0 KiB

BAT-007 Design

  • Status: confirmed
  • Batch: BAT-007
  • Profile: batch-lite

Architecture Summary

이 batch는 코드 구조 변경 없이 분석 및 문서화만 수행한다. 주요 설계 작업은 ensure_schema()와 Alembic revision 간 schema ownership 경계를 코드에서 직접 분석하고 그 결과를 baseline 문서에 반영하는 것이다.

코드 변경이 필요한 경우는 분석 결과 ownership 충돌이 발견될 때뿐이며, 이 batch 범위에서는 해당 충돌이 기존 IF NOT EXISTS/stamp 메커니즘으로 이미 처리되고 있음이 확인되었다.

Changed Areas

대상 변경 유형 REQ
README.md 로컬 DB 검증 절차, runbook 추가 REQ-001, REQ-003
docs/runtime-flows.md Local DB 초기화 흐름, Alembic/ensure_schema() 경계 흐름 추가 REQ-001, REQ-002, REQ-003
docs/project-structure.md Schema ownership 경계 섹션 추가 REQ-002, REQ-003
docker-compose.local-test.yml 변경 없음 — 현행 구성이 검증 시나리오 요건 충족 —
app/cli/commands/health.py 변경 없음 — init-db/migrate-db/health-check 출력 구조 확인 완료 —
app/db/migrations.py 변경 없음 — bootstrap_or_upgrade_to_head() 흐름 분석으로 coverage 충족 —
app/repositories/postgres.py 변경 없음 — ensure_schema() ownership 분석으로 coverage 충족 —

Key Decisions

D-1: design gate = no 유지, 최소 design.md 작성

Planning의 Design Gate: no 결정을 유지한다. 사용자가 draft-batch-design을 명시적으로 요청했으므로 이 문서를 생성하되, 신규 인터페이스/코드 구조 결정 사항이 없음을 확인하고 기록하는 용도로 사용한다.

D-2: ensure_schema() ownership 유지 — Alembic으로 이전 불필요

ensure_schema()는 runtime bootstrap fallback으로 유지한다. fresh DB → app 시작 → migrate-db 순서에서 bootstrap_or_upgrade_to_head()의 legacy stamp 경로가 이 충돌을 처리한다. 이번 batch에서 ensure_schema()를 제거하거나 Alembic으로 완전 이전하는 작업은 범위 밖이다.

D-3: 검증 시나리오를 README.md + docs/runtime-flows.md에 배분

검증 매트릭스(REQ-001)를 별도 파일로 생성하지 않고, 운영자가 참조하는 README.md와 기술적 흐름을 담는 docs/runtime-flows.md에 나누어 반영한다. 이 방식이 docs/project-structure.md 정책(docs/ = SDLC source-of-truth)과 일관된다.

Schema Ownership Analysis

ensure_schema()가 생성하는 객체

객체 타입 IF NOT EXISTS 보호
users TABLE ✓
auth_tokens TABLE ✓
idx_auth_tokens_user_created INDEX ✓
idx_auth_tokens_hash_active INDEX ✓
idx_auth_tokens_service_name_unique UNIQUE INDEX (partial) ✓
strategy_sets TABLE ✓
portfolios TABLE ✓
portfolios.name COLUMN ADD COLUMN IF NOT EXISTS
portfolios.owner_user_id COLUMN ADD COLUMN IF NOT EXISTS
uq_portfolios_owner_name UNIQUE CONSTRAINT DO ...IF NOT EXISTS
portfolio_ledger TABLE ✓
idx_portfolio_ledger_portfolio_time INDEX ✓
idx_portfolios_broker_status_updated INDEX ✓
portfolio_comments TABLE ✓
idx_portfolio_comments_portfolio_created INDEX ✓
portfolio_tags TABLE ✓
idx_portfolio_tags_tag_portfolio INDEX ✓
TimescaleDB hypertable HYPERTABLE if_not_exists=TRUE (조건부)

Alembic만 소유하는 객체 (ensure_schema()에 없음)

객체 타입 Revision
portfolios.market COLUMN 0014
auth_tokens.runtime_id COLUMN 0014
idx_auth_tokens_runtime_id_unique UNIQUE INDEX (partial) 0014
broker_credentials TABLE 0014
ledger_trades TABLE 0014
uq_portfolios_owner_name UNIQUE CONSTRAINT 0015 (Alembic + ensure_schema 공유)

충돌 지점 및 해결 메커니즘

충돌 지점 충돌 조건 해결 방식
핵심 테이블(users, auth_tokens 등) 중복 생성 ensure_schema() 선행 후 Alembic 실행 bootstrap_or_upgrade_to_head() legacy stamp → 이미 존재하면 head로 stamp
portfolios.name / owner_user_id 컬럼 중복 ensure_schema() 선행 후 Alembic 0008/0010 실행 Alembic revision이 _column_exists() guard 사용
uq_portfolios_owner_name 중복 ensure_schema() 선행 후 Alembic 0015 실행 Alembic 0015의 _constraint_exists() guard 사용
v1 API 전용 스키마 누락 ensure_schema()만 실행한 환경 migrate-db 실행 필요 — ensure_schema()는 v1 API 스키마를 포함하지 않음

허용/금지 실행 순서

허용 (safe):

  1. init-db → App 시작 → 정상 운영 (Alembic이 완전 스키마 생성, ensure_schema()는 no-op)
  2. App 시작 (ensure_schema() 선행) → init-db 또는 migrate-db (legacy stamp + upgrade 경로)
  3. 이미 Alembic 관리 DB → migrate-db (증분 upgrade)
  4. 검증 후 migrate-db 재실행 (모든 revision이 IF NOT EXISTS 보호)

주의 (caution):

  1. ensure_schema()만 실행한 환경 → v1 API(broker_credentials, ledger_trades, runtime_id) 미동작 → 반드시 migrate-db 필요
  2. migrate-db 단독 실행 → DB 미존재 시 실패 → init-db 우선 실행 필요

금지 (forbidden):

  1. alembic_version 테이블 수동 삭제 후 migrate-db 재실행 → legacy stamp 오판 위험

Edge Cases

  • TimescaleDB 미설치 환경: ensure_schema()의 TimescaleDB hypertable 생성은 pg_extension에서 timescaledb 존재 여부를 먼저 확인한다. 미설치 시 포트폴리오 운영은 가능하나 시계열 최적화 없이 작동한다.
  • ensure_schema()의 v1 스키마 미포함: broker_credentials, ledger_trades, runtime_id 컬럼은 ensure_schema()에 없다. ensure_schema()만 실행한 환경에서 GET /v1/user_info 또는 POST .../ledger/trades를 호출하면 DB 오류가 발생한다. migrate-db로 해결한다.
  • 비어있는 alembic_version: bootstrap_or_upgrade_to_head()는 먼저 alembic_version 테이블 존재를 확인한 뒤, 없으면 legacy 테이블 존재를 확인한다. fresh DB이면서 alembic_version 없으면 full upgrade 경로를 탄다.

Architecture Impact

both — docs/project-structure.md와 docs/runtime-flows.md 모두 갱신

Reference Doc Update Plan

문서 추가/수정 내용 REQ
README.md Local DB 검증 절차 섹션 추가 (준비, init-db, health-check, smoke flow, 반복 실행 기준) REQ-001, REQ-003
docs/runtime-flows.md "Flow: Local DB Initialization and Validation" 추가 (init-db/migrate-db 흐름, Alembic/ensure_schema() 경계) REQ-001, REQ-002, REQ-003
docs/project-structure.md "Schema Ownership Boundary" 섹션 추가 (객체별 소유 경로, 허용/금지 순서, 범위 제외 명시) REQ-002, REQ-003