Files
genichin 6e02d92282 Add ProofLine criteria documentation and Strategy Catalog v1 implementation
- Add acceptance criteria documentation (AC-0013 through AC-0023)
- Add Line-0003 discovery documentation
- Implement Strategy Catalog v1 with new database migration
- Update portfolio API endpoints and schemas
- Refactor strategy and portfolio services
- Add strategy management CLI commands
- Update domain models with strategy catalog support
- Add comprehensive tests for v1 strategies
- Update design documentation (data model, interfaces, runtime flows)
2026-08-15 11:18:31 +09:00

13 KiB

id, status
id status
dcy-0003 confirmed

전략 API v1 이전 및 관리자 전역 카탈로그 권한 분리

Problem

strategy_sets는 전역 공유 카탈로그이지만 비버전 /strategy-sets 쓰기 API와 포트폴리오의 get_or_create_strategy_set() 간접 생성 경로가 일반 trade-write 사용자에게 열려 있었다. 전략 정의의 관리자 관리 책임, 일반 사용자의 기존 active 전략 선택 책임, 공유 설정 저장 시점과 downstream 실행 슬롯 적용 시점이 분리되어야 한다.

본 문서는 이미 요청자 승인을 받은 GitHub 이슈 #26을 ProofLine에 사후 포착한다. 아래 Scope의 승인된 이슈 원문 전체는 구조적 heading만 canonical H2 충돌을 피하도록 한 단계 낮췄으며, 원문 비어 있지 않은 모든 행을 순서대로 보존한다.

Evidence

원문·승인·사후 문서화 경계

  • 원문: https://github.com/fourblocks2020/portfolio-hub/issues/26
  • 원문 제목: 전략 API v1 이전 및 관리자 전역 카탈로그 권한 분리
  • 원문 상태: OPEN
  • 원문 body SHA-256: 011ece78747cac8e0c38ad07b644ffef080ea1fb7480eef77380c44724b9727e
  • 원문 자체 승인 기록: APPROVED, 승인자 genichin, 승인 시각 2026-08-14T08:14:31Z, unresolved Open Questions 없음.
  • 요청자는 이슈 #26 본문을 최대한 포함한 confirmed Discovery와 approved REQ, 구현 상태를 반영한 active AC를 새 Line에 사후 작성하도록 명시했다.
  • 이 Line은 이미 수행된 로컬 구현을 승인된 지속 사양으로 포착한다. #26 구현이 ProofLine 정식 시퀀스로 수행됐다는 주장, ProofLine implementation/delivery closure, push, PR, 원격 main 반영, release 또는 deployment 완료를 소급 생성하지 않는다.

현재 구현·검증 증거

  • 구현 기준: main 5fc389dea8f05c6f711ecfe874f055979af5e58d
  • 구현 형태: 기준 HEAD 위 로컬 main working tree의 미커밋 product/test/doc 변경.
  • 구현 진행 댓글: https://github.com/fourblocks2020/portfolio-hub/issues/26#issuecomment-5291151212
  • 구현 완료 댓글: https://github.com/fourblocks2020/portfolio-hub/issues/26#issuecomment-5291927258
  • 댓글이 기록한 최종 검증: 이슈 집중 회귀 99 passed; 실제 PostgreSQL 동시성·migration 통합 4 passed; 관련 회귀 75 passed; 알려진 기존 외부 오염 파일 제외 광범위 회귀 608 passed, 3 skipped; 독립 최종 QC PASS.
  • 2026-08-15 현재 재검증: scoped API·migration·portfolio·CLI suite 70 passed, 4 skipped; 별도 실제 PostgreSQL 동시성·migration integration 4 passed.
  • 두 댓글의 exact body는 이 Line의 evidence/implementation-progress.md와 evidence/implementation-complete.md에 비정식 증적으로 보존한다.
  • 위 결과는 source-time 구현 증거다. active AC는 normative 상태이며, 그 자체가 현재 commit-bound satisfaction이나 ProofLine delivery closure를 뜻하지 않는다.

Scope

승인된 이슈 원문 전체

배경

현재 전략 설정 CRUD는 비버전 경로인 /strategy-sets에 있고, 포트폴리오·자산·태그·데몬 등 주요 제품 API는 /v1 아래에 있다. strategy_sets는 사용자 소유 리소스가 아닌 전역 공유 카탈로그지만, 현재 쓰기 API는 trade-write 권한을 허용한다.

/v1/portfolios의 생성·수정 요청은 strategy_name과 strategy_params를 받아 get_or_create_strategy_set()을 호출하므로, 전략 관리 API만 제한하면 일반 사용자의 간접 생성 경로가 남는다.

확인 근거

  • app/api/strategy_sets.py: 비버전 /strategy-sets와 trade-write 쓰기 권한
  • app/api/v1_portfolios.py: 생성·수정 시 get_or_create_strategy_set()을 통한 간접 생성
  • app/repositories/postgres.py: 전역 strategy_sets 저장과 포트폴리오 참조·삭제 방어
  • app/schemas/v1.py: 포트폴리오 요청의 strategy_name·strategy_params, 응답의 active_strategy_id·strategy_name·strategy_params
  • app/cli/commands/strategy.py: 운영자 CLI의 직접 저장소 관리 경로
  • 워크스페이스 소비자 조사: trex-core와 전략 daemon은 /v1/portfolios 응답의 strategy_name·strategy_params를 소비한다. /strategy-sets를 직접 호출하는 다른 repository 코드는 발견되지 않았다.

문제

  1. 전략 API만 비버전 경로에 남아 있어 API 계약 체계가 일관되지 않는다.
  2. 일반 trade-write 사용자가 전역 전략 설정을 생성·수정·삭제할 수 있다.
  3. 포트폴리오 생성·수정 API를 통한 전략 설정의 간접 생성이 가능하다.
  4. 전략 정의 관리와 일반 사용자의 기존 전략 선택 책임이 분리되어 있지 않다.
  5. 공유 설정 변경의 저장 시점과 trex-core 실행 슬롯의 실제 적용 시점이 구분되어 있지 않다.

승인된 범위

읽기·선택 API

  • 일반 사용자와 admin은 GET /v1/strategies 및 상세 조회 API로 active 전략을 조회할 수 있다.
  • 일반 사용자는 자기 포트폴리오 생성·수정 시 기존 active strategy_id만 선택할 수 있다.
  • 생성 시 strategy_id는 필수다.
  • 전역 active 카탈로그가 선택 가능 여부의 권위이며, legacy avabile_strategies는 신규 API의 선택 권한 근거로 사용하지 않는다.

관리자 카탈로그 API

  • GET /v1/admin/strategies
  • POST /v1/admin/strategies
  • PATCH /v1/admin/strategies/{strategy_id}
  • DELETE /v1/admin/strategies/{strategy_id}
  • 생성·수정·삭제는 admin만 허용한다.
  • admin 조회는 active와 inactive 전략을 모두 다룰 수 있다.

공유 설정과 revision

  • 전략은 안정적인 strategy_id로 식별되는 전역 공유 설정이다.
  • admin PATCH는 기존 row의 name/config를 제자리 수정하고 동일 ID의 revision을 원자적으로 증가시킨다.
  • 같은 ID를 참조하는 모든 포트폴리오의 이후 portfolio-hub API 조회에는 commit된 최신 config/revision이 반영된다.
  • 실행 중 trex-core 슬롯에는 즉시 적용하지 않는다. trex-core가 재시작되거나 하루 한 번 정해진 시각에 슬롯을 갱신할 때 최신 revision을 가져와 그때부터 적용한다.
  • 이미 생성된 슬롯·제출된 주문·완료된 거래에는 소급 적용하지 않는다.
  • portfolio-hub는 downstream daemon을 강제로 재시작하거나 설정을 push하지 않는다.

상태·삭제

  • 전략에 active/inactive 상태를 둔다.
  • 일반 조회와 신규 포트폴리오 선택에는 active 전략만 노출·허용한다.
  • 기존 포트폴리오가 참조하는 전략을 inactive로 바꿔도 참조는 보존한다.
  • DELETE는 어떤 포트폴리오에서도 참조하지 않는 전략만 hard delete한다.
  • 참조 중인 전략 DELETE는 HTTP 409를 반환한다. 신규 선택을 막는 retirement는 PATCH inactive로 처리한다.

포트폴리오 계약과 호환성

  • /v1/portfolios와 legacy /portfolios의 생성·수정 모두 ID-only 선택으로 통일한다.
  • 요청의 strategy_name·strategy_params는 제거하며 전달 시 HTTP 422로 거부한다.
  • 응답의 active_strategy_id·strategy_name·strategy_params는 trex-core 및 전략 daemon 소비 계약이므로 유지한다.
  • 비버전 /strategy-sets 경로는 새 /v1 API 도입과 동시에 제거하며 deprecated alias를 유지하지 않는다.
  • 운영자 CLI의 직접 저장소 쓰기는 신뢰된 운영자 전용 관리 경로로 유지하고 일반 사용자 API로 간주하지 않는다. HTTP와 동일한 상태·참조 무결성을 우회해서는 안 된다.

기본 전략 migration

  • Alembic data migration은 name="target_value", config={}, active인 기본 전략을 idempotent하게 생성한다.
  • 동일 (name, config) row가 이미 존재하면 해당 row를 재사용한다.
  • 기본 전략이 존재하더라도 포트폴리오 생성 요청의 strategy_id 필수 조건은 완화하지 않는다. 호출자는 카탈로그 조회로 ID를 얻어 명시한다.

오류 계약

  • 미존재 strategy_id: HTTP 404
  • inactive 전략 신규 선택: HTTP 409
  • 제거된 strategy_name·strategy_params 또는 malformed 입력: HTTP 422
  • 권한 부족: HTTP 403
  • 참조 중 전략 DELETE: HTTP 409

승인된 결정 사항

  1. 외부 API 명칭은 /v1/strategies, /v1/admin/strategies를 사용한다.
  2. active/inactive 상태를 도입하고 inactive 참조는 보존하되 신규 선택은 금지한다.
  3. PATCH는 기존 ID의 공유 설정을 제자리 수정하여 모든 참조 포트폴리오의 이후 API 조회에 반영한다.
  4. 포트폴리오는 active strategy_id를 필수로 명시하고 전역 active 카탈로그를 선택 권위로 사용한다.
  5. 포트폴리오 요청의 strategy_name·strategy_params는 제거하고 422로 거부한다.
  6. 비버전 /strategy-sets는 새 API 도입과 동시에 제거한다.
  7. 기본 target_value/{} 전략은 Alembic migration으로 idempotent하게 생성한다.
  8. legacy /portfolios도 ID-only로 통일하고 CLI는 신뢰된 운영자 경로로 유지한다.
  9. portfolio-hub 저장은 즉시 보이지만 실행 슬롯 적용은 trex-core 슬롯 재생성·정기 갱신 시점으로 지연한다.
  10. 기본 전략은 active 상태로 생성하거나 기존 동일 row를 재사용한다.
  11. 미존재 404, inactive 409, legacy/malformed 422, 권한 부족 403으로 구분한다.
  12. 참조 중 전략은 삭제하지 않고 409를 반환하며 retirement는 inactive로 처리한다.

승인된 수용 기준

  • 일반 사용자 토큰으로 active 전략 카탈로그 목록·상세를 조회할 수 있다.
  • 일반 사용자 토큰으로 전략 설정 생성·수정·삭제 시 HTTP 403을 반환한다.
  • admin 토큰으로 전략 설정 생성·조회·수정·상태 변경·미참조 삭제가 가능하다.
  • admin이 공유 설정을 수정하면 ID는 유지되고 revision이 증가하며 모든 참조 포트폴리오의 이후 API 조회에 최신 설정이 나타난다.
  • inactive 전략은 일반 카탈로그와 신규 선택에서 제외되지만 기존 포트폴리오 참조는 보존된다.
  • 포트폴리오 생성 시 active strategy_id가 필수이며 수정 시에도 active ID만 허용한다.
  • /v1/portfolios와 legacy /portfolios가 새로운 전략 설정을 간접 생성하지 않는다.
  • 포트폴리오 요청의 strategy_name·strategy_params는 HTTP 422로 거부하지만 응답의 전략 필드는 유지된다.
  • 미존재·inactive·권한 부족·malformed 요청이 승인된 HTTP 상태 코드로 구분된다.
  • 새 API 도입 시 비버전 /strategy-sets 경로가 제거되고 관련 문서·테스트가 갱신된다.
  • migration이 기본 active target_value/{} 전략을 중복 없이 생성 또는 재사용한다.
  • 참조 중 전략 DELETE는 409이며 포트폴리오 참조를 자동 이전하거나 삭제하지 않는다.
  • trex-core 슬롯은 설정 PATCH만으로 즉시 변경되지 않고 다음 슬롯 재생성·정기 갱신에서 최신 revision을 반영한다.
  • 권한·간접 생성·상태·revision·오류·삭제·migration·호환성에 대한 회귀 테스트가 추가된다.

범위 밖

  • trex-core의 정확한 일일 슬롯 갱신 시각 및 scheduler 구현 변경
  • portfolio-hub가 downstream daemon을 강제로 reload·restart하거나 설정을 push하는 기능
  • 이미 생성된 슬롯·제출된 주문·완료된 거래의 소급 재해석
  • 내부 DB 테이블명 strategy_sets 변경
  • 운영 배포·데이터 migration 실행·release 승인

위험 및 의존성

  • /strategy-sets 즉시 제거는 breaking change다. 현재 워크스페이스에서 외부 코드 소비자는 발견되지 않았지만 문서와 운영 호출자는 배포 전에 새 경로로 전환해야 한다.
  • 공유 config는 mutable하므로 revision 증가와 원자적 update가 필요하다.
  • trex-core의 실제 반영은 슬롯 refresh 계약에 의존한다. #26은 최신 revision을 제공하는 portfolio-hub 경계까지만 소유한다.
  • legacy 요청 필드가 framework 기본 동작으로 조용히 무시되지 않도록 명시적으로 422를 보장해야 한다.

Approval State

  • Status: APPROVED
  • Approved by: genichin
  • Approved at: 2026-08-14T08:14:31Z
  • Approval basis: 이슈 #26의 OQ-001~OQ-012 단일 선택 완료와 요청자의 명시적 Discovery 승인 지시
  • Unresolved Open Questions: 없음
  • Authority boundary: 이 승인은 위 Discovery 범위를 승인하며 구현 완료, main 반영, 배포 또는 release 승인을 의미하지 않는다.

Out of Scope

사후 ProofLine 경계

  • 이 사후 사양 포착은 구현이 ProofLine 정식 시퀀스로 수행됐다는 주장이나 implementation/delivery/release/deployment lifecycle closure를 만들지 않는다.
  • 구현 진행·완료 댓글은 canonical lifecycle artifact가 아니라 출처가 명시된 비정식 evidence다.
  • 현재 구현은 미커밋 working tree에 있으므로 exact implementation commit, 원격 main 통합, push, PR, 게시, 운영 배포 및 release는 확인되거나 승인된 것으로 간주하지 않는다.
  • 이슈 원문의 범위 밖 항목과 authority boundary는 위 승인 원문 전체에 보존되며 req-0003 및 연결 AC가 이를 축소하거나 확장하지 않는다.