;; lib/acl/engine.sx — ACL ruleset + decision reducer over lib/datalog/. ;; ;; The engine is a thin layer: it owns the permit ruleset (SX data rules) and ;; reduces a (subject, action, resource) decision to a Datalog query against a ;; db built from EDB facts. The rule engine itself is Datalog's. ;; ;; Phase 1 policy — direct grants with deny-overrides: ;; ;; permit(S, A, R) :- grant(S, A, R), not deny(S, A, R). ;; ;; A grant permits unless an explicit deny names the same (S, A, R). Deny wins: ;; the negated literal {:neg (deny S A R)} stratifies cleanly because deny is an ;; EDB relation (no rule derives it), so the fixpoint is well-defined. (define acl-phase1-rules (quote ((permit S A R <- (grant S A R) {:neg (deny S A R)})))) ;; Build a Datalog db from a list of EDB facts under the Phase 1 ruleset. (define acl-build-db (fn (facts) (dl-program-data facts acl-phase1-rules))) ;; Core decision: does the db permit subject S to perform action A on ;; resource R? Reduces to a ground Datalog query on the derived `permit` ;; relation — non-empty result means permitted. (define acl-permit? (fn (db subj act res) (> (len (dl-query db (list (quote permit) subj act res))) 0)))