feat(bat-021): REQ-047 Step2 동반 코드 수정 + 실 DB 통합검증 + 런북
- ensure_schema() broker_credentials: daemon_id NOT NULL, PK=(daemon_id,broker)로 갱신 - _row_to_broker_credential: Step2 컬럼 순서(daemon_id 선두)로 갱신 - upsert_broker_credential: ON CONFLICT (daemon_id,broker)로 수정, fallback try/except 제거 - list_broker_credentials: fallback 제거, SELECT 컬럼 순서 갱신 - test_bat020_broker_credential_domain.py: AC-3/AC-4 행 순서를 Step2 포맷으로 갱신 - tests/test_bat021_step2_ensure_schema_and_upsert.py: 12개 신규 테스트 - docs/runbooks/bat-021-req047-step2-migration-runbook.md: 운영 적용 런북 - docs/batches/bat-021: batch 문서(index/planning/design/implementation/verification) 실 PostgreSQL 통합검증(AC-1~7 전건 PASS): Step1 upgrade → backfill → Step2 upgrade → downgrade 시나리오 포함 NULL 사전검증(upgrade 거부) 및 downgrade 안전장치(중복 시 RuntimeError) 확인 521 passed, 0 failed (기존 509 + 신규 12)
This commit is contained in:
@@ -42,37 +42,42 @@ def test_broker_credential_daemon_id_set() -> None:
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# REQ-046 AC-3: _row_to_broker_credential 7컬럼(daemon_id 포함) 처리
|
||||
# REQ-046 AC-3 / BAT-021: _row_to_broker_credential Step2 컬럼 순서 검증
|
||||
# Step2(REQ-047) 이후 컬럼 순서: (daemon_id, user_id, broker, account_ref, encrypted_payload, credential_version, last_rotated_at)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_row_to_broker_credential_with_daemon_id() -> None:
|
||||
"""REQ-046 AC-3: 7컬럼 행(daemon_id 포함) 변환 시 daemon_id 세팅."""
|
||||
"""REQ-046 AC-3 / BAT-021: Step2 컬럼 순서(daemon_id 선두) 행 변환 검증."""
|
||||
from app.repositories.postgres import PostgresPortfolioRepository
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
row = ("user-1", "kis", "12345678", "encrypted", 2, now, "daemon-xyz")
|
||||
# Step2 이후 RETURNING/SELECT 순서: daemon_id, user_id, broker, account_ref, encrypted_payload, credential_version, last_rotated_at
|
||||
row = ("daemon-xyz", "user-1", "kis", "12345678", "encrypted", 2, now)
|
||||
cred = PostgresPortfolioRepository._row_to_broker_credential(row)
|
||||
assert cred.daemon_id == "daemon-xyz"
|
||||
assert cred.user_id == "user-1"
|
||||
assert cred.broker == "kis"
|
||||
assert cred.account_ref == "12345678"
|
||||
assert cred.encrypted_payload == "encrypted"
|
||||
assert cred.credential_version == 2
|
||||
assert cred.last_rotated_at == now
|
||||
assert cred.daemon_id == "daemon-xyz"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# REQ-046 AC-4: _row_to_broker_credential 6컬럼(daemon_id 없음) 하위호환
|
||||
# REQ-046 AC-4 / BAT-021: _row_to_broker_credential credential_version 기본값
|
||||
# Step2 이후 daemon_id는 항상 존재. 6컬럼(credential_version 없음) 기본값 1 확인.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_row_to_broker_credential_without_daemon_id() -> None:
|
||||
"""REQ-046 AC-4: 6컬럼 행(daemon_id 없음) 변환 시 daemon_id=None (하위호환)."""
|
||||
"""REQ-046 AC-4 / BAT-021: credential_version 없는 5컬럼 행 → credential_version 기본값 1."""
|
||||
from app.repositories.postgres import PostgresPortfolioRepository
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
row = ("user-1", "kis", "12345678", "encrypted", 1, now)
|
||||
# Step2 이후 컬럼 순서: daemon_id, user_id, broker, account_ref, encrypted_payload (5컬럼)
|
||||
row = ("daemon-abc", "user-1", "kis", "12345678", "encrypted")
|
||||
cred = PostgresPortfolioRepository._row_to_broker_credential(row)
|
||||
assert cred.daemon_id is None
|
||||
assert cred.daemon_id == "daemon-abc"
|
||||
assert cred.credential_version == 1
|
||||
assert cred.last_rotated_at is None
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -109,11 +114,11 @@ class _FakeConn:
|
||||
|
||||
|
||||
def _make_rows_for_user(user_id: str):
|
||||
"""daemon_id "d1", "d2" 각각 1건씩."""
|
||||
"""Step2 컬럼 순서: (daemon_id, user_id, broker, account_ref, encrypted_payload, credential_version, last_rotated_at)."""
|
||||
now = datetime.now(timezone.utc)
|
||||
return [
|
||||
(user_id, "kis", "ref-d1", "enc-d1", 1, now, "d1"),
|
||||
(user_id, "kis2", "ref-d2", "enc-d2", 1, now, "d2"),
|
||||
("d1", user_id, "kis", "ref-d1", "enc-d1", 1, now),
|
||||
("d2", user_id, "kis2", "ref-d2", "enc-d2", 1, now),
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user