BAT-006 (REQ-016/017/018): - client token 발급 경로 제거 (issue_client_token, POST /auth/tokens, 관련 스키마/테스트) - service-token rotate unique index revoked_at IS NULL 조건 추가 (Alembic CONCURRENTLY 마이그레이션) - POST /auth/service-tokens body daemon_id forward 누락 보정 (1-line fix) BAT-007 (REQ-022/023): - daemon deactivate 시 바인딩 service token 자동 revoke (CLI --force 옵션 + revoke_tokens_by_daemon_id) - NULL daemon_id legacy token 진단 CLI (migrate-null-daemon --dry-run) 거버넌스 문서: dcy-003/004 Discovery, REQ-016~023/025~032 신규, BAT-006/007 전체 산출물 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.8 KiB
5.8 KiB
REQ-031: portfolio comment CRUD v1 라우트
- Status: Approved
- Type: Interface
- Priority: Medium
- Owner: Justin Ko
Intent
- v1 API에 portfolio comment CRUD 경로(
/v1/portfolios/{portfolio_id}/comments)를 신설해 user/admin이 HTTP로 portfolio에 코멘트를 작성·관리할 수 있도록 한다. - ownership 규칙과 disabled 차단을 REQ-026/027과 동일 패턴으로 적용해 v1 portfolio surface 인가 일관성을 확보한다.
Requirement
- 신규 라우트 (Bearer 인증 필수):
POST /v1/portfolios/{portfolio_id}/comments— body:{"content": "<text>"}. 응답 HTTP 201 + 생성된 comment.GET /v1/portfolios/{portfolio_id}/comments— 응답 HTTP 200 + comment 목록(created_at desc 순).PATCH /v1/portfolios/{portfolio_id}/comments/{comment_id}— body:{"content": "<updated>"}. 응답 HTTP 200 + 갱신된 comment.DELETE /v1/portfolios/{portfolio_id}/comments/{comment_id}— 응답 HTTP 200 또는 204.
- ownership 규칙 (REQ-026/030과 동일):
token_type ∈ {service, client}→ HTTP 403 fail-closed.permission='admin'→ 모든 portfolio.permission ∈ {read, trade-write}→ 자기 소유 portfolio만, 불일치 시 HTTP 403.
- disabled portfolio 차단 (REQ-027 정합):
status='disabled'인 portfolio에 대해 POST/PATCH/DELETE는 HTTP 409 또는 422로 거부. GET은 허용. - 비존재
portfolio_id또는comment_id는 HTTP 404. - 기존
CommentCreateRequest/CommentUpdateRequest/CommentResponseschema 재사용 또는 v1 전용 래핑(PortfolioCommentRequest,PortfolioCommentResponse). - 기존 service 메서드(
create_comment,list_comments,update_comment,delete_comment) 재사용.
Acceptance Criteria
- Given session token + 본인 active portfolio, When
POST /v1/portfolios/{id}/commentsbody{"content": "..."}, Then HTTP 201 + 생성된 comment. - Given session token + 본인 portfolio + 적용된 comments, When
GET /v1/portfolios/{id}/comments, Then HTTP 200 + 코멘트 목록(created_at desc). - Given session token + 본인 portfolio + 본인 comment, When
PATCH /v1/portfolios/{id}/comments/{comment_id}body{"content": "..."}, Then HTTP 200 + 갱신된 comment. - Given session token + 본인 portfolio + 본인 comment, When
DELETE /v1/portfolios/{id}/comments/{comment_id}, Then HTTP 200/204. - Given session token + 타 user portfolio, When 임의 동사 호출, Then HTTP 403 (ownership 불일치).
- Given service/client token, When 임의 동사 호출, Then HTTP 403 fail-closed.
- Given session token + disabled portfolio, When
POST/PATCH/DELETE, Then HTTP 409 또는 422. - Given session token + disabled portfolio, When
GET /v1/portfolios/{id}/comments, Then HTTP 200 + 기존 comments 목록 반환(조회는 허용). - Given admin token + 타 user portfolio, When 임의 동사 호출, Then HTTP 200/201/204 (admin은 모든 portfolio 허용).
- Given Bearer token 없음, When 호출, Then HTTP 401.
- Given 비존재
portfolio_id또는comment_id, When 호출, Then HTTP 404.
Impacted Area
- Docs:
docs/interface-contract.md—/v1/portfolios/{id}/comments명세 (REQ-032)
- Modules:
app/api/v1_portfolios.py— comment 서브 라우트 추가app/schemas/v1.py— comment 관련 스키마 (기존app/schemas/portfolio.py:CommentCreateRequest/CommentUpdateRequest/CommentResponse재사용 또는 v1 래핑)app/services/portfolio_service.py:create_comment/list_comments/update_comment/delete_comment— 기존 메서드 재사용 + disabled 차단 검증 추가
- Tests:
- 신규/갱신
tests/test_v1_portfolios_tags_comments.py— AC-1~11 (comment 부분)
- 신규/갱신
Notes
- comment 작성자 ownership(본인 comment만 수정/삭제 가능)은 기존 portfolio_comments 테이블 구조에 따라 처리. dcy-003 본문은 portfolio ownership만 명시하고 comment 작성자 ownership은 별도 결정 사항 — 본 REQ에서는 portfolio ownership을 일관 적용하고 comment 작성자 ownership은 batch design 단계에서 확정.
- 본 REQ는 dcy-003 FR-8 산출물. tag(REQ-030)와 별도 REQ로 분리해 동사 surface를 명확히 함.
- Source: dcy-003 FR-8, NFR-1, NFR-3, NFR-4.
Change Log
CHG-20260520-02
- Date: 2026-05-20
- Author: Justin Ko
Change Summary
- Status: Proposed → Approved
Intent
- 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료, blocker 없음
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: promote-to-approved
- Follow-up Action: batch 계획 편입
CHG-20260520-01
- Date: 2026-05-20
- Author: Justin Ko
Change Summary
- 최초 생성 — dcy-003 confirm-discovery 후 draft-req 실행. dcy-003 FR-8 산출물.
Intent
- v1 portfolio comment CRUD 라우트 신설 + ownership/disabled 검증 일관 적용.
Acceptance Criteria Delta
- Added:
- AC-1~11 최초 작성
Impacted Area Delta
- Docs: docs/interface-contract.md (REQ-032)
- Modules: app/api/v1_portfolios.py, app/schemas/v1.py, app/services/portfolio_service.py — 최초 지정
- Tests: tests/test_v1_portfolios_tags_comments.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 계획 편입; comment 작성자 ownership 정책은 batch design 단계에서 확정
Validation Plan
- pytest TestClient로 AC-1~11 검증; ownership + disabled 차단 + admin 분기 시나리오