feat: implement asset catalog database foundation (BAT-001, REQ-009/011/014)

Asset Catalog Model Implementation (BAT-001):
- Introduce assets table with UUID PK, symbol UNIQUE, markets TEXT[] array
- Define MarketCode enum (KRX, NXT, SOR, NASDAQ, NYSE, UPBIT, BITHUMB)
- Add Asset domain model with catalog properties
- Implement asset CRUD protocols in portfolio_repository
- Add PostgreSQL asset CRUD operations with GIN index on markets

Portfolio Model Refactoring (REQ-011):
- Add portfolios.asset_id UUID FK to assets(asset_id) ON DELETE RESTRICT
- Remove portfolios.symbol and portfolios.market columns
- Update Portfolio domain model to reference asset_id instead of symbol/market
- Refactor all portfolio queries to JOIN assets catalog
- Update all repository methods to use asset references

Data Migration (REQ-014):
- Create 20260519_0017 Alembic revision for assets table creation
- Create 20260519_0018 Alembic revision for atomic data migration:
  * Extract unique symbol combinations from portfolios
  * Aggregate markets using ARRAY_AGG(DISTINCT market)
  * Populate assets catalog with extracted data
  * Update portfolios.asset_id to reference new assets
  * Remove legacy symbol/market columns in single transaction
- Implement migration with rollback support

Requirements Approved (REQ-001~008):
- REQ-001~008 transitioned from Proposed to Approved
- Complete tag model requirement set with implementation readiness

New Requirements Approved (REQ-009~015):
- REQ-009: assets table schema (approved, included in BAT-001)
- REQ-010: admin asset catalog CRUD (approved, future BAT-002)
- REQ-011: portfolios asset_id FK (approved, included in BAT-001)
- REQ-012: portfolio create catalog validation (approved, future BAT-002)
- REQ-013: GET /v1/assets token branching (approved, future BAT-002)
- REQ-014: portfolios data migration (approved, included in BAT-001)
- REQ-015: asset catalog baseline docs (approved)

Code Changes:
- app/domain/models.py: Add Asset model, MarketCode enum, Portfolio asset_id FK
- app/repositories/portfolio_repository.py: Define asset CRUD protocol
- app/repositories/postgres.py: Implement asset operations with full CRUD
- app/api/v1_assets.py: Remove symbol/market direct references
- app/cli/commands/portfolio.py: Update portfolio commands for asset references
- app/schemas/portfolio.py: Update portfolio schema with asset_id
- All portfolio operations throughout codebase: Use asset references

Testing:
- Add test_asset_catalog.py for asset CRUD operations
- Verify REQ-009 AC-1~5 (asset catalog creation, lookup, uniqueness)
- Verify REQ-011 AC-1~5 (FK constraint, portfolio asset reference)
- Verify REQ-014 AC-1~6 (migration atomicity, data correctness, rollback)
- Update existing tests for asset model usage

Documentation:
- Create BAT-001 batch documents (planning, design, implementation, verification)
- Update dcy-001 with implementation details and confirmed architecture
- Add 8 new requirement documents (REQ-009~015)
- Update docs/discovery/index.md with batch entry

Impact:
- Database: assets catalog table, portfolios refactored to reference assets
- Migration: 2 new Alembic revisions (0017 assets, 0018 portfolio migration)
- API: Symbol/market now accessed through asset references
- CLI: Portfolio commands require asset reference pattern
- All existing portfolio data preserved and correctly migrated
This commit is contained in:
2026-05-19 15:59:20 +00:00
parent 1082f041a1
commit e2226e28b6
40 changed files with 2118 additions and 168 deletions
+29 -1
View File
@@ -1,6 +1,6 @@
# REQ-001: tags 마스터 테이블 도입
- Status: Proposed
- Status: Approved
- Type: Data
- Priority: High
- Owner: Justin Ko
@@ -39,6 +39,34 @@
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
+29 -1
View File
@@ -1,6 +1,6 @@
# REQ-002: assets.tag_ids UUID[] 컬럼 추가
- Status: Proposed
- Status: Approved
- Type: Data
- Priority: High
- Owner: Justin Ko
@@ -38,6 +38,34 @@
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
@@ -1,6 +1,6 @@
# REQ-003: portfolios.tag_ids UUID[] 컬럼 추가 및 portfolio_tags 테이블 제거
- Status: Proposed
- Status: Approved
- Type: Data
- Priority: High
- Owner: Justin Ko
@@ -38,6 +38,34 @@
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
@@ -0,0 +1,109 @@
# REQ-009: assets 테이블 스키마 도입
- Status: Approved
- Type: Data
- Priority: High
- Owner: Justin Ko
## Intent
- admin이 거래 가능한 종목을 중앙 관리할 수 있도록 `assets` catalog 테이블을 신규 도입한다.
- 기존 `portfolios` 테이블에 혼합된 asset 정의(symbol, market)를 독립 엔티티로 분리하여 "자산"과 "포지션" 개념을 명확히 구분한다.
## Requirement
- `assets` 테이블을 신규 생성한다: `asset_id UUID PK`, `symbol TEXT NOT NULL UNIQUE`, `markets TEXT[] NOT NULL DEFAULT '{}'`, `display_name TEXT`, `status TEXT NOT NULL DEFAULT 'active'`, `created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()`, `updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()`.
- `assets.markets` 컬럼에 GIN 인덱스(`idx_assets_markets_gin`)를 생성한다.
- 시장 코드 허용 값을 Python Enum `MarketCode`(KRX, NXT, SOR, NASDAQ, NYSE, UPBIT, BITTHUMB)로 `app/domain/models.py`에 정의한다. API 수신 시 대문자 정규화 후 Enum 검증을 수행한다. DB CHECK constraint는 사용하지 않는다.
- `app/domain/models.py`에 `Asset` 도메인 모델(asset_id, symbol, markets, display_name, status, created_at, updated_at)을 추가한다.
- `app/repositories/portfolio_repository.py` Protocol에 asset CRUD 메서드(`get_asset_by_id`, `get_asset_by_symbol`, `list_assets`, `insert_asset`, `update_asset`)를 선언한다.
- `app/repositories/postgres.py`에 위 메서드의 Postgres 구현을 추가한다.
## Acceptance Criteria
1. Given Alembic migration 적용 후, When `assets` 테이블 스키마를 확인, Then `asset_id UUID PK`, `symbol TEXT NOT NULL UNIQUE`, `markets TEXT[] NOT NULL DEFAULT '{}'`, `display_name TEXT`, `status TEXT NOT NULL DEFAULT 'active'`, `created_at`, `updated_at` 컬럼이 존재한다.
2. Given `assets` 테이블 존재, When 동일 `symbol`로 두 번 insert를 시도, Then UNIQUE constraint violation이 발생한다.
3. Given `assets` 테이블 존재, When 인덱스 목록을 확인, Then `idx_assets_markets_gin` GIN 인덱스가 존재한다.
4. Given `MarketCode` Enum 검증 로직, When 허용되지 않은 코드(예: 'UNKNOWN')를 전달, Then Enum 검증 오류가 반환된다.
5. Given `MarketCode` Enum 검증 로직, When 소문자 'krx'를 전달, Then 대문자 정규화 후 `MarketCode.KRX`로 검증이 통과한다.
## Impacted Area
- Docs:
- docs/data-model.md — `assets` 엔티티 추가 (REQ-015에서 처리)
- Modules:
- `migrations/versions/` — `assets` 테이블 생성 Alembic revision 신규 추가
- `app/domain/models.py` — `Asset` 도메인 모델, `MarketCode` Enum 추가
- `app/repositories/portfolio_repository.py` — asset CRUD Protocol 선언 추가
- `app/repositories/postgres.py` — asset CRUD Postgres 구현 추가
- Tests:
- `tests/test_asset_catalog.py` (신규) — schema 존재 확인, UNIQUE constraint, GIN 인덱스, MarketCode Enum 검증
## Notes
- REQ-010(admin CRUD), REQ-011(portfolios 재설계), REQ-013(GET /v1/assets), REQ-014(migration) 모두 이 REQ 선행 구현을 필요로 한다.
- NFR-2(성능): `assets JOIN portfolios` 쿼리 성능은 이 REQ의 GIN 인덱스와 REQ-011의 FK 인덱스로 커버한다. 구체적인 응답 시간 목표는 batch design 단계에서 정의한다.
- `assets` 테이블은 Alembic으로만 관리한다(ensure_schema() 대상 아님). runtime-flows.md Alembic/ensure_schema 경계 규칙 준수.
- Source: dcy-001 FR-1
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- 최초 생성 — dcy-001 confirm-discovery 후 draft-req 실행
#### Intent
- dcy-001 FR-1을 Data REQ로 분리; assets 테이블 스키마, 도메인 모델, MarketCode Enum 정의
#### Acceptance Criteria Delta
- Added:
- AC-1~5 최초 작성
#### Impacted Area Delta
- Docs:
- docs/data-model.md — 최초 지정
- Modules:
- migrations/versions/, app/domain/models.py, app/repositories/portfolio_repository.py, app/repositories/postgres.py — 최초 지정
- Tests:
- tests/test_asset_catalog.py — 최초 지정
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 계획 편입
#### Validation Plan
- pytest로 AC-1~5 검증; DB 스키마 검사는 SQLAlchemy Inspector 또는 PostgreSQL psql로 확인
@@ -0,0 +1,116 @@
# REQ-011: portfolios 테이블 asset_id FK 추가 및 symbol/market 제거
- Status: Approved
- Type: Data
- Priority: High
- Owner: Justin Ko
## Intent
- `portfolios` 테이블이 `assets` catalog를 참조하도록 재설계하여 "포지션"이 항상 검증된 catalog 항목 위에서만 존재하도록 한다.
- symbol/market 컬럼을 portfolios에서 제거하고 assets JOIN으로 대체한다.
## Requirement
- `portfolios` 테이블에 `asset_id UUID NOT NULL` 컬럼을 추가하고 `FOREIGN KEY (asset_id) REFERENCES assets(asset_id) ON DELETE RESTRICT` DB-level FK constraint를 적용한다.
- `portfolios.symbol` 컬럼과 `portfolios.market` 컬럼을 제거한다.
- `portfolios.broker` 컬럼은 그대로 유지한다.
- `(owner_user_id, asset_id)` UNIQUE constraint는 추가하지 않는다(동일 user가 동일 asset에 복수 portfolio 허용).
- `portfolios.managed_by_daemon_id`는 기존과 동일하게 nullable soft reference로 유지한다.
- `app/domain/models.py`의 `Portfolio` 모델에서 `symbol`, `market` 필드를 제거하고 `asset_id` 참조를 추가한다.
- `app/repositories/postgres.py`의 portfolios 쿼리를 `assets JOIN portfolios` 형태로 변경한다.
- `symbol`/`market` 컬럼을 직접 참조하는 모든 쿼리, API response, CLI 출력을 수정한다(R-2 리스크 대응).
## Acceptance Criteria
1. Given Alembic migration 적용 후, When `portfolios` 테이블 스키마를 확인, Then `asset_id UUID NOT NULL`과 `FOREIGN KEY (asset_id) REFERENCES assets(asset_id) ON DELETE RESTRICT`가 존재하고 `symbol`, `market` 컬럼이 없다.
2. Given 존재하지 않는 `asset_id`로 portfolio insert 시도, When DB에 반영, Then FK constraint violation이 발생한다.
3. Given `status='inactive'`인 asset을 참조하는 portfolio가 존재, When 해당 asset 행을 DELETE 시도, Then ON DELETE RESTRICT로 인해 거부된다.
4. Given `portfolios` 테이블 재설계 후, When 기존 portfolio 조회 API/CLI 호출, Then symbol, market 필드 참조 오류 없이 정상 응답이 반환된다.
5. Given 동일 user, 동일 asset_id, When 두 번째 portfolio를 생성, Then 성공적으로 생성된다(UNIQUE constraint 없음).
## Impacted Area
- Docs:
- docs/data-model.md — `Portfolio` 엔티티 재정의 (REQ-015에서 처리)
- Modules:
- `migrations/versions/` — `portfolios.asset_id FK` 추가, `symbol`/`market` 컬럼 제거 Alembic revision
- `app/domain/models.py` — `Portfolio` 모델 symbol/market 필드 제거, asset_id 추가
- `app/repositories/postgres.py` — portfolios 쿼리 assets JOIN 반영, symbol/market 참조 제거
- `app/api/portfolios.py` — portfolio 생성/조회 response에서 symbol/market 제거
- `app/api/v1_assets.py` — response에서 symbol/market 제거 (asset 참조로 대체)
- `app/cli/commands/portfolio.py` — portfolio 출력에서 symbol/market 제거
- `app/schemas/` — `PortfolioListItem`, `PortfolioDetailResponse` 등 스키마 변경
- Tests:
- 기존 테스트 suite — symbol/market 참조 테스트 갱신
- `tests/test_asset_catalog.py` (신규) — FK constraint, RESTRICT 동작 검증
## Notes
- R-2(High): migration 전 `grep -rn "\.symbol\|\.market" app/`으로 참조 범위를 전수 조사해야 한다. broker는 portfolios에 유지되므로 별도 조사 불필요.
- NFR-2(성능): portfolios.asset_id FK 인덱스는 DB가 자동 생성한다. assets JOIN portfolios 쿼리 성능을 batch verification에서 확인한다.
- REQ-009 선행 필요(assets 테이블이 먼저 존재해야 FK 적용 가능).
- REQ-014(data migration)가 이 REQ의 schema 변경과 연계되어야 한다. schema 변경과 데이터 이전을 같은 Alembic revision 또는 순서 보장된 revision 시퀀스로 처리한다.
- Source: dcy-001 FR-3, R-2
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- 최초 생성 — dcy-001 confirm-discovery 후 draft-req 실행
#### Intent
- dcy-001 FR-3을 Data REQ로 분리; portfolios 테이블 asset_id FK 추가, symbol/market 제거
#### Acceptance Criteria Delta
- Added:
- AC-1~5 최초 작성
#### Impacted Area Delta
- Docs:
- docs/data-model.md — 최초 지정
- Modules:
- migrations/versions/, app/domain/models.py, app/repositories/postgres.py, app/api/portfolios.py, app/api/v1_assets.py, app/cli/commands/portfolio.py, app/schemas/ — 최초 지정
- Tests:
- 기존 테스트 suite, tests/test_asset_catalog.py — 최초 지정
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 계획 편입; REQ-009 선행 의존성 확인
#### Validation Plan
- pytest로 AC-1~5 검증; grep으로 symbol/market 참조 잔존 여부 확인
@@ -1,6 +1,6 @@
# REQ-008: 태그 모델 도입 baseline 문서 갱신
- Status: Proposed
- Status: Approved
- Type: Documentation
- Priority: Low
- Owner: Justin Ko
@@ -38,6 +38,34 @@
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
@@ -0,0 +1,103 @@
# REQ-015: asset catalog 도입 baseline 문서 갱신
- Status: Approved
- Type: Documentation
- Priority: Low
- Owner: Justin Ko
## Intent
- dcy-001에서 정의한 assets 테이블, portfolios 재설계, admin CRUD API/CLI, GET /v1/assets 토큰 분기 변경 내용을 baseline 문서에 반영하여 다음 Discovery/REQ 작성 시 잘못된 baseline 참조를 방지한다.
## Requirement
- `docs/data-model.md`에 `assets` 엔티티(asset_id, symbol, markets, display_name, status, created_at, updated_at)를 추가하고 `portfolios` 엔티티에서 symbol/market 제거 및 asset_id FK 참조를 반영한다.
- `docs/interface-contract.md`에 `POST /v1/assets`, `PATCH /v1/assets/{asset_id}`, `PATCH /v1/assets/{asset_id}/deactivate` 엔드포인트 명세를 추가하고 `GET /v1/assets`의 토큰 타입별 분기 동작을 갱신한다.
- `docs/runtime-flows.md`의 "Flow: v1 API — GET /v1/assets" 섹션을 service-token-only에서 토큰 타입 분기 구조로 교체하고, admin asset CRUD HTTP 흐름을 신규 추가한다.
- `docs/project-structure.md`의 `app/cli/` Command groups 목록에 `asset` 커맨드 그룹을 추가하고, `app/api/` v1 route surfaces에 admin asset CRUD 엔드포인트를 반영한다.
## Acceptance Criteria
1. Given 구현 완료 후, When `docs/data-model.md`를 검토, Then `assets` 테이블 스키마(asset_id, symbol UNIQUE, markets TEXT[], display_name, status)와 `portfolios`의 asset_id FK 참조, symbol/market 제거가 반영되어 있다.
2. Given 구현 완료 후, When `docs/interface-contract.md`를 검토, Then `POST/PATCH /v1/assets` 및 `PATCH /v1/assets/{id}/deactivate` 엔드포인트 명세, GET /v1/assets 토큰 타입별 분기 동작이 포함되어 있다.
3. Given 구현 완료 후, When `docs/runtime-flows.md`를 검토, Then "GET /v1/assets" 플로우가 토큰 타입 분기 구조(service/user/admin)로 갱신되어 있고 admin asset CRUD 흐름이 추가되어 있다.
4. Given 구현 완료 후, When `docs/project-structure.md`를 검토, Then `app/cli/` Command groups에 `asset`이 포함되고 `app/api/` v1 route surfaces에 admin asset CRUD 엔드포인트가 반영되어 있다.
## Impacted Area
- Docs:
- `docs/data-model.md`
- `docs/interface-contract.md`
- `docs/runtime-flows.md`
- `docs/project-structure.md`
- Modules: 없음 (문서 전용)
- Tests: 없음 (문서 검토로 확인)
## Notes
- 이 REQ는 REQ-009~014 구현 완료 후 마지막으로 수행한다.
- `docs/runtime-flows.md` Update Triggers: "새 top-level runtime 또는 domain 모듈이 추가되었을 때" — asset CLI 그룹 추가, GET /v1/assets 토큰 분기 재정의 모두 해당.
- `docs/project-structure.md` Update Triggers: "새 top-level runtime 또는 domain 모듈이 추가되었을 때" — `app/cli/commands/asset.py` 신규 추가 해당.
- Source: dcy-001 In Scope(baseline 문서 갱신)
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- 최초 생성 — dcy-001 confirm-discovery 후 draft-req 실행
#### Intent
- dcy-001 구현 범위의 baseline 문서 갱신 요구를 Documentation REQ로 분리
#### Acceptance Criteria Delta
- Added:
- AC-1~4 최초 작성
#### Impacted Area Delta
- Docs:
- docs/data-model.md, docs/interface-contract.md, docs/runtime-flows.md, docs/project-structure.md — 최초 지정
- Modules:
- 없음
- Tests:
- 없음
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: REQ-009~014 구현 완료 후 일괄 반영
#### Validation Plan
- 각 대상 문서를 직접 검토하여 AC-1~4 기술 내용 포함 여부 확인
+29 -1
View File
@@ -1,6 +1,6 @@
# REQ-004: tags 마스터 HTTP API
- Status: Proposed
- Status: Approved
- Type: Interface
- Priority: High
- Owner: Justin Ko
@@ -48,6 +48,34 @@
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
@@ -1,6 +1,6 @@
# REQ-005: 태그 적용·해제 HTTP API
- Status: Proposed
- Status: Approved
- Type: Interface
- Priority: High
- Owner: Justin Ko
@@ -48,6 +48,34 @@
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
+29 -1
View File
@@ -1,6 +1,6 @@
# REQ-007: pfhub tag CLI 명령어
- Status: Proposed
- Status: Approved
- Type: Interface
- Priority: Medium
- Owner: Justin Ko
@@ -47,6 +47,34 @@
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
@@ -0,0 +1,120 @@
# REQ-010: admin asset catalog CRUD
- Status: Approved
- Type: Interface
- Priority: High
- Owner: Justin Ko
## Intent
- admin이 CLI 및 HTTP API를 통해 거래 가능한 종목을 `assets` catalog에 등록·수정·비활성화할 수 있도록 한다.
- admin이 아닌 user 또는 daemon의 catalog 직접 변경 시도를 HTTP 403으로 거부한다(NFR-3).
## Requirement
- CLI: `pfhub asset create <symbol> [--markets <codes>] [--display-name <name>]` — admin 권한 필요. markets 값은 쉼표 구분 MarketCode Enum 값.
- CLI: `pfhub asset list [--inactive]` — active asset만 기본 출력; `--inactive` 지정 시 inactive 포함 전체 출력.
- CLI: `pfhub asset update <symbol> [--markets <codes>] [--display-name <name>]` — admin 권한 필요.
- CLI: `pfhub asset deactivate <symbol> [--force]` — admin 권한 필요. `--force` 없으면 확인 프롬프트 출력.
- HTTP API: `POST /v1/assets` — admin token 필요. request body에 symbol, markets, display_name. 성공 시 HTTP 201 + 생성된 asset 반환.
- HTTP API: `PATCH /v1/assets/{asset_id}` — admin token 필요. markets, display_name 변경 가능. 성공 시 HTTP 200 + 갱신된 asset 반환.
- HTTP API: `PATCH /v1/assets/{asset_id}/deactivate` — admin token 필요. `status='inactive'`로 변경. 성공 시 HTTP 200.
- admin 이외의 token으로 POST/PATCH 요청 시 HTTP 403을 반환한다.
- asset hard DELETE는 제공하지 않는다(soft delete 전용).
- `app/cli/commands/asset.py` 신규 파일로 pfhub asset 커맨드 그룹을 구현한다.
- `app/cli/main.py`에 `app.add_typer(asset_app, name="asset")`을 추가한다.
- `app/services/` 또는 관련 서비스에 asset create/update/deactivate/list 로직을 추가한다.
## Acceptance Criteria
1. Given admin 토큰, When `pfhub asset create "005930.KS" --markets KRX,NXT`, Then assets catalog에 symbol='005930.KS', markets=['KRX','NXT'], status='active' 항목이 생성된다.
2. Given admin 토큰, When `pfhub asset list`, Then status='active'인 asset 목록이 출력된다.
3. Given active/inactive asset 모두 존재, When `pfhub asset list --inactive`, Then inactive 포함 전체 목록이 출력된다.
4. Given admin 토큰, When `pfhub asset deactivate "005930.KS" --force`, Then 해당 asset의 status가 'inactive'로 변경된다.
5. Given admin 토큰, When `POST /v1/assets` with valid symbol and markets, Then HTTP 201과 생성된 asset_id가 반환된다.
6. Given admin 토큰, When `PATCH /v1/assets/{asset_id}` with updated markets, Then HTTP 200과 변경된 asset이 반환된다.
7. Given admin 토큰, When `PATCH /v1/assets/{asset_id}/deactivate`, Then HTTP 200과 status='inactive'가 반환된다.
8. Given non-admin token (user 또는 service token), When `POST /v1/assets` 요청, Then HTTP 403이 반환된다.
## Impacted Area
- Docs:
- docs/project-structure.md — `app/cli/` Command groups에 `asset` 추가 (REQ-015에서 처리)
- docs/interface-contract.md — POST/PATCH /v1/assets 엔드포인트 명세 추가 (REQ-015에서 처리)
- Modules:
- `app/cli/commands/asset.py` — 신규 파일, pfhub asset 커맨드 그룹
- `app/cli/main.py` — `app.add_typer(asset_app, name="asset")` 추가
- `app/services/` — asset create/update/deactivate/list 서비스 메서드 추가
- `app/api/v1_assets.py` — POST, PATCH 라우트 추가
- `app/schemas/` — `CreateAssetRequest`, `UpdateAssetRequest`, `AssetCatalogResponse` 스키마 추가
- Tests:
- `tests/test_asset_catalog.py` (신규) — admin CRUD CLI/API AC 검증, non-admin 403 검증
## Notes
- `pfhub asset list`의 HTTP 대응(catalog 전용 GET)은 별도 admin 전용 엔드포인트로 구현하거나, GET /v1/assets에 `?mode=catalog` 파라미터로 분기할 수 있다. 설계 결정은 batch design 단계에서 확정한다. REQ-013(GET /v1/assets 포트폴리오 조회)과 충돌하지 않도록 주의한다.
- deactivate 후 해당 asset을 참조하는 기존 portfolio는 보존된다. 신규 portfolio 생성만 거부(REQ-012에서 처리).
- REQ-009 선행 필요.
- Source: dcy-001 FR-2, NFR-3
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- 최초 생성 — dcy-001 confirm-discovery 후 draft-req 실행
#### Intent
- dcy-001 FR-2, NFR-3을 Interface REQ로 분리; admin catalog CRUD CLI + HTTP API 정의
#### Acceptance Criteria Delta
- Added:
- AC-1~8 최초 작성
#### Impacted Area Delta
- Docs:
- docs/project-structure.md, docs/interface-contract.md — 최초 지정
- Modules:
- app/cli/commands/asset.py, app/cli/main.py, app/services/, app/api/v1_assets.py, app/schemas/ — 최초 지정
- Tests:
- tests/test_asset_catalog.py — 최초 지정
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 계획 편입; REQ-009 선행 의존성 확인
#### Validation Plan
- pytest로 AC-1~8 검증; CLI는 CliRunner, HTTP는 TestClient 사용
@@ -0,0 +1,102 @@
# REQ-012: portfolio 생성 CLI catalog 검증
- Status: Approved
- Type: Interface
- Priority: High
- Owner: Justin Ko
## Intent
- user가 `pfhub portfolio create` CLI로 portfolio를 생성할 때 지정한 asset이 catalog에 active 상태로 존재하는지 검증하여, 미등록 또는 비활성 asset 기반의 portfolio 생성을 방지한다.
## Requirement
- `pfhub portfolio create` 명령에 `--asset-id <uuid>` 또는 `--symbol <symbol>` 옵션을 추가하여 catalog asset을 지정하도록 한다.
- portfolio 생성 전 지정된 `asset_id`(또는 symbol로 조회한 asset_id)가 `assets` catalog에 `status='active'`로 존재하는지 검증한다.
- catalog에 없거나 `status='inactive'`인 asset이면 오류 메시지와 함께 생성을 거부한다.
- `app/services/portfolio_service.py`의 `create_portfolio`에 asset 검증 로직을 추가한다.
- user portfolio CRUD HTTP API(POST /portfolios 등)는 이 REQ 범위 밖이다(별도 Discovery에서 처리).
## Acceptance Criteria
1. Given active asset이 catalog에 존재, When `pfhub portfolio create <name> --asset-id <asset_id> --user <username>`, Then portfolio가 생성되고 해당 asset_id로 연결된다.
2. Given 존재하지 않는 asset_id, When `pfhub portfolio create` with 미등록 asset_id, Then "asset not found" 오류가 출력되고 portfolio가 생성되지 않는다.
3. Given `status='inactive'`인 asset_id, When `pfhub portfolio create` with 해당 asset_id, Then "asset is inactive" 오류가 출력되고 portfolio가 생성되지 않는다.
4. Given `--symbol <symbol>` 옵션 사용, When 해당 symbol이 catalog에 active로 존재, Then symbol로 asset_id를 조회하여 portfolio를 생성한다.
## Impacted Area
- Docs: 없음 (별도 문서 갱신 불필요)
- Modules:
- `app/cli/commands/portfolio.py` — create 명령에 `--asset-id` / `--symbol` 옵션 추가
- `app/services/portfolio_service.py` — create_portfolio에 catalog 검증 로직 추가
- Tests:
- `tests/test_asset_catalog.py` (신규) — catalog 검증 AC-1~4 검증
## Notes
- REQ-009(assets 테이블), REQ-011(portfolios 재설계) 선행 필요.
- HTTP API를 통한 portfolio 생성 시 catalog 검증 정책은 동일하게 적용되어야 하나, HTTP mutation API는 Out of Scope(별도 Discovery 처리 예정)이다.
- Source: dcy-001 FR-4
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- 최초 생성 — dcy-001 confirm-discovery 후 draft-req 실행
#### Intent
- dcy-001 FR-4를 Interface REQ로 분리; portfolio create CLI catalog 검증 정의
#### Acceptance Criteria Delta
- Added:
- AC-1~4 최초 작성
#### Impacted Area Delta
- Docs:
- 없음
- Modules:
- app/cli/commands/portfolio.py, app/services/portfolio_service.py — 최초 지정
- Tests:
- tests/test_asset_catalog.py — 최초 지정
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 계획 편입; REQ-009, REQ-011 선행 의존성 확인
#### Validation Plan
- pytest CliRunner로 AC-1~4 검증
@@ -0,0 +1,112 @@
# REQ-013: GET /v1/assets 토큰 타입별 분기 재정의
- Status: Approved
- Type: Interface
- Priority: High
- Owner: Justin Ko
## Intent
- 현재 service token(daemon) 전용으로 구현된 `GET /v1/assets`를 user token 및 admin token도 지원하는 통합 portfolio 조회 엔드포인트로 재정의한다.
- daemon(service token), 로그인 사용자(user token), 관리자(admin token) 모두 단일 엔드포인트로 각자의 portfolio 목록을 조회할 수 있도록 한다.
## Requirement
- `GET /v1/assets` 엔드포인트를 토큰 타입에 따라 아래와 같이 분기한다.
- **service token (daemon)**: auth context에서 `daemon_id`를 자동 추출, `managed_by_daemon_id = auth.daemon_id` 필터링. `daemon_id`가 없으면 HTTP 403.
- **user token**: `owner_user_id = auth.user_id` 필터링. 본인 portfolio만 반환.
- **admin token**: 기본 `owner_user_id = auth.user_id`(본인 portfolio). `?user_id=<id>` 파라미터 지정 시 해당 user의 portfolio 반환.
- 모든 토큰 타입에서 `?market=<code>` 파라미터를 지원한다. 지정 시 `<code> = ANY(assets.markets)`인 portfolio만 반환한다.
- 응답 항목의 `asset_id`는 catalog의 `assets.asset_id`(UUID)를 참조한다(현재 `portfolio.portfolio_id`가 아님).
- `app/api/v1_assets.py`의 `list_assets` 함수를 토큰 타입 분기 로직으로 재작성한다. 현재 `_require_service_token` 강제를 제거하고 토큰 타입 자동 분기로 교체한다.
## Acceptance Criteria
1. Given daemon service token(daemon_id 있음), When `GET /v1/assets`, Then `managed_by_daemon_id = auth.daemon_id`로 필터링된 portfolio 목록이 반환된다.
2. Given daemon service token(daemon_id 없음), When `GET /v1/assets`, Then HTTP 403이 반환된다.
3. Given user token, When `GET /v1/assets`, Then `owner_user_id = auth.user_id`인 portfolio 목록만 반환된다.
4. Given admin token, When `GET /v1/assets` (`?user_id` 없음), Then admin 본인의 portfolio 목록이 반환된다.
5. Given admin token, When `GET /v1/assets?user_id=<target_user_id>`, Then 해당 user의 portfolio 목록이 반환된다.
6. Given 모든 토큰 타입, When `GET /v1/assets?market=KRX`, Then `KRX = ANY(assets.markets)`인 portfolio만 반환된다.
7. Given 응답 항목, When `asset_id` 필드 확인, Then `assets.asset_id`(catalog UUID)를 참조한다(portfolio_id가 아님).
## Impacted Area
- Docs:
- docs/runtime-flows.md — "GET /v1/assets" 플로우 재정의 (REQ-015에서 처리). 현재 기술(service-token-only, daemon-id guard)을 토큰 타입 분기 구조로 교체.
- docs/interface-contract.md — GET /v1/assets 명세 갱신 (REQ-015에서 처리)
- Modules:
- `app/api/v1_assets.py` — `list_assets` 토큰 타입 분기 재작성, `?user_id` 파라미터 추가, `_require_service_token` 강제 제거
- `app/repositories/postgres.py` — token-type별 portfolios 쿼리 분기
- Tests:
- `tests/test_v1_asset_catalog.py` (신규) — AC-1~7 검증
- 기존 `test_v1_assets.py` 또는 관련 테스트 — service token 전용 동작 갱신
## Notes
- 현재 `app/api/v1_assets.py`의 `_require_service_token`은 service token 전용으로 구현되어 있다. 이 REQ는 해당 guard를 제거하고 토큰 타입 자동 분기로 완전 재작성하는 작업이다.
- 현재 `runtime-flows.md` "Flow: v1 API — GET /v1/assets"는 service-token-only 구조를 기술하고 있다. 이 REQ 구현 후 해당 플로우를 REQ-015에서 갱신해야 한다.
- REQ-009(assets 테이블), REQ-011(portfolios 재설계) 선행 필요.
- Source: dcy-001 FR-5
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- 최초 생성 — dcy-001 confirm-discovery 후 draft-req 실행
#### Intent
- dcy-001 FR-5를 Interface REQ로 분리; GET /v1/assets 토큰 타입별 분기 정의
#### Acceptance Criteria Delta
- Added:
- AC-1~7 최초 작성
#### Impacted Area Delta
- Docs:
- docs/runtime-flows.md, docs/interface-contract.md — 최초 지정
- Modules:
- app/api/v1_assets.py, app/repositories/postgres.py — 최초 지정
- Tests:
- tests/test_v1_asset_catalog.py (신규), 기존 v1 테스트 — 최초 지정
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 계획 편입; REQ-009, REQ-011 선행 의존성 확인
#### Validation Plan
- pytest TestClient로 AC-1~7 검증; 토큰 타입별 시나리오를 각각 독립 테스트로 분리
@@ -1,6 +1,6 @@
# REQ-006: portfolio_tags 데이터 마이그레이션
- Status: Proposed
- Status: Approved
- Type: Migration
- Priority: High
- Owner: Justin Ko
@@ -44,6 +44,34 @@
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
@@ -0,0 +1,109 @@
# REQ-014: portfolios 데이터 migration
- Status: Approved
- Type: Migration
- Priority: High
- Owner: Justin Ko
## Intent
- 기존 `portfolios` 테이블의 운영 데이터를 `assets` catalog + `portfolios` 포지션 구조로 유실 없이 이전한다.
- migration은 단일 트랜잭션 내에서 원자적으로 실행되어야 하며 실패 시 롤백 가능해야 한다(NFR-1).
## Requirement
- Alembic revision으로 아래 데이터 이전을 수행한다.
- 기존 `portfolios` 행의 `symbol`을 기준으로 중복 없이 `assets` catalog 항목을 생성한다. 동일 symbol의 모든 `market` 값을 `ARRAY_AGG(DISTINCT market)`으로 집약하여 `assets.markets`에 저장한다. market 값이 NULL인 기존 행은 빈 배열로 처리한다.
- 각 portfolio 행에 생성된 asset의 `asset_id FK`를 연결한다.
- `portfolios.managed_by_daemon_id`는 기존 값을 그대로 유지한다.
- migration 전 `SELECT symbol, ARRAY_AGG(DISTINCT market) FROM portfolios GROUP BY symbol`로 symbol별 market 집합을 파악하는 사전 검증 쿼리를 migration script에 포함한다.
- 전체 이전 작업은 단일 트랜잭션으로 실행하며, 중간 실패 시 rollback되어 기존 상태로 복원된다.
- migration 완료 후 `portfolios.symbol`, `portfolios.market` 컬럼을 제거한다(REQ-011과 동일 revision 또는 순서 보장된 revision에서 처리).
## Acceptance Criteria
1. Given migration 실행 전, When `SELECT COUNT(*) FROM portfolios`로 기존 행 수 확인, Then migration 후 동일 행 수가 유지된다.
2. Given migration 실행 후, When `SELECT COUNT(*) FROM assets`를 확인, Then 기존 portfolios의 고유 symbol 수와 일치하는 assets 행이 존재한다.
3. Given migration 실행 후, When 임의 portfolio 행의 `asset_id`로 `assets` 테이블을 JOIN 조회, Then 해당 asset의 symbol과 migration 전 portfolio의 symbol이 일치한다.
4. Given migration 실행 후, When `assets.markets`를 확인, Then 동일 symbol을 가졌던 모든 market 값이 배열에 포함되어 있다.
5. Given migration 실행 중 오류 발생 시뮬레이션, When rollback 후 상태 확인, Then 기존 portfolios 데이터가 원상태로 보존된다.
6. Given migration 완료 후, When `portfolios` 테이블 스키마 확인, Then `symbol`, `market` 컬럼이 존재하지 않는다.
## Impacted Area
- Docs: 없음 (docs 갱신은 REQ-015에서 처리)
- Modules:
- `migrations/versions/` — portfolios 데이터 이전 + symbol/market 컬럼 제거 Alembic revision
- Tests:
- `tests/test_asset_catalog.py` (신규) — migration AC-1~6 검증
- 기존 테스트 suite — migration 후 regression 검증
## Notes
- R-1(High): 동일 symbol을 가진 여러 portfolio 행의 market 값이 서로 다를 수 있다. `ARRAY_AGG(DISTINCT market)` 집약 규칙을 migration script에 명시적으로 구현한다.
- A-1(가정): 동일 symbol → 단일 assets 항목 병합, ARRAY_AGG(DISTINCT market) 집약, broker → 각 portfolio 행 유지.
- migration 전 `SELECT COUNT(*) FROM portfolios WHERE managed_by_daemon_id IS NULL`로 미배정 portfolio 현황을 파악하고, 필요한 경우 migration 전 daemon 배정 절차를 선행한다(R-3).
- REQ-009(assets 테이블), REQ-011(portfolios 재설계) 선행 필요.
- Source: dcy-001 FR-6, NFR-1, R-1, A-1
## Change Log
### CHG-20260519-02
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- Status: Proposed → Approved
#### Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료
#### Acceptance Criteria Delta
- No change
#### Impacted Area Delta
- No change
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: batch 계획 편입
### CHG-20260519-01
- Date: 2026-05-19
- Author: Justin Ko
#### Change Summary
- 최초 생성 — dcy-001 confirm-discovery 후 draft-req 실행
#### Intent
- dcy-001 FR-6, NFR-1을 Migration REQ로 분리; portfolios 데이터 이전 및 원자적 실행 정의
#### Acceptance Criteria Delta
- Added:
- AC-1~6 최초 작성
#### Impacted Area Delta
- Docs:
- 없음
- Modules:
- migrations/versions/ — 최초 지정
- Tests:
- tests/test_asset_catalog.py, 기존 테스트 suite — 최초 지정
#### Delivery Trace Delta
- Batches:
- none (미정)
- Releases:
- none (미정)
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 계획 편입; REQ-009, REQ-011 선행 의존성 확인
#### Validation Plan
- pytest로 AC-1~6 검증; 트랜잭션 rollback은 savepoint 또는 테스트 DB 격리로 시뮬레이션
+18 -9
View File
@@ -74,22 +74,31 @@
## Next Requirement ID
- Current: `REQ-009`
- Current: `REQ-016`
- Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다.
## Requirement Register
| ID | Title | Type | Status | Priority | Owner | Link |
| --- | --- | --- | --- | --- | --- | --- |
| REQ-001 | tags 마스터 테이블 도입 | Data | Proposed | High | Justin Ko | [req-001](./Data/req-001_tags-master-table.md) |
| REQ-002 | assets.tag_ids UUID[] 컬럼 추가 | Data | Proposed | High | Justin Ko | [req-002](./Data/req-002_assets-tag-ids-column.md) |
| REQ-003 | portfolios.tag_ids UUID[] 컬럼 추가 및 portfolio_tags 테이블 제거 | Data | Proposed | High | Justin Ko | [req-003](./Data/req-003_portfolios-tag-ids-and-portfolio-tags-removal.md) |
| REQ-004 | tags 마스터 HTTP API | Interface | Proposed | High | Justin Ko | [req-004](./Interface/req-004_tags-http-api.md) |
| REQ-005 | 태그 적용·해제 HTTP API | Interface | Proposed | High | Justin Ko | [req-005](./Interface/req-005_tag-apply-remove-http-api.md) |
| REQ-006 | portfolio_tags 데이터 마이그레이션 | Migration | Proposed | High | Justin Ko | [req-006](./Migration/req-006_portfolio-tags-data-migration.md) |
| REQ-007 | pfhub tag CLI 명령어 | Interface | Proposed | Medium | Justin Ko | [req-007](./Interface/req-007_pfhub-tag-cli.md) |
| REQ-008 | 태그 모델 도입 baseline 문서 갱신 | Documentation | Proposed | Low | Justin Ko | [req-008](./Documentation/req-008_tag-baseline-docs-update.md) |
| REQ-001 | tags 마스터 테이블 도입 | Data | Approved | High | Justin Ko | [req-001](./Data/req-001_tags-master-table.md) |
| REQ-002 | assets.tag_ids UUID[] 컬럼 추가 | Data | Approved | High | Justin Ko | [req-002](./Data/req-002_assets-tag-ids-column.md) |
| REQ-003 | portfolios.tag_ids UUID[] 컬럼 추가 및 portfolio_tags 테이블 제거 | Data | Approved | High | Justin Ko | [req-003](./Data/req-003_portfolios-tag-ids-and-portfolio-tags-removal.md) |
| REQ-004 | tags 마스터 HTTP API | Interface | Approved | High | Justin Ko | [req-004](./Interface/req-004_tags-http-api.md) |
| REQ-005 | 태그 적용·해제 HTTP API | Interface | Approved | High | Justin Ko | [req-005](./Interface/req-005_tag-apply-remove-http-api.md) |
| REQ-006 | portfolio_tags 데이터 마이그레이션 | Migration | Approved | High | Justin Ko | [req-006](./Migration/req-006_portfolio-tags-data-migration.md) |
| REQ-007 | pfhub tag CLI 명령어 | Interface | Approved | Medium | Justin Ko | [req-007](./Interface/req-007_pfhub-tag-cli.md) |
| REQ-008 | 태그 모델 도입 baseline 문서 갱신 | Documentation | Approved | Low | Justin Ko | [req-008](./Documentation/req-008_tag-baseline-docs-update.md) |
| REQ-009 | assets 테이블 스키마 도입 | Data | Approved | High | Justin Ko | [req-009](./Data/req-009_assets-table-schema.md) |
| REQ-010 | admin asset catalog CRUD | Interface | Approved | High | Justin Ko | [req-010](./Interface/req-010_admin-asset-catalog-crud.md) |
| REQ-011 | portfolios asset_id FK 추가 및 symbol/market 제거 | Data | Approved | High | Justin Ko | [req-011](./Data/req-011_portfolios-asset-id-fk-and-column-removal.md) |
| REQ-012 | portfolio 생성 CLI catalog 검증 | Interface | Approved | High | Justin Ko | [req-012](./Interface/req-012_portfolio-create-catalog-validation.md) |
| REQ-013 | GET /v1/assets 토큰 타입별 분기 재정의 | Interface | Approved | High | Justin Ko | [req-013](./Interface/req-013_get-v1-assets-token-branching.md) |
| REQ-014 | portfolios 데이터 migration | Migration | Approved | High | Justin Ko | [req-014](./Migration/req-014_portfolios-data-migration.md) |
| REQ-015 | asset catalog 도입 baseline 문서 갱신 | Documentation | Approved | Low | Justin Ko | [req-015](./Documentation/req-015_asset-catalog-baseline-docs-update.md) |
## Recent Change Log Summary
- 2026-05-19: REQ-001~015 전체 Proposed → Approved 전환 — confirm-req 일괄 승인; 승인 게이트(필수 필드, AC 구체성, Change Log) 모두 충족
- 2026-05-19: REQ-009~015 최초 생성 — dcy-001 (자산 관리 구조 재설계) confirm-discovery 후 draft-req 실행
- 2026-05-19: REQ-001~008 최초 생성 — dcy-002 (태그 소유권 및 적용 대상 정책) confirm-discovery 후 draft-req 실행