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
@@ -0,0 +1,145 @@
# req-019: portfolio UUID 전환 관련 baseline 문서 갱신
- Status: Implemented
- Type: Documentation
- Priority: Medium
- Owner: repository-maintainers
## Intent
- REQ-016~018의 구현으로 변경되는 DB 스키마, CLI 흐름, HTTP API 계약을 baseline 문서(`docs/project-structure.md`, `docs/runtime-flows.md`, `docs/data-model.md`, `docs/interface-contract.md`)에 반영해 문서와 구현 간 불일치를 방지한다.
- trex-basic 동시 배포 계획을 `docs/interface-contract.md`에 기록한다.
## Requirement
- `docs/project-structure.md`를 갱신해 `app/repositories/postgres.py`에 신규 추가된 `get_portfolio_by_name_and_user()` 메서드와 `app/domain/models.py`의 `portfolio_id`(UUID 문자열) 의미 변경을 반영한다.
- `docs/runtime-flows.md`를 갱신해 아래를 반영한다.
- CLI 명령 흐름: `<name>` + `--user <username>` 조합으로 portfolio를 식별하고 내부에서 UUID를 조회하는 흐름
- `v1 API — GET /v1/assets` flow: `asset_id` 필드가 UUID를 반환함
- `docs/data-model.md`를 갱신해 `portfolios` 테이블의 `portfolio_id`(UUID, TEXT, PRIMARY KEY), `name`(TEXT) 신규 컬럼, `(owner_user_id, name)` 복합 UNIQUE 제약을 반영한다.
- `docs/interface-contract.md`를 갱신해 `GET /v1/assets` `asset_id` 필드가 UUID를 반환함을 기록하고, trex-basic과 portfolio-hub의 동시 배포 계획을 명시한다.
## Acceptance Criteria
1. Given `docs/project-structure.md`를 검토하면, Then `app/repositories/postgres.py` 설명에 `get_portfolio_by_name_and_user()` 메서드가 언급되고, `app/domain/models.py`의 `portfolio_id`가 UUID 기반임이 반영된다.
2. Given `docs/runtime-flows.md`를 검토하면, Then CLI 명령 흐름 설명에 `<name>` + `--user <username>` 조합 식별 방식이 반영되고, `v1 API — GET /v1/assets` flow에 `asset_id`가 UUID임이 명시된다.
3. Given `docs/data-model.md`를 검토하면, Then `portfolios` 테이블 스키마에 `portfolio_id`(UUID TEXT, PK), `name`(TEXT), `(owner_user_id, name)` UNIQUE 제약이 반영된다.
4. Given `docs/interface-contract.md`를 검토하면, Then `GET /v1/assets` `asset_id` 필드가 UUID를 반환함이 명시되고, trex-basic과 portfolio-hub의 동시 배포 계획이 기록된다.
## Impacted Area
- Docs:
- `docs/project-structure.md`
- `docs/runtime-flows.md`
- `docs/data-model.md`
- `docs/interface-contract.md`
- Modules: 없음 (문서 전용)
- Tests: 없음 (문서 전용)
## Notes
- 이 REQ는 REQ-016, REQ-017, REQ-018 구현 완료 후 또는 동일 batch에서 함께 처리하는 것이 적절하다.
- trex-basic 측 코드 변경은 이번 범위 밖이며, 동시 배포 계획을 문서화하는 것만 이 REQ 범위에 포함된다.
- NFR-1(단일 revision, IF NOT EXISTS, atomic)은 REQ-016에 흡수. NFR-2(단일 DB 쿼리, 오류 메시지)는 REQ-017에 흡수. NFR-3(동시 배포 계획 기록)은 이 REQ에서 처리.
- Source Discovery: dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution (FR-6, NFR-3)
## Change Log
### CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- 최초 생성 — dcy-004 draft-req에 의해 생성
#### Intent
- dcy-004 Discovery의 FR-6(docs/project-structure.md, docs/runtime-flows.md 갱신), NFR-3(동시 배포 계획 docs/interface-contract.md 기록) 반영. docs/data-model.md, docs/interface-contract.md 갱신 포함.
#### Acceptance Criteria Delta
- Added:
- 1~4 (최초 생성)
#### Impacted Area Delta
- Docs:
- docs/project-structure.md
- docs/runtime-flows.md
- docs/data-model.md
- docs/interface-contract.md
#### 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
- 각 baseline 문서에 변경 내용이 포함됐는지 코드 리뷰로 확인
### CHG-20260511-02
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- Approved 전환 — confirm-req 게이트 통과
#### Intent
- Delivery 입력으로 사용할 수 있도록 REQ-019를 승인 상태로 승격한다.
#### 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-019 AC-1~4 모두 baseline 문서 변경 내용 직접 확인으로 evidence 충족. 문서 전용 REQ로 테스트 불필요. 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~4: project-structure.md / runtime-flows.md / data-model.md / interface-contract.md 각 문서 변경 내용 manual 확인 완료
@@ -1,6 +1,6 @@
# req-004: GET /health 응답 스키마 확장
- Status: Approved
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: repository-maintainers
@@ -32,6 +32,35 @@
## Change Log
### CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- Implemented 전환 — BAT-001 re-verified verification passed, confirm-req-implemented 게이트 통과
#### Intent
- BAT-001 verification.md (re-verified, 2026-05-03) AC-1~5 모두 PASS. Blocking Issues 없음. AC2(degraded/failed 경로)는 REQ Notes에서 이번 반복 OOS로 명시 — 릴리스 블로커 아님.
#### Acceptance Criteria Delta
- none
#### Impacted Area Delta
- none
#### Delivery Trace Delta
- Batches: BAT-001 (release-candidate)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: draft-release (BAT-001 기반 release 편성 검토)
#### Validation Plan
- BAT-001 verification.md (re-verified) AC-1~5 evidence 연결 확인 완료
### CHG-20260502-02
- Date: 2026-05-02
- Author: repository-maintainers
@@ -1,6 +1,6 @@
# req-005: service-token 발급 시 runtime_id 동시 생성
- Status: Approved
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: repository-maintainers
@@ -34,6 +34,35 @@
## Change Log
### CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- Implemented 전환 — BAT-001 re-verified verification passed, confirm-req-implemented 게이트 통과
#### Intent
- BAT-001 verification.md (re-verified, 2026-05-03) AC-1~5 모두 PASS. Blocking Issues 없음. AC5 DB 미확인은 REQ-009와 동일 제약으로 non-blocker 처리.
#### Acceptance Criteria Delta
- none
#### Impacted Area Delta
- none
#### Delivery Trace Delta
- Batches: BAT-001 (release-candidate)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: draft-release (BAT-001)
#### Validation Plan
- BAT-001 verification.md (re-verified) AC-1~5 evidence 연결 확인 완료
### CHG-20260502-02
- Date: 2026-05-02
- Author: repository-maintainers
@@ -1,6 +1,6 @@
# req-006: GET /v1/assets 엔드포인트 구현
- Status: Approved
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: repository-maintainers
@@ -39,6 +39,35 @@
## Change Log
### CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- Implemented 전환 — BAT-001 re-verified verification passed, confirm-req-implemented 게이트 통과
#### Intent
- BAT-001 verification.md (re-verified, 2026-05-03, CHG-20260503-01 strategy_type 재검증 포함) AC-1~9 모두 PASS. Blocking Issues 없음.
#### Acceptance Criteria Delta
- none
#### Impacted Area Delta
- none
#### Delivery Trace Delta
- Batches: BAT-001 (release-candidate)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: draft-release (BAT-001)
#### Validation Plan
- BAT-001 verification.md (re-verified) AC-1~9 evidence 연결 확인 완료 (strategy_type 필드 재검증 포함)
### CHG-20260503-01
- Date: 2026-05-03
- Author: repository-maintainers
@@ -1,6 +1,6 @@
# req-007: GET /v1/user_info 엔드포인트 구현
- Status: Approved
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: repository-maintainers
@@ -38,6 +38,35 @@
## Change Log
### CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- Implemented 전환 — BAT-001 re-verified verification passed, confirm-req-implemented 게이트 통과
#### Intent
- BAT-001 verification.md (re-verified, 2026-05-03) AC-1~7 모두 PASS. Blocking Issues 없음.
#### Acceptance Criteria Delta
- none
#### Impacted Area Delta
- none
#### Delivery Trace Delta
- Batches: BAT-001 (release-candidate)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: draft-release (BAT-001)
#### Validation Plan
- BAT-001 verification.md (re-verified) AC-1~7 evidence 연결 확인 완료
### CHG-20260502-02
- Date: 2026-05-02
- Author: repository-maintainers
@@ -1,6 +1,6 @@
# req-008: POST /v1/assets/{asset_id}/ledger/trades 엔드포인트 구현
- Status: Approved
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: repository-maintainers
@@ -36,6 +36,35 @@
## Change Log
### CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- Implemented 전환 — BAT-001 re-verified verification passed, confirm-req-implemented 게이트 통과
#### Intent
- BAT-001 verification.md (re-verified, 2026-05-03) AC-1~5 모두 PASS. Blocking Issues 없음.
#### Acceptance Criteria Delta
- none
#### Impacted Area Delta
- none
#### Delivery Trace Delta
- Batches: BAT-001 (release-candidate)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: draft-release (BAT-001)
#### Validation Plan
- BAT-001 verification.md (re-verified) AC-1~5 evidence 연결 확인 완료
### CHG-20260502-02
- Date: 2026-05-02
- Author: repository-maintainers
@@ -0,0 +1,151 @@
# req-017: CLI portfolio 명령 — name+user 조합 식별 방식 전환
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: repository-maintainers
## Intent
- 현재 `portfolio_id` Argument로만 portfolio를 식별하는 CLI 뮤테이션 명령을 `<name>` + `--user <username>` 조합으로 전환해 소유권 검증을 명령 실행 경로에 포함한다.
- CLI 내부에서 `(owner_user_id, name)` → UUID 단일 쿼리 조회 후 처리하고, 조회 실패 시 명확한 오류 메시지를 출력한다.
## Requirement
- `portfolio create` 명령은 `name` Argument와 `--user <username>` 옵션을 필수로 받는다. `portfolio_id`는 서버가 UUID로 발급하며 사용자가 직접 지정하거나 조회할 수 없다.
- `status`, `buy`, `sell`, `invest`, `transfer`, `reset`, `delete`, `update` 명령은 `<name>` Argument와 `--user <username>` 옵션으로 portfolio를 식별한다. 내부에서 `(owner_user_id, name)` → `portfolio_id(UUID)`를 단일 DB 쿼리로 조회한 뒤 처리한다.
- `<name>` + `--user` 조합으로 portfolio를 찾지 못하면 오류 메시지 `포트폴리오를 찾을 수 없습니다: {name} (user: {username})`를 출력하고 명령을 중단한다.
- `name`은 `update` 명령으로 변경 가능하다. 변경 시 동일 `owner_user_id` 내에 같은 `name`이 이미 존재하면 오류 메시지 `이미 사용 중인 이름입니다: {name}`를 반환한다.
- `name` 변경 명령에는 명시적 확인 절차(`--force` 또는 confirm 프롬프트)를 요구한다.
- `name` 허용 문자는 `[a-zA-Z0-9._:-]`이며, 공백 불허, 1~100자, 대소문자 구분이 있다. 이 범위를 벗어나면 유효성 검사 오류를 반환한다.
## Acceptance Criteria
1. Given `pfhub portfolio create <name> --user <username> ...`을 실행하면, When 서버가 UUID를 발급하면, Then CLI가 portfolio_id를 직접 지정하거나 조회하지 않고 UUID가 DB에 저장된다.
2. Given `pfhub portfolio buy <name> --user alice ...`를 실행하면, When `(alice, <name>)` 조합으로 DB를 단일 쿼리로 조회해 UUID를 찾으면, Then 해당 portfolio에 buy 작업이 수행된다.
3. Given `--user bob`으로 alice 소유의 portfolio `<name>`을 조작하면, When `(bob, <name>)` 조합으로 조회해 레코드가 없으면, Then `포트폴리오를 찾을 수 없습니다: {name} (user: bob)` 오류가 출력되고 명령이 중단된다.
4. Given alice와 bob이 동일 name `tv`로 각각 portfolio를 생성하면, Then 두 레코드가 독립적으로 저장되고 각자 자신의 `tv` portfolio를 조작할 수 있다.
5. Given alice의 portfolio name을 `tv2`로 변경할 때 alice에게 이미 `tv2` 이름의 portfolio가 존재하면, When `update` 명령이 DB의 `(owner_user_id, name)` UNIQUE 제약 위반을 감지하면, Then `이미 사용 중인 이름입니다: tv2` 오류를 출력한다.
6. Given `--force` 없이 `update` 명령으로 name을 변경하려 하면, Then `--force`가 없으면 변경이 중단되거나 confirm 프롬프트가 표시된다.
7. Given `name` 허용 문자 범위(`[a-zA-Z0-9._:-]`) 밖의 문자가 포함된 이름을 `create` 시 입력하면, Then 유효성 검사 오류가 반환된다.
8. Given `name` 길이가 0이거나 100자를 초과하면, Then 유효성 검사 오류가 반환된다.
## Impacted Area
- Docs: `docs/runtime-flows.md` (CLI 명령 흐름 변경 반영 — REQ-019에서 처리)
- Modules:
- `app/cli/commands/portfolio.py`: `create`, `status`, `buy`, `sell`, `invest`, `transfer`, `reset`, `delete`, `update` 명령의 Argument/Option 전환
- `app/domain/services.py`: `(user_id, name)` → UUID 해석 로직 추가
- `app/repositories/postgres.py`: `get_portfolio_by_name_and_user()` 단일 쿼리 구현 (REQ-016과 공유)
- Tests:
- `tests/test_cli.py`: 소유권 검증 케이스, 오류 메시지 검증, name 유효성 검사, name 중복 변경 거부 테스트
## Notes
- `(owner_user_id, name)` → UUID 조회는 REQ-016에서 추가하는 `get_portfolio_by_name_and_user()` 메서드를 사용한다.
- `name` 대소문자 구분 있음 — `TV`와 `tv`는 다른 이름으로 처리.
- Source Discovery: dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution (FR-2, FR-3, FR-3a, NFR-2)
## Change Log
### CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- 최초 생성 — dcy-004 draft-req에 의해 생성
#### Intent
- dcy-004 Discovery의 FR-2(portfolio create 명령 name+user 전환), FR-3(CLI 뮤테이션 명령 식별 방식 전환), FR-3a(name mutable + 중복 변경 거부), NFR-2(단일 DB 쿼리, 오류 메시지) 반영
#### Acceptance Criteria Delta
- Added:
- 1~8 (최초 생성)
#### Impacted Area Delta
- Docs:
- docs/runtime-flows.md: CLI 명령 흐름 변경 (REQ-019에서 처리)
- Modules:
- app/cli/commands/portfolio.py: 명령 Argument/Option 전면 교체
- app/domain/services.py: (user_id, name) → UUID 해석 추가
- app/repositories/postgres.py: get_portfolio_by_name_and_user() 추가
- Tests:
- tests/test_cli.py: 소유권 검증, 오류 메시지, name 유효성 검사 케이스 추가
#### 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: 소유권 검증 케이스, 오류 메시지 검증, name 유효성 검사, name 중복 변경 거부, alice/bob 독립 portfolio 생성 검증
### CHG-20260511-02
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- Approved 전환 — confirm-req 게이트 통과
#### Intent
- Delivery 입력으로 사용할 수 있도록 REQ-017을 승인 상태로 승격한다.
#### 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-017 AC-1~8 모두 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~8 모두 test evidence 연결 확인 (tests/test_portfolio_uuid.py, tests/test_cli.py 전체 통과)
@@ -0,0 +1,152 @@
# req-018: HTTP API portfolio path parameter UUID 전환 및 v1 asset_id UUID 반환
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: repository-maintainers
## Intent
- HTTP API의 portfolio 관련 path parameter를 기존 문자열 `portfolio_id`에서 UUID 기반으로 전환해 REQ-016의 스키마 변경과 일관성을 맞춘다.
- `GET /v1/assets` 응답의 `asset_id` 필드를 UUID로 반환해 trex-basic 계약을 갱신하고, dcy-002 A-3을 철회한다.
## Requirement
- `app/api/portfolios.py`의 portfolio 관련 path parameter를 UUID 기반으로 변경한다.
- `GET /v1/assets` 응답의 `asset_id` 필드는 `portfolios.portfolio_id`(UUID)를 반환한다.
- `app/api/v1_assets.py`의 `AssetItem` 직렬화에서 `asset_id`는 `portfolio_id`(UUID) 값을 사용한다.
- `POST /v1/assets/{asset_id}/ledger/trades` 경로의 `asset_id` path parameter는 UUID를 받아 `repo.get(asset_id)`로 portfolio를 조회한다.
- dcy-002 문서의 A-3("asset_id는 portfolio_id를 그대로 사용") 조항은 이번 REQ 구현으로 공식 철회된다. `docs/discovery/dcy-002_20260502_trex-basic-consumer-api-contract.md`에 철회 주석을 추가한다.
## Acceptance Criteria
1. Given `GET /v1/assets`를 유효한 service-token으로 호출하면, When 응답 JSON의 `assets[].asset_id` 필드를 확인하면, Then 값이 UUID 형식(`re.match(r'^[0-9a-f-]{36}$', ...)`)이다.
2. Given UUID를 `asset_id`로 사용해 `POST /v1/assets/{asset_id}/ledger/trades`를 호출하면, When 해당 UUID의 portfolio가 존재하면, Then HTTP 201(`status="new"`) 또는 HTTP 200(`status="duplicate"`)으로 정상 처리된다.
3. Given UUID를 `asset_id`로 사용해 `POST /v1/assets/{asset_id}/ledger/trades`를 호출하면, When 해당 UUID의 portfolio가 존재하지 않으면, Then HTTP 404가 반환된다.
4. Given portfolio 관련 HTTP API path(`/portfolios/{portfolio_id}`)를 UUID로 호출하면, When 해당 UUID의 portfolio가 존재하면, Then 정상 응답이 반환된다.
5. Given `docs/discovery/dcy-002_20260502_trex-basic-consumer-api-contract.md`를 확인하면, Then A-3 항목에 이번 REQ 구현으로 철회되었다는 주석이 추가되어 있다.
## Impacted Area
- Docs:
- `docs/interface-contract.md` (GET /v1/assets asset_id 변경 반영 — REQ-019에서 처리)
- `docs/discovery/dcy-002_20260502_trex-basic-consumer-api-contract.md` (A-3 철회 주석 추가)
- Modules:
- `app/api/portfolios.py`: path parameter UUID 기반 전환
- `app/api/v1_assets.py`: asset_id 직렬화 UUID 사용
- `app/schemas/portfolio.py`, `app/schemas/v1.py`: asset_id/portfolio_id 필드 타입 문서화
- Tests:
- `tests/test_app.py` 또는 `tests/test_v1.py`: GET /v1/assets asset_id UUID 형식 검증, POST /v1/assets/{asset_id}/ledger/trades UUID 호출 정상 동작 확인
## Notes
- trex-basic 측 코드 변경은 이번 REQ 범위 밖. portfolio-hub API 변경만 담당.
- trex-basic과 portfolio-hub는 동시에 배포한다(NFR-3 — 동시 배포 계획 기록은 REQ-019에서 `docs/interface-contract.md`에 처리).
- dcy-002 A-3 철회 주석 추가는 이 REQ 구현 시 함께 수행한다.
- `GET /v1/assets` flow의 `asset_id` 직렬화: `docs/runtime-flows.md` Flow `v1 API — GET /v1/assets` 갱신 필요 (REQ-019에서 처리).
- Source Discovery: dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution (FR-4)
## Change Log
### CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- 최초 생성 — dcy-004 draft-req에 의해 생성
#### Intent
- dcy-004 Discovery의 FR-4(HTTP API path parameter UUID 전환, GET /v1/assets asset_id UUID 반환, dcy-002 A-3 철회) 반영
#### Acceptance Criteria Delta
- Added:
- 1~5 (최초 생성)
#### Impacted Area Delta
- Docs:
- docs/interface-contract.md: GET /v1/assets asset_id 변경 반영 (REQ-019에서 처리)
- docs/discovery/dcy-002_*: A-3 철회 주석 추가
- Modules:
- app/api/portfolios.py: path parameter UUID 전환
- app/api/v1_assets.py: asset_id UUID 직렬화
- app/schemas/portfolio.py, app/schemas/v1.py: 필드 타입 변경
- Tests:
- tests/test_app.py 또는 tests/test_v1.py: GET /v1/assets asset_id UUID 형식 검증
#### 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: GET /v1/assets asset_id UUID 형식 검증, POST /v1/assets/{asset_id}/ledger/trades UUID 호출 동작 검증, HTTP 404 반환 확인
### CHG-20260511-02
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- Approved 전환 — confirm-req 게이트 통과
#### Intent
- Delivery 입력으로 사용할 수 있도록 REQ-018을 승인 상태로 승격한다.
#### 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-018 AC-1~5 모두 evidence 포함 (AC-1~4: 구현 코드 검증, AC-5: dcy-002 A-3 철회 주석 문서 확인). 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); trex-basic 동시 배포 조정 필요
#### Validation Plan
- BAT-006 verification.md AC-1~5 evidence 연결 확인; dcy-002 A-3 철회 주석 직접 확인 완료
@@ -1,6 +1,6 @@
# req-009: v1 API 지원을 위한 DB 스키마 migration 추가
- Status: Approved
- Status: Implemented
- Type: Migration
- Priority: High
- Owner: repository-maintainers
@@ -39,6 +39,35 @@
## Change Log
### CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- Implemented 전환 — BAT-001 re-verified verification passed, confirm-req-implemented 게이트 통과
#### Intent
- BAT-001 verification.md (re-verified, 2026-05-03) AC-1~7 모두 코드 검토 PASS. DB 환경 실행 미확인은 non-blocker로 처리됨 (revision에 IF NOT EXISTS 패턴 전체 적용 확인). Blocking Issues 없음.
#### Acceptance Criteria Delta
- none
#### Impacted Area Delta
- none
#### Delivery Trace Delta
- Batches: BAT-001 (release-candidate)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: draft-release (BAT-001); 배포 전 Docker Compose 환경에서 실제 migration 실행 검증 권장
#### Validation Plan
- BAT-001 verification.md (re-verified) AC-1~7 코드 검토 evidence 연결 확인 완료
### CHG-20260502-02
- Date: 2026-05-02
- Author: repository-maintainers
@@ -0,0 +1,157 @@
# 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)
@@ -1,6 +1,6 @@
# req-010: credential_payload Fernet 암호화 및 startup validation
- Status: Approved
- Status: Implemented
- Type: Non-Functional
- Priority: High
- Owner: repository-maintainers
@@ -35,6 +35,35 @@
## Change Log
### CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
#### Change Summary
- Implemented 전환 — BAT-001 re-verified verification passed, confirm-req-implemented 게이트 통과
#### Intent
- BAT-001 verification.md (re-verified, 2026-05-03) AC-1~5 모두 PASS. Blocking Issues 없음. AC3 DB 미확인은 REQ-009와 동일 제약으로 non-blocker 처리.
#### Acceptance Criteria Delta
- none
#### Impacted Area Delta
- none
#### Delivery Trace Delta
- Batches: BAT-001 (release-candidate)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: draft-release (BAT-001)
#### Validation Plan
- BAT-001 verification.md (re-verified) AC-1~5 evidence 연결 확인 완료
### CHG-20260502-02
- Date: 2026-05-02
- Author: repository-maintainers
+17 -16
View File
@@ -74,7 +74,7 @@
## Next Requirement ID
- Current: `REQ-016`
- Current: `REQ-020`
- Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다.
## Requirement Register
@@ -84,26 +84,27 @@
| REQ-001 | 로컬 DB 초기화 및 마이그레이션 검증 시나리오 정의 | Testing | Approved | High | repository-maintainers | [REQ-001](./Testing/req-001_local-db-validation-scenarios.md) |
| REQ-002 | Alembic와 runtime schema ownership 경계 정리 | Migration | Approved | High | repository-maintainers | [REQ-002](./Migration/req-002_alembic-runtime-schema-ownership.md) |
| REQ-003 | 로컬 DB 운영 runbook 및 baseline 문서 갱신 | Documentation | Approved | Medium | repository-maintainers | [REQ-003](./Documentation/req-003_local-db-operations-runbook-and-baseline-updates.md) |
| REQ-004 | GET /health 응답 스키마 확장 | Interface | Approved | High | repository-maintainers | [REQ-004](./Interface/req-004_health-response-schema-extension.md) |
| REQ-005 | service-token 발급 시 runtime_id 동시 생성 | Interface | Approved | High | repository-maintainers | [REQ-005](./Interface/req-005_service-token-runtime-id-issuance.md) |
| REQ-006 | GET /v1/assets 엔드포인트 구현 | Interface | Approved | High | repository-maintainers | [REQ-006](./Interface/req-006_v1-assets-endpoint.md) |
| REQ-007 | GET /v1/user_info 엔드포인트 구현 | Interface | Approved | High | repository-maintainers | [REQ-007](./Interface/req-007_v1-user-info-endpoint.md) |
| REQ-008 | POST /v1/assets/{asset_id}/ledger/trades 엔드포인트 구현 | Interface | Approved | High | repository-maintainers | [REQ-008](./Interface/req-008_v1-ledger-trades-endpoint.md) |
| REQ-009 | v1 API 지원을 위한 DB 스키마 migration 추가 | Migration | Approved | High | repository-maintainers | [REQ-009](./Migration/req-009_v1-api-db-schema-migration.md) |
| REQ-010 | credential_payload Fernet 암호화 및 startup validation | Non-Functional | Approved | High | repository-maintainers | [REQ-010](./Non-Functional/req-010_credential-payload-fernet-encryption.md) |
| REQ-004 | GET /health 응답 스키마 확장 | Interface | Implemented | High | repository-maintainers | [REQ-004](./Interface/req-004_health-response-schema-extension.md) |
| REQ-005 | service-token 발급 시 runtime_id 동시 생성 | Interface | Implemented | High | repository-maintainers | [REQ-005](./Interface/req-005_service-token-runtime-id-issuance.md) |
| REQ-006 | GET /v1/assets 엔드포인트 구현 | Interface | Implemented | High | repository-maintainers | [REQ-006](./Interface/req-006_v1-assets-endpoint.md) |
| REQ-007 | GET /v1/user_info 엔드포인트 구현 | Interface | Implemented | High | repository-maintainers | [REQ-007](./Interface/req-007_v1-user-info-endpoint.md) |
| REQ-008 | POST /v1/assets/{asset_id}/ledger/trades 엔드포인트 구현 | Interface | Implemented | High | repository-maintainers | [REQ-008](./Interface/req-008_v1-ledger-trades-endpoint.md) |
| REQ-009 | v1 API 지원을 위한 DB 스키마 migration 추가 | Migration | Implemented | High | repository-maintainers | [REQ-009](./Migration/req-009_v1-api-db-schema-migration.md) |
| REQ-010 | credential_payload Fernet 암호화 및 startup validation | Non-Functional | Implemented | High | repository-maintainers | [REQ-010](./Non-Functional/req-010_credential-payload-fernet-encryption.md) |
| REQ-011 | trex-basic 계약 반영을 위한 baseline 문서 갱신 | Documentation | Approved | Medium | repository-maintainers | [REQ-011](./Documentation/req-011_baseline-docs-update-for-trex-basic-contract.md) |
| REQ-012 | service-token rotate CLI 명령 구현 | Interface | Approved | Medium | repository-maintainers | [REQ-012](./Interface/req-012_service-token-rotate-cli.md) |
| REQ-013 | CLI `portfolio list --user` 필수화 및 소유자 기반 조회 | Interface | Implemented | Medium | repository-maintainers | [REQ-013](./Interface/req-013_portfolio-list-user-required.md) |
| REQ-014 | CLI `portfolio create --user` 필수화 및 소유자 설정 | Interface | Implemented | Medium | repository-maintainers | [REQ-014](./Interface/req-014_portfolio-create-user-required.md) |
| REQ-015 | CLI `credential` 명령 그룹 구현 (브로커 인증 정보 관리) | Interface | Approved | Medium | repository-maintainers | [REQ-015](./Interface/req-015_broker-credential-cli.md) |
| REQ-016 | portfolios 테이블 UUID 전환 및 데이터 마이그레이션 | Migration | Implemented | High | repository-maintainers | [REQ-016](./Migration/req-016_portfolios-uuid-schema-migration.md) |
| REQ-017 | CLI portfolio 명령 — name+user 조합 식별 방식 전환 | Interface | Implemented | High | repository-maintainers | [REQ-017](./Interface/req-017_portfolio-cli-name-user-identification.md) |
| REQ-018 | HTTP API portfolio path parameter UUID 전환 및 v1 asset_id UUID 반환 | Interface | Implemented | High | repository-maintainers | [REQ-018](./Interface/req-018_portfolio-http-api-uuid-path-param.md) |
| REQ-019 | portfolio UUID 전환 관련 baseline 문서 갱신 | Documentation | Implemented | Medium | repository-maintainers | [REQ-019](./Documentation/req-019_portfolio-uuid-baseline-docs-update.md) |
## Recent Change Log Summary
- 2026-05-03: REQ-006 CHG-20260503-01 — strategy_type 필드 추가 (StrategySet.name), BAT-001 재검증 필요
- 2026-05-03: REQ-015 Approved 전환 — minor-change fast path (단일 저위험 REQ)
- 2026-05-03: REQ-015 Proposed 생성 — CLI `credential` 명령 그룹 구현 (브로커 인증 정보 관리)
- 2026-05-02: REQ-014 Implemented 전환 — BAT-004 verification evidence 확인 (44 passed)
- 2026-05-02: REQ-014 Approved 직행 (minor-change) — CLI `portfolio create --user` 필수화 및 소유자 설정
- 2026-05-02: REQ-013 Implemented 전환 — BAT-003 verification evidence 확인 (41 passed)
- 2026-05-02: REQ-013 Approved 전환 — CLI `portfolio list --user` 필수화 및 소유자 기반 조회 (source Discovery: dcy-003)
- 2026-05-02: REQ-012 Approved 직행 (minor-change) — service-token rotate CLI 명령 구현
- 2026-05-11: REQ-004~010 Implemented 전환 — BAT-001 re-verified verification passed, confirm-req-implemented 게이트 통과
- 2026-05-11: REQ-016~019 Implemented 전환 — BAT-006 verification passed, confirm-req-implemented 게이트 통과
- 2026-05-11: REQ-016~019 Approved 전환 — confirm-req 게이트 통과 (source Discovery: dcy-004)
- 2026-05-11: REQ-016~019 Proposed 생성 — dcy-004 draft-req (portfolio_id UUID 교체 및 CLI 사용자 범위 기반 자산 식별 구조 전환)
- 2026-05-03: REQ-006 CHG-20260503-01 — strategy_type 필드 추가 (StrategySet.name), BAT-001 재검증 필요