;; lib/mod/fed.sx — federation: cross-instance reports, decision sharing, trust, ;; revocation. fed-sx itself is mocked here (an in-memory outbox); the real wire ;; transport would replace mod/fed-send!. ;; ;; Trust is advisory by default (the hard rule): a peer's decision only binds ;; locally when (mod/trusted? peer :mod) holds. An untrusted peer's decision is ;; recorded as a suggestion in the advisory log and is NOT applied. Local ;; decisions propagate outward via the outbox. Revocation undoes a locally ;; applied action when its proof is invalidated, notifying the origin peer. (define mod/*fed-trust* (list)) ;; {:peer :scope} (define mod/*fed-outbox* (list)) ;; {:to :type :payload} (define mod/*fed-advisory* (list)) ;; {:peer :decision} — received, not applied (define mod/*fed-applied* (list)) ;; {:report-id :action :origin :revoked} (define mod/*fed-origins* (list)) ;; {:id :origin} (define mod/fed-reset! (fn () (begin (set! mod/*fed-trust* (list)) (set! mod/*fed-outbox* (list)) (set! mod/*fed-advisory* (list)) (set! mod/*fed-applied* (list)) (set! mod/*fed-origins* (list))))) ;; ── trust model ── (define mod/trust-match? (fn (t peer scope) (if (= (get t :peer) peer) (= (get t :scope) scope) false))) (define mod/grant-trust (fn (peer scope) (begin (append! mod/*fed-trust* {:scope scope :peer peer}) true))) (define mod/revoke-trust (fn (peer scope) (set! mod/*fed-trust* (reduce (fn (acc t) (if (mod/trust-match? t peer scope) acc (append acc (list t)))) (list) mod/*fed-trust*)))) (define mod/trusted? (fn (peer scope) (mod/any? (fn (t) (mod/trust-match? t peer scope)) mod/*fed-trust*))) ;; ── cross-instance reports ── (define mod/fed-receive-report (fn (peer by about reason) (let ((r (mod/report by about reason))) (begin (append! mod/*fed-origins* {:id (mod/report-id r) :origin peer}) r)))) (define mod/report-origin (fn (id) (reduce (fn (acc o) (if (= (get o :id) id) (get o :origin) acc)) "local" mod/*fed-origins*))) ;; ── decision sharing (mock fed-sx send) ── (define mod/fed-send! (fn (to type payload) (begin (append! mod/*fed-outbox* {:type type :to to :payload payload}) true))) (define mod/fed-outbox (fn () mod/*fed-outbox*)) (define mod/fed-share-decision (fn (decision peers) (reduce (fn (acc p) (begin (mod/fed-send! p "decision" decision) (append acc (list p)))) (list) peers))) ;; ── receiving a peer's decision (advisory unless trusted) ── (define mod/fed-applied-action (fn (report-id) (reduce (fn (acc a) (if (= (get a :report-id) report-id) a acc)) nil mod/*fed-applied*))) (define mod/fed-receive-decision (fn (peer decision) (if (mod/trusted? peer :mod) (begin (append! mod/*fed-applied* {:revoked false :action (get decision :action) :report-id (get decision :report-id) :origin peer}) {:advisory false :peer peer :applied true :decision decision}) (begin (append! mod/*fed-advisory* {:peer peer :decision decision}) {:advisory true :peer peer :applied false :decision decision})))) ;; ── revocation ── (define mod/fed-revoke! (fn (report-id reason) (begin (set! mod/*fed-applied* (map (fn (a) (if (= (get a :report-id) report-id) {:revoked true :action (get a :action) :report-id (get a :report-id) :origin (get a :origin)} a)) mod/*fed-applied*)) (mod/fed-send! (mod/report-origin report-id) "revocation" {:report-id report-id :reason reason}) report-id))) ;; re-run the engine; if the action no longer holds, the prior decision's proof ;; is invalidated — revoke the applied moderation. (define mod/fed-revoke-if-invalidated (fn (report decision reports rules) (let ((d2 (mod/decide-report report reports rules))) (if (= (get d2 :action) (get decision :action)) {:revoked false :decision d2} (begin (mod/fed-revoke! (get decision :report-id) "proof invalidated") {:revoked true :decision d2})))))