File size: 2,617 Bytes
1d3f990 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | % Rules: Provenance and Receipt Chain Validation
% Ensures complete traceability of all operations
:- module(provenance, [
receipt_chain_valid/1,
receipt_chain_head/1,
trace_receipt_lineage/2,
receipt_sequence_valid/1,
lineage_complete/1
]).
:- use_module(receipts).
:- use_module(agents).
% receipt_chain_valid(IsValid)
% The entire receipt chain is valid if:
% - All receipts are cryptographically valid
% - The chain is unbroken (each receipt links to its predecessor)
% - Sequence numbers are monotonic
% - All agents are authorized
receipt_chain_valid(true) :-
receipt_chain_head(HeadID),
receipt_issued(HeadID, _SeqNum, _Agent, _Cap, _Instr, _Action, _InHash, _OutHash, _TS),
receipt_sequence_valid(HeadID),
lineage_complete(HeadID).
receipt_chain_valid(false).
% receipt_sequence_valid(ReceiptID)
% Verify monotonic sequence numbers starting from this receipt and walking backwards
receipt_sequence_valid(ReceiptID) :-
receipt_issued(ReceiptID, SeqNum, _, _, _, _, _, _, _),
(SeqNum = 0 -> true ; trace_receipt_lineage(ReceiptID, PrevID), receipt_issued(PrevID, PrevSeq, _, _, _, _, _, _, _), PrevSeq < SeqNum),
(previous_receipt(ReceiptID, _) -> receipt_sequence_valid(previous_receipt_id(ReceiptID)) ; true).
% Simplified: For Prolog query, just verify head is valid
receipt_sequence_valid(ReceiptID) :-
receipt_issued(ReceiptID, _SeqNum, Agent, CapID, _Instr, _Action, _InHash, _OutHash, _TS),
agent_active(Agent, true),
capability_valid(CapID, true).
% trace_receipt_lineage(ReceiptID, PreviousReceiptID)
% Walk backwards through receipt chain to establish provenance
trace_receipt_lineage(ReceiptID, PrevID) :-
previous_receipt(ReceiptID, PrevID).
trace_receipt_lineage(ReceiptID, AncestorID) :-
previous_receipt(ReceiptID, PrevID),
trace_receipt_lineage(PrevID, AncestorID).
% lineage_complete(ReceiptID)
% Verify that the receipt chain is complete: either at sequence 0 or has valid predecessor
lineage_complete(ReceiptID) :-
receipt_issued(ReceiptID, 0, _, _, _, _, _, _, _).
lineage_complete(ReceiptID) :-
receipt_issued(ReceiptID, SeqNum, _, _, _, _, _, _, _),
SeqNum > 0,
previous_receipt(ReceiptID, PrevID),
receipt_valid(PrevID, true),
lineage_complete(PrevID).
% Agent authorization carries through the chain
receipt_agent_authorized(ReceiptID) :-
receipt_issued(ReceiptID, _Seq, Agent, CapID, _Instr, _Action, _InHash, _OutHash, _TS),
agent_active(Agent, true),
capability_valid(CapID, true).
|