- REQ-002 scope redefinition: portfolios.tag_ids → assets.tag_ids UUID[] column with GIN index
- REQ-010 augmentation: GET /v1/assets redesigned as admin catalog endpoint (admin-only, no token_type branching)
- Asset tagging infrastructure: tag_ids column, archived flag synthesis for inactive tags, list_assets N+1 optimization
- DB migration 20260521_0023: assets.tag_ids UUID[] NOT NULL DEFAULT '{}', idx_assets_tag_ids_gin
- Test suite: 17 new test cases for assets.tag_ids + GET /v1/assets AC-9~12 (362 tests total)
- Documentation: runtime flows, release baseline, batch verification all updated
- BAT-012 added to REL-001 Included Batch and marked release-candidate
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12 KiB
12 KiB
REQ-010: admin asset catalog CRUD
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: Justin Ko
Intent
- admin이 CLI 및 HTTP API를 통해 거래 가능한 종목을
assetscatalog에 등록·수정·비활성화할 수 있도록 한다. - 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. - HTTP API:
GET /v1/assets— admin token 필요. query paramstatus(active|inactive|all, 기본active),market(선택, MarketCode 1개). 응답:{ items: [{ asset_id, symbol, markets, display_name, status, created_at, updated_at }] }형식. 응답 본문에 portfolio 관련 필드는 포함하지 않는다(path 의미 분리 — portfolio 조회는GET /v1/portfolios). - admin 이외의 token으로 POST/PATCH/GET 요청 시 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
- Given admin 토큰, When
pfhub asset create "005930.KS" --markets KRX,NXT, Then assets catalog에 symbol='005930.KS', markets=['KRX','NXT'], status='active' 항목이 생성된다. - Given admin 토큰, When
pfhub asset list, Then status='active'인 asset 목록이 출력된다. - Given active/inactive asset 모두 존재, When
pfhub asset list --inactive, Then inactive 포함 전체 목록이 출력된다. - Given admin 토큰, When
pfhub asset deactivate "005930.KS" --force, Then 해당 asset의 status가 'inactive'로 변경된다. - Given admin 토큰, When
POST /v1/assetswith valid symbol and markets, Then HTTP 201과 생성된 asset_id가 반환된다. - Given admin 토큰, When
PATCH /v1/assets/{asset_id}with updated markets, Then HTTP 200과 변경된 asset이 반환된다. - Given admin 토큰, When
PATCH /v1/assets/{asset_id}/deactivate, Then HTTP 200과 status='inactive'가 반환된다. - Given non-admin token (user 또는 service token), When
POST /v1/assets요청, Then HTTP 403이 반환된다. - Given admin 토큰 + active/inactive asset 혼재, When
GET /v1/assets, Then HTTP 200 + status='active' 항목만 포함된{items: [...]}응답. 각 item은asset_id, symbol, markets, display_name, status, created_at, updated_at필드만 포함하고 portfolio 관련 필드(portfolio_id,owner_user_id,cash_balance등)는 포함하지 않는다. - Given admin 토큰 + active/inactive asset 혼재, When
GET /v1/assets?status=all, Then 두 상태 모두 포함;GET /v1/assets?status=inactive, Then inactive만 포함. - Given admin 토큰 + 서로 다른 markets 값을 가진 asset 다수, When
GET /v1/assets?market=KRX, Thenmarkets에KRX가 포함된 asset만 응답된다. - Given non-admin token (read/trade-write 권한 또는 service token), When
GET /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/GET /v1/assets 엔드포인트 명세 추가 (CHG-20260521-02에서 GET 추가; 후속 docs sync 필요 시 별도 REQ)
- docs/project-structure.md —
- 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 라우트 추가; GET /v1/assets 라우트는 admin catalog 조회로 재정의(기존 token_type 분기 portfolio 조회 코드 제거)app/schemas/v1.py—CreateAssetRequest,UpdateAssetRequest,AssetCatalogItem,AssetCatalogListResponse스키마 추가
- Tests:
tests/test_asset_catalog.py(신규) — admin CRUD CLI/API AC 검증, non-admin 403 검증, GET /v1/assets AC-9~12 검증tests/test_v1.py(기존) — GET /v1/assets에 portfolio 응답을 기대하는 케이스가 있다면 GET /v1/portfolios로 이전 또는 catalog 응답 schema로 갱신
Notes
pfhub asset list의 HTTP 대응(catalog 전용 GET): dcy-003 옵션 B(path 명명 분리) 결정에 따라 REQ-013(GET /v1/assets 포트폴리오 조회)이 Deprecated(2026-05-20) 처리되어 path 충돌 우려 해소.GET /v1/assets는 admin catalog 조회 전용으로 본 REQ에서 다룬다(2026-05-21 CHG-20260521-02로 augmentation 적용). 포지션 조회GET /v1/portfolios는 REQ-028에서 분리 구현됨.- deactivate 후 해당 asset을 참조하는 기존 portfolio는 보존된다. 신규 portfolio 생성만 거부(REQ-012에서 처리).
- REQ-009 선행 필요.
- Source: dcy-001 FR-2, NFR-3; CHG-20260521-02 augmentation는 dcy-003 옵션 B (REQ-013 Deprecation) 후속 작업.
Change Log
CHG-20260521-03
- Date: 2026-05-21
- Author: Justin Ko
Change Summary
- Status: Approved → Implemented (CHG-20260521-02 augmentation으로 신설된 AC-9~12가 BAT-012 verification에서 evidence 확보)
Intent
- BAT-012 confirm-batch-verification 완료. GET /v1/assets admin catalog 재정의(AC-9
12) 신규 evidence + 기존 AC-18 회귀 통과 모두 확인.
Acceptance Criteria Delta
- No change
Impacted Area Delta
- No change
Delivery Trace Delta
- Batches:
- BAT-012 (release-candidate) — primary trace, AC-1~12 전체 evidence
- BAT-002 (release-candidate) — augmentation superseded by BAT-012. BAT-002 본래 trace인 REQ-012/REQ-015는 영향 없음.
- Releases:
- REL-001 — CHG-20260521-02 augmentation scope는 BAT-012로 이관됨. REL-001 release 본문은 BAT-012 inclusion 정리 시 별도 갱신 필요.
Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: REL-001 release 문서에 BAT-012 trace 반영 (또는 신규 REL에 BAT-012 포함)
Validation Plan
- tests/test_asset_catalog.py AC-9~12 신규 8건: test_get_v1_assets_admin_returns_catalog_response, test_get_v1_assets_status_filter_*, test_get_v1_assets_market_filter, test_get_v1_assets_user_token_returns_403, test_get_v1_assets_service_token_returns_403
- 기존 AC-1~8 회귀 9건: test_asset_cli_create_success / list / update / deactivate / test_asset_http_create_returns_201 / update_returns_200 / deactivate_returns_200 / non_admin_403
- 전체 회귀: 362 passed in 13.06s
CHG-20260521-02
- Date: 2026-05-21
- Author: Justin Ko
Change Summary
- Status: Implemented → Approved (REL-001 smoke 검증에서 GET /v1/assets가 dcy-001 시점 portfolio 조회 코드를 유지 중인 불일치 확인. 본 REQ Notes의 1순위 경로(REQ-010 augmentation)에 따라 GET 명세를 추가하고 기존 구현을 재정의.)
Intent
- dcy-003 옵션 B로 REQ-013 Deprecated 후 본 REQ Notes에 명시된 "GET /v1/assets는 admin catalog 조회 전용" 재정의가 미구현 상태로 잔존. REL-001 배포 직전 로컬 smoke(rel-001.md:50)에서 admin session token → HTTP 403 "Unsupported token type" 발생으로 release 체크리스트와 코드 상태 불일치 확인. 본 augmentation으로 GET /v1/assets를 admin catalog 조회로 재정의해 path 분리 정책(dcy-003 옵션 B)을 코드에 반영.
Acceptance Criteria Delta
- Added:
- AC-9 (admin token GET 200 + asset catalog 응답)
- AC-10 (
status=all/status=inactive필터) - AC-11 (
market=<code>필터) - AC-12 (non-admin token → HTTP 403)
- 기존 AC-1~8: 변경 없음.
Impacted Area Delta
- Modules added:
app/api/v1_assets.py— GET /v1/assets 라우트를 portfolio 조회에서 asset catalog 조회로 재정의 (token_type 분기 제거, admin permission 검증 +list_assets호출)app/schemas/v1.py—AssetCatalogItem,AssetCatalogListResponse신규 schema
- Tests added/updated:
tests/test_asset_catalog.py— GET /v1/assets AC-9~12 검증 신규 케이스 (기존 portfolio 조회 의미의 GET /v1/assets 테스트가 있다면 제거/대체)tests/test_v1.py— 기존 GET /v1/assets 호출 패턴이 portfolio 응답을 기대한다면 GET /v1/portfolios로 이전 또는 응답 schema 변경 반영
- Repository:
app/repositories/postgres.py—list_assets메서드가 이미 존재하면 재사용; 없으면 보강
Delivery Trace Delta
- Batches:
- BAT-002 (asset-catalog-api-completion) — augmentation 누적, verification 재실행 필요
- Releases:
- REL-001 — scope 잔존, 본 augmentation 포함 (
docs/releases/rel-001_20260521_v1-api-full-surface.md)
- REL-001 — scope 잔존, 본 augmentation 포함 (
Revalidation Impact
- Reverification Needed: yes
- Existing Implementation Invalidated: yes (기존 GET /v1/assets portfolio 조회 동작이 제거됨)
- Status Recommendation: revert-to-approved
- Follow-up Action: 구현 → pytest 회귀 → 로컬 smoke 재실행 → confirm-req-implemented 재진입
Validation Plan
- pytest로 AC-9~12 검증; 로컬 smoke로 admin session token + GET /v1/assets → HTTP 200 + asset catalog 응답 확인
CHG-20260521-01
- Date: 2026-05-21
- Author: Justin Ko
Change Summary
- Status: Approved → Implemented
Intent
- BAT-002 confirm-batch-verification 완료. admin asset catalog CRUD CLI/HTTP API(POST/PATCH/deactivate), non-admin 403 모든 AC 검증 통과.
Acceptance Criteria Delta
- No change
Impacted Area Delta
- No change
Delivery Trace Delta
- Batches:
- BAT-002
- Releases:
- REL-001
Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: none
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 사용