Package-level declarations
Types
Where a command comes from (documentation/designs/08-data-protocols.md §4): correlationId is the id of the root command of the chain, and causationId the direct upstream, such as the event stream (ref@version) a saga reacted to. A command a user sends directly carries none: it is its own root.
An admitted command: who it targets and what it asks, with every fact decided once at admission and read-only afterwards.
What a decide function (or an after hook) can ask of the kernel besides returning its decision.
What a decide function concluded about a command: the events it produces, that it changes nothing, or that it rejects the command. A rejection is a business outcome the caller is told about; it writes nothing unless it carries events, which are appended with it (Rejected.events).
A Wow API that cannot serve a call as the code made it: the code's own mistake, a wrong argument (a read of a state class no aggregate has, a command to a context no peer describes) or a wrong state of use (a command object to a peer that takes named commands alone, a peer the configuration gives no address), never the caller's, nor a peer's or the wire's, which are transport failures. It is a subclass of IllegalArgumentException or IllegalStateException, never the class itself, which a decide function's own require and check throw and the kernel answers as the command's rejection: a decide function that runs into a Misuse fails its command, as an unexpected exception does, and a subscription handler's is unrecoverable, since it fails the same way every time. The kernel's decide scope, the read API and the command clients throw it.
A decide function's refusal thrown instead of returned: the kernel answers it exactly as the Decision.Rejected of rejection, so nothing is appended, a compensation runs as for a returned rejection, and the caller gets the same answer. Kotlin throws one with reject(code, message) (or DecideScope.reject); Java writes throw new RejectedException(Rejection.of("out-of-stock", "Only 2 left.")), and a handler may rethrow one.
Why a command was refused. code is stable and machine-readable (it names an error in the Manifest); message is for people. extensions are the rejection's structured data, by name, each a JSON value (a string, a number, a boolean, a list, a map, or a data class of them), such as the ids and titles of what blocks the command: the command's result carries them (me.ahoo.wow.api.result.ErrorInfo.extensions), and an HTTP answer writes each as an extension member of its problem.
Among which aggregates a reserved key is unique (DecideScope.reserve); always among the aggregates of one type.
Functions
Throws a Misuse.State of message unless value holds: check for a Wow API's own state.
Refuses the command being decided with the rejection code, message and structured extensions: it throws a RejectedException, which the kernel answers as that rejection. message is shown to the caller. Nothing is appended unless the rejection carries events: ordinary events of the aggregate, each sourced by it, appended with the rejection in one stream, and the answer then names the version they reached (an audit of the attempt, a counter of refusals). A rejection of a creation, whose aggregate does not exist, appends nothing. The way a decide function that returns its event type rejects, with or without a DecideScope; require (wow.command.invalid) and check (wow.command.refused) reject a broken precondition alike. It is inline like error(), so the rejecting line is the caller's.
Throws a Misuse.Argument of message unless value holds: require for a Wow API's own arguments.