Files
portfolio-hub/docs/srs/Migration/req-016_portfolios-uuid-schema-migration.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.3 KiB

req-016: portfolios 테이블 UUID 전환 및 데이터 마이그레이션

  • Status: Implemented
  • Type: Migration
  • Priority: High
  • Owner: repository-maintainers

Intent

  • 현재 사용자가 직접 지정하는 TEXT PRIMARY KEY(portfolio_id)를 서버 생성 UUID로 교체하고, 기존 portfolio_id 문자열을 name 컬럼으로 이전한다.
  • (owner_user_id, name) 복합 UNIQUE 제약을 DB 레벨에서 도입해 사용자 범위 내 이름 유일성을 보장한다.
  • 기존 데이터와 FK 참조 테이블(portfolio_ledger, portfolio_comments, portfolio_tags, ledger_trades)을 단일 Alembic revision으로 atomic하게 마이그레이션한다.

Requirement

  • 단일 Alembic revision을 추가해 아래를 수행한다.
    1. portfolios 테이블에 name TEXT 컬럼을 추가한다.
    2. 기존 portfolio_id 값을 name 컬럼으로 복사한다 (변환 없이 그대로).
    3. 각 기존 레코드에 uuid.uuid4()로 새 UUID를 생성해 portfolio_id 컬럼 값을 교체한다.
    4. FK 참조 테이블(portfolio_ledger, portfolio_comments, portfolio_tags, ledger_trades)의 portfolio_id 컬럼 값도 새 UUID로 함께 갱신한다.
    5. (owner_user_id, name) 복합 UNIQUE 제약을 portfolios 테이블에 추가한다.
    6. Portfolio dataclass(app/domain/models.py)의 portfolio_id 필드를 UUID 문자열로 유지하고 name 필드를 명확히 선언한다.
    7. app/repositories/postgres.py의 create_portfolio() 메서드가 서버에서 uuid.uuid4()로 생성된 UUID를 portfolio_id로 사용한다.
  • 마이그레이션은 IF NOT EXISTS 패턴을 준수해 재실행 시 오류가 없어야 한다(REQ-002 준수).
  • FK 참조 테이블과의 갱신은 단일 트랜잭션 내에서 atomic하게 처리한다.
  • 마이그레이션 완료 후 FK 고아 레코드(orphan) 0건을 검증하는 쿼리를 revision 안에 포함한다.

Acceptance Criteria

  1. Given 기존 portfolio_id 문자열로 운영 중인 portfolios 레코드가 있을 때, When 신규 Alembic revision을 alembic upgrade head로 실행하면, Then 각 레코드의 name 컬럼에 기존 portfolio_id 값이 그대로 복사되고, portfolio_id는 UUID 형식(re.match(r'^[0-9a-f-]{36}$', ...))으로 교체된다.
  2. Given 마이그레이션 완료 후, When portfolio_ledger, portfolio_comments, portfolio_tags, ledger_trades의 portfolio_id 컬럼을 확인하면, Then 고아 레코드(FK 불일치 레코드)가 0건이다.
  3. Given (owner_user_id, name) 복합 UNIQUE 제약이 적용된 상태에서, When 동일 owner_user_id와 동일 name으로 portfolio 레코드를 추가하면, Then DB 레벨에서 UNIQUE 제약 위반 오류가 발생한다.
  4. Given 동일 name이지만 다른 owner_user_id로 portfolio 레코드를 추가하면, Then 정상 삽입된다.
  5. Given 신규 Alembic revision을 이미 적용한 환경에서, When 동일 revision을 재실행하면, Then 오류 없이 완료된다(IF NOT EXISTS 준수).
  6. Given app/repositories/postgres.py의 create_portfolio() 메서드가 실행되면, Then 서버에서 uuid.uuid4()로 생성된 UUID가 portfolio_id로 저장된다.

Impacted Area

  • Docs: docs/data-model.md (portfolios 테이블 스키마 변경 반영 — REQ-019에서 처리)
  • Modules:
    • migrations/versions/: 신규 Alembic revision 파일
    • app/domain/models.py: Portfolio dataclass portfolio_id 및 name 필드
    • app/repositories/postgres.py: create_portfolio() UUID 생성, get_portfolio_by_name_and_user() 신규 메서드
  • Tests:
    • 신규 tests/test_portfolio_uuid.py 또는 tests/test_cli.py — portfolio_id UUID 형식 검증, 동일 name 독립 생성 테스트, (owner_user_id, name) UNIQUE 제약 동작 확인

Notes

  • 기존 portfolio_id 문자열은 name 컬럼으로 변환 없이 복사한다(Discovery A-3 확정).
  • portfolio_id 컬럼 타입은 TEXT 유지(PostgreSQL UUID 타입으로의 전환은 이번 범위 밖).
  • app/domain/models.py의 Portfolio.portfolio_id는 UUID 문자열로 의미가 바뀌나 Python 타입(str)은 유지.
  • get_portfolio_by_name_and_user() 메서드는 REQ-017(CLI 식별 방식 전환)에서도 사용한다.
  • Source Discovery: dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution (FR-1, FR-5, NFR-1)

Change Log

CHG-20260511-01

  • Date: 2026-05-11
  • Author: repository-maintainers

Change Summary

  • 최초 생성 — dcy-004 draft-req에 의해 생성

Intent

  • dcy-004 Discovery의 FR-1(portfolios.portfolio_id UUID 교체 및 name 컬럼 추가), FR-5(기존 데이터 마이그레이션), NFR-1(단일 revision, IF NOT EXISTS, atomic 트랜잭션) 반영

Acceptance Criteria Delta

  • Added:
    • 1~6 (최초 생성)

Impacted Area Delta

  • Docs:
    • docs/data-model.md: portfolios 테이블 스키마 변경 (REQ-019에서 처리)
  • Modules:
    • migrations/versions/: 신규 revision 추가
    • app/domain/models.py: Portfolio dataclass 변경
    • app/repositories/postgres.py: create_portfolio UUID 생성, get_portfolio_by_name_and_user() 추가
  • Tests:
    • tests/test_portfolio_uuid.py 또는 tests/test_cli.py: UUID 형식 검증, UNIQUE 제약 동작 확인

Delivery Trace Delta

  • Batches: none (batch 미결정)
  • Releases: none

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current
  • Follow-up Action: confirm-req → suggest-batch-reqs → draft-batch

Validation Plan

  • pytest: portfolio_id UUID 형식 검증, FK 고아 레코드 0건 확인, (owner_user_id, name) UNIQUE 제약 동작 확인, IF NOT EXISTS 재실행 안전성 확인

CHG-20260511-02

  • Date: 2026-05-11
  • Author: repository-maintainers

Change Summary

  • Approved 전환 — confirm-req 게이트 통과

Intent

  • Delivery 입력으로 사용할 수 있도록 REQ-016을 승인 상태로 승격한다.

Acceptance Criteria Delta

  • Added:
    • none
  • Updated:
    • none
  • Removed:
    • none

Impacted Area Delta

  • Docs:
    • none
  • Modules:
    • none
  • Tests:
    • none

Delivery Trace Delta

  • Batches:
    • none
  • Releases:
    • none

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current
  • Follow-up Action: suggest-batch-reqs로 batch grouping 검토

Validation Plan

  • confirm-req 게이트 재평가 결과: 필수 메타데이터, 구체적 Acceptance Criteria, Impacted Area, Change Log, blocker 없음 확인

CHG-20260511-03

  • Date: 2026-05-11
  • Author: repository-maintainers

Change Summary

  • Implemented 전환 — BAT-006 verification passed, confirm-req-implemented 게이트 통과

Intent

  • BAT-006 verification.md의 REQ-016 Acceptance Mapping이 모든 AC에 대해 test evidence를 포함하고 있으며, Blocking Issues 없음으로 구현 완료 상태로 전환한다.

Acceptance Criteria Delta

  • none

Impacted Area Delta

  • none

Delivery Trace Delta

  • Batches: BAT-006 (release-candidate)
  • Releases: none

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: implemented
  • Follow-up Action: draft-release (BAT-006)

Validation Plan

  • BAT-006 verification.md AC-1~6 모두 test evidence 연결 확인 (tests/test_portfolio_uuid.py 14/14 passed, full suite 129/129 passed)