Files
portfolio-hub/docs/releases/rel-006_20260513_daemon-model-implementation.md
T
genichin 3bb3ff547d feat: extend daemon model with daemon status tracking and list support
- Add daemon status tracking with state and metrics (idle, running, error)
- Implement pfhub daemon list CLI command for viewing registered daemons
- Extend auth schema and service for daemon lifecycle management
- Add postgres repository queries for daemon state persistence
- Expand test coverage for daemon registry and status transitions
- Update rel-006 release document with daemon model verification results
- Support daemon graceful shutdown and error recovery patterns
2026-05-14 06:29:52 +00:00

7.1 KiB

REL-006: Daemon Model Implementation

  • Status: draft
  • Profile: app-service
  • Included Batch: BAT-010

Scope

  • Included:
    • BAT-010 (REQ-009/023/005/012/006/007/008/011/028): 데몬 모델 전체 구현
      • Alembic migration 20260513_0016: daemons 테이블, auth_tokens.daemon_id, portfolios.managed_by_daemon_id 추가
      • Daemon registry CRUD: pfhub daemon create/list/update
      • Service-token 발급 시 daemon_id binding (--daemon-id 옵션)
      • Service-token rotate daemon_id 불변식 (runtime_id만 갱신, daemon_id 유지)
      • GET /v1/assets daemon-scoped 필터 + NULL daemon_id token → 403 fail-closed
      • GET /v1/user_info daemon_id 필드 추가 + NULL → 200+null diagnostic
      • POST /v1/assets/{asset_id}/ledger/trades daemon assignment authorization (3단계 fail-closed)
      • docs/interface-contract.md, docs/data-model.md, docs/runtime-flows.md daemon-aware 갱신
      • README.md daemon provisioning runbook + enforcement enablement gate + runtime_id/daemon_id 역할 구분
  • Excluded:
    • CLI pfhub portfolio update --daemon-id (portfolio에 daemon 직접 할당 CLI 경로 — 향후 배치)
    • pre-existing test_cli.py 7개 실패 수정 (별도 배치)
    • 실제 TimescaleDB 인스턴스 integration test (환경 미구성 — 배포 시 수행)

Rollout Plan

  1. 사전 준비: 아래 enforcement gate 4종 evidence 확보
    • NULL daemon_id 서비스 토큰 inventory 쿼리 실행 및 zero-active-NULL 확인
    • Dry-run: daemon mismatch 쿼리 실행 및 zero-mismatch 확인
    • Release approver 사전 승인
  2. DB migration 적용: PORTFOLIOHUB_DB_ENABLED=true pfhub migrate-db 실행 (migration 20260513_0016 → daemons table, daemon_id 컬럼 추가)
  3. Service 배포: portfoliohub 서비스 재시작 (새 바이너리/코드 배포)
    • 주의: NULL daemon_id token은 GET /v1/assets + POST ledger/trades에서 즉시 403 반환 시작
    • 기존 service-token이 있다면 배포 전 daemon 등록 + token rotate 또는 신규 발급 완료 후 배포
  4. Health 확인: GET /health → {"status": "ok"} 확인
  5. Daemon provisioning smoke: pfhub daemon create → pfhub service-token issue --daemon-id → GET /v1/assets 정상 응답 확인

Rollback Plan

  • Migration rollback: alembic downgrade 20260511_0015
    • 조건: migrate-db 실패 또는 daemons 테이블 생성 오류
    • 영향: daemons 테이블 제거, auth_tokens.daemon_id + portfolios.managed_by_daemon_id 컬럼 제거
    • 주의: daemon_id 컬럼은 nullable이므로 downgrade 전 기존 데이터 손실 여부 확인
  • Service rollback: 이전 커밋으로 서비스 롤백
    • 조건: 배포 후 health endpoint 실패 또는 v1 API 연쇄 403 발생 (non-NULL token 포함)
    • 이전 서비스는 daemon_id 컬럼을 무시하므로 DB 롤백 없이 서비스만 롤백 가능
  • 데이터 롤백 불필요 조건: NULL backfill 상태 유지 중(daemon 미등록)이면 컬럼만 제거하면 됨

Verification Checklist

Local validation snapshot (KST 2026-05-14 08:31): docker-compose.local-test.yml 기반 TimescaleDB와 로컬 app process smoke로 확인했다. 아래 체크는 actual deploy evidence가 아니라 local pre-release validation 결과다.

참고: migration 20260513_0016은 local test DB에 online apply로 검증했다. offline alembic --sql dry-run은 migration 내부의 inspect(op.get_bind()) 사용 때문에 현재 그대로는 성립하지 않는다.

배포 전

  • migration 20260513_0016이 local test DB(target DB 대체 검증)에 online 적용 가능한지 확인 (pfhub migrate-db → head, alembic history 정상)
  • NULL daemon_id service-token inventory 확인 (SELECT COUNT(*) FROM auth_tokens WHERE daemon_id IS NULL AND token_type='service' AND revoked_at IS NULL → 0)
  • daemon mismatch dry-run 확인 (SELECT COUNT(*) FROM portfolios WHERE managed_by_daemon_id IS NOT NULL → 0)
  • pytest tests/ 결과 확인 (128 passed / 7 failed, pre-existing CLI 실패와 일치)
  • release approver 승인 확보

배포 후

  • GET /health → HTTP 200, {"status": "ok", "service": "portfolio-hub"}
    • local app process smoke 결과: status=ok, service=portfolio-hub, version=0.1.0
  • pfhub_DB_ENABLED=true pfhub health-check → exit code 0
  • pfhub daemon create alpha-bot --user <admin_user> → daemon_id 반환 확인
    • local CLI plain output에서 Daemon(id=...) 확인. 단, --format json은 datetime serialization bug로 실패한다.
  • pfhub service-token issue test-daemon-token --user <user> --daemon-id <daemon_id> --no-expiry → token 발급 확인
    • local CLI JSON output에서 token_id, runtime_id, daemon_id 반환 확인. raw token은 의도적으로 마스킹된다.
  • GET /v1/assets (daemon-bound token) → HTTP 200, daemon 소유 asset만 포함
    • local smoke fixture에서 매칭 daemon portfolio 1건만 반환되고 다른 daemon portfolio는 비노출 확인
  • GET /v1/assets (NULL daemon_id token) → HTTP 403 확인
    • 응답 detail: daemon_id not assigned to this token
  • GET /v1/user_info (daemon-bound token) → HTTP 200, daemon_id 필드 포함
  • pfhub service-token rotate test-daemon-token --force → 새 runtime_id, 동일 daemon_id 확인
    • local CLI 검증 실패: idx_auth_tokens_service_name_unique 제약으로 rotate insert가 막힌다.
  • journalctl/Caddy access log에 ERROR 없음 확인

Release Execution Evidence

  • Release Status Transition Target: released

Deployment Facts

  • Executed At:
    • <배포 시작 시각>
  • Completed At:
    • <배포 완료 시각>
  • Environment:
    • <배포 대상 환경>
  • Operator:
    • <배포 수행자>
  • Revision or Artifact:
    • <커밋 SHA 또는 배포 artifact 식별자>
  • Commands or Procedure:
    • <실행 명령 또는 배포 절차 요약>

Profile-Specific Checks

  • app-service:
    • Health Endpoint:
      • <호출 결과와 확인 시각>
    • Startup Log Fields:
      • <app, event, command, run_id 확인 결과>
    • Request Log Fields:
      • <request_id 포함 여부와 확인 결과>
    • Smoke or Manual Verification:
      • <배포 후 재실행한 검증과 결과>

Rollback Outcome

  • Rollback Required:
    • <yes 또는 no>
  • Rollback Trigger:
    • <발생 시 원인, 없으면 none>
  • Rollback Action:
    • <수행한 조치, 없으면 none>

Release Decision Evidence

  • Released Decision:
    • <released 전환 여부>
  • Rationale:
    • <released 전환 판단 근거>
  • Recorded By:
    • <기록자>
  • Recorded At:
    • <기록 시각>

Feedback Handoff

  • Observation Summary:
    • <운영 관찰 사실 요약 또는 없음>
  • Discovery Input:
    • NULL daemon_id token을 보유한 기존 service-token의 마이그레이션 경로 (rotate + daemon-id rebinding 자동화 후보)
    • CLI pfhub portfolio update --daemon-id 추가 검토 (현재 DB 직접 수정 필요)
  • REQ Input:
    • portfolio에 daemon을 CLI로 할당/해제하는 명령 (managed_by_daemon_id 업데이트)
    • daemon deactivation 시 bound token 자동 revoke 정책
  • Change Request Input:
    • pre-existing test_cli.py 7개 실패 수정 (별도 CHG 또는 신규 REQ)