Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 56s
Datalog ACL layer (schema/facts/engine/api) over lib/datalog/. Direct grant permits unless explicit deny names same (S,A,R) — deny-overrides via stratified negation. Conformance wrapper + scoreboard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
171 lines
5.6 KiB
Plaintext
171 lines
5.6 KiB
Plaintext
;; lib/acl/tests/direct.sx — Phase 1: direct grants + deny-overrides.
|
|
|
|
(define acl-dt-pass 0)
|
|
(define acl-dt-fail 0)
|
|
(define acl-dt-failures (list))
|
|
|
|
(define
|
|
acl-dt-check!
|
|
(fn
|
|
(name got expected)
|
|
(if
|
|
(= got expected)
|
|
(set! acl-dt-pass (+ acl-dt-pass 1))
|
|
(do
|
|
(set! acl-dt-fail (+ acl-dt-fail 1))
|
|
(append!
|
|
acl-dt-failures
|
|
(str name "\n expected: " expected "\n got: " got))))))
|
|
|
|
;; A small fixture used by most cases: alice can read page1, is denied edit on
|
|
;; page1, and a service may federate peer1.
|
|
(define
|
|
acl-dt-fixture
|
|
(fn
|
|
()
|
|
(acl-build-db
|
|
(list
|
|
(acl-actor (quote alice) (quote user))
|
|
(acl-actor (quote svc1) (quote service))
|
|
(acl-resource-fact (quote page1) (quote page))
|
|
(acl-resource-fact (quote peer1) (quote peer))
|
|
(acl-grant (quote alice) (quote read) (quote page1))
|
|
(acl-grant (quote alice) (quote edit) (quote page1))
|
|
(acl-deny (quote alice) (quote edit) (quote page1))
|
|
(acl-grant (quote svc1) (quote federate) (quote peer1))))))
|
|
|
|
(define
|
|
acl-dt-run-all!
|
|
(fn
|
|
()
|
|
(let
|
|
((db (acl-dt-fixture)))
|
|
(do
|
|
(acl-dt-check!
|
|
"direct grant permits"
|
|
(acl-permit? db (quote alice) (quote read) (quote page1))
|
|
true)
|
|
(acl-dt-check!
|
|
"service grant permits federate"
|
|
(acl-permit? db (quote svc1) (quote federate) (quote peer1))
|
|
true)
|
|
(acl-dt-check!
|
|
"missing action denied"
|
|
(acl-permit? db (quote alice) (quote comment) (quote page1))
|
|
false)
|
|
(acl-dt-check!
|
|
"missing resource denied"
|
|
(acl-permit? db (quote alice) (quote read) (quote page2))
|
|
false)
|
|
(acl-dt-check!
|
|
"missing subject denied"
|
|
(acl-permit? db (quote bob) (quote read) (quote page1))
|
|
false)
|
|
(acl-dt-check!
|
|
"wrong subject for service grant denied"
|
|
(acl-permit? db (quote alice) (quote federate) (quote peer1))
|
|
false)
|
|
(acl-dt-check!
|
|
"grant plus deny -> deny wins"
|
|
(acl-permit? db (quote alice) (quote edit) (quote page1))
|
|
false)
|
|
(acl-dt-check!
|
|
"deny alone still denies"
|
|
(acl-permit?
|
|
(acl-build-db
|
|
(list (acl-deny (quote alice) (quote read) (quote page1))))
|
|
(quote alice)
|
|
(quote read)
|
|
(quote page1))
|
|
false)
|
|
(acl-dt-check!
|
|
"deny on edit does not block read"
|
|
(acl-permit? db (quote alice) (quote read) (quote page1))
|
|
true)
|
|
(acl-dt-check!
|
|
"empty db denies"
|
|
(acl-permit?
|
|
(acl-build-db (list))
|
|
(quote alice)
|
|
(quote read)
|
|
(quote page1))
|
|
false)
|
|
(let
|
|
((db2 (acl-build-db (list (acl-grant (quote a) (quote read) (quote r)) (acl-grant (quote b) (quote read) (quote r)) (acl-deny (quote b) (quote read) (quote r))))))
|
|
(do
|
|
(acl-dt-check!
|
|
"subject a allowed"
|
|
(acl-permit? db2 (quote a) (quote read) (quote r))
|
|
true)
|
|
(acl-dt-check!
|
|
"subject b denied by override"
|
|
(acl-permit? db2 (quote b) (quote read) (quote r))
|
|
false)))
|
|
(let
|
|
((db3 (acl-build-db (list (acl-actor (quote editors) (quote role)) (acl-grant (quote editors) (quote edit) (quote post1))))))
|
|
(acl-dt-check!
|
|
"role subject direct grant"
|
|
(acl-permit? db3 (quote editors) (quote edit) (quote post1))
|
|
true))
|
|
(do
|
|
(acl/load!
|
|
(list
|
|
(acl-grant (quote carol) (quote moderate) (quote thread1))))
|
|
(acl-dt-check!
|
|
"api permit via current db"
|
|
(acl/permit? (quote carol) (quote moderate) (quote thread1))
|
|
true)
|
|
(acl-dt-check!
|
|
"api deny via current db"
|
|
(acl/permit? (quote carol) (quote read) (quote thread1))
|
|
false))
|
|
(do
|
|
(acl/load! (list))
|
|
(acl-dt-check!
|
|
"api reload clears prior grants"
|
|
(acl/permit? (quote carol) (quote moderate) (quote thread1))
|
|
false))
|
|
(acl-dt-check!
|
|
"schema grant arity valid"
|
|
(acl-fact-valid? (acl-grant (quote x) (quote read) (quote y)))
|
|
true)
|
|
(acl-dt-check!
|
|
"schema bad arity invalid"
|
|
(acl-fact-valid? (list (quote grant) (quote x)))
|
|
false)
|
|
(acl-dt-check!
|
|
"schema unknown predicate invalid"
|
|
(acl-fact-valid? (list (quote frobnicate) (quote x)))
|
|
false)
|
|
(acl-dt-check!
|
|
"schema subject kind known"
|
|
(acl-subject-kind? (quote service))
|
|
true)
|
|
(acl-dt-check!
|
|
"schema resource kind unknown"
|
|
(acl-resource-kind? (quote galaxy))
|
|
false)
|
|
(acl-dt-check!
|
|
"schema known action"
|
|
(acl-known-action? (quote moderate))
|
|
true)
|
|
(acl-dt-check!
|
|
"grant constructor shape"
|
|
(acl-grant (quote u) (quote read) (quote p))
|
|
(list (quote grant) (quote u) (quote read) (quote p)))
|
|
(acl-dt-check!
|
|
"actor constructor shape"
|
|
(acl-actor (quote u) (quote user))
|
|
(list (quote actor) (quote u) (quote user)))))))
|
|
|
|
(define
|
|
acl-direct-tests-run!
|
|
(fn
|
|
()
|
|
(do
|
|
(set! acl-dt-pass 0)
|
|
(set! acl-dt-fail 0)
|
|
(set! acl-dt-failures (list))
|
|
(acl-dt-run-all!)
|
|
{:failures acl-dt-failures :total (+ acl-dt-pass acl-dt-fail) :passed acl-dt-pass :failed acl-dt-fail})))
|