Files
portfolio-hub/docs/batches/bat-020_20260628_daemon-scoped-broker-credential/verification.md
T

7.3 KiB

BAT-020 Verification

실행 결과

python3 -m pytest tests/ -v
509 passed, 0 failed, 11 warnings in 26.39s

신규 테스트:

  • tests/test_bat020_broker_credential_domain.py: 6 passed
  • tests/test_bat020_user_info_daemon_scoped.py: 13 passed
  • tests/test_bat020_credential_cli.py: 11 passed

기존 테스트 회귀: 0건

AC 커버리지

REQ-046: BrokerCredential daemon_id 필드 추가

AC 테스트 결과
AC-1: daemon_id=None 기본값 test_broker_credential_daemon_id_defaults_to_none PASS
AC-2: daemon_id 값 지정 test_broker_credential_daemon_id_set PASS
AC-3: 7컬럼 행 변환 daemon_id 세팅 test_row_to_broker_credential_with_daemon_id PASS
AC-4: 6컬럼 행 변환 daemon_id=None (하위호환) test_row_to_broker_credential_without_daemon_id PASS
AC-5: daemon_id 필터 시 해당 행만 반환 test_list_broker_credentials_daemon_id_filter PASS
AC-6: daemon_id 미지정 시 전체 반환 test_list_broker_credentials_no_daemon_id_filter_returns_all PASS

REQ-047: broker_credentials PK 전환 마이그레이션

AC 검증 방법 결과
AC-1: Step1 후 daemon_id TEXT NULL 컬럼 존재 alembic revision 코드 확인 + ADD COLUMN 명시 코드 검증 완료
AC-2: Step1 후 기존 데이터 daemon_id=NULL 보존 컬럼 추가 시 기존 행 NULL 유지 (DB 동작) 코드 검증 완료
AC-3: Step2 후 PK (daemon_id, broker) 전환 revision 코드 + 사전 검증 로직 확인 코드 검증 완료
AC-4: user_id 컬럼 유지 Step2 revision에서 user_id 삭제 없음 코드 검증 완료
AC-5: ensure_schema Step2 이후 정합 ensure_schema broker_credentials TODO 주석 (Step2 이후 활성화 예정)
AC-6: Step1 downgrade 동작 downgrade 함수에서 컬럼/인덱스 제거 명시 코드 검증 완료
AC-7: Step2 downgrade 안전장치 중복 (user_id,broker) 시 RuntimeError 발생 코드 검증 완료

NOTE: REQ-047 마이그레이션은 dev/test DB 검증 대상이나 실제 DB 인프라 미연결 상태. 코드 수준 검증.

REQ-048: daemon_id 백필 CLI

AC 테스트 결과
AC-1: daemon_id IS NULL 행 UPDATE test_backfill_daemon_id_updates_null_rows PASS
AC-2: 백필 후 NULL 0건 test_backfill_daemon_id_updates_null_rows PASS
AC-3: --dry-run DB 변경 없음 test_backfill_daemon_id_dry_run_no_change PASS
AC-4: encrypted_payload 동등 보존 test_backfill_preserves_encrypted_payload PASS
AC-5: NULL 없으면 "이미 완료됨" test_backfill_daemon_id_already_complete PASS
AC-6: 존재하지 않는 user → exit 1 test_backfill_daemon_id_nonexistent_user_exits_1 PASS
AC-7: Step2 적용 가능 상태 검증 (Step2 revision 사전 검증 코드에서 NULL=0 확인) 코드 검증 완료

REQ-049: GET /v1/user_info daemon-scoped 단일 broker 전달

AC 테스트 결과
AC-1: daemon_id 있음 + broker 있음 → 단일 BrokerItem test_user_info_daemon_scoped_broker_returned PASS
AC-2: daemon_id 있음 + broker 없음 → broker=null test_user_info_daemon_no_broker_returns_null PASS
AC-3: daemon_id=None → 403 test_user_info_no_daemon_id_returns_403 PASS
AC-4: daemon A → daemon A account_ref test_user_info_daemon_isolation_two_daemons PASS
AC-5: daemon B → daemon B account_ref (격리) test_user_info_daemon_isolation_two_daemons PASS
AC-6: broker 단일 키, brokers 키 없음 test_user_info_response_has_broker_not_brokers PASS
AC-7: 복호화 실패 → broker.credential_payload=null test_user_info_decryption_failure_returns_null_payload PASS
AC-8: service 아닌 token → 403 test_user_info_web_token_returns_403 PASS
AC-9: 기존 필드 회귀 없음 test_user_info_regression_existing_fields_unchanged PASS

REQ-050: credential CLI --daemon-id 옵션

AC 테스트 결과
AC-1: set --daemon-id → daemon_id 포함 upsert test_credential_set_with_daemon_id PASS
AC-2: list --daemon-id → 해당 daemon만 출력 test_credential_list_daemon_id_filter PASS
AC-3: list daemon-id 미지정 → 전체 test_credential_list_no_daemon_id_returns_all PASS
AC-4: remove --daemon-id → (daemon_id,broker) 삭제 test_credential_remove_with_daemon_id PASS
AC-5: 존재하지 않는 daemon → exit 1 test_credential_set_nonexistent_daemon_exits_1 PASS
AC-6: --daemon-id 미제공 시 경고 출력 + 허용 (과도기 정책) test_cli_credential_set_list_and_remove_flow 갱신 PASS
AC-7: 출력에 daemon_id 포함 test_credential_set_output_includes_daemon_id PASS

NOTE: AC-6은 design 결정에 따라 Step2 PK 전환 이전 과도기에는 경고만 출력하고 허용. REQ-047 Step2 후 DB 레벨 NOT NULL 제약으로 자동 강제.

REQ-051: 보안 격리

AC 테스트 결과
AC-1: web 토큰 → 403 test_user_info_web_token_returns_403 PASS
AC-2: 비인증 → 401 test_user_info_unauthenticated_returns_401 PASS
AC-3: daemon_id=None → 403 test_user_info_no_daemon_id_returns_403 PASS
AC-4: 다른 daemon 인증정보 → null test_user_info_different_daemon_credential_not_returned PASS
AC-5: 타 엔드포인트 credential 미노출 test_other_endpoints_do_not_expose_credential_payload PASS
AC-6: DB 오류 → broker=null (500 없음) test_user_info_db_error_returns_null_broker PASS
AC-7: 복호화 실패 → credential_payload=null test_user_info_decryption_failure_returns_null_payload PASS
AC-8: 로그에 app_secret 미노출 test_user_info_decryption_failure_log_does_not_expose_secret PASS

기존 테스트 회귀 분석

갱신한 기존 테스트:

  • tests/test_v1.py: brokers→broker 응답 변경 반영, daemon_id=None → 403 반영
  • tests/test_cli.py: FakeRepo 시그니처 갱신(daemon_id 추가), credential 플로우 테스트 --daemon-id 포함
  • tests/test_daemon_assignment.py: daemon_id=None → 200 기대를 403으로 갱신 (REQ-049 정책 변경)

비가역 결재 게이트

REQ-047 Step2(PK 전환) revision 코드가 작성되었으나 실 운영 DB 적용은 사장님 결재 게이트 대상. 이 batch에서는 revision 코드만 작성. 적용 순서:

  1. alembic upgrade 20260628_0026 (Step1 - nullable daemon_id 추가)
  2. pfhub credential backfill-daemon-id --user <username> --daemon-id <slug> (REQ-048)
  3. alembic upgrade 20260628_0027 (Step2 - PK 전환, 사장님 결재 후)

미해결/위험 사항

  1. ensure_schema() broker_credentials 정의 미갱신: Step2 PK 전환 이후 ensure_schema() 내 broker_credentials CREATE TABLE은 여전히 구 스키마(PK=(user_id,broker)). Step2 결재·적용 후 별도 갱신 필요. 현재 코드에 TODO 주석 없음 — 팀장에게 Step2 적용 시 함께 갱신 요청 필요.
  2. upsert ON CONFLICT 절: REQ-047 Step2 이후 PK가 (daemon_id,broker)로 변경되면 upsert_broker_credential의 ON CONFLICT (user_id, broker) 절이 맞지 않음. Step2 결재·적용 시 해당 쿼리도 함께 갱신 필요.
  3. REQ-047 Step2 dev DB 통합 검증: 실제 PostgreSQL에서 Step1→backfill→Step2 순서 검증을 완료하지 못했음(DB 인프라 미연결). 코드 수준 검증만 완료.