{"record":{"id":"26191663801f31d2","repo":"affaan-m/ECC","slug":"invalid-supplied-provenance-declaration","errorCode":null,"errorMessage":"Invalid supplied provenance declaration","messagePattern":"Invalid supplied provenance declaration","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/assets.py","lineNumber":235,"sourceCode":"\ndef validate_assets(receipt_path: str | Path) -> dict[str, Any]:\n    \"\"\"Re-hash every bound file and validate receipt semantics; no remote calls.\"\"\"\n    path = _path(receipt_path, Path.cwd())\n    receipt = _load(path)\n    if receipt.get('schema') != SCHEMA:\n        raise ValueError('Unsupported asset receipt schema')\n    if type(receipt.get('provider_calls')) is not int or receipt['provider_calls'] != 0:\n        raise ValueError('Local ingestion must have zero provider calls')\n    if receipt.get('provider_execution') is not False:\n        raise ValueError('Local ingestion cannot claim provider execution')\n    _, requests = (_bundle(receipt['bundle_receipt'], path.parent, True)\n                   if 'bundle_receipt' in receipt else (None, {}))\n    for asset in _assets(receipt.get('assets')):\n        _taste(asset, requests, True)\n        _verify_binding(asset, path.parent, asset['modality'])\n        provenance = _provenance(asset, path.parent, True)\n        if provenance is not None and provenance != asset['provider_provenance']:\n            raise ValueError('Invalid supplied provenance declaration')\n    inputs = receipt.get('input_artifacts')\n    if not isinstance(inputs, list):\n        raise ValueError('input_artifacts must be a list')\n    for artifact in inputs:\n        _verify_binding(artifact, path.parent)\n    if 'genre_spec' in receipt:\n        _verify_binding(receipt['genre_spec'], path.parent)\n    return receipt\n","sourceCodeStart":217,"sourceCodeEnd":244,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/assets.py#L217-L244","documentation":"For assets with origin external_result, _provenance recomputes the provenance record (provider, identifiers, evidence fingerprint) from the local evidence file and compares it to the 'provider_provenance' stored in the receipt. A mismatch means the declared provenance does not match the evidence bound on disk — the claim was altered, the evidence file changed, or the evidence binding is stale.","triggerScenarios":"Calling validate_assets where an external_result asset's provider_provenance dict differs from the recomputed record (edited provider/request_id/workflow_id, replaced or modified evidence file, stale path/bytes/sha256 in the receipt).","commonSituations":"Manual edits to the provenance block; the evidence file was regenerated or moved after ingest; copying receipts between machines where relative evidence paths resolve differently; swapping evidence files with same-name different-content files.","solutions":["Re-run ingest_assets to produce a fresh receipt that re-fingerprints current evidence files.","Diff receipt['provider_provenance'] against the evidence file at the bound path to identify the changed field.","If only the evidence file changed, restore the original bytes or re-ingest with the new evidence.","Do not edit provider/request_id/workflow_id in a receipt; re-ingest with corrected config instead."],"exampleFix":"# before: evidence file replaced after ingest -> validate_assets raises\nvalidate_assets('receipt.json')\n# after: re-bind current evidence into a new receipt\nreceipt = ingest_assets('config.json', 'receipt.v2.json')\nvalidate_assets('receipt.v2.json')","handlingStrategy":"try-catch","validationCode":"# re-fingerprint evidence and compare to receipt before validating\nimport json, hashlib\nev = r['assets'][i]['provider_provenance']['evidence']\nd = hashlib.sha256(open(ev['path'],'rb').read()).hexdigest()\nassert d == ev['sha256'], 'evidence changed; re-ingest'","typeGuard":null,"tryCatchPattern":"try:\n    validate_assets(p)\nexcept ValueError as e:\n    if 'Invalid supplied provenance declaration' in str(e):\n        fresh = ingest_assets(cfg, new_receipt_path())\n    else:\n        raise","preventionTips":["Keep evidence files immutable after ingest (hash-pin them).","Never edit provider/request_id/workflow_id fields in a receipt.","Re-ingest whenever evidence or provenance inputs change.","Use relative, stable paths under the receipt directory for evidence."],"tags":["validation","provenance","integrity","tampering"],"backgroundTag":"checksum-mismatch","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}