"""Phase-local removal of storage navigation, never facts or database cells.""" import copy NOTICE = "Model view omits storage hashes, byte sizes, archive/member navigation and JSON pointers from provenance containers. Source/evidence IDs, origins, authors, times, facts, rows, scope and uncertainty retain their meaning. Omitted navigation is not absence evidence; the complete immutable context is archived." def project(value): result = copy.deepcopy(value) def provenance(node): if isinstance(node, list): return [provenance(x) for x in node] if not isinstance(node, dict): return node return {k: provenance(v) if k in ('origin', 'provenance') else v for k, v in node.items() if k not in ('json_pointer', 'archive_ref', 'member_name', 'sha256', 'size') and not (v is None and k in ('author', 'observed_at'))} def visit(node): if isinstance(node, list): for x in node: visit(x) elif isinstance(node, dict): # Values in literal DB/source data must not be interpreted as metadata. for k, v in list(node.items()): if k in ('row', 'rows', 'value', 'values', 'text', 'lines'): continue if k in ('provenance', 'origin'): node[k] = provenance(v) else: visit(v) visit(result) if isinstance(result, dict): evidence = result.get('evidence', {}) for entry in result.get('evidence_catalog', []): if isinstance(entry, dict) and entry.get('id') in evidence: # The complete capture/query/provenance is already visible. eid = entry['id'] collector = entry.get('collector') entry.clear() entry.update(id=eid, collector=collector, details_in='evidence') if result != value: result['navigation_projection'] = NOTICE return result