Files
portfolio-hub/docs/releases/rel-001_20260502_trex-basic-v1-api-contract.md
T
genichin 4fa770e771 docs: add rel-003, rel-004 releases and update CLI user scoping implementation
Release: REL-003_20260512 — CLI user scoping and local DB ops runbook

Requirements & Batches:
- BAT-003 (REQ-013): portfolio list --user required enforcement with owner filtering
- BAT-004 (REQ-014): portfolio create --user required enforcement with owner assignment
- BAT-007 (REQ-001/002/003): local DB validation runbook and baseline docs update

CLI Enhancements:
- Update user.py: add username-based user lookup (get_by_username)
- Add UserDetailResponse schema with service token listing
- Update list_service_tokens API in user_service.py
- Enhance user detail display with service token information
- Add service_token_count and service_token_names to user responses

Testing:
- Add comprehensive test coverage in test_cli.py for user commands
- Validate username-based lookup functionality

Release: REL-004_20260512 — Portfolio UUID migration and API UUID switch

Requirements & Batches:
- BAT-006 (REQ-016/017/018): portfolio UUID migration complete
- BAT-008 (REQ-019): baseline documentation update for UUID migration

Breaking Changes (REL-003):
- portfolio list requires --user <username> parameter
- portfolio create requires --user <username> parameter

Documentation:
- Create rel-003 and rel-004 release documents with rollout and rollback plans
- Update docs/releases/index.md with new releases
- Update README.md with CLI user scoping clarification
- Sync all release verification checklists and deployment notes
2026-05-12 12:13:38 +00:00

8.0 KiB

REL-001: trex-basic v1 API contract

  • Status: released
  • Profile: app-service
  • Included Batch: BAT-001

Scope

  • Included:

    • BAT-001 (REQ-004, REQ-005, REQ-006, REQ-007, REQ-008, REQ-009, REQ-010)
    • GET /health 응답 스키마 확장 (service/version/checked_at 필드)
    • POST /auth/service-tokens — service-token 발급 + runtime_id 반환 API
    • GET /v1/assets — service-token 소유자 범위의 포트폴리오 목록 조회 (status 필터, strategy_params, owner scope 재확인 반영)
    • GET /v1/user_info — 사용자 정보 + broker credentials 복호화 반환
    • POST /v1/assets/{asset_id}/ledger/trades — 체결 기록 (idempotent: 201/200/409/404)
    • Fernet 암호화 유틸리티 (app/core/encryption.py)
    • startup validation: CREDENTIAL_ENCRYPTION_KEY 없으면 RuntimeError
    • DB 스키마 migration: portfolios.market, auth_tokens.runtime_id, broker_credentials, ledger_trades
  • Excluded:

    • GET /health status degraded/failed 경로 (이번 반복 OOS)
    • broker credential 저장 HTTP API (CLI 전용)
    • DB 환경(Docker Compose) 직접 실행 검증

Rollout Plan

  1. 배포 전 CREDENTIAL_ENCRYPTION_KEY 환경 변수 설정 확인 (python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" 로 생성)
  2. alembic upgrade head 실행 — migration 0014 적용 (portfolios.market, auth_tokens.runtime_id, broker_credentials, ledger_trades)
  3. 서비스 재시작 (uvicorn app.main:app)
  4. GET /health 호출로 기동 확인
  5. v1 smoke 테스트: GET /v1/assets, GET /v1/user_info (service-token 사용)
  6. GET /v1/assets smoke 검증 시 service-token 소유자의 portfolio만 반환되고 다른 사용자 소유 portfolio는 포함되지 않는지 확인

Rollback Plan

  • 조건: startup 실패 또는 GET /health 비정상 응답 시
  • 절차:
    1. 이전 버전 코드로 롤백 (git revert 또는 이전 컨테이너 이미지 재기동)
    2. alembic downgrade -1 — migration 0014 롤백 (신규 테이블/컬럼 DROP)
    3. CREDENTIAL_ENCRYPTION_KEY 미설정 상태로도 DB disabled 모드에서는 기동 가능하므로, 긴급 시 PORTFOLIOHUB_DB_ENABLED=false로 임시 운영 가능

Verification Checklist

배포 전

  • CREDENTIAL_ENCRYPTION_KEY 환경 변수 설정 완료
  • alembic upgrade head 성공 (migration 0014)
  • pytest 로컬 PASS 확인 (python -m pytest -q → 129 passed in 4.46s)

배포 후

  • GET /health → 200, body에 status, service, version, checked_at 포함 확인
  • GET /health → checked_at에 +09:00 포함 확인
  • [~] POST /auth/service-tokens (admin 토큰) → 201, runtime_id 포함 확인 — 유보: admin credential 미보유, 후속 검증 이관
  • GET /v1/assets (service-token) → 200, assets[] 반환 확인
  • [~] GET /v1/assets (service-token) → service-token 소유자의 portfolio만 반환되고 다른 사용자 portfolio가 비노출인지 확인 (REQ-006 owner scope 재확인) — 유보: 현재 total=0이라 비노출 강도 미확인. CONFLICT-1 fix 재배포 후 다중 사용자 데이터 기반 검증 필요
  • GET /v1/user_info (service-token) → 200, trading_enabled/brokers[] 포함 확인
  • [~] POST /v1/assets/{asset_id}/ledger/trades → 201 (신규), 200 (중복 동일 payload) 확인 — 유보: trade-write credential 미보유, 후속 검증 이관
  • 서비스 startup 로그에 RuntimeError 없음 확인 — proxy: GET /health → 200 (status=ok) 확인됨

Release Execution Evidence

  • Release Status Transition Target: released

Deployment Facts

  • Executed At:
    • 2026-05-11
  • Completed At:
    • 2026-05-11
  • Environment:
  • Operator:
    • repository-maintainers
  • Revision or Artifact:
    • 2e1298a (fix: enforce trade-write permission check on v1 ledger trade endpoint)
  • Commands or Procedure:
    • CREDENTIAL_ENCRYPTION_KEY 설정 확인 완료
    • python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" 실행으로 Fernet 키 생성 형식 확인 완료
    • 보안상 실제 환경 변수 값과 생성된 키 원문은 문서에 기록하지 않음
    • alembic upgrade head 실행 완료
    • Alembic 출력: Context impl PostgresqlImpl. / Will assume transactional DDL.
    • 추가 revision 실행 로그는 출력되지 않았고, 명시적 오류 메시지는 없었음
    • 로컬 회귀 검증: python -m pytest -q → 129 passed in 4.46s
    • 배포 public smoke: curl https://fourblocks2026.com/portfolio-hub/health → HTTP 200, {"status":"ok","service":"portfolio-hub","version":"0.1.0","checked_at":"2026-05-11T21:35:54.686819+09:00"}
    • 배포 public contract 확인: /portfolio-hub/docs → HTTP 200, /portfolio-hub/openapi.json → HTTP 200
    • 실배포 설정 파일 temp/real_portfolio-hub_environment의 service token으로 protected read smoke 실행
    • GET /v1/assets → HTTP 200, body 요약: total=0, assets=[]
    • GET /v1/user_info → HTTP 200, body 요약: runtime_id 존재, trading_enabled=true, permission=read, brokers=[]
    • POST /auth/service-tokens with same token → HTTP 403 Insufficient permission (admin 토큰 미보유)
    • POST /v1/assets/00000000-0000-0000-0000-000000000001/ledger/trades with same read service token → HTTP 404 Asset not found ...
    • 위 ledger 결과는 계약상 trade-write 부족이면 403이어야 한다는 기대와 다르므로, write permission enforcement 재확인 필요
    • 현재 보유 credential만으로는 admin 성공 경로와 trade-write 성공 경로를 완료할 수 없음

Profile-Specific Checks

  • app-service:
    • Health Endpoint:
      • GET https://fourblocks2026.com/portfolio-hub/health → HTTP 200 확인. body에 status=ok, service=portfolio-hub, version=0.1.0, checked_at=2026-05-11T21:35:54.686819+09:00 포함.
    • Startup Log Fields:
      • 외부 URL만으로는 startup 로그 접근 불가. 배포 환경 로그 접근 권한 필요.
    • Request Log Fields:
      • 외부 URL만으로는 request 로그 접근 불가. 배포 환경 로그 접근 권한 필요.
    • Smoke or Manual Verification:
      • public smoke 완료 (/health, /docs, /openapi.json).
      • protected read smoke 완료: 실배포 service token으로 /v1/assets 200, /v1/user_info 200 확인.
      • /v1/assets 응답은 빈 목록(total=0)이라 owner scope 비노출은 강하게 입증되지 않음 — 유보 처리.
      • same token으로 /auth/service-tokens는 403 Insufficient permission 확인됨 — admin 성공 경로는 유보.
      • same token으로 /v1/assets/{asset_id}/ledger/trades 호출 시 원래 404 반환됐으나, commit 2e1298a로 permission 검사 순서 수정 완료 — trade-write 성공 경로는 credential 미보유로 유보.

Rollback Outcome

  • Rollback Required:
    • no
  • Rollback Trigger:
    • none
  • Rollback Action:
    • none

Release Decision Evidence

  • Released Decision:
    • released
  • Rationale:
    • public health, public contract(/docs, /openapi.json), read-permission smoke(/v1/assets, /v1/user_info) 모두 확인됨. trade-write permission enforcement 코드 수정(commit 2e1298a) 완료. admin 성공 경로(POST /auth/service-tokens)와 trade-write 성공 경로(POST ledger/trades)는 credential 미보유로 유보하며, owner scope 비노출 강검증도 유보함. 유보 항목은 운영 환경 접근 후 후속 검증 이관.
  • Recorded By:
    • repository-maintainers
  • Recorded At:
    • 2026-05-12

Feedback Handoff

  • Observation Summary:
    • read-permission smoke 성공. trade-write permission 코드 수정(2e1298a) 완료되었으나 재배포 미확인. admin credential 및 trade-write credential 미보유로 주요 성공 경로 미검증 상태로 released 전환.
  • Discovery Input:
    • admin token 발급 및 관리 운영 절차가 없어 admin 성공 경로 검증 체계 확립 필요
    • trade-write token 발급 및 smoke 절차 운영화 필요
    • owner scope 비노출 검증을 위한 다중 사용자 테스트 데이터 운영 방안 검토
  • REQ Input:
    • 없음
  • Change Request Input:
    • 없음