feat(V1-API): implement TREX-Basic consumer API contract with encryption and persistence
- Add V1 API endpoints: assets, ledger, user-info - Implement Fernet-based credential payload encryption (req-010) - Extend health response schema with runtime info (req-004) - Add service token runtime ID issuance (req-005) - Implement database schema migration for V1 API (req-009) - Add comprehensive test coverage for V1 endpoints - Update SRS with 10 new requirements (REQ-004 through REQ-011) - Create batch planning, design, and verification for BAT-001 - Integrate review-discovery StagePilot skill - Update documentation indices and baseline specs
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# req-004: GET /health 응답 스키마 확장
|
||||
|
||||
- Status: Approved
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: repository-maintainers
|
||||
|
||||
## Intent
|
||||
- trex-basic Consumer-Driven Contract는 GET /health가 status, service, version, checked_at을 반환할 것을 요구한다.
|
||||
- 현재 구현은 `{"status": "ok"}`만 반환하므로 계약 스키마를 충족하도록 응답을 확장한다.
|
||||
|
||||
## Requirement
|
||||
- GET /health 엔드포인트는 status, service(고정값 "portfolio-hub"), version(앱 버전), checked_at(ISO 8601 KST) 필드를 포함한 JSON을 반환해야 한다.
|
||||
- status 허용값은 ok, degraded, failed이며 정상 응답은 ok를 반환해야 한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given 서비스가 정상 동작 중일 때, When GET /health를 요청하면, Then 응답 JSON에 status, service, version, checked_at 필드가 모두 존재해야 한다.
|
||||
2. Given GET /health 응답을 받을 때, When status 값을 확인하면, Then "ok", "degraded", "failed" 중 하나여야 한다.
|
||||
3. Given GET /health 응답을 받을 때, When checked_at 형식을 검증하면, Then ISO 8601 형식을 만족해야 한다.
|
||||
4. Given GET /health 응답을 받을 때, When service 필드를 확인하면, Then 고정값 "portfolio-hub"여야 한다.
|
||||
5. Given 인증 없이 GET /health를 요청해도, Then 200 응답이 반환되어야 한다(비인증 엔드포인트).
|
||||
|
||||
## Impacted Area
|
||||
- Docs: docs/interface-contract.md (REQ-011에서 갱신 예정), docs/runtime-flows.md
|
||||
- Modules: app/api/health.py, app/schemas/ (HealthResponse 스키마 추가)
|
||||
- Tests: tests/test_health.py (신규) 또는 tests/test_app.py 확장
|
||||
|
||||
## Notes
|
||||
- degraded 상태를 반환하는 트리거 조건은 이번 반복에서 정의하지 않는다(OQ-2 Answered). 스키마에 허용값으로만 포함한다.
|
||||
- 앱 버전은 pyproject.toml의 version 필드 또는 settings에서 읽어 반환한다. 설계 단계에서 구체적 방법을 확정한다.
|
||||
- Source Discovery: dcy-002 (FR-1)
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260502-02
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-004 confirm-req 승인 전환 (Status: Proposed → Approved)
|
||||
|
||||
#### Intent
|
||||
- 필수 필드(Status, Type, Priority, Owner, Intent, Requirement, Acceptance Criteria 5개, Impacted Area, Change Log) 모두 충족 확인 후 승인
|
||||
|
||||
#### 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: keep-current
|
||||
- Follow-up Action: suggest-batch-reqs → draft-batch
|
||||
|
||||
### CHG-20260502-01
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-004 최초 생성 (source Discovery: dcy-002 FR-1)
|
||||
|
||||
#### Intent
|
||||
- trex-basic Consumer-Driven Contract의 GET /health 응답 스키마 요구사항을 REQ backlog로 정규화
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- 전체 Acceptance Criteria 신규 작성
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- docs/interface-contract.md (REQ-011 에서 갱신 예정)
|
||||
- Modules:
|
||||
- app/api/health.py
|
||||
- Tests:
|
||||
- tests/test_health.py 신규
|
||||
|
||||
#### 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 후 batch 배정
|
||||
@@ -0,0 +1,99 @@
|
||||
# req-005: service-token 발급 시 runtime_id 동시 생성
|
||||
|
||||
- Status: Approved
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: repository-maintainers
|
||||
|
||||
## Intent
|
||||
- trex-basic 데몬은 GET /v1/user_info에서 runtime_id를 조회해 자신을 식별한다.
|
||||
- runtime_id는 service-token 발급 시 함께 생성되어 해당 토큰에 연결 저장되어야 한다.
|
||||
- CLI(pfhub service-token issue)와 API 엔드포인트 양쪽에서 발급 결과에 runtime_id가 포함되어야 한다.
|
||||
|
||||
## Requirement
|
||||
- pfhub service-token issue CLI 커맨드와 대응 API 엔드포인트는 service-token 발급 시 고유 runtime_id를 동시 생성하고 auth_tokens 테이블에 연결 저장한 뒤 발급 결과(token + runtime_id)를 반환해야 한다.
|
||||
- runtime_id는 해당 service-token에 1:1 연결되며, 동일 사용자의 다른 service-token은 각기 다른 runtime_id를 가진다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given `pfhub service-token issue <name> --user <username>` 실행 시, When 발급이 성공하면, Then 출력에 token 문자열과 runtime_id가 모두 포함되어야 한다.
|
||||
2. Given API 엔드포인트(POST /auth/tokens 또는 동등 경로)로 service-token 발급 시, When 성공 응답을 받으면, Then 응답 JSON에 token과 runtime_id가 포함되어야 한다.
|
||||
3. Given runtime_id가 발급된 service-token으로 GET /v1/user_info를 호출하면, Then 응답의 runtime_id가 발급 시 생성된 값과 동일해야 한다.
|
||||
4. Given 동일 사용자에 대해 두 번의 service-token 발급을 수행하면, Then 각각 다른 runtime_id가 반환되어야 한다.
|
||||
5. Given auth_tokens 테이블을 직접 조회하면, Then 발급된 service-token 행에 runtime_id 값이 저장되어 있어야 한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs: docs/runtime-flows.md (REQ-011에서 갱신 예정)
|
||||
- Modules: app/cli/commands/service_tokens.py, app/api/auth_routes.py, app/domain/models.py (AuthToken.runtime_id 필드 추가), app/services/auth_service.py, app/repositories/postgres.py
|
||||
- Tests: tests/test_auth.py 확장 또는 tests/test_service_tokens.py (신규)
|
||||
|
||||
## Notes
|
||||
- runtime_id 포맷은 UUID v4를 권장한다. 설계 단계에서 확정한다.
|
||||
- auth_tokens 테이블에 runtime_id 컬럼 추가는 REQ-009 migration에서 처리한다.
|
||||
- 기존 service-token(runtime_id 없음) 처리 방식은 R-4로 식별됨. GET /v1/user_info(REQ-007) 설계 단계에서 결정한다.
|
||||
- Source Discovery: dcy-002 (FR-2, A-2)
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260502-02
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-005 confirm-req 승인 전환 (Status: Proposed → Approved)
|
||||
|
||||
#### Intent
|
||||
- 필수 필드(Status, Type, Priority, Owner, Intent, Requirement, Acceptance Criteria 5개, Impacted Area, Change Log) 모두 충족 확인 후 승인
|
||||
|
||||
#### 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: keep-current
|
||||
- Follow-up Action: suggest-batch-reqs → draft-batch
|
||||
|
||||
### CHG-20260502-01
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-005 최초 생성 (source Discovery: dcy-002 FR-2)
|
||||
|
||||
#### Intent
|
||||
- service-token 발급 시 runtime_id 동시 생성 요구사항을 REQ backlog로 정규화
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- 전체 Acceptance Criteria 신규 작성
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- docs/runtime-flows.md (REQ-011에서 갱신 예정)
|
||||
- Modules:
|
||||
- app/cli/commands/service_tokens.py
|
||||
- app/api/auth_routes.py
|
||||
- app/domain/models.py
|
||||
- Tests:
|
||||
- tests/test_auth.py 확장 또는 tests/test_service_tokens.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 migration과 함께 delivery 단위 구성 권장.
|
||||
@@ -0,0 +1,100 @@
|
||||
# req-006: GET /v1/assets 엔드포인트 구현
|
||||
|
||||
- Status: Approved
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: repository-maintainers
|
||||
|
||||
## Intent
|
||||
- trex-basic 데몬이 관리 자산 목록과 전략 파라미터를 조회할 수 있도록 portfolio 데이터를 asset 뷰로 변환해 제공한다.
|
||||
- asset_id는 기존 portfolio_id를 그대로 사용하며 별도 식별자 체계를 만들지 않는다(A-3).
|
||||
|
||||
## Requirement
|
||||
- GET /v1/assets는 service-token bearer 인증으로 토큰 소유자의 portfolio 목록을 asset_id, symbol, market, status, cash, quantity, broker_type, strategy_id, strategy_params, updated_at 필드로 반환해야 한다.
|
||||
- status=active 쿼리 파라미터로 필터링이 가능해야 한다.
|
||||
- strategy_params는 해당 portfolio의 active_strategy_id로 조회한 StrategySet.config에서 파생한다. strategy_id는 허용값 검증 없이 그대로 반환한다(OQ-1 Answered).
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given 유효한 service-token bearer 인증으로 GET /v1/assets 요청 시, When 토큰이 유효하면, Then HTTP 200과 해당 사용자 소유 portfolio 목록이 반환되어야 한다.
|
||||
2. Given GET /v1/assets?status=active 요청 시, Then status가 active인 항목만 반환되어야 한다.
|
||||
3. Given 응답의 각 항목을 확인하면, Then asset_id, symbol, market, status, cash, quantity, broker_type, strategy_id, strategy_params, updated_at 필드가 모두 포함되어야 한다.
|
||||
4. Given portfolio에 연결된 StrategySet이 있을 때, When strategy_params를 확인하면, Then StrategySet.config 값에서 파생된 JSON 객체여야 한다.
|
||||
5. Given StrategySet config가 없거나 파싱 실패 시, Then strategy_params는 빈 객체({})를 반환하고 에러가 전파되지 않아야 한다.
|
||||
6. Given portfolios.market이 NULL인 경우, Then 응답의 market 필드도 null로 반환되어야 한다(DECIDE_MARKET_DEFAULT Answered).
|
||||
7. Given 인증 없이 GET /v1/assets 요청 시, Then HTTP 401이 반환되어야 한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs: docs/interface-contract.md (REQ-011에서 갱신 예정), docs/project-structure.md (신규 라우터 파일 반영 필요)
|
||||
- Modules: app/api/v1_assets.py (신규), app/services/ (assets 조회 서비스 메서드 추가), app/schemas/ (v1 assets 응답 스키마 추가), app/repositories/postgres.py (portfolio + strategy_set JOIN 쿼리 추가), app/main.py (/v1 라우터 등록)
|
||||
- Tests: tests/test_v1_assets.py (신규)
|
||||
|
||||
## Notes
|
||||
- broker_type은 portfolios.broker 컬럼을 그대로 매핑한다(m-2 finding 반영).
|
||||
- strategy_id는 portfolios.active_strategy_id를 그대로 반환한다.
|
||||
- GET /v1/assets의 소유권 스코프는 service-token 소유자(owner_user_id)를 기준으로 한다.
|
||||
- Source Discovery: dcy-002 (FR-3, A-3, OQ-1)
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260502-02
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-006 confirm-req 승인 전환 (Status: Proposed → Approved)
|
||||
|
||||
#### Intent
|
||||
- 필수 필드(Status, Type, Priority, Owner, Intent, Requirement, Acceptance Criteria 7개, Impacted Area, Change Log) 모두 충족 확인 후 승인
|
||||
|
||||
#### 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: keep-current
|
||||
- Follow-up Action: suggest-batch-reqs → draft-batch
|
||||
|
||||
### CHG-20260502-01
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-006 최초 생성 (source Discovery: dcy-002 FR-3)
|
||||
|
||||
#### Intent
|
||||
- trex-basic Consumer-Driven Contract의 GET /v1/assets 요구사항을 REQ backlog로 정규화
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- 전체 Acceptance Criteria 신규 작성
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- docs/interface-contract.md (REQ-011에서 갱신 예정)
|
||||
- Modules:
|
||||
- app/api/v1_assets.py 신규
|
||||
- app/main.py (/v1 라우터 등록)
|
||||
- Tests:
|
||||
- tests/test_v1_assets.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 migration(market 컬럼 추가)과 함께 delivery 단위 구성 권장.
|
||||
@@ -0,0 +1,103 @@
|
||||
# req-007: GET /v1/user_info 엔드포인트 구현
|
||||
|
||||
- Status: Approved
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: repository-maintainers
|
||||
|
||||
## Intent
|
||||
- trex-basic 데몬이 사용자 거래 가능 여부와 브로커 인증 정보를 조회할 수 있도록 한다.
|
||||
- runtime_id는 인증 service-token에 연결된 값을 반환하며, environment 필드는 포함하지 않는다(NFR-1).
|
||||
- credential_payload는 DB에서 Fernet 복호화 후 반환한다(NFR-3/REQ-010 의존).
|
||||
|
||||
## Requirement
|
||||
- GET /v1/user_info는 service-token bearer 인증으로 runtime_id, trading_enabled(users.is_active 매핑), disabled_reason, brokers[](broker, account_ref, credential_payload, credential_version, last_rotated_at)를 반환해야 한다.
|
||||
- environment 필드를 응답에 포함하지 않는다.
|
||||
- credential_payload는 Fernet으로 복호화된 JSON을 반환한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given runtime_id가 연결된 service-token으로 GET /v1/user_info 호출 시, Then HTTP 200과 응답 JSON에 runtime_id, trading_enabled, brokers[] 필드가 포함되어야 한다.
|
||||
2. Given GET /v1/user_info 응답을 확인하면, Then environment 필드가 존재하지 않아야 한다.
|
||||
3. Given users.is_active가 true인 사용자의 service-token으로 호출 시, Then 응답의 trading_enabled가 true여야 한다.
|
||||
4. Given users.is_active가 false인 사용자의 service-token으로 호출 시, Then 응답의 trading_enabled가 false여야 한다.
|
||||
5. Given broker_credentials에 KIS credential이 저장된 사용자의 토큰으로 호출 시, When 응답의 brokers[] 항목을 확인하면, Then credential_payload가 복호화된 JSON({app_key, app_secret})으로 반환되어야 한다.
|
||||
6. Given runtime_id가 없는 구형 service-token으로 호출 시, Then 설계 단계에서 확정된 오류 응답이 반환되어야 한다(R-4, 404 또는 즉시 runtime_id 생성 중 선택).
|
||||
7. Given 인증 없이 요청 시, Then HTTP 401이 반환되어야 한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs: docs/interface-contract.md (REQ-011에서 갱신 예정), docs/data-model.md (REQ-011에서 갱신 예정)
|
||||
- Modules: app/api/v1_user_info.py (신규), app/domain/models.py (BrokerCredential 모델 추가), app/services/ (user_info 조회 서비스 메서드 추가), app/schemas/ (v1 user_info 응답 스키마 추가), app/repositories/postgres.py (broker_credentials 조회 추가), app/main.py (/v1 라우터 등록)
|
||||
- Tests: tests/test_v1_user_info.py (신규)
|
||||
|
||||
## Notes
|
||||
- trading_enabled는 users.is_active 단순 매핑이다(A-4 Confirmed). 별도 trading 전용 상태 필드는 이번 반복 Out of Scope.
|
||||
- disabled_reason: trading_enabled가 false일 때 이유 문자열. 이번 반복에서는 is_active가 false인 경우 "account_inactive" 고정값을 사용하는 방안을 설계 단계에서 확정한다.
|
||||
- R-4(기존 service-token에 runtime_id 없는 경우 처리): 404 또는 즉시 생성 중 설계 단계에서 결정. 이 REQ의 Acceptance Criteria 6번은 설계 결정 후 구체화한다.
|
||||
- Fernet 복호화는 REQ-010에서 정의한 암호화 유틸리티를 사용한다.
|
||||
- Source Discovery: dcy-002 (FR-4, NFR-1, A-4)
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260502-02
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-007 confirm-req 승인 전환 (Status: Proposed → Approved)
|
||||
|
||||
#### Intent
|
||||
- 필수 필드(Status, Type, Priority, Owner, Intent, Requirement, Acceptance Criteria 7개, Impacted Area, Change Log) 모두 충족 확인 후 승인
|
||||
- 설계 의존성 주의: AC #6(runtime_id 없는 구형 토큰 R-4 처리: 404 또는 즉시 생성)은 설계 단계에서 확정 필요. 핵심 Requirement가 명확하고 Notes에 명시적으로 deferred 처리됨 — 승인 게이트 통과 판단.
|
||||
|
||||
#### 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: keep-current
|
||||
- Follow-up Action: suggest-batch-reqs → draft-batch. 설계 단계에서 R-4 처리 방식 확정 후 AC #6 구체화.
|
||||
|
||||
### CHG-20260502-01
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-007 최초 생성 (source Discovery: dcy-002 FR-4)
|
||||
|
||||
#### Intent
|
||||
- trex-basic Consumer-Driven Contract의 GET /v1/user_info 요구사항을 REQ backlog로 정규화
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- 전체 Acceptance Criteria 신규 작성
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- docs/interface-contract.md (REQ-011에서 갱신 예정)
|
||||
- Modules:
|
||||
- app/api/v1_user_info.py 신규
|
||||
- app/domain/models.py BrokerCredential 추가
|
||||
- Tests:
|
||||
- tests/test_v1_user_info.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(broker_credentials 테이블), REQ-010(Fernet 암호화), REQ-005(runtime_id)와 함께 delivery 단위 구성 권장.
|
||||
@@ -0,0 +1,100 @@
|
||||
# req-008: POST /v1/assets/{asset_id}/ledger/trades 엔드포인트 구현
|
||||
|
||||
- Status: Approved
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: repository-maintainers
|
||||
|
||||
## Intent
|
||||
- trex-basic이 체결 내역을 portfolio-hub에 idempotent하게 전송할 수 있도록 한다.
|
||||
- 동일 (asset_id, order_id, execution_id) 조합의 중복 수신은 DB unique constraint로 감지하고 status=duplicate를 반환한다(NFR-2).
|
||||
- 동일 키에 다른 payload가 오면 충돌로 처리한다.
|
||||
|
||||
## Requirement
|
||||
- POST /v1/assets/{asset_id}/ledger/trades는 service-token bearer 인증으로 체결 내역(execution_id, order_id, side, quantity, price, fee_amount, tax_amount, executed_at)을 ledger_trades 테이블에 저장하고 HTTP 201을 반환해야 한다.
|
||||
- 동일 (asset_id, order_id, execution_id) 재수신은 신규 행 생성 없이 status=duplicate와 기존 ledger_entry_id를 HTTP 200으로 반환해야 한다.
|
||||
- 동일 키에 payload가 다른 경우 HTTP 409를 반환해야 한다.
|
||||
- idempotency는 DB unique constraint로 보장하며, 애플리케이션 로직만으로 보장하지 않는다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given 유효한 service-token과 신규 체결 데이터로 POST /v1/assets/{asset_id}/ledger/trades 요청 시, Then HTTP 201과 생성된 ledger_entry_id가 반환되어야 한다.
|
||||
2. Given 동일 (asset_id, order_id, execution_id)와 동일 payload로 두 번째 요청 시, Then HTTP 200과 status="duplicate", 기존 ledger_entry_id가 반환되어야 하며 DB에 단일 행만 존재해야 한다.
|
||||
3. Given 동일 (asset_id, order_id, execution_id)에 다른 payload로 요청 시, Then HTTP 409가 반환되어야 한다.
|
||||
4. Given asset_id가 존재하지 않는 portfolio_id인 경우, Then HTTP 404가 반환되어야 한다.
|
||||
5. Given 인증 없이 요청 시, Then HTTP 401이 반환되어야 한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs: docs/interface-contract.md (REQ-011에서 갱신 예정), docs/data-model.md (REQ-011에서 갱신 예정)
|
||||
- Modules: app/api/v1_ledger.py (신규), app/domain/models.py (LedgerTrade 모델 추가), app/services/ (ledger 저장 서비스 메서드 추가), app/schemas/ (v1 ledger 요청/응답 스키마 추가), app/repositories/postgres.py (ledger_trades 저장 및 중복 감지 쿼리 추가), app/main.py (/v1 라우터 등록)
|
||||
- Tests: tests/test_v1_ledger.py (신규)
|
||||
|
||||
## Notes
|
||||
- NFR-2(idempotency DB unique constraint): (asset_id, order_id, execution_id) unique constraint는 REQ-009 migration에서 정의한다.
|
||||
- ledger_trades 테이블과 기존 portfolio_ledger 테이블은 별개다. portfolio_ledger는 내부 원장이고 ledger_trades는 trex-basic이 외부에서 기록하는 체결 내역이다.
|
||||
- 중복 감지 구현: DB unique constraint 위반(psycopg UniqueViolation) 캐치 → 기존 행 조회 → payload 동일 여부 비교 → duplicate 또는 409 응답.
|
||||
- Source Discovery: dcy-002 (FR-5, NFR-2)
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260502-02
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-008 confirm-req 승인 전환 (Status: Proposed → Approved)
|
||||
|
||||
#### Intent
|
||||
- 필수 필드(Status, Type, Priority, Owner, Intent, Requirement, Acceptance Criteria 5개, Impacted Area, Change Log) 모두 충족 확인 후 승인
|
||||
|
||||
#### 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: keep-current
|
||||
- Follow-up Action: suggest-batch-reqs → draft-batch
|
||||
|
||||
### CHG-20260502-01
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-008 최초 생성 (source Discovery: dcy-002 FR-5)
|
||||
|
||||
#### Intent
|
||||
- trex-basic Consumer-Driven Contract의 POST /v1/assets/{asset_id}/ledger/trades 요구사항을 REQ backlog로 정규화
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- 전체 Acceptance Criteria 신규 작성
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- docs/interface-contract.md (REQ-011에서 갱신 예정)
|
||||
- Modules:
|
||||
- app/api/v1_ledger.py 신규
|
||||
- app/domain/models.py LedgerTrade 추가
|
||||
- Tests:
|
||||
- tests/test_v1_ledger.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(ledger_trades 테이블 + unique constraint)와 함께 delivery 단위 구성 필수.
|
||||
Reference in New Issue
Block a user