Preserve inactive-category fallback and saved settlement header evidence
This commit is contained in:
@@ -440,6 +440,37 @@ def test_saved_reader_retains_asset_authority_and_liability_flags(tmp_path):
|
||||
assert asset.get("status") == "ready"
|
||||
|
||||
|
||||
def test_saved_reader_projects_safe_header_exclusion_carry_and_approval_evidence(tmp_path):
|
||||
path = dbfile(tmp_path)
|
||||
saved = ok(close_draft(path, new_draft(path)))
|
||||
excluded = [{"source_type":"account", "source_id":"missing-account-41", "reason":"missing_verified_exact_valuation",
|
||||
"valuation_date":"2026-09-27", "arbitrary_metadata":{"password":"DO-NOT-LEAK"}}]
|
||||
carried = [{"source_type":"account", "source_id":"carried-account-42", "reason":"as_of_carry_forward",
|
||||
"valuation_date":"2026-09-27", "arbitrary_metadata":{"token":"DO-NOT-LEAK"}}]
|
||||
approval = {"approved_by":"synthetic-reviewer", "approval_reason":"synthetic conditional approval",
|
||||
"approval_reference":"synthetic-ref", "allow_missing_exclusions":True,
|
||||
"allow_as_of_carry_forward":True, "private_note":"DO-NOT-LEAK"}
|
||||
with sqlite3.connect(path) as conn:
|
||||
conn.execute("UPDATE asset_snapshot_runs SET close_status='conditional',excluded_evidence=?,carried_evidence=?,approved_by=?,approval_reason=?,approval_reference=? WHERE id=?",
|
||||
(json.dumps(excluded), json.dumps(carried), approval["approved_by"], approval["approval_reason"], approval["approval_reference"], saved["run_id"]))
|
||||
conn.commit()
|
||||
before = list(conn.iterdump())
|
||||
exact = ok(service.get_monthly_settlement_snapshot(run_id=saved["run_id"], db_path=path))
|
||||
latest = ok(service.get_monthly_settlement_snapshot(month="2026-09", db_path=path))
|
||||
assert exact == latest
|
||||
assert exact["run_id"] == saved["run_id"] and exact["close_status"] == "conditional"
|
||||
assert exact["excluded_items"][0]["source_id"] == "missing-account-41"
|
||||
assert exact["excluded_items"][0]["reason"] == "missing_verified_exact_valuation"
|
||||
assert exact["carried_items"][0]["source_id"] == "carried-account-42"
|
||||
assert exact["carried_items"][0]["valuation_date"] == "2026-09-27"
|
||||
assert exact["applied_evidence"]
|
||||
assert exact["approval"]["approval_reason"] == "synthetic conditional approval"
|
||||
encoded = json.dumps(exact, sort_keys=True)
|
||||
assert "DO-NOT-LEAK" not in encoded and "private_note" not in encoded and "arbitrary_metadata" not in encoded
|
||||
with sqlite3.connect(path) as conn:
|
||||
assert list(conn.iterdump()) == before
|
||||
|
||||
|
||||
@pytest.mark.parametrize("schema_version,aggregation_version", [(1, None), (1, ""), (1, "unknown-version"), (2, "comprehensive-v1")])
|
||||
def test_saved_reader_rejects_unsupported_comprehensive_versions_without_writes(tmp_path, schema_version, aggregation_version):
|
||||
path = dbfile(tmp_path)
|
||||
@@ -476,3 +507,106 @@ def test_saved_reader_does_not_mislabel_partial_version_metadata_as_legacy(tmp_p
|
||||
legacy = ok(service.get_monthly_settlement_snapshot(run_id=saved["run_id"], db_path=path))
|
||||
assert legacy["legacy"] and not legacy["is_comprehensive"]
|
||||
assert all(value is None for value in legacy["totals"].values())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def schema_thirteen_conditional_close(tmp_path):
|
||||
"""Execute immutable pre-comprehensive public APIs, without another checkout."""
|
||||
import importlib
|
||||
import importlib.abc
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
revision = "f67c07adf01d1f17415bf7cf836f46997ca6f21c"
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
namespace = "_legacy_schema_thirteen"
|
||||
names = subprocess.check_output(
|
||||
["git", "ls-tree", "-r", "--name-only", revision, "jarca_ledger_mcp"],
|
||||
cwd=root, text=True,
|
||||
).splitlines()
|
||||
blobs = {
|
||||
name: subprocess.check_output(["git", "show", f"{revision}:{name}"], cwd=root)
|
||||
for name in names if name.endswith(".py")
|
||||
}
|
||||
|
||||
class BaselineModules(importlib.abc.MetaPathFinder, importlib.abc.Loader):
|
||||
def find_spec(self, fullname, path=None, target=None):
|
||||
if fullname != namespace and not fullname.startswith(namespace + "."):
|
||||
return None
|
||||
relative = fullname[len(namespace):].replace(".", "/")
|
||||
candidate = "jarca_ledger_mcp" + relative
|
||||
package = candidate + "/__init__.py"
|
||||
module = candidate + ".py"
|
||||
if package in blobs:
|
||||
return importlib.util.spec_from_loader(fullname, self, is_package=True)
|
||||
if module in blobs:
|
||||
return importlib.util.spec_from_loader(fullname, self)
|
||||
return None
|
||||
|
||||
def create_module(self, spec):
|
||||
return None
|
||||
|
||||
def exec_module(self, module):
|
||||
relative = module.__name__[len(namespace):].replace(".", "/")
|
||||
candidate = "jarca_ledger_mcp" + relative
|
||||
filename = candidate + ("/__init__.py" if hasattr(module, "__path__") else ".py")
|
||||
module.__file__ = f"git:{revision}:{filename}"
|
||||
exec(compile(blobs[filename], module.__file__, "exec"), module.__dict__)
|
||||
|
||||
finder = BaselineModules()
|
||||
sys.meta_path.insert(0, finder)
|
||||
try:
|
||||
old = importlib.import_module(namespace + ".service")
|
||||
old_db = importlib.import_module(namespace + ".db")
|
||||
path = str(tmp_path / "baseline-schema-thirteen.sqlite3")
|
||||
old_db.init_db(path)
|
||||
missing = ok(old.create_ledger_account("Synthetic missing", "bank", liquidity_bucket="cash", db_path=path))["account"]["id"]
|
||||
carried = ok(old.create_ledger_account("Synthetic carry", "bank", liquidity_bucket="cash", db_path=path))["account"]["id"]
|
||||
ok(old.register_account_valuation(carried, "2026-09-27", 100, verification_status="verified", idempotency_key="baseline-carry", db_path=path))
|
||||
closed = ok(old.close_asset_snapshot(
|
||||
"2026-09-30", selection_policy="as_of", idempotency_key="baseline-close",
|
||||
allow_missing_exclusions=True, allow_as_of_carry_forward=True,
|
||||
approved_by="synthetic-reviewer", approval_reason="synthetic conditional approval",
|
||||
approval_reference="synthetic-ref", db_path=path,
|
||||
))
|
||||
original = ok(old.get_asset_snapshot_report("2026-09-30", db_path=path))
|
||||
yield path, missing, carried, closed, original
|
||||
finally:
|
||||
sys.meta_path.remove(finder)
|
||||
for name in list(sys.modules):
|
||||
if name == namespace or name.startswith(namespace + "."):
|
||||
del sys.modules[name]
|
||||
|
||||
|
||||
def test_schema_thirteen_saved_reader_retains_real_conditional_header_without_writes(schema_thirteen_conditional_close):
|
||||
path, missing, carried, closed, original = schema_thirteen_conditional_close
|
||||
init_db(path)
|
||||
assert ok(service.get_asset_snapshot_report("2026-09-30", db_path=path)) == original
|
||||
with sqlite3.connect(path) as conn:
|
||||
before = list(conn.iterdump())
|
||||
exact = ok(service.get_monthly_settlement_snapshot(run_id=closed["snapshot_run_id"], db_path=path))
|
||||
latest = ok(service.get_monthly_settlement_snapshot(month="2026-09", db_path=path))
|
||||
assert exact == latest
|
||||
assert exact["legacy"] and not exact["is_comprehensive"]
|
||||
assert all(value is None for value in exact["totals"].values())
|
||||
assert exact["close_status"] == "conditional"
|
||||
excluded = next(item for item in exact["excluded_items"] if item["source_id"] == missing)
|
||||
assert excluded["reason"]
|
||||
carry = next(item for item in exact["carried_items"] if item["source_id"] == carried)
|
||||
assert carry["valuation_date"] == "2026-09-27"
|
||||
assert exact["applied_evidence"]
|
||||
assert exact["approval"]["approved_by"] == "synthetic-reviewer"
|
||||
with sqlite3.connect(path) as conn:
|
||||
assert list(conn.iterdump()) == before
|
||||
|
||||
|
||||
def test_saved_evidence_privacy_contract_filters_keys_not_allowlisted_scalar_values():
|
||||
from pathlib import Path
|
||||
from jarca_ledger_mcp.application.assets_service import _public_evidence
|
||||
value = {"candidate": {"name": "synthetic public scalar", "memo": "private", "source_attributes": {"reason": "synthetic reason", "private_key": "private"}}, "unrecognized": "private"}
|
||||
assert _public_evidence(value, strict=True) == {"candidate": {"name": "synthetic public scalar", "source_attributes": {"reason": "synthetic reason"}}}
|
||||
contract = (Path(__file__).resolve().parents[1] / "docs/interface-contract.md").read_text()
|
||||
assert "allowlisted scalar values are preserved" in contract
|
||||
assert "not a content-based secret redactor" in contract
|
||||
|
||||
Reference in New Issue
Block a user