July 22, 2026
4.15.1
(fix): Fix ConsoleLogger dropping DEBUG-level log messages. The ConsoleHandler used by the
default logger keeps java.util.logging’s default INFO handler level, so FINE records
(SDK debug logs, including HTTP request/response logging) were silently discarded even
when LogConfig was configured with LogLevel.DEBUG and silent(false). The handler
level is now set to ALL so the configured LogLevel controls filtering.
4.15.0
(feat): Add webhook body-hash binding support. When a webhook’s HMAC signature verification
declares a bodyHashBinding in the IR, the generated verifySignature helper now
recomputes the encoded hash of the raw request body using the binding’s own
algorithm/encoding, extracts the configured query parameter from the notification URL,
and timing-safe-compares them (failing closed) before performing the existing HMAC
verification over the verbatim notification URL. A stdlib-only WebhookBodyHash core
utility (unkeyed digest plus read-only query-parameter extraction) is emitted alongside
the existing signature utility. Output is unchanged when no binding is present.
(feat): Add webhook signature verification support. When a webhook declares HMAC signature
verification in the IR, the generated SDK now emits a WebhooksHelper with a static
verifySignature method and a stdlib-only core utility for HMAC computation and
constant-time comparison.
(feat): Extend the generated verifySignature webhook helper with Twilio-compatible
verification, mirroring the TypeScript reference:
- Multi-value form params: when
payloadFormat.bodySortis set, aMap<String, ?>overload accepts POST body parameters whose values are aStringor aCollection<String>; keys are sorted, each key’s values are deduped and sorted, andkey + valuepairs are concatenated with no separator before signing. - Runtime body-hash branch: when a
bodyHashBindingis configured, the configured query parameter is read from the notification URL at runtime. When present (JSON) the raw body is hashed and constant-time compared and the signature is checked over the URL only; when absent (classic form) the signature is checked over the URL + params with no body-hash check. - No-throw: the verifier is a pure boolean. Every throw on the verification path (null
or empty inputs, a missing/malformed timestamp) now returns
false. - URL any-match normalization: when
notificationUrlNormalizationis configured, the signature is verified against several normalized notification-URL candidates (standard-port/no-port variants and legacy query re-encoding), accepting on the first constant-time match. A stdlib-onlynotificationUrlCandidatesmethod is added to theWebhookSignaturecore utility. Output is unchanged for webhooks that do not configure these fields, other than the no-throw behavior which applies to all generated helpers.