Reject replay after post-correction authority drift
This commit is contained in:
@@ -97,22 +97,28 @@ def test_f002_correction_replay_preserves_full_initial_response(tmp_path):
|
||||
def test_f006_initial_replay_survives_multiple_later_corrections(tmp_path):
|
||||
db_path = str(tmp_path / "ledger.sqlite3")
|
||||
service.create_manual_asset(
|
||||
"현금", 100, "2026-06-30", "cash", db_path=db_path
|
||||
"현금 A", 100, "2026-06-30", "cash", db_path=db_path
|
||||
)
|
||||
asset_id = service.list_manual_assets(db_path=db_path)["manual_assets"][0]["id"]
|
||||
service.create_manual_asset(
|
||||
"현금 B", 200, "2026-06-30", "cash", db_path=db_path
|
||||
)
|
||||
assets = {
|
||||
item["name"]: item["id"]
|
||||
for item in service.list_manual_assets(db_path=db_path)["manual_assets"]
|
||||
}
|
||||
first = service.close_asset_snapshot(
|
||||
"2026-06-30", idempotency_key="multi-initial", db_path=db_path
|
||||
)
|
||||
assert first["success"] is True
|
||||
|
||||
service.update_manual_asset(asset_id, valuation_amount=110, db_path=db_path)
|
||||
service.update_manual_asset(assets["현금 A"], valuation_amount=110, db_path=db_path)
|
||||
first_correction = service.close_asset_snapshot(
|
||||
"2026-06-30", correction_reason="first correction",
|
||||
idempotency_key="multi-correction-1", db_path=db_path,
|
||||
)
|
||||
assert first_correction["success"] is True
|
||||
|
||||
service.update_manual_asset(asset_id, valuation_amount=120, db_path=db_path)
|
||||
service.update_manual_asset(assets["현금 A"], valuation_amount=120, db_path=db_path)
|
||||
second_correction = service.close_asset_snapshot(
|
||||
"2026-06-30", correction_reason="second correction",
|
||||
idempotency_key="multi-correction-2", db_path=db_path,
|
||||
@@ -124,6 +130,13 @@ def test_f006_initial_replay_survives_multiple_later_corrections(tmp_path):
|
||||
)
|
||||
assert replay == first
|
||||
|
||||
service.update_manual_asset(assets["현금 B"], valuation_amount=220, db_path=db_path)
|
||||
drifted_replay = service.close_asset_snapshot(
|
||||
"2026-06-30", idempotency_key="multi-initial", db_path=db_path
|
||||
)
|
||||
assert drifted_replay["success"] is False
|
||||
assert drifted_replay["error_code"] == "idempotency_conflict"
|
||||
|
||||
|
||||
def test_f003_zero_row_conditional_runs_are_timeseries_authority_with_aliases(tmp_path):
|
||||
db_path = str(tmp_path / "ledger.sqlite3")
|
||||
|
||||
Reference in New Issue
Block a user