diff --git a/.proofline/criteria/ac-0013.md b/.proofline/criteria/ac-0013.md index 2bed9bb..fbcadba 100644 --- a/.proofline/criteria/ac-0013.md +++ b/.proofline/criteria/ac-0013.md @@ -7,11 +7,11 @@ status: active ## Criterion -일반 사용자와 admin은 `/v1/strategies`의 목록·상세 조회에서 active 전략만 받을 수 있어야 하며, inactive 전략은 목록에서 제외하고 상세에서 전략 본문 대신 `409`를 반환하고 미존재 전략은 `404`를 반환해야 한다. +일반 사용자와 admin은 `/v1/strategies`의 목록·상세 조회에서 active 전략만 받을 수 있어야 하며, 각 응답은 안정적인 ID, 사용자 표시용 `nick`, 내부 전략명 `name`, config, status와 revision을 반환해야 한다. inactive 전략은 목록에서 제외하고 상세에서 전략 본문 대신 `409`를 반환하며 미존재 전략은 `404`를 반환해야 한다. ## Verification -- 성공 조건: active 전략은 목록과 상세에서 안정적인 ID, 이름, config, status와 revision을 반환한다. +- 성공 조건: active 전략은 목록과 상세에서 같은 ID, `nick`, `name`, config, status와 revision을 반환하며 `nick`과 `name`이 서로 달라도 각각 보존된다. - 실패·경계 조건: inactive 전략은 목록에서 제외되고 일반 상세 조회는 전략 본문 대신 `409`를 반환하며, 미존재 ID는 `404`다. -- 검사 방법: 일반·admin token의 목록/상세 API 회귀 테스트로 active/inactive/missing을 각각 검사한다. -- 현재 구현 평가: working tree의 `app/api/v1_strategies.py`와 `tests/test_v1_strategies.py`가 이 계약을 실행 가능하게 검증하며 scoped 재실행에 포함되어 PASS했다. +- 검사 방법: 일반·admin token의 목록/상세 API 회귀 테스트로 `nick`과 `name`의 독립 보존 및 active/inactive/missing을 각각 검사한다. +- 현재 구현 평가: `app/api/v1_strategies.py`와 `tests/test_v1_strategies.py`가 목록·상세 `nick` 응답과 active/inactive 경계를 실행 가능하게 검증하며 scoped 재실행에 포함되어 PASS했다. diff --git a/.proofline/criteria/ac-0014.md b/.proofline/criteria/ac-0014.md index 74ef418..794e47b 100644 --- a/.proofline/criteria/ac-0014.md +++ b/.proofline/criteria/ac-0014.md @@ -7,11 +7,11 @@ status: active ## Criterion -admin은 `/v1/admin/strategies`에서 active·inactive 전체 전략을 조회하고 생성·수정·상태 변경·미참조 삭제할 수 있어야 하며, 비-admin 사용자의 모든 관리 mutation은 `403`이어야 한다. +admin은 `/v1/admin/strategies`에서 active·inactive 전체 전략을 `nick`, `name`, config, status와 revision으로 조회하고 생성·수정·상태 변경·미참조 삭제할 수 있어야 하며, 비-admin 사용자의 모든 관리 mutation은 `403`이어야 한다. 동일 `(name, config)` POST는 effective `nick`과 status까지 같을 때만 idempotent 성공해야 하고 하나라도 다르면 기존 row를 바꾸지 않고 `409`를 반환하며, 기존 전략의 변경은 PATCH만 수행해야 한다. ## Verification -- 성공 조건: admin CRUD와 상태 변경이 영속화되고 관리 조회가 active·inactive를 모두 반환한다. -- 실패·경계 조건: 일반 사용자 또는 권한 부족 token의 create/update/delete는 변경 없이 `403`이다. -- 검사 방법: 역할별 token으로 admin 목록·생성·PATCH·DELETE와 비-admin 거부를 API 테스트로 검사한다. -- 현재 구현 평가: working tree의 모든 admin route가 공통 `require_admin` dependency를 사용하고 admin CRUD tests 및 비-admin 관리 GET `403` test가 scoped 재실행에서 PASS했다. 비-admin POST/PATCH/DELETE 각각의 독립 negative test는 현재 없어 mutation별 executable coverage는 `PARTIAL`이다. +- 성공 조건: admin CRUD와 상태 변경이 영속화되고 관리 조회가 active·inactive의 `nick`, `name`, config, status와 revision을 반환하며 완전히 같은 POST 재시도는 기존 row와 revision을 유지한다. +- 실패·경계 조건: 동일 `(name, config)`지만 effective `nick` 또는 status가 다른 POST는 `409`와 무변경이고, 일반 사용자 또는 권한 부족 token의 create/update/delete도 변경 없이 `403`이다. +- 검사 방법: 역할별 token으로 admin 목록·생성·PATCH·DELETE, 동일 POST 재시도, 충돌 POST의 row·revision 무변경과 비-admin mutation 거부를 API 테스트로 검사한다. +- 현재 구현 평가: admin route의 공통 `require_admin`, CRUD와 `nick` 응답 테스트는 존재한다. 다만 현재 create service는 동일 `(name, config)` row의 `nick`이 다르면 POST로 기존 row를 변경할 수 있고 비-admin POST/PATCH/DELETE 각각의 독립 negative test도 없어 이 AC는 `PARTIAL`이다. diff --git a/.proofline/criteria/ac-0015.md b/.proofline/criteria/ac-0015.md index b5fbbae..ea79aec 100644 --- a/.proofline/criteria/ac-0015.md +++ b/.proofline/criteria/ac-0015.md @@ -7,11 +7,11 @@ status: active ## Criterion -admin PATCH는 기존 전략 row의 ID를 유지하면서 요청된 `name`·`config`·`status`의 실질적 변경을 원자적으로 반영하고 revision을 증가시켜야 하며, 모든 참조 포트폴리오의 이후 portfolio-hub API 조회는 commit된 최신 설정과 revision을 반환해야 한다. +`nick`은 전략의 독립 저장 identity이며 trim 후 비어 있지 않고 전략 간 유일해야 한다. 생성에서 `nick`을 생략하면 기존 호환성을 위한 결정적 기본값을 만들고 explicit null 또는 blank는 거부해야 하며, PATCH에서 `nick`을 생략하면 `name`·`config` 변경과 관계없이 기존 값을 보존해야 한다. admin PATCH는 기존 전략 row의 ID를 유지하면서 요청된 `nick`·`name`·`config`·`status`의 실질적 변경을 원자적으로 반영하고 revision을 증가시켜야 하며, 모든 참조 포트폴리오의 이후 portfolio-hub API 조회는 commit된 최신 `nick`, 설정과 revision을 반환해야 한다. ## Verification -- 성공 조건: 실질적 PATCH 뒤 ID는 동일하고 revision은 단조 증가하며 derived `nick`과 name/config가 같은 committed state에서 계산되고 참조 포트폴리오 조회에 최신 값이 나타난다. -- 실패·경계 조건: no-op PATCH는 revision을 올리지 않고, 동시 partial PATCH도 서로의 최신 필드를 잃거나 불일치한 `nick`을 만들지 않는다. -- 검사 방법: API/repository 회귀와 실제 PostgreSQL 동시 partial PATCH 시험으로 ID, revision, name/config/nick 및 포트폴리오 응답을 검사한다. -- 현재 구현 평가: `FOR UPDATE` 기반 update와 revision 응답 테스트가 존재하며, 2026-08-15 실제 PostgreSQL integration 재실행 `4 passed`에 동시 partial PATCH 검증이 포함됐다. +- 성공 조건: 사용자 지정 `nick` 생성과 `nick` 단독 PATCH 뒤 ID는 동일하고 revision은 단조 증가하며, `name`·`config`만 바꾼 PATCH는 기존 `nick`을 보존하고 참조 포트폴리오 조회에 최신 `nick`, 설정과 revision이 나타난다. +- 실패·경계 조건: explicit null·blank·중복 `nick`은 무변경으로 거부되고 no-op PATCH는 revision을 올리지 않으며, 동시 partial PATCH도 명시적으로 바꾸지 않은 `nick`이나 다른 최신 필드를 잃지 않는다. +- 검사 방법: API/repository 회귀와 실제 PostgreSQL 동시 partial PATCH 시험으로 omission/null/blank/중복, ID, revision, `nick` 보존·변경, name/config/status 및 포트폴리오 read-back을 검사한다. +- 현재 구현 평가: `FOR UPDATE` 기반 update, 사용자 지정·trim·null/blank·중복·no-op·revision 테스트와 생략된 `nick` 보존 PostgreSQL 시험이 존재한다. 포트폴리오 `strategy_nick` read-back을 직접 단언하는 테스트는 없어 그 검증은 `PARTIAL`이다. diff --git a/.proofline/criteria/ac-0017.md b/.proofline/criteria/ac-0017.md index 8e99ee2..77db79b 100644 --- a/.proofline/criteria/ac-0017.md +++ b/.proofline/criteria/ac-0017.md @@ -7,11 +7,11 @@ status: active ## Criterion -`/v1/portfolios`와 legacy `/portfolios`의 생성에는 active `strategy_id`가 필수이고 수정도 ID-only여야 하며, 요청의 `strategy_name`·`strategy_params`는 `422`로 거부하는 동시에 응답의 `active_strategy_id`·`strategy_name`·`strategy_params`·`strategy_revision`은 유지되어야 한다. +`/v1/portfolios`와 legacy `/portfolios`의 생성에는 active `strategy_id`가 필수이고 수정도 ID-only여야 하며, 요청의 `strategy_name`·`strategy_params`는 `422`로 거부해야 한다. v1 `PortfolioItem` 응답은 현재 참조 전략의 `active_strategy_id`·`strategy_nick`·`strategy_name`·`strategy_params`·`strategy_revision`을 같은 committed row에서 반환해야 하고 참조가 없거나 해석할 수 없으면 `strategy_nick`은 `null`이어야 하며, legacy 응답의 기존 호환 필드는 유지되어야 한다. ## Verification -- 성공 조건: 명시한 active ID로만 포트폴리오가 생성·수정되고 응답에 현재 전략 identity·이름·config·revision이 나타난다. +- 성공 조건: 명시한 active ID로만 포트폴리오가 생성·수정되고 v1 create/PATCH/list 응답에 현재 전략 ID·`nick`·이름·config·revision이 나타나며 참조가 없으면 `strategy_nick`은 `null`이다. - 실패·경계 조건: strategy ID 누락, 제거 필드 전달 또는 malformed 요청은 새 전략 row를 만들지 않고 `422`다. -- 검사 방법: v1·legacy create/update schema와 저장소 row count, 응답 호환 필드를 API/CLI 회귀로 검사한다. -- 현재 구현 평가: schemas와 양쪽 portfolio API가 ID-only 입력 및 `extra="forbid"` 계약을 구현하고 scoped portfolio/CLI 회귀는 PASS했다. 다만 제거된 `strategy_name`·`strategy_params` 각각의 `422`와 응답 호환 필드 전체를 직접 단언하는 전용 negative/response test는 현재 없어 해당 executable coverage는 `PARTIAL`이다. +- 검사 방법: v1·legacy create/update schema와 저장소 row count, v1 create/PATCH/list의 `strategy_nick` read-back, unbound `null` 및 기존 응답 호환 필드를 API/CLI 회귀로 검사한다. +- 현재 구현 평가: schemas와 양쪽 portfolio API가 ID-only 입력 및 `extra="forbid"` 계약을 구현하고 v1 mapper가 `strategy_nick`을 반환한다. 다만 `strategy_nick` read-back, 제거된 `strategy_name`·`strategy_params` 각각의 `422`와 응답 호환 필드 전체를 직접 단언하는 전용 test가 없어 executable coverage는 `PARTIAL`이다. diff --git a/.proofline/criteria/ac-0018.md b/.proofline/criteria/ac-0018.md index a1af016..0b26c43 100644 --- a/.proofline/criteria/ac-0018.md +++ b/.proofline/criteria/ac-0018.md @@ -7,11 +7,11 @@ status: active ## Criterion -전략 조회·선택·관리 API는 미존재 `404`, inactive 신규 선택과 참조 중 삭제 `409`, 제거 필드·malformed 입력 `422`, 권한 부족 `403`을 서로 구분해 반환해야 한다. +전략 조회·선택·관리 API는 미존재 `404`, inactive 신규 선택·참조 중 삭제·중복 `nick` 및 충돌하는 동일 `(name, config)` POST는 `409`, 제거 필드·malformed 입력·explicit null 또는 trim 후 blank `nick`은 `422`, 권한 부족은 `403`으로 서로 구분해 반환해야 한다. create의 `nick` 생략은 호환 기본값 생성을 허용하고 PATCH의 `nick` 생략은 기존 값을 보존하며 모든 거부 요청은 row와 revision을 변경하지 않아야 한다. ## Verification -- 성공 조건: 각 오류 조건이 승인된 상태 코드와 안정적인 비민감 오류 응답으로 구분된다. -- 실패·경계 조건: 권한 부족을 `404`로, inactive를 `422`로, malformed 입력을 묵시적으로 무시하는 등 오류 클래스가 합쳐지지 않는다. -- 검사 방법: 조건별 독립 API negative test로 status code와 무변경을 검사한다. -- 현재 구현 평가: `tests/test_v1_strategies.py`와 `tests/test_v1_portfolios_crud.py`의 negative matrix가 scoped 재실행에서 PASS했다. +- 성공 조건: omission, explicit null, blank, duplicate와 충돌 POST가 각각 승인된 성공 또는 오류 경계로 처리되고 오류 응답은 안정적이며 비민감하다. +- 실패·경계 조건: 권한 부족을 `404`로, inactive·중복·충돌을 `422`로, null·blank를 묵시적 omission으로 합치거나 거부 요청이 row 또는 revision을 바꾸면 실패한다. +- 검사 방법: 조건별 독립 API negative test로 status code, row identity, `nick`, status와 revision의 무변경을 검사한다. +- 현재 구현 평가: `tests/test_v1_strategies.py`는 omission, explicit null, blank와 duplicate `nick` 경계를 검사하고 기존 negative matrix도 scoped 재실행에서 PASS했다. 충돌하는 동일 `(name, config)` POST의 `409`·무변경 계약은 현재 구현·테스트에 없어 이 부분은 `PARTIAL`이다. diff --git a/.proofline/criteria/ac-0023.md b/.proofline/criteria/ac-0023.md index 321a593..cf75d36 100644 --- a/.proofline/criteria/ac-0023.md +++ b/.proofline/criteria/ac-0023.md @@ -7,11 +7,11 @@ status: active ## Criterion -전략 PATCH, 포트폴리오 전략 선택, 전략 상태 변경·삭제와 거래 저장이 경합해도 최신 전략 참조와 revision은 직렬화 가능하게 보존되고, stale portfolio snapshot은 현재 전략 선택을 되살리거나 덮어쓰지 않으며 portfolio mutation과 ledger 기록은 원자적이어야 한다. +전략의 `nick`·`name`·`config`·`status` partial PATCH, 포트폴리오 전략 선택, 전략 상태 변경·삭제와 거래 저장이 경합해도 명시적으로 변경하지 않은 독립 catalog field, 최신 전략 참조와 revision은 직렬화 가능하게 보존되고, stale portfolio snapshot은 현재 전략 선택을 되살리거나 덮어쓰지 않으며 portfolio mutation과 ledger 기록은 원자적이어야 한다. ## Verification -- 성공 조건: 동시 partial PATCH는 모든 변경과 단조 revision을 보존하고, A snapshot 후 B 선택·A 삭제·stale 거래 저장에서도 B 참조와 A 삭제가 유지되며 portfolio UPDATE와 ledger INSERT가 함께 commit된다. +- 성공 조건: `nick` PATCH와 name/config/status PATCH의 양방향 동시 실행은 모든 독립 변경과 단조 revision을 보존하고, A snapshot 후 B 선택·A 삭제·stale 거래 저장에서도 B 참조와 A 삭제가 유지되며 portfolio UPDATE와 ledger INSERT가 함께 commit된다. - 실패·경계 조건: stale write가 삭제된 A를 복원하거나 B를 잃지 않고, transaction 실패 시 portfolio와 ledger가 부분 commit되지 않는다. -- 검사 방법: 실제 PostgreSQL에서 동시 PATCH, select-vs-inactivate/delete, stale BUY/SELL snapshot과 transaction rollback 시나리오를 실행한다. -- 현재 구현 평가: repository transaction/row-lock 경계와 integration tests가 존재하며, 2026-08-15 실제 PostgreSQL integration 재실행 `4 passed`에서 동시 PATCH, 선택-vs-delete, stale BUY snapshot과 migration 시나리오를 확인했다. 독립 source-time QC도 PASS를 기록한다. 다만 portfolio UPDATE 성공 후 ledger INSERT 실패를 의도적으로 주입해 rollback을 관찰하는 fault-injection test는 현재 없어 그 세부 검증은 `PARTIAL`이다. +- 검사 방법: 실제 PostgreSQL에서 `nick`과 다른 catalog field의 양방향 동시 PATCH, select-vs-inactivate/delete, stale BUY/SELL snapshot과 transaction rollback 시나리오를 실행한다. +- 현재 구현 평가: repository transaction/row-lock 경계와 integration tests가 존재하며, 2026-08-15 실제 PostgreSQL integration 재실행 `4 passed`에서 name/config 동시 PATCH 중 기존 `nick` 보존, 선택-vs-delete, stale BUY snapshot과 migration 시나리오를 확인했다. 명시적 `nick` PATCH와 다른 field PATCH의 양방향 경합 및 portfolio UPDATE 성공 후 ledger INSERT 실패 fault-injection test는 없어 해당 검증은 `PARTIAL`이다.