Access Control and Data Validation for Clojure(Script) written in Clojure Spec.
A covenant, is a solemn promise to engage in or refrain from a specified action. - Wikipedia

Covenant is developed and maintained by Degree9
Covenant is divided into a few namespaces:
covenant.coreICovenant protocol and public api.covenant.schematype/value based data comparison on top of clojure.spec.covenant.aclprovides covenants around Access Control List's (ACL).covenant.rbacprovides covenants around Role Based Access Control (RBAC).covenant.abacprovides covenants around Attribute Based Access Control (ABAC).
Covenant exposes a protocol that closely matches cljs native spec.
(defprotocol ICovenant
"Provides an abstraction for validating data using clojure.spec based on a covenant."
(assert [covenant data] "See clojure.spec/assert.")
(conform [covenant data] "See clojure.spec/conform.")
(explain [covenant data] "See clojure.spec/explain.")
(problems [covenant data] "See clojure.spec/explain-data.")
(validate [covenant data] "See clojure.spec/valid?.")
(spec [covenant] "Returns related spec for `covenant`."))The spec function will return a spec based on the passed data.
A simple example is that (covenant.core/spec nil) will return
:covenant.core/nil which is preregistered with spec as
(clojure.spec.alpha/def :covenant.core/nil nil?).
Scalar primitives simply return a spec/predicate based on their data type while collections also compare their contents.
covenant.rbac provides validation fns that are "loose" for collections.
If some values in the passed collection (deep) matches the passed covenant then
covenant.core/validate returns true after covenant.rbac has been required.
(require 'covenant.rbac)
(covenant.core/validate {:roles [:admin :editor]} {:roles [:admin]}) ; true
(covenant.core/validate {:roles [:admin :editor]} {:roles [:admin :editor]}) ; true
(covenant.core/validate {:roles [:admin :editor]} {:roles [:editor]}) ; true
(covenant.core/validate {:roles [:admin :editor]} {:roles []}) ; false
(covenant.core/validate {:roles [:admin :editor]} {:roles [:foo]}) ; false(:require covenant.core :as covenant)
For more examples check out the test suite.
A vanilla spec + scalar primitive will pass covenant/explain.
(covenant/explain :covenant.core/number 1)
; =>
;Success!

Support this and other open-source projects on Patreon!