Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s
mod/decision->wire emits a versioned pipe-delimited line (MOD1|r1|hide|spam-hide); mod/wire->decision parses it back (mod/wire-valid? guards). split-char built over slice/len (loaded env has no split). Integration test runs the full federated path: serialize → wire → deserialize → fed-receive-decision trust-gating (untrusted→advisory, trusted→applied). +16 tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
56 lines
1.4 KiB
Plaintext
56 lines
1.4 KiB
Plaintext
;; lib/mod/wire.sx — portable decision wire format for federation transport.
|
|
;;
|
|
;; fed.sx shares decisions as in-memory dicts and leaves mod/fed-send! as the
|
|
;; transport seam. This is the bytes that cross it: a versioned, pipe-delimited
|
|
;; line encoding the verdict a peer needs (report id, action, rule) — enough to
|
|
;; trust-gate and apply/advise, without shipping the whole proof tree. The
|
|
;; loaded env has no string split, so split is built over slice/len.
|
|
|
|
(define
|
|
mod/split-loop
|
|
(fn
|
|
(s ch n start pos acc)
|
|
(if
|
|
(= pos n)
|
|
(append acc (list (slice s start n)))
|
|
(if
|
|
(= (slice s pos (+ pos 1)) ch)
|
|
(mod/split-loop
|
|
s
|
|
ch
|
|
n
|
|
(+ pos 1)
|
|
(+ pos 1)
|
|
(append acc (list (slice s start pos))))
|
|
(mod/split-loop s ch n start (+ pos 1) acc)))))
|
|
|
|
(define
|
|
mod/split-char
|
|
(fn (s ch) (mod/split-loop s ch (len s) 0 0 (list))))
|
|
|
|
(define
|
|
mod/decision->wire
|
|
(fn
|
|
(d)
|
|
(str "MOD1|" (get d :report-id) "|" (get d :action) "|" (get d :rule))))
|
|
|
|
(define
|
|
mod/wire-valid?
|
|
(fn
|
|
(w)
|
|
(let
|
|
((parts (mod/split-char w "|")))
|
|
(if
|
|
(= (len parts) 4)
|
|
(= (nth parts 0) "MOD1")
|
|
false))))
|
|
|
|
(define
|
|
mod/wire->decision
|
|
(fn
|
|
(w)
|
|
(if
|
|
(mod/wire-valid? w)
|
|
(let ((parts (mod/split-char w "|"))) {:action (nth parts 2) :wire true :rule (nth parts 3) :report-id (nth parts 1)})
|
|
nil)))
|