Delivery acks the external-actions handler-execution topology and ships POST /api/external-actions/execute
What
Ack on 2026-05-22-platform-external-actions-handler-execution-topology and the external-actions queue contract v1.2.0. No issues with the design. The HTTP-callback direction is the right call: a per-domain runner would fragment the single-runner guarantee and vendoring handler code into Platform's runner would couple Platform to every provider SDK.
Delivery's POST /api/external-actions/execute endpoint is live. The implementation covers:
lib/external-actions/verify-execute-request.ts provides verifyExecuteRequest, which reads the raw body, computes HMAC-SHA256 against EXTERNAL_ACTIONS_EXECUTE_SECRET_DELIVERY, and constant-time compares the result to the X-External-Actions-Signature header (accepted with or without the sha256= prefix, mirroring the dispatcher inbox convention). It also exports buildHandlerContext, which maps the runner's snake_case wire format to the SDK's HandlerContext type.
modules/external-actions-execute/routes/execute.routes.ts is the POST handler. It verifies the signature (401 on mismatch, 503 if the secret is unconfigured), looks up the registered handler via getExternalActionHandler(provider, action_kind), and returns terminal_failure if no handler is found so the runner dead-letters rather than retrying. It calls handler.execute(payload, context) and returns the HandlerResult as JSON with HTTP 200. A handler that throws unexpectedly returns terminal_failure rather than a 500, so the runner does not burn retry budget on a likely bug.
app/api/external-actions/execute/route.ts is the Next.js adapter.
The survey module import at the top of the route file (import "@/modules/survey") runs registerExternalActionHandler(quoSmsSendHandler) as a side effect at boot, so the SMS send handler is live before the first runner call arrives.
What remains
Platform needs EXTERNAL_ACTIONS_EXECUTE_URL_DELIVERY and EXTERNAL_ACTIONS_EXECUTE_SECRET_DELIVERY wired in its runner config for Delivery's endpoint to receive live callbacks. Once those env vars are set, the NPS V1 survey send is end-to-end.