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
22 KiB
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 참조:
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_idTEXT를 FK로 참조한다.- dcy-002 A-3에 따라
GET /v1/assets의asset_id응답 필드가portfolio_id를 그대로 반환하므로, trex-basic 데몬이asset_id로 ledger 기록 등 후속 API를 호출한다. Portfoliodataclass(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_idPRIMARY KEY를 서버 생성 UUID로 교체하고nameTEXT 컬럼을 신규 추가:(owner_user_id, name)복합 UNIQUE 제약 적용, 기존 portfolio_id 문자열을 name으로 이전하는 데이터 마이그레이션 포함- CLI 뮤테이션 명령 식별 방식 전환: 모든 뮤테이션 명령에서
portfolio_idArgument를<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.nameTEXT 컬럼으로 이전한다.(owner_user_id, name)복합 UNIQUE 제약을 DB 레벨에서 보장한다. - FR-2:
portfolio createCLI 명령은nameArgument와--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_idUUID 교체 및name컬럼 추가(owner_user_id, name)복합 UNIQUE 제약- 기존 데이터 마이그레이션 (FK 참조 포함)
- CLI 뮤테이션 명령 식별 방식 전환 (
--user + name) - HTTP API path parameter UUID 전환
GET /v1/assetsasset_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변경 이력 감사 로그 — 향후 반복으로 Deferredname허용 문자 유효성 검사 정책 — 확정됨.[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/assetsasset_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).
- 완화 방안: name 변경 CLI 명령에 명시적 확인 절차(--force 또는 confirm 프롬프트)를 요구한다. DB의
가정
아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다.
- 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/assetsasset_id가 UUID로 바뀔 때 trex-basic 측의 대응 준비 일정이 확정되기 전에 portfolio-hub를 먼저 배포할 수 있는지, 아니면 임시 호환 레이어(name으로 fallback 조회)가 필요한지.- 상태: Answered
- 처리 방안: trex-basic과 portfolio-hub를 동시에 변경·배포한다. 임시 호환 레이어 불필요.
- 종료 조건: 완료 — 2026-05-11 사용자 확인으로 Answered 처리.
- OQ-2:
namemutable 정책 — 생성 이후 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이 동일 nametv로 각각 portfolio를 생성할 수 있다. - S-2:
pfhub portfolio buy tv --user alice --quantity 10 --price 71000 --force가 alice 소유의tvportfolio에만 적용되고,--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 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다.
- 범위(In Scope/Out of Scope) 확정
- 기준: OQ-3(HTTP API name 조회 엔드포인트) 결정 완료, Out of Scope 경계 승인
- 성공 지표의 측정 방식/데이터 출처 확정
- 기준: S-1~S-4 측정 방식이 pytest 또는 코드 리뷰로 추적 가능한 형태로 기술됨
- High 영향 리스크 우선순위 및 해소 책임자 지정
- 기준: R-1(마이그레이션 데이터 무결성), R-2(trex-basic 계약 파괴) 완화 방안 확정 및 담당자 지정
- 모든 오픈 질문(OQ)
Open상태 없음 확인- 기준: OQ 목록에
Open상태 항목이 0개이거나, 잔여 항목 전부Deferred처리 완료
- 기준: OQ 목록에
- 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. 요구사항 목록 > 범위 경계
- 리스크/오픈 질문: # 6. 리스크/가정 목록
- 성공 기준: # 7. 초기 성공 기준
- 인계 전 확인: # 8. REQ로 넘기기 전 확인 체크
- 사용자 결정 필요: # 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