You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Integrate the route approved in #48 behind a backend boundary with a shared operation record, verified provider events, idempotent updates, and reconciled wallet delivery.
session_expired is a session state. It is not an automatic terminal outcome for a payment that may already have been submitted. A widget or session expiry can still be followed by a late webhook that completes, fails, or refunds the operation.
Exact transition names may map to the selected provider's events, but the separation above is required.
Transition table to implement
Situation
Required behavior
Late webhook after browser return
Update from the verified event; browser return alone never sets completed
Replayed webhook or duplicate event
Idempotent against Sendly operation ID and provider ID; no second operation; no flip from a terminal failure into completed without an explicit verified refund or reopen rule from #48
Return or refresh after completed
Show the stored terminal outcome; do not create a new session for the same idempotency key
session_expired with no submit evidence
Stay non-terminal or mark session expired; wait for timeout policy from #48 before failing
session_expired after submitted
Keep settlement path open until definitive provider status arrives or an approved timeout fails the operation
Required funding path (M5)
Sendly UI
-> backend creates funding session for the authenticated user
-> approved hosted or widget flow from #48
-> browser return (UI only)
-> verified provider final-status event
-> backend verifies authenticity and updates operation
-> reconcile destination wallet delivery
-> terminal outcome
Provider secrets stay backend-only.
Binding and idempotency rules
Bind the destination wallet address to the authenticated user before session creation.
Closing the browser tab must not mark the operation completed.
A replayed event must not create a second operation or flip a terminal failure into success.
Redirect or widget callback is not proof of settlement by itself.
Parent: M5: Embedded USDC Funding Pilot release gate
Outcome
Integrate the route approved in #48 behind a backend boundary with a shared operation record, verified provider events, idempotent updates, and reconciled wallet delivery.
Gate from #48
Do not start implementation until #48 records a go with:
Circle Onramp Kit is the primary candidate, but the adapter is for the approved route only.
Shared operation record
Define one Sendly funding operation that stores at least:
Separate current status from terminal outcomes. Do not list
pendingas a terminal status.Status core
session_expiredis a session state. It is not an automatic terminal outcome for a payment that may already have been submitted. A widget or session expiry can still be followed by a late webhook that completes, fails, or refunds the operation.Exact transition names may map to the selected provider's events, but the separation above is required.
Transition table to implement
completedcompletedwithout an explicit verified refund or reopen rule from #48completedsession_expiredwith no submit evidencesession_expiredaftersubmittedRequired funding path (M5)
Provider secrets stay backend-only.
Binding and idempotency rules
Acceptance criteria
session_expiredis not treated as automatic payment failure after submit.