Fix Review 64 valuation authority regressions

This commit is contained in:
2026-10-07 13:39:26 +00:00
parent c7a9cfa50d
commit e41db959e4
6 changed files with 220 additions and 7 deletions
+34 -6
View File
@@ -259,6 +259,16 @@ def _manual_asset_valuation_items(conn: sqlite3.Connection, active_only: bool =
return included, excluded
def _persisted_evidence_array(value: Any) -> list[dict[str, Any]] | None:
try:
decoded = json.loads(value or "[]")
except (TypeError, json.JSONDecodeError):
return None
if not isinstance(decoded, list) or any(not isinstance(item, dict) for item in decoded):
return None
return decoded
def _snapshot_rows_for_run(conn: sqlite3.Connection, run_id: str) -> tuple[list[sqlite3.Row], dict[str, Any]]:
"""Load one immutable close run and only the rows persisted by that run."""
run = conn.execute(
@@ -287,6 +297,11 @@ def _snapshot_rows_for_run(conn: sqlite3.Connection, run_id: str) -> tuple[list[
)""",
(basis_date, run["_run_rowid"]),
).fetchone()[0]
evidence = {
field: _persisted_evidence_array(run[field])
for field in ("applied_evidence", "excluded_evidence", "carried_evidence")
}
integrity_error = any(value is None for value in evidence.values())
metadata = {
"snapshot_run_id": run["id"],
"is_correction": bool(run["correction_of_run_id"]),
@@ -298,9 +313,10 @@ def _snapshot_rows_for_run(conn: sqlite3.Connection, run_id: str) -> tuple[list[
"approved_at": run["approved_at"],
"approval_reason": run["approval_reason"],
"approval_reference": run["approval_reference"],
"applied_evidence": json.loads(run["applied_evidence"] or "[]"),
"excluded_evidence": json.loads(run["excluded_evidence"] or "[]"),
"carried_evidence": json.loads(run["carried_evidence"] or "[]"),
"applied_evidence": evidence["applied_evidence"] or [],
"excluded_evidence": evidence["excluded_evidence"] or [],
"carried_evidence": evidence["carried_evidence"] or [],
"evidence_integrity_error": integrity_error,
"closed_at": run["created_at"] or "",
"previous_snapshot_row_count": previous_rows,
"total_snapshot_rows_for_basis_date": total_rows,
@@ -372,7 +388,10 @@ def _closed_run_metadata(metadata: dict[str, Any]) -> dict[str, Any]:
for item in exclusions:
if item.get("candidate"):
key = (item.get("source_type", ""), item.get("source_id", ""))
warning = candidate_warnings.setdefault(key, {"code": "unverified_candidate", "source_type": key[0], "source_id": key[1], "candidates": []})
warning_shape = {"code": "unverified_candidate", "source_type": key[0], "source_id": key[1], "candidates": []}
if item.get("blocking") is False:
warning_shape["blocking"] = False
warning = candidate_warnings.setdefault(key, warning_shape)
warning["candidates"].append(item["candidate"])
else:
warnings.append({"code": item.get("reason", "excluded_item"), "source_type": item.get("source_type", ""), "source_id": item.get("source_id", ""), "currency": item.get("currency", "KRW")})
@@ -667,6 +686,8 @@ def close_asset_snapshot(basis_date: str = "", source_note: str = "", memo: str
if preview_fingerprint and preview_fingerprint != _preview_fingerprint(preview, basis, selection_policy):
return fail("authority_drift", "asset authority changed since preview", basis_date=basis)
latest_rows, latest_meta = _snapshot_rows_for_latest_run(conn, basis)
if latest_meta.get("evidence_integrity_error"):
return fail("data_integrity_error", "snapshot evidence is malformed", snapshot_run_id=latest_meta.get("snapshot_run_id", ""))
legacy_snapshot_rows = bool(latest_rows and not latest_meta.get("snapshot_run_id"))
if legacy_snapshot_rows and not correction_reason.strip():
return fail(
@@ -734,6 +755,8 @@ def close_asset_snapshot(basis_date: str = "", source_note: str = "", memo: str
or immutable_replay_run
):
replay_rows, replay_meta = _snapshot_rows_for_run(conn, existing_run["id"])
if replay_meta.get("evidence_integrity_error"):
return fail("data_integrity_error", "snapshot evidence is malformed", snapshot_run_id=existing_run["id"])
replay_items = [_public_evidence(item) for item in replay_meta.get("applied_evidence", [])]
replay_warnings = _closed_warnings(replay_meta, basis, replay_rows)
replay_public = _closed_run_metadata(replay_meta)
@@ -816,7 +839,7 @@ def close_asset_snapshot(basis_date: str = "", source_note: str = "", memo: str
),
)
snapshot_ids.append(snapshot_id)
applied_evidence = [{k: item.get(k) for k in ("id", "source_type", "source_id", "authority_source", "name", "type", "liquidity_bucket", "active", "amount", "valuation_amount", "last_balance", "last_synced_at", "currency", "valuation_id", "valuation_kind", "valuation_date", "age_days", "carried_forward", "verification_status", "evidence_kind") if item.get(k) is not None} for item in included]
applied_evidence = [{k: item.get(k) for k in ("id", "source_type", "source_id", "authority_source", "name", "type", "liquidity_bucket", "active", "amount", "valuation_amount", "last_balance", "last_synced_at", "currency", "valuation_id", "valuation_kind", "valuation_date", "age_days", "carried_forward", "verification_status", "evidence_kind", "unverified_candidates") if item.get(k) is not None} for item in included]
excluded_evidence = [{k: item.get(k) for k in ("source_type", "source_id", "reason", "currency")} for item in preview.get("excluded_items", [])]
excluded_evidence.extend(
{
@@ -824,6 +847,7 @@ def close_asset_snapshot(basis_date: str = "", source_note: str = "", memo: str
"source_id": warning.get("source_id", ""),
"reason": "unverified_candidate",
"candidate": candidate,
"blocking": warning.get("blocking", True),
"state_hash": next(
state["state_hash"]
for state in preview["_candidate_state_hashes"]
@@ -922,6 +946,8 @@ def get_asset_snapshot_report(basis_date: str = "", db_path: str | None = None,
return fail("validation_error", f"invalid date: {basis_date}")
with read_db(db_path) as conn:
rows, close_metadata = _snapshot_rows_for_latest_run(conn, basis)
if close_metadata.get("evidence_integrity_error"):
return fail("data_integrity_error", "snapshot evidence is malformed", snapshot_run_id=close_metadata.get("snapshot_run_id", ""))
has_close_run = bool(close_metadata.get("snapshot_run_id"))
snapshots = _snapshot_items(conn, basis) if rows else []
legacy_snapshots = snapshots if rows and not has_close_run else []
@@ -1032,8 +1058,10 @@ def get_net_worth_timeseries(start_date: str = "", end_date: str = "", months: i
points = []
for row in basis_rows:
basis = row["basis_date"]
items = _snapshot_items(conn, basis)
_, metadata = _snapshot_rows_for_latest_run(conn, basis)
if metadata.get("evidence_integrity_error"):
return fail("data_integrity_error", "snapshot evidence is malformed", snapshot_run_id=metadata.get("snapshot_run_id", ""))
items = _snapshot_items(conn, basis)
run_public = _closed_run_metadata(metadata)
run_public["warnings"] = _closed_warnings(metadata, basis, conn.execute("SELECT rowid AS _rowid, * FROM asset_snapshots WHERE basis_date=? ORDER BY created_at ASC, name ASC", (basis,)).fetchall())
run_provenance = _evidence_provenance(metadata.get("applied_evidence", []), basis)