diff --git a/docs/srs/Interface/req-008_v1-ledger-trades-endpoint.md b/docs/srs/Interface/req-008_v1-ledger-trades-endpoint.md index 7eba332..5fd5f5b 100644 --- a/docs/srs/Interface/req-008_v1-ledger-trades-endpoint.md +++ b/docs/srs/Interface/req-008_v1-ledger-trades-endpoint.md @@ -40,6 +40,43 @@ ## Change Log +### CHG-20260518-01 +- Date: 2026-05-18 +- Author: repository-maintainers + +#### Change Summary +- `insert_ledger_trade()` 미구현 결함 수정 — PostgresPortfolioRepository에 메서드가 존재하지 않아 모든 POST /v1/assets/{asset_id}/ledger/trades 요청이 HTTP 500으로 실패하던 결함을 수정. Status Approved 유지. + +#### Intent +- `app/api/v1_ledger.py:78`에서 `repo.insert_ledger_trade()`를 호출하지만 PostgresPortfolioRepository에 구현이 없어 AttributeError → HTTP 500이 발생했다. FakeRepo 기반 테스트는 통과했으나 실 DB 환경에서는 endpoint 전체가 불동작 상태였다. trex-basic의 write-back이 전면 차단된 High 심각도 결함이었으며, 구현을 추가해 정상화했다. + +#### Acceptance Criteria Delta +- Added: 없음 +- Updated: 없음 +- Removed: 없음 + +#### Impacted Area Delta +- Docs: 없음 +- Modules: + - `app/repositories/postgres.py`: `insert_ledger_trade(asset_id, order_id, execution_id, side, quantity, price, executed_at, fee_amount, tax_amount)` 추가. `INSERT INTO ledger_trades ... ON CONFLICT ON CONSTRAINT uq_ledger_trades_idempotency DO NOTHING RETURNING *` 패턴으로 신규/중복 여부를 `(LedgerTrade, bool)` 튜플로 반환. + - `app/repositories/portfolio_repository.py`: Protocol에 `insert_ledger_trade` 선언 추가, `LedgerTrade` import 추가 +- Tests: 기존 FakeRepo 기반 테스트는 영향 없음. 실 DB 통합 테스트(AC-1~7)는 별도 재검증 필요. + +#### Delivery Trace Delta +- Batches: BAT-010 (release-candidate) — 결함 수정이 BAT-010 delivery scope에 포함 +- Releases: REL-006 (draft) — 배포 전 결함 수정 완료. 실 DB 통합 재검증 후 배포 권장. + +#### Revalidation Impact +- Reverification Needed: yes +- Existing Implementation Invalidated: no (AC 정의는 유효, postgres 구현만 누락되어 있었음) +- Status Recommendation: keep-current (Approved; CHG-20260513-01에 의해 Approved 상태) +- Follow-up Action: 실 DB 환경에서 AC-1(신규 체결 201), AC-2(중복 200+duplicate), AC-3(payload 불일치 409), AC-6~7(daemon mismatch/미배정 403) 통합 시나리오 검증 후 Implemented 전환 가능 + +#### Validation Plan +- `POST /v1/assets/{asset_id}/ledger/trades`에 유효 daemon-bound service-token으로 요청 시 HTTP 201 반환 확인 +- 동일 (asset_id, order_id, execution_id) 재요청 시 HTTP 200 + status=duplicate 확인 +- daemon mismatch, 미배정 asset 요청 시 HTTP 403 확인 + ### CHG-20260513-01 - Date: 2026-05-13 - Author: repository-maintainers diff --git a/docs/srs/Interface/req-017_portfolio-cli-name-user-identification.md b/docs/srs/Interface/req-017_portfolio-cli-name-user-identification.md index 30fb8e0..f74abcf 100644 --- a/docs/srs/Interface/req-017_portfolio-cli-name-user-identification.md +++ b/docs/srs/Interface/req-017_portfolio-cli-name-user-identification.md @@ -43,6 +43,41 @@ ## Change Log +### CHG-20260518-01 +- Date: 2026-05-18 +- Author: repository-maintainers + +#### Change Summary +- `get_portfolio_by_name_and_user()` 미구현 결함 수정 — PostgresPortfolioRepository에 메서드가 존재하지 않아 실 DB 환경에서 모든 name+user 식별 경로가 AttributeError로 실패하던 결함을 수정. Status Implemented 유지. + +#### Intent +- REQ-017 AC-2~4(name+user 조합으로 portfolio 조회)를 구현한 CLI 코드와 FakeRepo는 완성되어 있었으나, PostgresPortfolioRepository에 `get_portfolio_by_name_and_user()`가 누락되어 실 DB 환경에서 AttributeError가 발생했다. 결함을 수정해 Implemented 근거를 복원한다. + +#### Acceptance Criteria Delta +- Added: 없음 +- Updated: 없음 +- Removed: 없음 + +#### Impacted Area Delta +- Docs: 없음 +- Modules: + - `app/repositories/postgres.py`: `get_portfolio_by_name_and_user(owner_user_id, name)` 추가 (`_SELECT_PORTFOLIO WHERE owner_user_id = %s AND name = %s`) + - `app/repositories/portfolio_repository.py`: Protocol에 `get_portfolio_by_name_and_user` 선언 추가 +- Tests: `tests/test_portfolio_uuid.py` 14 passed (기존 FakeRepo 기반 테스트는 영향 없음) + +#### Delivery Trace Delta +- Batches: BAT-006 (release-candidate) — 결함 수정이 BAT-006 delivery scope에 포함 +- Releases: REL-006 (draft) — 배포 전 결함 수정 완료 + +#### Revalidation Impact +- Reverification Needed: no +- Existing Implementation Invalidated: no +- Status Recommendation: keep-current (Implemented) +- Follow-up Action: 없음 (실 DB 통합 테스트로 AC-2~4 재확인 권장) + +#### Validation Plan +- `pfhub portfolio status --user `, `pfhub portfolio buy --user ` 등 name+user 식별 명령이 실 DB 환경에서 정상 응답하는지 확인 + ### CHG-20260511-01 - Date: 2026-05-11 - Author: repository-maintainers diff --git a/docs/srs/Interface/req-023_daemon-registry-and-service-token-daemon-binding.md b/docs/srs/Interface/req-023_daemon-registry-and-service-token-daemon-binding.md index 2a29c68..78c0dfa 100644 --- a/docs/srs/Interface/req-023_daemon-registry-and-service-token-daemon-binding.md +++ b/docs/srs/Interface/req-023_daemon-registry-and-service-token-daemon-binding.md @@ -20,10 +20,13 @@ 2. Given 기존 daemon에 대해 `daemon_display_name` 수정을 요청할 때, Then daemon entry가 갱신된다. 3. Given 동일 owner user 내에 이미 존재하는 `daemon_slug`로 daemon create를 요청할 때, Then 명시적 오류로 거부되고 중복 entry가 생성되지 않는다. 4. Given daemon list 조회를 요청할 때, Then 인증된 user 소유의 daemon만 반환된다. +5. Given `pfhub portfolio update --user --daemon-id `를 실행할 때, Then 해당 portfolio의 `managed_by_daemon_id`가 지정한 daemon_id로 갱신된다. +6. Given `pfhub portfolio list --user `을 실행할 때, Then `managed_by_daemon_id`가 설정된 portfolio에는 해당 daemon_id가 출력에 포함되고, 미설정 portfolio에는 해당 항목이 출력되지 않는다. ## Impacted Area - Docs: `docs/interface-contract.md`, `docs/runtime-flows.md` - Modules: `app/domain/models.py`, `app/repositories/postgres.py`, `app/api/auth_routes.py` 또는 별도 daemon management route, `app/cli/commands/` (daemon subcommand 신규) +- Modules (AC-5~6 추가): `app/cli/commands/portfolio.py` (`update` 명령 `--daemon-id` 옵션), `app/schemas/portfolio.py` (`UpdatePortfolioRequest.managed_by_daemon_id`, `PortfolioSummary.managed_by_daemon_id`), `app/services/portfolio_service.py` (`_to_portfolio_summary` 필드 전달), `app/cli/core/utils.py` (`print_portfolio_list` daemon 표시) - Tests: 신규 `tests/test_daemon_registry.py` ## Notes @@ -33,6 +36,45 @@ ## Change Log +### CHG-20260518-01 +- Date: 2026-05-18 +- Author: repository-maintainers + +#### Change Summary +- AC-5(`portfolio update --daemon-id`), AC-6(`portfolio list` daemon-id 표시) 추가 및 Impacted Area 보강. 구현 완료. Status Approved 유지. + +#### Intent +- daemon provisioning runbook에서 "asset → daemon 배정" 단계가 CLI로 수행 가능해야 한다. 기존 AC-1~4는 daemon registry CRUD만 다루며 portfolio-daemon 배정 경로가 누락되어 있었다. 운영팀 요청(2026-05-18)에 따라 `portfolio update --daemon-id` CLI 옵션과 `portfolio list` 결과의 daemon-id 표시를 REQ 범위에 추가한다. + +#### Acceptance Criteria Delta +- Added: + - AC-5: `pfhub portfolio update --user --daemon-id `로 `managed_by_daemon_id` 갱신 + - AC-6: `pfhub portfolio list --user ` 결과에 `managed_by_daemon_id` 조건부 표시 +- Updated: 없음 +- Removed: 없음 + +#### Impacted Area Delta +- Modules: + - `app/cli/commands/portfolio.py`: `update` 명령에 `--daemon-id` 옵션 추가 + - `app/schemas/portfolio.py`: `UpdatePortfolioRequest.managed_by_daemon_id`, `PortfolioSummary.managed_by_daemon_id` 필드 추가 + - `app/services/portfolio_service.py`: `_to_portfolio_summary`에 `managed_by_daemon_id` 전달 추가 + - `app/repositories/postgres.py`: `update_portfolio` allowed dict에 `managed_by_daemon_id` 추가 + - `app/cli/core/utils.py`: `print_portfolio_list`에 daemon 줄 조건부 출력 추가 + +#### Delivery Trace Delta +- Batches: BAT-010 (release-candidate) — AC-5~6 구현이 BAT-010 delivery scope에 포함 +- Releases: REL-006 (draft) + +#### Revalidation Impact +- Reverification Needed: yes (AC-5~6 신규이므로 검증 증거 추가 필요) +- Existing Implementation Invalidated: no (AC-1~4 기존 구현 유효) +- Status Recommendation: keep-current (Approved) +- Follow-up Action: BAT-010 verification.md에 AC-5~6 검증 증거 추가 후 Implemented 전환 가능 + +#### Validation Plan +- `pfhub portfolio update --user --daemon-id --force` 실행 후 DB `portfolios.managed_by_daemon_id` 값 확인 +- `pfhub portfolio list --user ` 출력에서 daemon-id 유무 항목별 표시 확인 + ### CHG-20260513-02 - Date: 2026-05-13 - Author: repository-maintainers diff --git a/docs/srs/Interface/req-029_portfolio-list-borderless-output.md b/docs/srs/Interface/req-029_portfolio-list-borderless-output.md new file mode 100644 index 0000000..7640051 --- /dev/null +++ b/docs/srs/Interface/req-029_portfolio-list-borderless-output.md @@ -0,0 +1,69 @@ +# REQ-029: CLI `portfolio list` 출력 — 테두리 없는 리스트 형식 + +- Status: Approved +- Type: Interface +- Priority: Low +- Owner: repository-maintainers + +## Intent +- `pfhub portfolio list` 기본 출력을 Rich Table(테두리 포함) 대신 항목별 텍스트 블록으로 변경해 터미널 폭에 구애받지 않는 가독성을 확보한다. +- JSON 출력(`--format json`)은 기존과 동일하게 유지한다. + +## Requirement +- `pfhub portfolio list --user ` 명령의 기본 출력(text 형식)은 테두리·구분선 없는 리스트 형태로 각 portfolio를 표시해야 한다. +- 각 항목은 3줄 블록으로 구성한다: (1) name/symbol/status/broker [tags], (2) cash/qty/price/buffer/total 수치, (3) portfolio_id. +- `managed_by_daemon_id`가 설정된 항목은 (3) 다음 줄에 daemon_id를 추가로 표시하고, 미설정 항목은 해당 줄을 생략한다. +- 항목 간에 빈 줄 한 줄로 구분한다. +- `--format json` 옵션 사용 시 기존 JSON 응답을 그대로 반환한다. + +## Acceptance Criteria +1. Given `pfhub portfolio list --user ` 실행 시, Then Rich Table 형식(헤더·테두리)이 아닌 텍스트 블록 리스트가 출력된다. +2. 각 portfolio 항목은 name, symbol, status, broker 정보와 cash/qty/price/buffer/total 수치, portfolio_id를 포함한다. +3. Given `managed_by_daemon_id`가 설정된 portfolio가 있을 때, Then 해당 항목에 daemon_id 줄이 추가로 표시된다. +4. Given `pfhub portfolio list --user --format json` 실행 시, Then JSON 배열이 반환되며 텍스트 블록 출력이 표시되지 않는다. + +## Impacted Area +- Docs: 없음 +- Modules: + - `app/cli/core/utils.py`: `print_portfolio_table` 제거, `print_portfolio_list` 신규 구현, `render_output`에서 `print_portfolio_list` 호출 +- Tests: 기존 `tests/test_portfolio_uuid.py` 출력 내용 미검증이므로 별도 영향 없음 + +## Notes +- 이 변경은 CLI 출력 형식만 변경하며 API, 데이터 모델, DB 스키마에는 영향을 주지 않는다. +- REQ-023 AC-6(managed_by_daemon_id 표시)와 구현을 공유한다. + +## Change Log + +### CHG-20260518-01 +- Date: 2026-05-18 +- Author: repository-maintainers + +#### Change Summary +- 최초 생성 및 Approved 전환 — 운영팀 요청(2026-05-18)에 따라 `portfolio list` 출력 형식을 테두리 없는 리스트 형태로 변경 완료. 구현 및 사용자 확인 완료. + +#### Intent +- Rich Table 형식은 터미널 폭이 좁거나 항목 수가 많을 때 가독성이 떨어진다. 텍스트 블록 리스트는 항목별 스캔이 쉽고 터미널 폭 의존성이 없다. + +#### Acceptance Criteria Delta +- Added: AC-1~4 (최초 생성) +- Updated: 없음 +- Removed: 없음 + +#### Impacted Area Delta +- Modules: + - `app/cli/core/utils.py`: `print_portfolio_table` → `print_portfolio_list` 교체, REQ-023 AC-6 daemon 줄 출력 포함 + +#### Delivery Trace Delta +- Batches: 미정 (minor-change fast path로 batch-lite 생성 예정) +- Releases: 미정 + +#### Revalidation Impact +- Reverification Needed: no (신규 REQ, 기존 구현 무효화 없음) +- Existing Implementation Invalidated: no +- Status Recommendation: Approved +- Follow-up Action: batch-lite 생성 → 검증 → confirm-req-implemented + +#### Validation Plan +- `pfhub portfolio list --user ` 실행 결과에 Rich Table 헤더·테두리가 없는지 확인 +- daemon-id 있는 항목과 없는 항목 혼재 시 조건부 표시 확인 +- `--format json` 옵션 시 JSON 반환 확인 diff --git a/docs/srs/index.md b/docs/srs/index.md index c6dc639..91274a9 100644 --- a/docs/srs/index.md +++ b/docs/srs/index.md @@ -74,7 +74,7 @@ ## Next Requirement ID -- Current: `REQ-029` +- Current: `REQ-030` - Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다. ## Requirement Register @@ -105,11 +105,12 @@ | REQ-022 | 운영 로그 접근 및 release evidence 기록 절차 | Documentation | Approved | Medium | repository-maintainers | [REQ-022](./Documentation/req-022_operator-log-access-and-release-evidence-recording.md) | | REQ-023 | Daemon Registry 관리 경로 | Interface | Approved | High | repository-maintainers | [REQ-023](./Interface/req-023_daemon-registry-and-service-token-daemon-binding.md) | | REQ-028 | README.md Daemon Provisioning Runbook 반영 | Documentation | Approved | Medium | repository-maintainers | [REQ-028](./Documentation/req-028_daemon-model-baseline-docs-update.md) | +| REQ-029 | CLI `portfolio list` 출력 — 테두리 없는 리스트 형식 | Interface | Approved | Low | repository-maintainers | [REQ-029](./Interface/req-029_portfolio-list-borderless-output.md) | ## Recent Change Log Summary -- 2026-05-13: REQ-023, REQ-028 Approved 전환 — confirm-req 게이트 통과 (필수 필드, AC, blocker 없음) -- 2026-05-13: REQ-023, REQ-028 Proposed 생성 — dcy-006 FR-1(daemon registry CRUD)·FR-6(README.md runbook); REQ-024~027은 REQ-005~009/011/012 CHG-20260513-01과 완전 중복으로 미생성 -- 2026-05-13: REQ-005~009, REQ-011~012 CHG-20260513-01 — dcy-006 daemon_id / exact-one asset assignment 반영으로 revised contract가 기존 Implemented evidence를 무효화해 Status를 Approved로 되돌림 -- 2026-05-13: REQ-021 CHG-20260513-01 — token provenance 절차에 `daemon_id` evidence 필드와 rotate invariant 반영, Status 유지 -- 2026-05-12: REQ-020~022 Approved 전환 — confirm-req 게이트 통과 (필수 필드, AC, blocker 없음) \ No newline at end of file +- 2026-05-18: REQ-029 Approved 생성 — `portfolio list` 테두리 없는 리스트 형식, minor-change fast path, 구현 완료 +- 2026-05-18: REQ-023 CHG-20260518-01 — AC-5(`portfolio update --daemon-id`), AC-6(`portfolio list` daemon-id 표시) 추가, Impacted Area 보강, Status Approved 유지 +- 2026-05-18: REQ-008 CHG-20260518-01 — `insert_ledger_trade` postgres 미구현 결함 수정, HTTP 500 정상화, Status Approved 유지 +- 2026-05-18: REQ-017 CHG-20260518-01 — `get_portfolio_by_name_and_user` postgres 미구현 결함 수정, Status Implemented 유지 +- 2026-05-13: REQ-023, REQ-028 Approved 전환 — confirm-req 게이트 통과 (필수 필드, AC, blocker 없음) \ No newline at end of file