Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
5.4 KiB
5.4 KiB
BAT-022 Verification
- Status: draft
- Batch: BAT-022
- Verification Date: 2026-06-28
테스트 실행 결과
신규 테스트 (44 케이스)
tests/test_bat022_req052_credential_api.py — 17 passed
tests/test_bat022_req053_admin_daemon_crud.py — 15 passed
tests/test_bat022_req054_security.py — 12 passed
전체 테스트 스위트
565 passed, 11 warnings in 32.53s
기존 521 테스트 회귀: 0건 (521 → 565, +44 신규만 추가)
REQ-052 AC별 검증 Evidence
| AC | 테스트 | 결과 |
|---|---|---|
| AC-1: PUT → 200 + 메타데이터, secret 없음 | test_put_credential_returns_meta_without_secret |
PASS |
| AC-2: 회전 시 credential_version 증가 | test_put_credential_rotation_increments_version |
PASS |
| AC-3: CLI·API·service-token 정합 (upsert daemon_id 전달) | test_put_credential_upsert_called_with_correct_daemon_id |
PASS |
| AC-4: GET → 200 + 메타데이터, secret 없음 | test_get_credential_meta_returns_metadata_without_secret |
PASS |
| AC-5: DELETE → 204 + 이후 has_credential=False | test_delete_credential_returns_204, test_get_after_delete_returns_has_credential_false |
PASS |
| AC-6 (음성): 타 사용자 토큰 → 403 | test_put/get/delete_credential_other_user_returns_403 (3개) |
PASS |
| AC-7: 비인증 → 401 | test_credential_no_token_returns_401 |
PASS |
| AC-8: 미존재 daemon → 404 | test_credential_nonexistent_daemon_returns_404, test_put_nonexistent_daemon_returns_404 |
PASS |
| AC-9 (음성): admin으로 타인 daemon write → 403 | test_admin_cannot_write/read_other_user_credential (2개) |
PASS |
| AC-10 (음성): service-token → 403 | test_service_token_credential_get/put/delete_returns_403 (3개) |
PASS |
REQ-053 AC별 검증 Evidence
| AC | 테스트 | 결과 |
|---|---|---|
| AC-1: POST 생성 → 201 + DaemonAdminResponse | test_admin_create_daemon_returns_201 |
PASS |
| AC-2: 중복 slug → 409 | test_admin_create_daemon_duplicate_slug_returns_409 |
PASS |
| AC-3: display_name 변경 → BrokerCredential 유지 | test_admin_patch_display_name_credential_preserved |
PASS |
| AC-4: owner 재할당 → BrokerCredential 자동 삭제 | test_admin_patch_owner_invalidates_credentials |
PASS |
| AC-5: 재할당 후 이전 owner 인증정보 무효화 | test_admin_patch_owner_then_old_owner_loses_credential |
PASS |
| AC-6: 비활성화 → is_active=False + service token revoke | test_admin_deactivate_daemon_revokes_tokens |
PASS |
| AC-7: 재활성화 → is_active=True | test_admin_activate_daemon_returns_active |
PASS |
| AC-8 (음성): DELETE → 405 | test_admin_delete_daemon_returns_405 |
PASS |
| AC-9 (음성): user-token(비admin) → 403 | test_non_admin_user_token_create/patch/deactivate (3개) |
PASS |
| AC-10 (음성): service-token → 403 | test_service_token_admin_crud_returns_403 |
PASS |
| AC-11: 비인증 → 401 | test_admin_crud_no_token_returns_401 |
PASS |
| AC-12: 미존재 daemon → 404 | test_admin_patch/deactivate_nonexistent_daemon_returns_404 (2개) |
PASS |
REQ-054 AC별 검증 Evidence
| AC | 테스트 | 결과 |
|---|---|---|
| AC-1: PUT 응답에 app_key/app_secret 없음 | test_put_credential_response_has_no_secret_fields |
PASS |
| AC-2: GET 응답에 app_key/app_secret 없음 | test_get_credential_meta_response_has_no_secret_fields |
PASS |
| AC-3: admin CRUD 응답에 credential 필드 없음 | test_admin_create/patch_response_has_no_credential_fields (2개) |
PASS |
| AC-4: caplog — PUT 처리 중 app_key/app_secret 값 미포함 | test_put_credential_log_does_not_expose_secret |
PASS |
| AC-5: Fernet 암호화 저장 확인 (gAAAA... 형태) | test_put_credential_stores_encrypted_payload |
PASS |
| AC-6: PUT 후 service-token user_info → 동일 account_ref | test_put_then_service_token_user_info_returns_correct_account_ref |
PASS |
| AC-7: REQ-051 회귀 (4개 테스트) | test_req051_regression_* (4개) |
PASS |
음성 테스트 체크리스트
| 음성 시나리오 | 케이스 수 | 결과 |
|---|---|---|
| 소유 스코프 403 (AC-6: 타 사용자 토큰) | 3 | PASS |
| admin 소유 스코프 403 (AC-9) | 2 | PASS |
| service-token 403 (AC-10, REQ-052) | 3 | PASS |
| service-token 403 (AC-10, REQ-053) | 1 | PASS |
| DELETE 405 (AC-8, REQ-053) | 1 | PASS |
| secret 필드 부재 (AC-1/2/3, REQ-054) | 4 | PASS |
| caplog secret 미노출 (AC-4, REQ-054) | 1 | PASS |
회귀 테스트
- REQ-051 AC-1~3, AC-5: 신규 API 추가 후 GET /v1/user_info 보안 격리 불변 확인 (4개 테스트 PASS)
- 기존 521 테스트 전건 회귀 없음
잔여 위험 / 미해결
-
AC-3 통합 수준: REQ-052 AC-3(CLI·API·service-token 3경로 정합)은 이 batch에서 unit-level로 검증(upsert daemon_id 전달 확인). 실 DB 통합 검증은 dev DB 환경 필요(비가역 아님, 선택적 추후 확인 가능).
-
DELETE credential 기본 broker "kis": GET/DELETE 에서 broker 파라미터 없이 "kis" 고정. 다중 broker 지원이 필요해지면 경로 파라미터 추가 필요 — 현재 단일 broker 가정 설계 일치.
-
update_daemon_owner autocommit 부분 실패: postgres.py
update_daemon_owner()는 daemon UPDATE + credential DELETE를 autocommit 2회 연산으로 처리. daemon 업데이트 성공 후 credential 삭제 실패 케이스는 테스트 범위 밖(네트워크 장애 등). 실 운영에서 발생 시 수동 정리 필요.