Module: Axn::Webhooks

Extended by:
Configurable
Defined in:
lib/axn/webhooks.rb,
lib/axn/webhooks/errors.rb,
lib/axn/webhooks/verify.rb,
lib/axn/webhooks/handler.rb,
lib/axn/webhooks/inbound.rb,
lib/axn/webhooks/request.rb,
lib/axn/webhooks/respond.rb,
lib/axn/webhooks/version.rb,
lib/axn/webhooks/dispatch.rb,
lib/axn/webhooks/outbound.rb,
lib/axn/webhooks/response.rb,
lib/axn/webhooks/resolvers.rb,
lib/axn/webhooks/signature.rb,
lib/axn/webhooks/verifiers.rb,
lib/axn/webhooks/inbound/dsl.rb,
lib/axn/webhooks/header_value.rb,
lib/axn/webhooks/outbound/dsl.rb,
lib/axn/webhooks/vendor_facet.rb,
lib/axn/webhooks/outbound/emit.rb,
lib/axn/webhooks/inbound/router.rb,
lib/axn/webhooks/static_respond.rb,
lib/axn/webhooks/verifiers/hmac.rb,
lib/axn/webhooks/inbound/parsers.rb,
lib/axn/webhooks/outbound/config.rb,
lib/axn/webhooks/outbound/signer.rb,
lib/axn/webhooks/inbound/endpoint.rb,
lib/axn/webhooks/outbound/deliver.rb,
lib/axn/webhooks/inbound/challenge.rb,
lib/axn/webhooks/outbound/envelope.rb,
lib/axn/webhooks/outbound/transport.rb,
lib/axn/webhooks/outbound/subscriber.rb,
lib/axn/webhooks/verifiers/basic_auth.rb,
lib/axn/webhooks/inbound/build_request.rb,
lib/axn/webhooks/outbound/target_policy.rb,
lib/axn/webhooks/inbound/respond_context.rb,
lib/axn/webhooks/outbound/callable_arity.rb,
lib/axn/webhooks/inbound/challenge_required.rb,
lib/axn/webhooks/verifiers/standard_webhooks.rb

Defined Under Namespace

Modules: Handler, HeaderValue, Inbound, Outbound, Parsers, Resolvers, Signature, VendorFacet, Verifiers Classes: Dispatch, Error, InvalidTarget, Request, Resolver, Respond, Response, RetryLater, StaticRespond, UnparseableBody, Verify

Constant Summary collapse

VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.deprecatorObject

A dedicated deprecator instance, so a consuming Rails app can register it (Rails.application.deprecators = Axn::Webhooks.deprecator) and govern its behavior (silence in test, raise in CI, etc.).



57
58
59
# File 'lib/axn/webhooks.rb', line 57

def self.deprecator
  @deprecator ||= ActiveSupport::Deprecation.new("1.0", "axn-webhooks")
end

.emit(event, data: {}, to: nil, async: nil) ⇒ Object

Emit an outbound webhook event. Fans out one signed, self-retrying delivery per subscriber. Raises loudly (Axn::Webhooks::Error) on an unknown event.

vendor: is deliberately NOT resolved here: Config#vendor_for raises the same unknown-event error that Emit itself already raises internally (via config.wire_type), but resolving it ahead of call! would raise before axn's executor ever runs -- bypassing on_exception reporting for what should be a loud, REPORTED failure (Codex P2 finding). Emit resolves its own vendor once it's running inside that boundary.

to: and async: are per-call overrides. to: REPLACES the event's declared targets for this call only (never merges) — the event must still be declared, since it supplies the wire type and vendor. async: true requires a configured adapter and raises without one; async: false forces the inline path. Omitted means today's :auto. rubocop:disable-next Naming/MethodParameterName



69
70
71
# File 'lib/axn/webhooks/outbound.rb', line 69

def self.emit(event, data: {}, to: nil, async: nil)
  Outbound::Emit.call!(event:, data:, to:, async:)
end

.inbound(name, &block) ⇒ Object

Declare an inbound webhook endpoint. Evaluated at boot (e.g. a Rails initializer) so registration is deterministic, in or out of Rails.

With one or more nested endpoint blocks, this registers one endpoint per child, named :"#name_#child", and does NOT register name itself — see Inbound::DSL#endpoint.

Raises:

  • (ArgumentError)


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/axn/webhooks/inbound.rb', line 79

def self.inbound(name, &block)
  raise ArgumentError, "Axn::Webhooks.inbound requires a block" unless block

  dsl = Inbound::DSL.new
  dsl.instance_exec(&block)
  children = dsl.__children__
  return Inbound.replace_declaration(name, { name.to_sym => build_endpoint(name, dsl) }) if children.empty?

  # A parent with children is a container, not an endpoint. A top-level `dispatch` is what
  # would make it look like one, and registering both it and the children would leave an extra
  # endpoint nobody mounted, silently — so that combination is a declaration mistake, caught at
  # boot. A parent `respond`/`static_respond` is NOT: it renders nothing on its own, and
  # sharing one renderer across a vendor's endpoints is precisely what nesting is for, so it
  # inherits like every other declaration (Codex review).
  if dsl.__dispatch_declared?
    raise ArgumentError,
          "inbound #{name.inspect} declares `endpoint` blocks AND its own `dispatch` — a parent " \
          "with endpoints registers nothing itself; move the dispatch into an endpoint"
  end

  # Build and validate EVERY child before publishing any: the registry is process-global, so
  # registering as we go left earlier children live when a later one raised — a rescued
  # declaration failure or a reload would mix endpoints from different declarations
  # (Codex review).
  built = children.map { |child, child_block| [:"#{name}_#{child}", build_endpoint(:"#{name}_#{child}", dsl.__child_dsl__(child_block))] }
  Inbound.replace_declaration(name, built.to_h)
end

.outbound(&block) ⇒ Object

Declare outbound emission. Evaluated at boot (e.g. a Rails initializer).

Raises:

  • (ArgumentError)


47
48
49
50
51
52
53
# File 'lib/axn/webhooks/outbound.rb', line 47

def self.outbound(&block)
  raise ArgumentError, "Axn::Webhooks.outbound requires a block" unless block

  dsl = Outbound::DSL.new
  dsl.instance_exec(&block)
  Outbound.install(dsl.__config__)
end

.retry_later!(after: nil) ⇒ Object

Raises:



44
45
46
# File 'lib/axn/webhooks/errors.rb', line 44

def self.retry_later!(after: nil)
  raise RetryLater.new(retry_after: after)
end