Repository navigation
Phase 5: Telnyx and Vonage adapters, provider contract, Noticed - #5
Merged
Merged
Conversation
…iced Add Telnyx (Messaging API v2, Ed25519 webhook signatures with a five-minute tolerance) and Vonage (SMS API, md5hash and HMAC webhook signatures matching the official SDK). Vonage's "number barred" error maps to :unroutable because it also covers blocks other than opt-outs. Ship Smswire::ProviderContract, a Minitest suite covering receipts, status vocabulary, error taxonomy, a pipeline send, and, for declared capabilities, callback parsing and signature rejection. All three adapters pass it with the dummy app's messenger, and the provider generator now writes an adapter and test that pass it as generated. Add Noticed::DeliveryMethods::Smswire, loaded when Noticed is present. It delivers through the messenger with deliver_later and records the Noticed notification and event ids in delivery metadata. Webhook endpoints now share one controller and accept both event kinds, so a provider that posts everything to one URL is routed by event type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L5SuBiSMN4r9qr5CXbKkHV
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements Phase 5 of
docs/SPEC.md. Stacked on #4 (then #3, #2, #1). Merge in order.What's included
messaging_servicemaps tomessaging_profile_id, and media URLs and a per-message webhook URL are passed through. Webhooks are verified with Ed25519 overtimestamp|raw bodyagainst the account public key, rejecting events more than five minutes old. Telnyx's STOP block, 40300, records an opt-out. Carrier throughput codes are retried.md5hashand the HMAC methods, and stale timestamps are rejected. Multipart sends keep the first part's id and total the price.Smswire::ProviderContractis a Minitest module shipped in the gem. It checks receipts, the normalized status vocabulary, permanent error reasons, retryable errors, a full pipeline send, and, for declared capabilities, status and inbound parsing plus rejection of forged signatures.Noticed::DeliveryMethods::Smswireis loaded when Noticed is present.deliver_by :smswirewith a messenger and action sends through the full pipeline usingdeliver_later. Each delivery stores the Noticed notification and event ids in its metadata.Decisions
:unroutable, not:opted_out. It means "number barred," which can include opt-outs but also other blocks, and treating it as an opt-out would write false consent records. The contract gained acontract_reports_opt_outs?hook so an adapter can say this explicitly instead of the suite accepting a guess.deliver_later. Smswire's retries then apply, since Noticed's own delivery jobs don't retry. The delivery-to-notification join uses metadata instead of a callback write-back, so neither gem depends on the other's schema.Verification
OrderMessenger#shipped.🤖 Generated with Claude Code
https://claude.ai/code/session_01L5SuBiSMN4r9qr5CXbKkHV