RFC-012: Artifact Lifecycle Protocol (ALP) — 6. Provenance Chain
AIGP Specification › RFC-012: Artifact Lifecycle Protocol (ALP) › 6. Provenance Chain
← 5. Protocol Messages · Section index · 7. Approval Rules →
6. Provenance Chain
Every artifact MUST maintain a complete provenance chain from context sources through execution outcome. The provenance chain is the audit trail that answers: who asked for this, what informed it, who approved it, and what happened when it ran?
6.1 Provenance Record
{ "provenance_id": "prov-art-20260504-001", "artifact_id": "art-20260504-001", "chain": [ { "step": 1, "type": "CONTEXT_ASSEMBLY", "timestamp": "2026-05-04T09:55:00Z", "acp_context_id": "ctx-1714800000000", "sources": [ {"provider": "analytics-service", "context_type": "conversion_state", "fields_fetched": 8}, {"provider": "governance-server", "context_type": "governance_posture", "fields_fetched": 5}, {"provider": "identity-service", "context_type": "user_entitlements", "fields_fetched": 6} ] }, { "step": 2, "type": "AI_INVOCATION", "timestamp": "2026-05-04T09:56:00Z", "aigp_request_id": "req-1714800000000", "model_id": "us.anthropic.claude-opus-4-7", "use_case": "artifact_generation", "input_tokens": 4200, "output_tokens": 1800 }, { "step": 3, "type": "ARTIFACT_CREATED", "timestamp": "2026-05-04T10:00:00Z", "artifact_id": "art-20260504-001", "content_hash": "sha256:a1b2c3d4e5f6...", "agent_id": "agent-remediation-v1" }, { "step": 4, "type": "APPROVAL", "timestamp": "2026-05-04T10:30:00Z", "approver": "owner@ai-governance-protocol.org", "approver_type": "HUMAN", "reviewed_hash": "sha256:a1b2c3d4e5f6..." }, { "step": 5, "type": "EXECUTION", "timestamp": "2026-05-04T11:00:00Z", "run_id": "run-20260504-001", "environment": "dev", "exit_code": 0, "duration_ms": 150000 }, { "step": 6, "type": "OUTCOME", "timestamp": "2026-05-04T11:02:30Z", "state": "COMPLETED", "output_summary": "12 policies remediated successfully", "final_hash": "sha256:c3d4e5f6g7h8..." } ]}6.2 Provenance Integrity
The provenance chain MUST be hash-linked. Each step’s hash includes the previous step’s hash, forming an immutable chain:
import hashlibimport json
def compute_step_hash(step: dict, previous_hash: str) -> str: """Compute hash for a provenance step, chaining to previous.""" step_bytes = json.dumps(step, sort_keys=True).encode() combined = f"{previous_hash}\n{step_bytes.hex()}" return f"sha256:{hashlib.sha256(combined.encode()).hexdigest()}"If any step in the chain is modified, all subsequent hashes become invalid, and the provenance chain fails verification.
6.3 Provenance Verification
def verify_provenance_chain(provenance: dict) -> tuple[bool, str]: """Verify the integrity of a provenance chain.""" previous_hash = "sha256:0000000000000000000000000000000000000000000000000000000000000000" for step in provenance["chain"]: expected_hash = compute_step_hash(step, previous_hash) if step.get("step_hash") != expected_hash: return False, f"Chain broken at step {step['step']}: expected {expected_hash}, got {step.get('step_hash')}" previous_hash = expected_hash return True, "Provenance chain verified"← 5. Protocol Messages · Section index · 7. Approval Rules →