(in-package #:nekod.socket) ;;; Deterministic receipts for every socket operation through the pipeline (defstruct receipt (timestamp 0 :type integer) (socket-path-hash "" :type string) (request-method "" :type string) (request-path "" :type string) (request-hash "" :type string) (response-status 0 :type integer) (response-hash "" :type string) (event-class nil :type list) (router-input-hash "" :type string) (selected-experts nil :type list) (expert-weights nil :type list) (policy-decision "" :type string)) (defun sxhash-string (str) "Deterministic hash of string for receipt." (format nil "~16,'0x" (sxhash str))) (defun hash-octets (octets) "Deterministic hash of octet vector for receipt." (format nil "~16,'0x" (sxhash (coerce octets 'list)))) (defun make-operation-receipt (&key method path request-body response-status response-body socket-path event-classes feature-vector experts weights policy) "Create a receipt for a complete pipeline operation." (make-receipt :timestamp (get-universal-time) :socket-path-hash (sxhash-string (or socket-path "")) :request-method (or method "") :request-path (or path "") :request-hash (sxhash-string (or request-body "")) :response-status (or response-status 0) :response-hash (if response-body (if (stringp response-body) (sxhash-string response-body) (hash-octets response-body)) "") :event-class (or event-classes nil) :router-input-hash (if feature-vector (sxhash-string (format nil "~a" (coerce feature-vector 'list))) "") :selected-experts (or experts nil) :expert-weights (or weights nil) :policy-decision (or policy "ALLOW"))) (defun receipt-to-alist (r) "Convert receipt to alist for serialization." (list (cons :timestamp (receipt-timestamp r)) (cons :socket-path-hash (receipt-socket-path-hash r)) (cons :request-method (receipt-request-method r)) (cons :request-path (receipt-request-path r)) (cons :request-hash (receipt-request-hash r)) (cons :response-status (receipt-response-status r)) (cons :response-hash (receipt-response-hash r)) (cons :event-class (receipt-event-class r)) (cons :router-input-hash (receipt-router-input-hash r)) (cons :selected-experts (receipt-selected-experts r)) (cons :expert-weights (receipt-expert-weights r)) (cons :policy-decision (receipt-policy-decision r))))