From 8d3c99ba308c65043daea63da4d6738aa4fa9bb4 Mon Sep 17 00:00:00 2001 From: Sameer6305 Date: Tue, 28 Jul 2026 17:25:01 +0530 Subject: [PATCH] perf(provenance): optimize lineage integrity checks and clean up top-level imports (#792) - Reuse lineage['integrity_verified'] in _build_provenance in O(1) time when available, eliminating redundant SHA-256 verification loops across lineage chains. - Improve compute_checksum dictionary handling in semantica/provenance/integrity.py so None values fall back cleanly to ProvenanceEntry defaults. - Move json and verify_checksum imports to module top-level in semantica/provenance/manager.py to avoid function-local import overhead during get_lineage calls. --- semantica/explorer/routes/provenance.py | 7 +++++-- semantica/provenance/integrity.py | 12 ++++++------ semantica/provenance/manager.py | 5 ++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/semantica/explorer/routes/provenance.py b/semantica/explorer/routes/provenance.py index e225852f..4a6ac5da 100644 --- a/semantica/explorer/routes/provenance.py +++ b/semantica/explorer/routes/provenance.py @@ -144,8 +144,11 @@ def _build_provenance(session: GraphSession, node_id: Optional[str] = None) -> d if manager is not None: lineage = manager.get_lineage(node_id) if lineage and lineage.get("entity_count", 0) > 0: - entries = lineage.get("lineage_chain") or lineage.get("entries") or [] - if all(verify_checksum(entry) for entry in entries): + integrity_ok = lineage.get("integrity_verified") + if integrity_ok is None: + entries = lineage.get("lineage_chain") or lineage.get("entries") or [] + integrity_ok = all(verify_checksum(entry) for entry in entries) + if integrity_ok: return _transform_audit_lineage(lineage, node_id) logger.warning( f"Provenance integrity verification failed for {node_id}, falling back to graph traversal" diff --git a/semantica/provenance/integrity.py b/semantica/provenance/integrity.py index 58c95b19..e5327089 100644 --- a/semantica/provenance/integrity.py +++ b/semantica/provenance/integrity.py @@ -51,12 +51,12 @@ def compute_checksum(entry: Any) -> str: # Concatenate critical fields for checksum if isinstance(entry, dict): data = ( - f"{entry.get('entity_id', '')}" - f"{entry.get('entity_type', '')}" - f"{entry.get('activity_id', '')}" - f"{entry.get('source_document', '')}" - f"{entry.get('timestamp', '')}" - f"{entry.get('confidence', 1.0)}" + f"{entry.get('entity_id') or ''}" + f"{entry.get('entity_type') or ''}" + f"{entry.get('activity_id') or ''}" + f"{entry.get('source_document') or ''}" + f"{entry.get('timestamp') or ''}" + f"{entry.get('confidence') if entry.get('confidence') is not None else 1.0}" ) else: data = ( diff --git a/semantica/provenance/manager.py b/semantica/provenance/manager.py index b23f7565..9e2679bf 100644 --- a/semantica/provenance/manager.py +++ b/semantica/provenance/manager.py @@ -29,11 +29,12 @@ from collections.abc import Mapping from datetime import datetime from contextlib import contextmanager import copy +import json import threading from .schemas import ProvenanceEntry, SourceReference from .storage import ProvenanceStorage, InMemoryStorage, SQLiteStorage -from .integrity import compute_checksum +from .integrity import compute_checksum, verify_checksum @contextmanager @@ -553,7 +554,6 @@ class ProvenanceManager: meta = entry.metadata if isinstance(meta, str): try: - import json meta = json.loads(meta) except (json.JSONDecodeError, TypeError): pass @@ -561,7 +561,6 @@ class ProvenanceManager: if isinstance(meta, dict): aggregated_metadata.update(meta) - from .integrity import verify_checksum integrity_verified = all(verify_checksum(entry) for entry in lineage_entries) chain_dicts = [entry.to_dict() for entry in lineage_entries] return {