7.5 KiB
line-0004 구현 에이전트 수정 재요청
- 대상 이슈:
fourblocks2020/portfolio-hub#27 - 대상 Line:
line-0004 - 작업 worktree:
/home/genichin/workspace/trex-lead/repos/portfolio-hub/.worktrees/line-0004 - 작업 브랜치:
line/line-0004-implementation - 수정 기준 커밋:
e2102b6f2b855b7679ab67818202ef706d9848fb - 범위 권위:
.proofline/lines/line-0004/dcy-0004.md - 1차 QC 결과:
.proofline/lines/line-0004/evidence/first-qc-review.md - 요청 상태: QC 반려 수정 요청
1. 작업 원칙
기존 구현의 의미와 승인된 Discovery 범위를 변경하지 말고 아래 blocker 및 관련 회귀 검증만 수정한다. 새로운 제품 결정, 다른 서비스 계약 영향, 승인 범위와의 충돌이 발견되면 구현을 중단하고 팀장에게 반환한다.
trex-web은 명시적인 Out of Scope다. 해당 저장소의 코드·타입·화면·테스트를 변경하거나 실행하지 않는다.
2. 필수 수정 — 참조 중 daemon owner transfer 차단
현재 daemon이 portfolio에 배정된 뒤 update_daemon_owner()로 daemon 소유자를 변경하면 다음 불변식이 깨진다.
daemon.owner_user_id == portfolio.owner_user_id
update_daemon_owner()에서 해당 daemon을 참조하는 portfolio가 하나라도 있으면 owner transfer가 원자적으로 실패하도록 수정한다.
필수 결과:
- 참조 중 daemon owner transfer:
409 Conflict - daemon owner: 변경되지 않음
- portfolio
managed_by_daemon_id: 변경되지 않음 - 기존 broker credentials: 삭제되지 않음
- transaction 일부만 반영되는 상태: 금지
다음 자동 동작은 승인 범위 밖이므로 구현하지 않는다.
- portfolio assignment 자동 해제
- portfolio를 새 daemon owner에게 자동 이전
- 다른 daemon으로 자동 재배정
- 기존 데이터 backfill
3. 필수 수정 — assignment와 owner transfer 직렬화
portfolio assignment와 daemon owner transfer가 동일 daemon을 대상으로 동시에 실행될 때 일관된 row-lock 순서와 transaction 경계를 사용한다.
허용되는 결과:
- owner transfer가 먼저 commit되면 이전 owner portfolio의 assignment는 foreign daemon으로 판단되어 실패한다.
- assignment가 먼저 commit되면 owner transfer는 참조 충돌로 실패한다.
금지되는 최종 상태:
portfolio.managed_by_daemon_id = daemon.id
portfolio.owner_user_id != daemon.owner_user_id
동시 실행이 timeout 또는 deadlock으로 끝나지 않도록 lock order를 검토한다.
4. 도메인 및 API 오류 계약
참조 중 owner transfer 충돌을 daemon 미존재 오류와 구분한다.
권장 구현 경계:
- 전용 domain error 추가
- repository
update_daemon_owner()에서 전용 error 발생 PATCH /v1/admin/daemons/{daemon_id}에서 HTTP 409로 매핑- 기존 daemon 미존재 404 유지
- 기존 admin 인증·권한 계약 유지
- 미참조 owner transfer의 기존 credential invalidation 정책 유지
5. 필수 테스트
5.1 단위/API
다음을 추가하거나 보강한다.
- 미참조 daemon owner transfer 성공
- 참조 중 daemon owner transfer
409 409후 daemon owner 무변경409후 portfolio assignment 유지409후 broker credentials 유지- daemon 미존재
404회귀 없음 - PATCH missing daemon
404및 portfolio 무변경 - admin PATCH에서 호출자 대신 target portfolio owner 기준 검증
- deactivation 후 기존 assignment reference 보존
- deactivation 시 기존 service token revoke 유지
5.2 실제 PostgreSQL
migration head가 적용된 disposable PostgreSQL에서 검증한다.
순차 owner transfer
- owner A daemon 생성
- owner A portfolio에 daemon 배정
- daemon을 owner B로 이전 시도
- owner transfer 실패
- 동일 소유자 불변식 유지
- owner·assignment·credential 무변경 확인
assignment/owner-transfer race
- 별도 connection/thread에서 assignment와 owner transfer 동시 실행
- 두 실행 순서를 모두 유도하거나 반복 검증
- 허용된 결과만 발생하는지 확인
- 최종 DB 동일 소유자 불변식 확인
- thread timeout/deadlock 없음 확인
미참조 owner transfer
- portfolio가 참조하지 않는 daemon owner transfer 성공
- 기존 broker credential invalidation 정책 유지
6. PostgreSQL 실행 전제
완전히 빈 DB에는 먼저 migration head를 적용한다.
export TIMESCALEDB_HOST=127.0.0.1
export TIMESCALEDB_PORT=5432
export TIMESCALEDB_NAME=<disposable-db>
export TIMESCALEDB_USER=portfolio_hub_user
export TIMESCALEDB_PASSWORD=<local-test-password>
export TIMESCALEDB_SSLMODE=prefer
export PFHUB_DB_ENABLED=true
.venv/bin/pfhub migrate-db
PORTFOLIOHUB_RUN_POSTGRES_INTEGRATION=1 \
.venv/bin/python -m pytest -q \
tests/test_v1_portfolios_daemon_postgres_integration.py
실행 후 disposable DB를 삭제한다. 기존 공유·운영 DB를 오염시키지 않는다.
7. 문서 및 evidence
실제 동작과 일치하도록 필요한 범위에서 갱신한다.
docs/interface-contract.mddocs/data-model.md- daemon admin owner-transfer runtime flow 문서
.proofline/lines/line-0004/evidence/implementation-progress.md
문서에 다음을 명시한다.
- 참조 중 daemon owner transfer는 409
- owner transfer와 assignment의 원자적 직렬화
- 자동 assignment 해제·portfolio owner 변경 없음
- 충돌 시 owner·assignment·credential partial mutation 없음
implementation-progress.md의 “미커밋” 표기를 실제 상태로 수정하고 다음 실행 근거를 기록한다.
- QC 반려 blocker와 해결 방식
- 수정 파일 목록
- 수정 커밋
- 집중 테스트 결과
- 전체 회귀 결과
- 실제 PostgreSQL 순차·경합 검증 결과
- Ruff, compileall, diff check, ProofLine validate 결과
- push·PR·main 반영·배포·release 미수행 경계
QC 재검증 전에는 implementation complete 또는 lifecycle 완료 문서를 새로 만들지 않는다.
8. 최소 재검증
.venv/bin/python -m pytest -q \
tests/test_v1_portfolios_daemon_assignment.py \
tests/test_v1_portfolios_crud.py \
tests/test_bat022_req053_admin_daemon_crud.py
.venv/bin/python -m pytest -q
PORTFOLIOHUB_RUN_POSTGRES_INTEGRATION=1 \
.venv/bin/python -m pytest -q \
tests/test_v1_portfolios_daemon_postgres_integration.py
ruff check \
app/api/v1_portfolios.py \
app/api/v1_admin_daemons.py \
app/domain/errors.py \
app/repositories/portfolio_repository.py \
app/repositories/postgres.py \
tests/test_v1_portfolios_daemon_assignment.py \
tests/test_v1_portfolios_daemon_postgres_integration.py \
tests/test_bat022_req053_admin_daemon_crud.py
.venv/bin/python -m compileall -q app tests
git diff --check
proofline validate
9. 금지 사항
trex-web변경·테스트 금지- approved Discovery 범위 변경 금지
- 명시적
managed_by_daemon_id: null해제 구현 금지 - 자동 daemon 해제·이전·재배정·backfill 금지
- main 작업 금지
- push·PR·배포·release 금지
10. 반환 조건
수정·테스트·로컬 커밋 후 다음을 팀장에게 반환한다.
- 새 커밋 SHA
- 변경 파일 목록
- blocker 해결 방식과 transaction/lock order
- 테스트별 실제 pass/fail/skip 수
- 실제 PostgreSQL 순차·경합 결과
- 남은 비차단 위험
- worktree clean 여부
수정 완료는 QC 재검증 입력일 뿐 QC PASS나 lifecycle 완료를 의미하지 않는다.