7.7 KiB
7.7 KiB
구현 진행 상황
- 대상: 포트폴리오 추가 시 연결 데몬을 설정해도 지정되지 않음 (GitHub Issue #27)
- 브랜치:
line/line-0004-implementation - 기준:
main(bb3bb5d3f0ce57358f7385084fba1343f7ff06e1) - 상태: 2차 QC 반려 수정 구현·검증·로컬 커밋 완료 (QC 재검증 대기)
- 최종 업데이트: 2026-08-15 13:18 KST
구현 계획 및 작업 목록
- 공유 daemon validation 도메인 오류 정의
DaemonNotFoundError(HTTP 404)·DaemonInactiveError(HTTP 409)를app/domain/errors.py에 추가해 전 계층에서 같은 오류 계약을 사용한다.
create_portfolio저장소 계약·구현에managed_by_daemon_id전달- 프로토콜 시그니처(
portfolio_repository.py)와 PostgreSQL 구현(postgres.py)에managed_by_daemon_id파라미터를 추가하고 INSERT 컬럼까지 반영해 생성 persistence 경계에 누락을 제거한다.
- 프로토콜 시그니처(
- 생성·수정 트랜잭션 안의 원자적 daemon 검증 경계
- 기존
_lock_active_strategy패턴처럼 daemon row를FOR SHARElock하고 존재·소유권·active를 같은 트랜잭션에서 검증해, portfolio write와 하나의 원자적 판정으로 묶어 TOCTOU를 차단한다.
- 기존
POST /v1/portfolios생성 handler에서 비-null daemon 전달·오류 매핑- UUID 형식이 아니면 422, 미존재·foreign(타인 소유)이면 404, inactive면 409로 매핑하고 admin의
user_idoverride 생성은 최종 target owner 기준으로 검증한다.
- UUID 형식이 아니면 422, 미존재·foreign(타인 소유)이면 404, inactive면 409로 매핑하고 admin의
PATCH /v1/portfolios/{portfolio_id}비-null 지정·재지정에도 동일 검증 적용- 기존 비-null PATCH 지정·재지정 경로에 생성과 동일한 daemon 검증·오류 계약을 적용하되, 포트폴리오 소유권·disabled 보호·service/client 거부 등 기존 mutation 계약은 유지한다.
- 단위/API 테스트 추가
- 성공 생성 응답의
managed_by_daemon_id일치, 미선택 생성 시 null 유지, malformed 422, 미존재·foreign 404, inactive 409, admin target-owner 허용/거부, PATCH 지정·재지정을 검증한다.
- 성공 생성 응답의
- 실제 PostgreSQL 통합 테스트 추가
POST → GETpersistence 보존, 검증 실패 시 portfolio 무변경, assignment와 daemon 비활성화가 경합해도 inactive daemon에 새 assignment가 확정되지 않는 동시성 race를 검증한다.
- 문서 갱신
docs/interface-contract.md,docs/data-model.md에 daemon 배정 검증 계약·오류 코드·원자적 판정 경계를 반영한다.
- 회귀·정적 검사 및 진행 상황 업데이트
- 기존 portfolio 생성·수정의 인증·소유권·strategy·asset·disabled 계약 회귀, 전체 관련 테스트, compile·
git diff --check·Ruff 검사를 실행하고 진행 상황 파일을 갱신한다.
- 기존 portfolio 생성·수정의 인증·소유권·strategy·asset·disabled 계약 회귀, 전체 관련 테스트, compile·
- 참조 중 daemon owner transfer 차단 및 409 계약
update_daemon_owner()가 daemon row를FOR UPDATE로 잠근 뒤 참조 portfolio를 검사하고, 참조가 있으면 credential 삭제·owner 변경 전에DaemonInUseError를 발생시킨다. admin PATCH는 이를 HTTP 409으로 반환한다.
- assignment/owner-transfer 직렬화 및 실제 PostgreSQL 검증
- assignment의
FOR SHARE와 transfer의FOR UPDATE를 동일 daemon row에 적용해 transfer-first 또는 assignment-first의 허용 결과만 남기고, 순차·경합·credential·token-revoke 회귀를 실제 PostgreSQL로 검증한다.
- assignment의
진행 기록
- 2026-08-15 13:00 KST — Issue #27의 승인된 Discovery(
dcy-0004) 범위를 기준으로 구현 계획을 확정했다. 근본 원인(v1_portfolios.py생성 handler가repo.create_portfolio(...)에managed_by_daemon_id를 전달하지 않음)과 승인된 결정(존재·active·동일 소유자, 404/409/422 오류 계약, 원자적 판정 경계)을 반영해 작업 목록을 구성했다. - 2026-08-15 15:10 KST —
app/domain/errors.py에DaemonNotFoundError·DaemonInactiveError를 추가하고,create_portfolio프로토콜·구현과 INSERT 컬럼에managed_by_daemon_id를 반영했다.postgres.py에_lock_active_daemon(daemon rowFOR SHARE+ 존재·동일 소유자·active 검증)을 추가해 생성·수정 트랜잭션 안에서 원자적 판정 경계를 구성했다. - 2026-08-15 15:10 KST —
POST /v1/portfolios와PATCH /v1/portfolios/{id}handler에 UUID 형식(422)·미존재/foreign(404)·inactive(409) 검증과 오류 매핑을 적용했다. admin target-user 생성은 최종 target owner 기준으로 daemon 소유권을 검증한다. - 2026-08-15 15:12 KST — 기존
test_v1_portfolios_crud.py의_FakeRepo.create_portfolio시그니처를 새 파라미터에 맞춰 보완했다. - 2026-08-15 15:15 KST — 전용 API 테스트
tests/test_v1_portfolios_daemon_assignment.py(13개)를 추가했다. POST 성공·null 유지·malformed 422·미존재/foreign 404·inactive 409·admin target-owner 허용/거부, PATCH 지정·재지정·malformed·foreign·inactive를 검증해 통과했다. - 2026-08-15 15:18 KST — 실제 PostgreSQL 통합 테스트
tests/test_v1_portfolios_daemon_postgres_integration.py(4개)를 추가했다. HTTPPOST → GETpersistence, 검증 실패 시 portfolio 무변경, assignment vs deactivation race의 허용 outcome, PATCH 재배정 persistence를 실제 DB에서 검증했다. - 2026-08-15 15:20 KST — 회귀 검증: 전체 단위 스위트
625 passed, 11 skipped, 실제 PostgreSQL 통합(daemon 4 + strategy 4)8 passed. Python compile,git diff --check, 변경 핵심 파일 Ruff 검사 통과(Ruff 이슈 44건은 기준 커밋과 동일한 기존 항목이며 신규 도입 없음). - 2026-08-15 13:10 KST — 1차 QC가
update_daemon_owner()가 참조 중 daemon의 소유자를 변경해daemon.owner_user_id == portfolio.owner_user_id불변식을 깨뜨리는 blocker를 재현해 FAIL 판정했다..proofline/lines/line-0004/evidence/implementation-fix-rerequest.md의 명시 요구에 따라 2차 보완 계획을 적용했다. - 2026-08-15 13:18 KST —
DaemonInUseError를 추가하고update_daemon_owner()를 daemonFOR UPDATE→ 참조 portfolio 검사 → credential 삭제 → owner UPDATE 순서의 단일 트랜잭션으로 변경했다. assignment는 기존 daemonFOR SHARE를 먼저 획득하므로 transfer-first면 이전 owner assignment가 foreign으로 실패하고, assignment-first면 transfer가 409으로 실패한다. 자동 assignment 해제·portfolio owner 이전·재배정·backfill은 추가하지 않았다. - 2026-08-15 13:18 KST — admin daemon PATCH 409 매핑, PATCH missing daemon 404·무변경, 참조 transfer의 owner/assignment/credential 무변경, 미참조 transfer의 credential invalidation, assignment/transfer race, deactivation 후 assignment reference 보존과 service-token revoke를 테스트로 보강했다.
- 2026-08-15 13:18 KST — 수정 커밋
e90519a fix(daemons): block owner transfer while assigned를 생성했다. 집중 단위/API62 passed, 전체 스위트627 passed, 15 skipped, 실제 PostgreSQL daemon integration8 passed,compileall,git diff --check,proofline validate를 통과했다. 지정 Ruff 검사는 기준e2102b6의 기존76건에서 현재74건으로 감소했으며 새 lint 항목은 없다.
각 작업이 실제로 완료되고 검증될 때마다 이 댓글의 체크박스와 진행 기록을 갱신한다. 체크 표시는 구현 완료 또는 해당 검증의 실제 통과를 의미하며, 배포·릴리스 완료를 의미하지 않는다. 1차 구현은
e2102b6, 2차 QC 반려 수정은e90519a에 로컬 커밋되었다. push·PR·main 반영·배포·release는 수행하지 않았으며, 이 기록은 QC PASS 또는 lifecycle 완료를 뜻하지 않는다.