fix(approval): replay immutable action responses

This commit is contained in:
caoxiaozhu
2026-07-16 15:49:43 +08:00
parent 4940ebc419
commit 28b834edd3
20 changed files with 552 additions and 60 deletions

View File

@@ -28,7 +28,7 @@ from app.models.risk_observation import RiskObservation
MIGRATION_TEST_DATABASE_URL = os.getenv("MIGRATION_TEST_DATABASE_URL", "").strip()
LEGACY_PROBE_TABLE = "legacy_migration_probe_records"
HEAD_REVISION = "20260716_0011"
HEAD_REVISION = "20260716_0012"
SERVER_DIR = Path(__file__).resolve().parents[1]
ALEMBIC_INI_PATH = SERVER_DIR / "alembic.ini"
@@ -487,6 +487,14 @@ def _assert_head_schema(engine: Engine) -> None:
("tenant_id", "observation_id"),
"risk_observations",
)
risk_disposition_event_columns = {
str(item["name"])
for item in inspect(engine).get_columns(
"risk_disposition_events",
schema="public",
)
}
assert "response_json" in risk_disposition_event_columns
with engine.connect() as connection:
append_only_trigger_count = int(
connection.scalar(
@@ -1325,6 +1333,8 @@ def _assert_base_schema(engine: Engine) -> None:
("20260716_0010_approval_action_protocol.py", "downgrade"),
("20260716_0011_risk_disposition.py", "upgrade"),
("20260716_0011_risk_disposition.py", "downgrade"),
("20260716_0012_risk_disposition_response_snapshot.py", "upgrade"),
("20260716_0012_risk_disposition_response_snapshot.py", "downgrade"),
],
)
def test_postgresql_only_migrations_reject_other_dialects_before_mutation(
@@ -1341,6 +1351,18 @@ def test_postgresql_only_migrations_reject_other_dialects_before_mutation(
assert operation_guard.mutation_calls == []
def test_risk_disposition_snapshot_migration_refuses_lossy_downgrade() -> None:
migration = _load_migration_module("20260716_0012_risk_disposition_response_snapshot.py")
operation_guard = _UnsupportedDialectOperationGuard(dialect_name="postgresql")
operation_guard.bind.scalar = lambda _statement: 1
migration.op = operation_guard
with pytest.raises(RuntimeError, match="contains 1 immutable snapshot"):
migration.downgrade()
assert operation_guard.mutation_calls == []
def test_head_model_declares_soft_claim_reference_and_organization_only_active_index() -> None:
claim_column = RiskObservation.__table__.c.claim_id
assert not claim_column.foreign_keys