# req-009: v1 API 지원을 위한 DB 스키마 migration 추가 - Status: Approved - Type: Migration - Priority: High - Owner: repository-maintainers ## Intent - dcy-002에서 요구하는 4개 DB 변경(portfolios.market 컬럼, auth_tokens.runtime_id 컬럼, broker_credentials 테이블, ledger_trades 테이블)을 Alembic revision으로 구현한다. - dcy-006의 daemon-aware authorization 모델을 위해 `daemons` registry, `auth_tokens.daemon_id`, `portfolios.managed_by_daemon_id`, transition backfill 및 관련 제약을 같은 migration ownership 규칙 안에서 확장한다. - IF NOT EXISTS 패턴을 유지해 REQ-002 정책을 준수한다(NFR-4). ## Requirement - 다음 스키마 변경을 IF NOT EXISTS 패턴을 사용하는 신규 Alembic migration으로 추가해야 한다. 1. portfolios 테이블에 market TEXT NULLABLE 컬럼 추가 (기존 행은 NULL로 유지) 2. auth_tokens 테이블에 runtime_id TEXT UNIQUE NULLABLE 컬럼 추가 3. broker_credentials 테이블 신규 생성 (user_id, broker, account_ref, encrypted_payload, credential_version, last_rotated_at 포함) 4. ledger_trades 테이블 신규 생성 (ledger_entry_id PK, asset_id, order_id, execution_id, side, quantity, price, fee_amount, tax_amount, executed_at, recorded_at 포함, (asset_id, order_id, execution_id) unique constraint 포함) 5. daemons registry 테이블 신규 생성 (`daemon_id`, `owner_user_id`, stable slug/display metadata, 생성/갱신 시각 포함) 6. auth_tokens 테이블에 `daemon_id` NULLABLE FK 컬럼 추가, portfolios 테이블에 `managed_by_daemon_id` NULLABLE FK 컬럼 추가 7. transition migration은 기존 service-token과 portfolio의 daemon 관련 컬럼을 `NULL`로 backfill하고, post-cutover exact-one assignment로 수렴할 수 있도록 same-user consistency 및 invalid reference rejection을 위한 FK/check/unique 제약을 제공해야 한다. ## Acceptance Criteria 1. Given alembic upgrade head 실행 후, When portfolios 테이블을 조회하면, Then market TEXT NULLABLE 컬럼이 존재해야 한다. 2. Given alembic upgrade head 실행 후, When auth_tokens 테이블을 조회하면, Then runtime_id TEXT NULLABLE UNIQUE 컬럼이 존재해야 한다. 3. Given alembic upgrade head 실행 후, Then broker_credentials 테이블이 존재해야 한다. 4. Given alembic upgrade head 실행 후, Then ledger_trades 테이블이 존재해야 한다. 5. Given (asset_id, order_id, execution_id) 동일 조합으로 ledger_trades에 두 번 삽입 시, Then UniqueViolation이 발생해야 한다. 6. Given migration을 이미 실행한 DB에 동일 migration을 재실행하면, Then 에러 없이 완료되어야 한다(IF NOT EXISTS 보장). 7. Given portfolios 테이블의 기존 행, When migration 실행 후 조회하면, Then market 값이 NULL이어야 한다(기존 데이터 보정 없음, DECIDE_MARKET_DEFAULT Answered). 8. Given alembic upgrade head 실행 후, When schema를 조회하면, Then `daemons` 테이블과 `auth_tokens.daemon_id` 컬럼이 존재해야 한다. 9. Given alembic upgrade head 실행 후, When portfolios 테이블을 조회하면, Then `managed_by_daemon_id` 컬럼이 존재하고 기존 행은 `NULL`로 backfill되어 있어야 한다. 10. Given 존재하지 않는 `daemon_id`를 auth_tokens 또는 portfolios에 바인딩하려고 시도하면, Then FK 또는 동등 제약으로 거부되어야 하며, owner user 일관성을 깨는 binding/assignment는 DB 레벨 제약 또는 동등한 무결성 장치로 방지되어야 한다. ## Impacted Area - Docs: docs/data-model.md (REQ-011에서 갱신 예정) - Modules: migrations/versions/, app/domain/models.py, app/repositories/portfolio_repository.py, app/repositories/postgres.py - Tests: tests/test_app.py 또는 migration 검증 테스트, daemon schema integrity 검증 ## Notes - NFR-4(IF NOT EXISTS 패턴) 준수 — REQ-002 Alembic migration 정책 기반. - broker_credentials 테이블의 encrypted_payload 컬럼은 Fernet 암호화된 ciphertext를 TEXT로 저장한다. 암복호화 로직은 REQ-010 참조. - 컬럼 상세 타입(NUMERIC vs FLOAT, TIMESTAMPTZ 등)은 설계 단계(draft-batch-design)에서 확정한다. - daemon exact-one assignment의 steady-state `NOT NULL`/강제 cutover는 inventory/backfill 완료 이후 단계적으로 적용할 수 있다. transition migration은 `NULL` backfill을 허용하되 fail-open을 허용하면 안 된다. - migration revision ID는 구현 시 기존 revision chain의 마지막 head를 down_revision으로 참조한다. - Source Discovery: dcy-002 (영향 범위, NFR-4, DECIDE_MARKET_DEFAULT), dcy-006 (FR-1, FR-2, NFR-2, NFR-3) ## Change Log ### CHG-20260513-01 - Date: 2026-05-13 - Author: repository-maintainers #### Change Summary - runtime_id 중심 v1 migration REQ를 daemon registry/binding/assignment 스키마까지 포함하도록 확장하고, 기존 Implemented 상태를 Approved로 되돌림 #### Intent - dcy-006의 daemon-aware model은 기존 REQ-009 구현 범위를 넘어서 `daemons`, `auth_tokens.daemon_id`, `portfolios.managed_by_daemon_id`, transition backfill, same-user consistency 제약을 추가로 요구한다. BAT-001/REL-001 migration evidence는 이 범위를 포함하지 않는다. #### Acceptance Criteria Delta - Added: - AC-8: `daemons`, `auth_tokens.daemon_id` - AC-9: `portfolios.managed_by_daemon_id` + NULL backfill - AC-10: daemon FK / 무결성 제약 - Updated: - Requirement 본문에 daemon registry 및 transition backfill 항목 추가 - Removed: - none #### Impacted Area Delta - Docs: - `docs/data-model.md`, `docs/runtime-flows.md` - Modules: - `migrations/versions/`, `app/domain/models.py`, `app/repositories/portfolio_repository.py`, `app/repositories/postgres.py` - Tests: - migration integrity / daemon schema constraint 검증 #### Delivery Trace Delta - Batches: - BAT-001 (release-candidate; REL-001 released input) — 기존 migration verification은 daemon schema, backfill, constraint evidence를 포함하지 않음 - Releases: - REL-001 (released) — release facts는 runtime_id/broker_credentials/ledger_trades까지만 다루므로 revised migration REQ를 충족하지 않음 #### Revalidation Impact - Reverification Needed: yes - Existing Implementation Invalidated: yes - Status Recommendation: rollback-to-approved - Follow-up Action: dcy-006 후속 batch에서 신규 Alembic revision과 migration validation을 설계하고, cutover/backfill evidence를 release 단계에서 수집한다. #### Validation Plan - 현재 migration chain과 `app/repositories/postgres.py` schema ownership을 재검토해 daemon schema 추가 위치를 설계한다. - 구현 후 alembic upgrade / re-run / invalid daemon reference 검증을 포함한 migration test plan을 수행한다. ### CHG-20260511-01 - Date: 2026-05-11 - Author: repository-maintainers #### Change Summary - Implemented 전환 — BAT-001 re-verified verification passed, confirm-req-implemented 게이트 통과 #### Intent - BAT-001 verification.md (re-verified, 2026-05-03) AC-1~7 모두 코드 검토 PASS. DB 환경 실행 미확인은 non-blocker로 처리됨 (revision에 IF NOT EXISTS 패턴 전체 적용 확인). Blocking Issues 없음. #### Acceptance Criteria Delta - none #### Impacted Area Delta - none #### Delivery Trace Delta - Batches: BAT-001 (release-candidate) - Releases: none #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: implemented - Follow-up Action: draft-release (BAT-001); 배포 전 Docker Compose 환경에서 실제 migration 실행 검증 권장 #### Validation Plan - BAT-001 verification.md (re-verified) AC-1~7 코드 검토 evidence 연결 확인 완료 ### CHG-20260502-02 - Date: 2026-05-02 - Author: repository-maintainers #### Change Summary - REQ-009 confirm-req 승인 전환 (Status: Proposed → Approved) #### Intent - 필수 필드(Status, Type, Priority, Owner, Intent, Requirement, Acceptance Criteria 7개, Impacted Area, Change Log) 모두 충족 확인 후 승인 #### 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: keep-current - Follow-up Action: suggest-batch-reqs → draft-batch ### CHG-20260502-01 - Date: 2026-05-02 - Author: repository-maintainers #### Change Summary - REQ-009 최초 생성 (source Discovery: dcy-002) #### Intent - v1 API 지원에 필요한 DB 스키마 변경을 REQ backlog로 정규화 #### Acceptance Criteria Delta - Added: - 전체 Acceptance Criteria 신규 작성 #### Impacted Area Delta - Docs: - docs/data-model.md (REQ-011에서 갱신 예정) - Modules: - migrations/versions/ 신규 migration 파일 - app/domain/models.py 모델 필드 추가 - Tests: - migration 검증 테스트 #### 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 배정. REQ-005, REQ-006, REQ-007, REQ-008과 함께 delivery 단위 구성 필수(runtime_id, market, broker_credentials, ledger_trades 모두 이 migration에 의존).