Single source of truth for non-budget policy checks.
Composes Raxol.Payments.SpendingPolicy.domain_approved?/2 and
requires_confirmation?/2 into one decision used by every payment
entry point. Budget caps (per-request, session window, lifetime) stay
in Raxol.Payments.Ledger so spend recording remains atomic.
Trust model
domainMUST be the host the agent declared intent toward -- for HTTP flows that is the request URL host, not anything supplied by the server (challenge body, response headers).amountis the server-claimed amount from the protocol challenge, so the per-request cap and confirmation threshold are evaluated against the server's claim.
Confirmation gate
When the amount exceeds policy.require_confirmation_above, the gate
consults the caller-supplied :on_confirm callback. With no callback
the gate denies, which is the safe default for non-interactive paths
(e.g. HTTP 402 auto-pay). Callers that can surface a prompt synchronously
-- agent Command hooks, interactive shells -- can pass a 2-arity
function returning :approve or :deny.
Summary
Functions
Evaluate the non-budget policy gates for a payment attempt.
Types
@type decision() :: :ok | {:deny, deny_reason()}
@type opts() :: [{:on_confirm, confirm_fn() | nil}]
Functions
@spec evaluate(Raxol.Payments.SpendingPolicy.t(), Decimal.t(), String.t(), opts()) :: decision()
Evaluate the non-budget policy gates for a payment attempt.
Returns :ok if the payment may proceed, or {:deny, reason} if the
domain is not approved or the amount requires confirmation that was
not granted.