Files
portfolio-hub/docs/batches/bat-020_20260628_daemon-scoped-broker-credential/planning.md
T
genichinandClaude Sonnet 4.6 51b7cbee35 feat(bat-020): daemon-scoped 브로커 인증정보 (REQ-046~051)
- REQ-046: BrokerCredential.daemon_id 필드 추가, repository 시그니처 갱신
- REQ-047: alembic revision Step1(daemon_id NULL 컬럼 추가), Step2(PK 전환, dev/test DB 한정)
- REQ-048: backfill-daemon-id CLI subcommand (--dry-run/--force/--broker 지원)
- REQ-049: GET /v1/user_info daemon-scoped 단일 broker 전달 (brokers→broker, daemon_id 없으면 403)
- REQ-050: credential set/list/remove --daemon-id 옵션 추가 (daemon_slug 해석)
- REQ-051: 보안 격리 - service-token 전용, web 토큰 차단, 로그 app_secret 비노출, graceful degrade

비가역 결재 게이트: REQ-047 Step2(PK 전환)는 사장님 결재 후 실DB 적용 예정(이 batch는 revision 코드만)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
2026-06-28 00:45:46 +09:00

4.5 KiB

BAT-020 Planning

구현 의존 순서

  1. REQ-046 — BrokerCredential 도메인 모델 + repository 시그니처 변경 (daemon_id 필드)
  2. REQ-047 Step1 — alembic revision: broker_credentials에 daemon_id TEXT NULL 컬럼 추가
  3. REQ-048 — backfill-daemon-id CLI subcommand 추가
  4. REQ-047 Step2 — alembic revision: PK (user_id,broker) → (daemon_id,broker) 전환 (dev/test DB만)
  5. REQ-049 — GET /v1/user_info daemon-scoped 단일 broker 전달 (스키마 + 엔드포인트)
  6. REQ-050 — credential CLI --daemon-id 옵션 추가 (set/list/remove)
  7. REQ-051 — 보안 격리 테스트: service-token 전용, web 토큰 차단, 로그 비노출 검증

Task Breakdown

T-1: REQ-046 모델·repository 변경

  • app/domain/models.py — BrokerCredential.daemon_id: str | None = None 추가
  • app/repositories/postgres.py — _row_to_broker_credential daemon_id 처리 (7컬럼/6컬럼 하위호환)
  • app/repositories/postgres.py — upsert_broker_credential(daemon_id=None) 파라미터 추가
  • app/repositories/postgres.py — list_broker_credentials(daemon_id=None) 파라미터 + 필터 추가
  • app/repositories/postgres.py — delete_broker_credential(daemon_id=None) 파라미터 추가
  • Tests: REQ-046 AC-1~6 단위 테스트 신규

T-2: REQ-047 Step1 alembic revision

  • migrations/versions/20260628_0026_broker_credential_daemon_id_step1.py
  • 내용: broker_credentials에 daemon_id TEXT NULL 컬럼 추가 + downgrade(컬럼 제거, PK 복원)
  • Tests: AC-1 (컬럼 존재), AC-2 (기존 데이터 NULL 보존), AC-6 (downgrade)

T-3: REQ-048 backfill CLI

  • app/cli/commands/credential.py — backfill-daemon-id subcommand 추가
  • Tests: AC-1~6 단위 테스트 (mock repo 기반)

T-4: REQ-047 Step2 alembic revision

  • migrations/versions/20260628_0027_broker_credential_daemon_id_step2.py
  • 내용: PK 전환 (user_id,broker) → (daemon_id,broker), daemon_id NOT NULL 제약, downgrade 안전장치
  • app/repositories/postgres.py — ensure_schema() broker_credentials 정의 최종 스키마로 갱신 (Step2 이후 활성화 주석)
  • Tests: AC-3~5 (dev DB에서 Step1→백필→Step2 순서 검증), AC-7 (downgrade 안전장치)

T-5: REQ-049 user_info daemon-scoped 확장

  • app/schemas/v1.py — UserInfoResponse.broker: BrokerItem | None = None, brokers: list 제거
  • app/api/v1_user_info.py — daemon_id 없으면 403, daemon_id 기반 list_broker_credentials 호출, 단일 broker 반환
  • Tests: REQ-049 AC-1~9 (daemon_id 있음/없음, broker 있음/없음, 2데몬 격리, 복호화 실패, 회귀)

T-6: REQ-050 credential CLI --daemon-id

  • app/cli/commands/credential.py — set/list/remove 에 --daemon-id 옵션 추가
  • tests/test_cli.py FakeRepo — upsert/list/delete에 daemon_id 파라미터 반영
  • Tests: REQ-050 AC-1~7

T-7: REQ-051 보안 격리 테스트

  • web 토큰 403 (AC-1), 비인증 401 (AC-2), daemon_id=None 403 (AC-3), 타데몬 null (AC-4)
  • 타 엔드포인트 credential 미노출 (AC-5)
  • DB 오류 graceful degrade (AC-6), 복호화 실패 degrade (AC-7)
  • 로그 비노출 (AC-8, caplog fixture)

파일 변경 대상 요약

파일 변경 내용
app/domain/models.py BrokerCredential.daemon_id 추가
app/repositories/postgres.py _row_to_broker_credential, upsert/list/delete 시그니처, ensure_schema broker_credentials
app/schemas/v1.py UserInfoResponse brokers→broker 단일화
app/api/v1_user_info.py daemon-scoped 조회, daemon_id 없음 403, 로그 비노출 확인
app/cli/commands/credential.py set/list/remove --daemon-id, backfill-daemon-id subcommand
migrations/versions/20260628_0026_*.py Step1 revision
migrations/versions/20260628_0027_*.py Step2 revision
tests/test_v1.py user_info 테스트 갱신 + 신규(daemon-scoped, 보안)
tests/test_cli.py credential CLI 테스트 갱신 + 신규
tests/test_bat020_broker_credential_domain.py REQ-046 단위 테스트 신규
tests/test_bat020_broker_credential_migration.py REQ-047 마이그레이션 테스트 신규

위험

  • REQ-049: brokers → broker 응답 변경으로 기존 test_v1.py의 brokers 필드 참조 테스트가 실패할 수 있음 → 갱신 필수
  • REQ-047 Step2: 실 DB 적용 금지(게이트). dev/test DB에서만 검증.
  • get_daemon_by_slug은 owner_user_id + daemon_slug 조합으로 조회 → REQ-050에서 daemon_slug로 받으면 user 조회 먼저 필요