Package-level declarations

Types

Link copied to clipboard
sealed class AccessAttribute<in S : Any, V : Any>

A reference to an access attribute of the aggregate whose state is S: a Single value or Multiple ones of type, under its published name. The state declares its attributes with @Access, and the compiler generates a reference to each in <State>Access (AccessAttributes); OWNER and SPACE are the built-in ones every aggregate has, its scope's, so they are references of every state (S is in: a reference of Any is one of each state). An access policy of a state takes the references of that state alone, which the compiler checks.

Link copied to clipboard
abstract class AccessAttributes<S : Any>

What the generated <State>Access of the state S extends: the built-in attributes beside the state's own, which it names in upper snake case after their names, as the query fields are named (DocumentStateAccess.SHARED_WITH is sharedWith).

Link copied to clipboard

How a AccessPredicate.Comparison compares an attribute's value with the caller's: EQUAL, IN, STARTS_WITH and IS_NULL a single attribute's value, CONTAINS, CONTAINS_ANY and IS_EMPTY a multiple one's.

Link copied to clipboard
class AccessPolicy<S : Any> @InternalWowApi constructor(val stateType: Class<S>, val aggregate: AggregateType?, read: AccessScope<S>.(Caller) -> AccessPredicate, write: AccessScope<S>.(Caller) -> AccessPredicate)

Who may read and who may change the aggregates whose state is S: for a caller, a predicate over their access attributes (AccessPredicate) to read them and one to write them. A service declares one per aggregate whose state declares access attributes (@Access), as a bean; aggregate names the aggregate when several share the state type, null otherwise. Build one with accessPolicy.

Link copied to clipboard

Builds an AccessPolicy. Nothing is granted by omission: a policy gives what may be read and what may be changed, read and write, or readWrite for both at once; one without a write predicate is refused, and write { denyAll() } makes a read-only aggregate explicit.

Link copied to clipboard
sealed interface AccessPredicate

What an access policy decides for one caller (AccessPolicy): a predicate over an aggregate's access attributes, the caller's claims already in it. The query side compiles it to a filter its storage applies; the kernel and the test DSL evaluate it on an aggregate's attribute values (allows). Both read it alike:

Link copied to clipboard
class AccessScope<S : Any>

What an access policy's predicates are written with, for the aggregates whose state is S: comparisons of their access attributes (<State>Access, typed by S) with the caller's claims, and logic. A comparison with a claim the caller does not hold, a null or no values, denies (AccessPredicate.Unknown), as does one of a value the aggregate does not have.

Link copied to clipboard

The default rule: who reads and changes an aggregate that no access policy of its own governs (AccessPolicy). A caller acting in a scope reads and changes the aggregates whose owner is the scope's owner and whose space is its space, each part compared only when the scope names it: a caller with neither, of its tenant or acting across scopes without naming one, reads and changes every aggregate of its tenant. The aggregate's ownership narrows the scope first (me.ahoo.wow.api.aggregate.Ownership.scopeOf): no owner is compared for an aggregate of its tenant.

Functions

Link copied to clipboard
inline fun <reified S : Any> accessPolicy(aggregate: AggregateType? = null, noinline block: AccessPolicyBuilder<S>.() -> Unit): AccessPolicy<S>

The access policy of the aggregates whose state is S, from block: it gives AccessPolicyBuilder.read and AccessPolicyBuilder.write, or AccessPolicyBuilder.readWrite for one predicate of both. aggregate names the aggregate when several share the state type.

fun <S : Any> accessPolicy(stateType: Class<S>, aggregate: AggregateType? = null, block: AccessPolicyBuilder<S>.() -> Unit): AccessPolicy<S>

The access policy of the aggregates whose state is stateType, as the reified accessPolicy builds it.

Link copied to clipboard
fun resolveAccessPolicies(policies: List<AccessPolicy<*>>, hosted: Set<AggregateType>, aggregatesOf: (Class<*>) -> List<AggregateType>, declaring: Map<AggregateType, List<String>>, strict: Boolean = true): Map<AggregateType, AccessPolicy<*>>

The aggregate each of policies governs, as a node resolves them once, for its reads and its commands alike: the one it names, else the one of aggregatesOf its state type among the node's aggregates (hosted). It refuses, naming the policy or the aggregate: