Core Changes: - Migrate portfolio_id from string to UUID in schema and repository layer - Update portfolio CLI commands to use name+user combination for identification - Update HTTP API to accept portfolio_id as UUID path parameter - Implement portfolio ownership validation in repository queries Requirements Completed (REQ-016 to REQ-019): - REQ-016: portfolios table UUID schema migration with data migration script - REQ-017: CLI portfolio commands with name+user identification - REQ-018: HTTP API portfolio path parameters and v1 asset_id UUID returns - REQ-019: Portfolio UUID baseline documentation updates BAT-001 Re-verification: - REQ-004~010 marked as Implemented after verification evidence validation - All v1 API endpoints verified with comprehensive test coverage Documentation Updates: - Update data-model.md with portfolio UUID structure - Update interface-contract.md with UUID path parameters - Update runtime-flows.md with ownership-based resolution flows - Update project-structure.md with database layer changes - Add migration script for portfolio UUID transition Testing: - Add test_portfolio_uuid.py for migration validation - Update test_cli.py and test_portfolio_ownership.py for ownership checks
241 lines
22 KiB
Markdown
241 lines
22 KiB
Markdown
# 0. 문서 상태
|
|
이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다.
|
|
|
|
- 상태: confirmed
|
|
- 문서 ID: dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution
|
|
- 이슈명: portfolio_id UUID 교체 및 CLI 사용자 범위 기반 자산 식별 구조 전환
|
|
- 작성 시각(KST): 2026-05-11 00:00
|
|
- 마지막 갱신 시각(KST): 2026-05-11 (draft-req 완료 — REQ-016~019 생성)
|
|
- 대체됨: 없음
|
|
- 후속 Discovery 참조: 없음
|
|
- 생성된 REQ 참조:
|
|
- [REQ-016](../srs/Migration/req-016_portfolios-uuid-schema-migration.md) — portfolios 테이블 UUID 전환 및 데이터 마이그레이션 (FR-1, FR-5, NFR-1)
|
|
- [REQ-017](../srs/Interface/req-017_portfolio-cli-name-user-identification.md) — CLI portfolio 명령 name+user 조합 식별 방식 전환 (FR-2, FR-3, FR-3a, NFR-2)
|
|
- [REQ-018](../srs/Interface/req-018_portfolio-http-api-uuid-path-param.md) — HTTP API portfolio path parameter UUID 전환 및 v1 asset_id UUID 반환 (FR-4)
|
|
- [REQ-019](../srs/Documentation/req-019_portfolio-uuid-baseline-docs-update.md) — portfolio UUID 전환 관련 baseline 문서 갱신 (FR-6, NFR-3)
|
|
|
|
# 1. 계획 상태 요약
|
|
현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다.
|
|
|
|
- 연계 문서 현황:
|
|
- 관련 계약 문서: docs/discovery/dcy-002_20260502_trex-basic-consumer-api-contract.md (A-3: asset_id는 portfolio_id를 그대로 사용)
|
|
- 관련 TODO/메모: 없음
|
|
- 해석:
|
|
- 현재 `portfolio_id`는 사용자가 직접 지정하는 전역 고유 문자열이어서 다중 사용자 환경에서 이름 충돌이 발생하고, CLI 뮤테이션 명령이 소유권 검증 없이 portfolio_id만으로 실행된다.
|
|
- 이번 Discovery는 `portfolio_id`를 서버 생성 UUID로 교체하고 사용자 표시용 `name`을 `(owner_user_id, name)` 복합 유니크 제약으로 관리하는 구조 전환 전체 범위를 정의한다.
|
|
|
|
# 2. 요구사항 판정 결과
|
|
이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다.
|
|
|
|
- 판정: 신규
|
|
- 근거
|
|
- 기존 dcy-001은 DB 마이그레이션 검증, dcy-002는 trex-basic 소비자 API 계약, dcy-003은 portfolio list --user 필수화를 다루며, portfolio_id 식별자 체계 전환을 다루는 Discovery가 없다.
|
|
- `portfolio_id`를 UUID로 교체하고 `(owner_user_id, name)` 복합 유니크 제약을 도입하는 것은 DB 스키마, 도메인 모델, CLI 인터페이스, HTTP API 경로, 소비자 계약 전반에 영향하는 독립적인 구조 변경 주제다.
|
|
|
|
# 3. 문제점의 요약
|
|
문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다. Discovery의 핵심 맥락을 가장 먼저 이해할 수 있어야 한다.
|
|
|
|
- 현재 상태
|
|
- `portfolios.portfolio_id`는 TEXT PRIMARY KEY로 사용자가 직접 지정하는 전역 단일 네임스페이스다. alice가 `005930:tv`를 먼저 생성하면 bob은 동일 이름을 사용할 수 없다.
|
|
- CLI 뮤테이션 명령(`buy`, `sell`, `invest`, `transfer`, `reset`, `delete`, `status`, `update`)은 `portfolio_id`를 Argument로만 받고 소유자 검증을 하지 않는다. 권한 있는 운영자가 다른 사용자 소유의 portfolio를 portfolio_id만 알면 조작할 수 있다.
|
|
- `ledger_entries`(portfolio_ledger), `portfolio_comments`, `portfolio_tags`, `ledger_trades` 테이블이 `portfolio_id` TEXT를 FK로 참조한다.
|
|
- dcy-002 A-3에 따라 `GET /v1/assets`의 `asset_id` 응답 필드가 `portfolio_id`를 그대로 반환하므로, trex-basic 데몬이 `asset_id`로 ledger 기록 등 후속 API를 호출한다.
|
|
- `Portfolio` dataclass(`app/domain/models.py`)와 PostgreSQL 레포지터리 전반이 `portfolio_id` 문자열을 기준으로 설계되어 있다.
|
|
- 기대 상태
|
|
- `portfolios.portfolio_id`는 서버가 발급하는 UUID(TEXT 또는 UUID 타입)로 교체된다. 사용자는 create 시 `name`만 지정하면 된다.
|
|
- `name` 컬럼은 `(owner_user_id, name)` 복합 UNIQUE 제약으로 같은 사용자 내에서 유일하게 관리된다. 다른 사용자는 동일 `name`을 사용할 수 있다.
|
|
- CLI 뮤테이션 명령은 `--user <username> <name>` 조합으로 portfolio를 식별하고, 내부적으로 UUID를 조회해 처리한다. 소유권 검증이 명령 실행 경로에 포함된다.
|
|
- HTTP API 경로는 UUID를 path parameter로 사용하며, `GET /v1/assets`의 `asset_id`도 UUID를 반환한다.
|
|
- 기존 데이터는 마이그레이션으로 새 UUID를 할당받고, 기존 `portfolio_id` 문자열은 `name` 컬럼으로 이전된다.
|
|
- 이해관계자
|
|
- portfolio-hub 유지보수 담당자 (구현 주체)
|
|
- trex-basic 팀 (GET /v1/assets asset_id 필드 변경 영향을 받는 소비자)
|
|
- CLI 운영자 (명령 인터페이스 변경 대상)
|
|
- 제약사항
|
|
- 기존 Alembic revision chain을 깨지 않는 IF NOT EXISTS 기반 migration을 추가한다(dcy-001/REQ-002 정책 준수).
|
|
- dcy-002 A-3("asset_id는 portfolio_id를 그대로 사용")은 이번 Discovery에서 철회된다. trex-basic 팀에게 breaking change를 사전 통보해야 한다.
|
|
- `name`은 owner 내에서 유일하며, 허용 문자는 `[a-zA-Z0-9._:-]`, 공백 불허, 1~100자, 대소문자 구분으로 확정됐다 (DATA_NAME_ALLOWED_CHARS Answered 2026-05-11).
|
|
|
|
## 주요 사용자 시나리오
|
|
사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다.
|
|
|
|
- 운영자가 `pfhub portfolio create tv --symbol 005930 --user alice --cash-balance 10000000 --force`로 포트폴리오를 생성하면 서버가 UUID를 부여하고, 이후 `pfhub portfolio buy tv --user alice --quantity 10 --price 71000 --force`로 alice의 `tv` 포트폴리오를 정확히 조작한다. bob이 같은 이름 `tv`를 가진 포트폴리오를 생성해도 독립된 레코드로 관리된다.
|
|
- trex-basic 데몬이 `GET /v1/assets`를 호출하면 `asset_id`로 UUID를 수신하고, 이후 `POST /v1/assets/{asset_id}/ledger/trades`에 UUID를 사용해 체결 내역을 기록한다. UUID 도입으로 asset_id가 전역 유일하게 보장된다.
|
|
- 기존에 `005930:tv`라는 portfolio_id로 운영 중인 데이터가 있을 때, 마이그레이션 후 기존 레코드의 `name`이 `005930:tv`로 이전되고 새 UUID가 `portfolio_id`로 할당된다. ledger, comments 등 FK 참조도 새 UUID로 함께 갱신된다.
|
|
|
|
# 4. 이번에 정의할 변경
|
|
이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다. 기능, 구조, 규칙 변경을 함께 포함해도 된다.
|
|
|
|
- `portfolios.portfolio_id` PRIMARY KEY를 서버 생성 UUID로 교체하고 `name` TEXT 컬럼을 신규 추가: `(owner_user_id, name)` 복합 UNIQUE 제약 적용, 기존 portfolio_id 문자열을 name으로 이전하는 데이터 마이그레이션 포함
|
|
- CLI 뮤테이션 명령 식별 방식 전환: 모든 뮤테이션 명령에서 `portfolio_id` Argument를 `<name>` + `--user <username>` 조합으로 교체하고, 내부에서 `(owner_user_id, name)` → UUID 조회 후 처리
|
|
- HTTP API 경로 및 GET /v1/assets asset_id 전환: path parameter와 응답 필드를 UUID 기반으로 변경, dcy-002 A-3 철회 및 trex-basic 계약 갱신
|
|
|
|
## 영향 범위
|
|
변경이 미칠 코드/문서/운영 범위를 명시해 REQ 정제와 batch planning에서 추정 누락을 줄인다.
|
|
|
|
- 코드 영향:
|
|
- `migrations/versions/`: portfolios PK 교체, name 컬럼 추가, (owner_user_id, name) UNIQUE 제약, 기존 데이터 이전 마이그레이션
|
|
- `app/domain/models.py`: Portfolio dataclass portfolio_id → UUID, name 필드 명확화
|
|
- `app/repositories/postgres.py`: create_portfolio(서버 UUID 생성), get_portfolio_by_name_and_user() 신규, 모든 portfolio_id 참조 업데이트
|
|
- `app/domain/services.py`: transfer, buy, sell 등 서비스 메서드 시그니처 — (user_id, name) → UUID 해석 추가
|
|
- `app/cli/commands/portfolio.py`: status, buy, sell, invest, transfer, reset, delete, update 명령의 Argument 교체
|
|
- `app/api/portfolios.py` (HTTP API): path parameter UUID 기반 전환
|
|
- `app/api/v1_assets.py`: asset_id 응답 필드를 UUID로 반환
|
|
- `app/schemas/portfolio.py`, `app/schemas/v1.py`: asset_id/portfolio_id 필드 타입 문서화
|
|
- 문서 영향:
|
|
- `docs/data-model.md`: portfolios 테이블 스키마 변경 반영
|
|
- `docs/interface-contract.md`: GET /v1/assets asset_id 변경 반영
|
|
- `docs/project-structure.md`: 갱신 필요 (repositories, services 변경 반영)
|
|
- `docs/runtime-flows.md`: 갱신 필요 (CLI 명령 흐름, v1 API 흐름 변경 반영)
|
|
- `docs/discovery/dcy-002_*`: A-3 철회 주석 추가
|
|
- 운영 영향:
|
|
- trex-basic 팀에게 asset_id 필드값이 UUID로 바뀜을 사전 통보 필요
|
|
- CLI 운영 스크립트에서 portfolio_id 직접 지정 방식을 `--user + name` 방식으로 교체 필요
|
|
- 기존 운영 runbook 갱신 필요
|
|
|
|
# 5. 요구사항 목록
|
|
실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다.
|
|
|
|
## 기능 요구사항
|
|
- FR-1: `portfolios.portfolio_id`를 서버 생성 UUID(TEXT)로 교체한다. 기존 사용자 지정 portfolio_id 문자열은 `portfolios.name` TEXT 컬럼으로 이전한다. `(owner_user_id, name)` 복합 UNIQUE 제약을 DB 레벨에서 보장한다.
|
|
- FR-2: `portfolio create` CLI 명령은 `name` Argument와 `--user` 옵션을 필수로 받고, `portfolio_id`는 서버가 UUID로 발급한다. 사용자는 UUID를 직접 지정하거나 조회할 수 없다.
|
|
- FR-3: CLI 뮤테이션 명령(`status`, `buy`, `sell`, `invest`, `transfer`, `reset`, `delete`, `update`)은 `<name>` Argument와 `--user <username>` 옵션으로 portfolio를 식별한다. 내부에서 `(owner_user_id, name)` → `portfolio_id(UUID)`를 조회한 뒤 처리한다. `name` + `--user` 조합으로 portfolio를 찾지 못하면 명확한 오류를 반환한다.
|
|
- FR-3a: `name`은 생성 후 변경 가능하다. 단, 변경 시 동일 `owner_user_id` 내에 같은 `name`이 이미 존재하면 DB의 `(owner_user_id, name)` UNIQUE 제약으로 변경이 거부되고, 서비스 레이어는 사용자에게 명확한 오류 메시지(`이미 사용 중인 이름입니다: {name}`)를 반환한다.
|
|
- FR-4: HTTP API의 portfolio 관련 path parameter를 UUID 기반으로 전환한다. `GET /v1/assets` 응답의 `asset_id` 필드는 UUID를 반환한다. dcy-002 A-3을 이번 Discovery에서 철회한다.
|
|
- FR-5: 기존 데이터 마이그레이션 — 현재 `portfolio_id` 문자열 값을 `name` 컬럼으로 복사하고, 각 레코드에 새 UUID를 `portfolio_id`로 할당한다. `portfolio_ledger`, `portfolio_comments`, `portfolio_tags`, `ledger_trades` 등 FK 참조 테이블의 portfolio_id도 새 UUID로 함께 갱신한다.
|
|
- FR-6: `docs/project-structure.md`와 `docs/runtime-flows.md`를 이번 변경 내용에 맞게 갱신한다(repositories/services 인터페이스 변경, CLI 흐름, v1 API 흐름 변경 반영).
|
|
|
|
## 비기능 요구사항
|
|
성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다.
|
|
|
|
- NFR-1: 데이터 마이그레이션은 단일 Alembic revision으로 수행하며, IF NOT EXISTS 패턴을 준수해 재실행 시 오류가 없어야 한다(REQ-002 준수). FK 참조 테이블과의 갱신은 트랜잭션 내에서 atomic하게 처리한다.
|
|
- NFR-2: CLI `(owner_user_id, name)` → UUID 조회는 단일 DB 쿼리로 처리하며, 조회 실패 시 명확한 오류 메시지(`포트폴리오를 찾을 수 없습니다: {name} (user: {username})`)를 출력해야 한다.
|
|
- NFR-3: trex-basic 계약 변경(asset_id UUID 전환)은 portfolio-hub와 trex-basic을 동시에 배포하며 처리한다. 변경 일정 및 동시 배포 계획을 docs/interface-contract.md에 기록해야 한다.
|
|
|
|
## 범위 경계
|
|
이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다.
|
|
|
|
- In Scope
|
|
- `portfolios.portfolio_id` UUID 교체 및 `name` 컬럼 추가
|
|
- `(owner_user_id, name)` 복합 UNIQUE 제약
|
|
- 기존 데이터 마이그레이션 (FK 참조 포함)
|
|
- CLI 뮤테이션 명령 식별 방식 전환 (`--user + name`)
|
|
- HTTP API path parameter UUID 전환
|
|
- `GET /v1/assets` asset_id UUID 반환
|
|
- `docs/project-structure.md`, `docs/runtime-flows.md` 갱신
|
|
- `docs/interface-contract.md`, `docs/data-model.md` 갱신
|
|
- Out of Scope
|
|
- trex-basic 측 코드 변경 — portfolio-hub API 변경만 담당
|
|
- `name` 변경 이력 감사 로그 — 향후 반복으로 Deferred
|
|
- `name` 허용 문자 유효성 검사 정책 — 확정됨. `[a-zA-Z0-9._:-]` 허용, 공백 불허, 1~100자, 대소문자 구분 (2026-05-11)
|
|
- HTTP API에서 `(username, name)` 조합 조회 엔드포인트 추가 — 추가하지 않음. HTTP API는 `portfolio_id`(UUID)만으로 조회 (OQ-3 Answered 2026-05-11)
|
|
|
|
# 6. 리스크/가정 목록
|
|
불확실성과 전제 조건을 분리해서 적는다. 리스크는 영향과 완화 방안을, 가정은 현재 판단의 전제를 기록한다.
|
|
|
|
## 리스크
|
|
- R-1 (High): 기존 FK 참조 테이블(`portfolio_ledger`, `portfolio_comments`, `portfolio_tags`, `ledger_trades`)의 portfolio_id를 새 UUID로 일괄 갱신하는 마이그레이션 중 오류 발생 시 데이터 불일치가 생길 수 있다.
|
|
- 완화 방안: 마이그레이션 전 DB 전체 백업 수행. 마이그레이션 스크립트를 단일 트랜잭션으로 작성하고, 검증 쿼리(FK 고아 레코드 0건 확인)를 마이그레이션 스크립트 마지막에 실행한다.
|
|
- R-2 (High): `GET /v1/assets` `asset_id`가 UUID로 바뀌면 trex-basic 데몬의 `POST /v1/assets/{asset_id}/ledger/trades` 경로가 즉시 동작하지 않는다. 배포 타이밍 불일치 시 운영 장애가 발생한다.
|
|
- 완화 방안: trex-basic과 portfolio-hub를 동시에 배포한다(OQ-1 Answered). 임시 호환 레이어 불필요. 두 저장소의 배포 파이프라인에서 릴리즈 타이밍을 조율한다.
|
|
- R-3 (Medium): `name`이 mutable이므로 CLI 스크립트나 외부 참조에서 portfolio를 name으로 식별하던 코드가 name 변경 후 깨질 수 있다.
|
|
- 완화 방안: name 변경 CLI 명령에 명시적 확인 절차(--force 또는 confirm 프롬프트)를 요구한다. DB의 `(owner_user_id, name)` UNIQUE 제약이 같은 사용자 내 중복 name 변경을 자동으로 차단한다(OQ-2 Answered).
|
|
|
|
## 가정
|
|
아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다.
|
|
|
|
- A-1: `portfolio_id`(UUID)는 서버에서 `uuid.uuid4()`로 생성하며, 사용자가 직접 지정하거나 예측할 수 없다.
|
|
- A-2: `name`은 `(owner_user_id, name)` 복합 UNIQUE 제약을 만족하면 되며, 전역 유일성은 요구하지 않는다.
|
|
- A-3: 기존 `portfolio_id` 문자열(`005930:tv` 형식)은 데이터 마이그레이션 시 `name` 컬럼 값으로 그대로 이전한다. 변환 없이 복사한다.
|
|
- A-4: HTTP API 경로에서 `(username, name)` 조합 조회 엔드포인트는 추가하지 않는다. HTTP API는 `portfolio_id`(UUID)만으로 portfolio를 식별한다. CLI만 `(owner_user_id, name)` → UUID 조회 경로를 사용한다(OQ-3 Answered 2026-05-11).
|
|
|
|
## 오픈 질문
|
|
답을 아직 모르는 항목을 적는다. 추정으로 덮지 말고 REQ 초안 작성 이전에 확인할 질문으로 남긴다.
|
|
|
|
- OQ-1: trex-basic 계약 호환성 전략 — `GET /v1/assets` asset_id가 UUID로 바뀔 때 trex-basic 측의 대응 준비 일정이 확정되기 전에 portfolio-hub를 먼저 배포할 수 있는지, 아니면 임시 호환 레이어(name으로 fallback 조회)가 필요한지.
|
|
- 상태: Answered
|
|
- 처리 방안: trex-basic과 portfolio-hub를 동시에 변경·배포한다. 임시 호환 레이어 불필요.
|
|
- 종료 조건: 완료 — 2026-05-11 사용자 확인으로 Answered 처리.
|
|
- OQ-2: `name` mutable 정책 — 생성 이후 name 변경을 허용할지 여부. 허용할 경우 기존 CLI 스크립트 참조 안정성 확보 방안.
|
|
- 상태: Answered
|
|
- 처리 방안: name 변경 허용. 단, 동일 사용자 내 같은 name이 존재하면 DB의 `(owner_user_id, name)` UNIQUE 제약으로 변경 거부. FR-3a에 반영 완료.
|
|
- 종료 조건: 완료 — 2026-05-11 사용자 확인으로 Answered 처리.
|
|
- OQ-3: HTTP API에서 `(username, name)` 조합으로 portfolio를 조회하는 엔드포인트 추가 여부 — 외부 API 소비자가 UUID를 직접 관리해야 하는 부담을 줄이기 위해 `/portfolios?user=alice&name=tv` 형태의 조회 경로가 필요한지.
|
|
- 상태: Answered
|
|
- 처리 방안: 추가하지 않음. HTTP API는 `portfolio_id`(UUID)만으로 조회. A-4, Out of Scope 반영 완료.
|
|
- 종료 조건: 완료 — 2026-05-11 사용자 확인으로 Answered 처리.
|
|
|
|
# 7. 초기 성공 기준
|
|
이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다. 가능하면 데이터 출처까지 연결한다.
|
|
|
|
- S-1: `pfhub portfolio create tv --symbol 005930 --user alice --force` 실행 시 UUID가 portfolio_id로 발급되고, alice와 bob이 동일 name `tv`로 각각 portfolio를 생성할 수 있다.
|
|
- S-2: `pfhub portfolio buy tv --user alice --quantity 10 --price 71000 --force`가 alice 소유의 `tv` portfolio에만 적용되고, `--user bob`으로는 alice의 portfolio를 조작할 수 없다.
|
|
- S-3: 마이그레이션 후 기존 데이터의 `portfolio_ledger`, `portfolio_comments` 등 FK 참조 테이블에 고아 레코드(orphan)가 0건이고, `GET /v1/assets` 응답의 `asset_id`가 UUID 형식이다.
|
|
- S-4: `docs/project-structure.md`, `docs/runtime-flows.md`, `docs/data-model.md`, `docs/interface-contract.md`가 변경 내용을 반영해 갱신된다.
|
|
|
|
## 측정 방식 및 데이터 출처
|
|
각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다.
|
|
|
|
- S-1 측정 방식: pytest — portfolio create 후 portfolio_id가 UUID 형식(`re.match(r'^[0-9a-f-]{36}$', ...)`)임을 검증. alice/bob 동일 name 독립 생성 테스트 / 데이터 출처: `tests/test_cli.py` 또는 신규 `tests/test_portfolio_uuid.py`
|
|
- S-2 측정 방식: pytest — `--user bob`으로 alice 소유 portfolio 조작 시 오류 반환 검증 / 데이터 출처: `tests/test_cli.py` 소유권 검증 케이스
|
|
- S-3 측정 방식: 마이그레이션 스크립트 내 검증 쿼리 실행 결과 0건 확인 + pytest `test_v1.py::test_v1_assets_*` asset_id UUID 형식 검증 / 데이터 출처: `migrations/versions/` 마이그레이션 스크립트, `tests/test_v1.py`
|
|
- S-4 측정 방식: 각 baseline 문서에 CLI 흐름, repositories/services 인터페이스, v1 API asset_id UUID 내용이 포함됐는지 코드 리뷰로 확인 / 데이터 출처: `docs/project-structure.md`, `docs/runtime-flows.md`, `docs/data-model.md`, `docs/interface-contract.md`
|
|
|
|
# 8. REQ로 넘기기 전 확인 체크
|
|
REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다.
|
|
|
|
- [x] 범위(In Scope/Out of Scope) 확정
|
|
- 기준: OQ-3(HTTP API name 조회 엔드포인트) 결정 완료, Out of Scope 경계 승인
|
|
- [x] 성공 지표의 측정 방식/데이터 출처 확정
|
|
- 기준: S-1~S-4 측정 방식이 pytest 또는 코드 리뷰로 추적 가능한 형태로 기술됨
|
|
- [x] High 영향 리스크 우선순위 및 해소 책임자 지정
|
|
- 기준: R-1(마이그레이션 데이터 무결성), R-2(trex-basic 계약 파괴) 완화 방안 확정 및 담당자 지정
|
|
- [x] 모든 오픈 질문(OQ) `Open` 상태 없음 확인
|
|
- 기준: OQ 목록에 `Open` 상태 항목이 0개이거나, 잔여 항목 전부 `Deferred` 처리 완료
|
|
- [x] Freeze 확정 담당자(CONFIRMED_BY) 지정
|
|
- 기준: Justin 또는 지정된 승인자가 confirm-discovery skill로 Freeze 확정
|
|
|
|
# 9. 파일 처리 결과
|
|
이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다.
|
|
|
|
- 처리 결과: 생성
|
|
- 생성 경로: docs/discovery/dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution.md
|
|
- 참조 문서:
|
|
- docs/discovery/dcy-002_20260502_trex-basic-consumer-api-contract.md (A-3 철회 대상)
|
|
- docs/discovery/dcy-003_20260502_portfolio-list-user-required.md (--user 필수화 선행 작업)
|
|
- app/domain/models.py
|
|
- app/cli/commands/portfolio.py
|
|
- app/repositories/postgres.py
|
|
- migrations/versions/20260403_0001_initial_portfolio_schema.py
|
|
|
|
# 10. 사용자 결정 필요 항목 요약
|
|
사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다.
|
|
|
|
## DECIDE
|
|
- ~~{{DECIDE_NAME_MUTABILITY}}~~: **Answered** — name mutable 허용. 동일 사용자 내 중복 name 변경은 DB UNIQUE 제약으로 거부. FR-3a 반영 완료. (OQ-2 2026-05-11)
|
|
- ~~{{DECIDE_TREX_COMPAT_STRATEGY}}~~: **Answered** — trex-basic과 portfolio-hub 동시 배포로 확정. 임시 호환 레이어 불필요. (OQ-1 2026-05-11)
|
|
|
|
## CONFIRM
|
|
- ~~{{CONFIRM_API_NAME_LOOKUP_SCOPE}}~~: **Answered** — `(username, name)` 조합 엔드포인트 추가 안 함. HTTP API는 `portfolio_id`(UUID)만으로 조회. (OQ-3 2026-05-11)
|
|
- ~~{{CONFIRM_MIGRATION_STRATEGY}}~~: **Answered** — 기존 `portfolio_id` 문자열을 `name` 컬럼으로 변환 없이 그대로 복사. (A-3 2026-05-11)
|
|
|
|
## DATA
|
|
- ~~{{DATA_NAME_ALLOWED_CHARS}}~~: **Answered** — `name` 허용 문자 `[a-zA-Z0-9._:-]`(영숫자 + `.` `_` `:` `-`), 공백 불허, 1~100자, 대소문자 구분 있음. (2026-05-11)
|
|
|
|
# 11. Discovery Freeze
|
|
REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다.
|
|
|
|
## 섹션 참조
|
|
- 범위: [# 5. 요구사항 목록 > 범위 경계](#5-요구사항-목록)
|
|
- 리스크/오픈 질문: [# 6. 리스크/가정 목록](#6-리스크가정-목록)
|
|
- 성공 기준: [# 7. 초기 성공 기준](#7-초기-성공-기준)
|
|
- 인계 전 확인: [# 8. REQ로 넘기기 전 확인 체크](#8-req로-넘기기-전-확인-체크)
|
|
- 사용자 결정 필요: [# 10. 사용자 결정 필요 항목 요약](#10-사용자-결정-필요-항목-요약)
|
|
|
|
## Freeze 플래그
|
|
- Handoff Decision: 승인
|
|
- Handoff Rationale: 모든 OQ Answered 완료, 모든 CONFIRM/DATA 항목 확정. confirm-discovery 게이트 통과 — REQ 초안 작성으로 인계 가능.
|
|
- Ready for REQ Drafting: true
|
|
- Confirmed By: Justin
|
|
- Confirmed At (KST): 2026-05-11
|