Skip to content

Add generic SMS executor for flow-based SMS sending#2128

Merged
ThaminduDilshan merged 1 commit intoasgardeo:mainfrom
Dilusha-Madushan:feature/generic-sms-executor
Apr 6, 2026
Merged

Add generic SMS executor for flow-based SMS sending#2128
ThaminduDilshan merged 1 commit intoasgardeo:mainfrom
Dilusha-Madushan:feature/generic-sms-executor

Conversation

@Dilusha-Madushan
Copy link
Copy Markdown
Contributor

@Dilusha-Madushan Dilusha-Madushan commented Apr 2, 2026

Purpose

Adds a new generic SMSExecutor utility executor that enables flow designers to send arbitrary SMS messages at any point within a flow. This is distinct from the existing SMSOTPAuthExecutor, which is tightly coupled to OTP-based authentication. The new executor enables use cases such as sending a welcome SMS after registration, delivery notifications, or any other flow-triggered SMS communication.

Approach

SMSSenderService — a new service layer (SMSSenderServiceInterface / smsSenderService) introduced in the notification package. It abstracts SMS delivery by looking up the configured sender by ID, resolving the appropriate message client (Twilio, Vonage, custom webhook, etc.), and dispatching the message. This service is wired through notification.Initialize and injected into the executor at startup.

SMSExecutor — a new utility-type flow executor registered as SMSExecutor. It operates in send mode and reads two required properties from the node configuration:

senderId — the notification sender to use
messageBody — the SMS content to deliver
The recipient (mobileNumber) is resolved from UserInputs first, falling back to RuntimeData, allowing flexibility in where the phone number is collected within the flow. If no SMS sender service is configured, the executor completes gracefully as a no-op (smsSent=false) rather than failing the flow.

Error handling follows the existing executor pattern:

Client errors (invalid sender, bad recipient) → ExecFailure with a failure reason, allowing the flow to handle it gracefully
Server errors → propagated as a Go error to halt the flow

Related Issues

Summary by CodeRabbit

  • New Features
    • SMS messaging added to the notification system; workflows can send SMS using a configurable sender ID and default message. Execution responses include an smsSent flag and clear failure reasons when recipient or configuration is missing.
  • Tests
    • Added unit tests and autogenerated mocks covering the SMS sender service and the workflow SMS executor across success and failure scenarios.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds SMS sending support: new SMSSenderServiceInterface and implementation, a new SMS flow executor and tests, new constants and mocks, and wiring to propagate the SMS sender through notification and executor initialization.

Changes

Cohort / File(s) Summary
Service manager & notification init
backend/cmd/server/servicemanager.go, backend/internal/notification/init.go, backend/internal/notification/init_test.go
notification.Initialize now returns an SMSSenderServiceInterface; call sites updated to capture and forward smsSenderService into executor.Initialize. Tests updated for new return arity.
Notification SMS sender
backend/internal/notification/sms_sender_service.go, backend/internal/notification/sms_sender_service_test.go
New SMSSenderServiceInterface and smsSenderService implementation that looks up senders, validates type, obtains message client, invokes SendSMS, and maps errors. Unit tests cover success and error paths.
Flow executor: SMS
backend/internal/flow/executor/sms_executor.go, backend/internal/flow/executor/sms_executor_test.go
New SMSExecutor registered as SMSExecutor that resolves recipient and senderId, calls SMSSenderService.SendSMS, maps client vs server errors appropriately, and sets DataSMSSent in responses. Extensive tests added.
Executor registry & constants
backend/internal/flow/executor/init.go, backend/internal/flow/executor/constants.go
executor.Initialize signature extended to accept smsSenderService; registers ExecutorNameSMSExecutor. Added propertyKeySMSSenderID, ExecutorNameSMSExecutor, and a default SMS message constant.
Flow constants & mocks
backend/internal/flow/common/constants.go, backend/internal/notification/SMSSenderServiceInterface_mock_test.go
Added DataSMSSent = "smsSent" flow key. Added generated mock SMSSenderServiceInterfaceMock for tests.

Sequence Diagram(s)

sequenceDiagram
    participant SM as ServiceManager
    participant NI as Notification.Init
    participant SS as SMSSenderService
    participant EI as Executor.Init

    SM->>NI: Initialize(mux, jwtService)
    NI->>SS: newSMSSenderService(senderMgtService)
    NI-->>SM: (notificationMgr, otpService, smsSenderService, exporter, err)
    SM->>EI: Initialize(..., smsSenderService, ...)
    EI->>EI: Register SMSExecutor via newSMSExecutor(flowFactory, smsSenderService)
    EI-->>SM: initialized
Loading
sequenceDiagram
    participant Flow as FlowExecutor
    participant SMSEx as SMSExecutor
    participant Mgr as SenderManager
    participant Prov as MessageClientProvider
    participant Client as MessageClient

    Flow->>SMSEx: Execute(ctx, mode=send)
    alt missing recipient
        SMSEx-->>Flow: ExecFailure (recipient required)
    else recipient present
        SMSEx->>Mgr: GetSender(senderID)
        alt sender not found or wrong type
            SMSEx-->>Flow: ExecFailure / Error
        else sender valid
            SMSEx->>Prov: GetMessageClient(sender)
            alt provider error
                SMSEx-->>Flow: Error
            else client acquired
                SMSEx->>Client: SendSMS({To, Body})
                alt client returns client-error
                    SMSEx-->>Flow: ExecFailure (service error message)
                else server/network error
                    SMSEx-->>Flow: Error ("SMS send failed")
                else success
                    SMSEx-->>Flow: ExecComplete (smsSent=true)
                end
            end
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

Type/Improvement

Suggested reviewers

  • ThaminduDilshan
  • darshanasbg
  • senthalan
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: introducing a generic SMS executor for flow-based SMS sending, which is the primary focus of this PR.
Description check ✅ Passed The PR description covers Purpose, Approach with detailed explanations of SMSSenderService and SMSExecutor design, error handling strategy, and Related Issues. Most template sections are addressed; Checklist items are incomplete but secondary.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 2, 2026

Codecov Report

❌ Patch coverage is 91.61290% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.84%. Comparing base (bd21cd3) to head (4699cbd).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...end/internal/notification/message/twilio_client.go 73.33% 4 Missing ⚠️
...end/internal/notification/message/vonage_client.go 73.33% 4 Missing ⚠️
backend/internal/flow/executor/sms_executor.go 97.18% 1 Missing and 1 partial ⚠️
...end/internal/notification/message/custom_client.go 87.50% 2 Missing ⚠️
backend/internal/notification/init.go 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2128      +/-   ##
==========================================
- Coverage   89.85%   89.84%   -0.01%     
==========================================
  Files         898      900       +2     
  Lines       58937    59050     +113     
==========================================
+ Hits        52955    53055     +100     
- Misses       4416     4428      +12     
- Partials     1566     1567       +1     
Flag Coverage Δ
backend-integration-postgres 53.83% <27.09%> (-0.09%) ⬇️
backend-integration-sqlite 53.79% <27.09%> (-0.09%) ⬇️
backend-unit 84.61% <87.74%> (+<0.01%) ⬆️
frontend-apps-console-unit 90.40% <ø> (-0.01%) ⬇️
frontend-apps-gate-unit 97.48% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
backend/internal/notification/sms_sender_service.go (1)

64-66: Consider preserving the original error for observability.

When client.SendSMS fails, the original error is discarded. While returning a generic ErrorInternalServerError is appropriate for client-facing responses, the underlying error details are lost for debugging and observability.

Consider logging the error before returning, or wrapping it for internal observability:

🔧 Optional improvement to preserve error context
-	if err := client.SendSMS(common.SMSData{To: recipient, Body: body}); err != nil {
-		return &ErrorInternalServerError
-	}
+	if err := client.SendSMS(common.SMSData{To: recipient, Body: body}); err != nil {
+		log.GetLogger().Error("Failed to send SMS", log.Error(err), log.String("recipient", recipient))
+		return &ErrorInternalServerError
+	}

Note: Per repository conventions, server errors are typically logged at the handler layer. However, since the executor may not have visibility into this specific failure detail, adding a debug/error log here could aid troubleshooting.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/internal/notification/sms_sender_service.go` around lines 64 - 66,
The call to client.SendSMS discards the original error and returns
ErrorInternalServerError, losing observability; update the failure path in
sms_sender_service.go (the block that calls client.SendSMS with
common.SMSData{To: recipient, Body: body}) to preserve the underlying error by
either logging it with the service/component logger at error/debug level or
wrapping it (e.g., fmt.Errorf("send sms: %w", err)) before returning the
external ErrorInternalServerError, ensuring the original err from client.SendSMS
is not lost.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/cmd/server/servicemanager.go`:
- Around line 204-206: Add user-facing documentation for the new SMSExecutor
flow executor: create or update a guide under docs/content/guides/ describing
SMSExecutor and its purpose, list required node configuration properties
senderId and messageBody with examples of expected formats, explain how
mobileNumber is resolved (check UserInputs first, then RuntimeData fallback),
and document failure semantics (no-op when SMS service is not configured and
return ExecFailure on client errors). Reference the executor by name
(SMSExecutor) and note that it is registered via
execRegistry/executor.Initialize so flow authors can add it to their node
configurations. Ensure the doc clearly states configuration keys and runtime
behavior for flow authors.

In `@backend/internal/flow/executor/sms_executor.go`:
- Around line 39-57: Add documentation for the new SMSExecutor utility flow node
introduced by newSMSExecutor/ExecutorNameSMSExecutor: describe required node
properties senderId and messageBody, explain the mobileNumber lookup order
(UserInputs first, then RuntimeData using userAttributeMobileNumber), and
document runtime behavior including the smsSent output and the no-op behavior
when smsSenderService is nil (no SMS provider configured). Update the
flow-executor guide under docs/content/guides/ (or add a dedicated page) to
include usage examples, expected node schema, and the failure/no-op semantics so
this user-facing change is fully documented before merging.
- Around line 21-29: The SMS executor currently treats many notification
failures as server errors and returns a generic message; update the failure
handling in sms_executor.go (within the SMSExecutor Execute/send path) to
classify by ServiceError.Type: if the error is a client-side notification error
(i.e., ServiceError.Type indicates a client error as defined in the notification
package / MNS-* range), treat it as a client failure and return the original
user-friendly ServiceError.Reason (preserve the client reason) instead of the
generic server message; adjust the same logic in the other failure branches
mentioned (the blocks around the current checks that only match specific MNS-*
values) so all notification-defined client errors (up to MNS-1015 and similar)
are detected via ServiceError.Type and handled as client errors.

---

Nitpick comments:
In `@backend/internal/notification/sms_sender_service.go`:
- Around line 64-66: The call to client.SendSMS discards the original error and
returns ErrorInternalServerError, losing observability; update the failure path
in sms_sender_service.go (the block that calls client.SendSMS with
common.SMSData{To: recipient, Body: body}) to preserve the underlying error by
either logging it with the service/component logger at error/debug level or
wrapping it (e.g., fmt.Errorf("send sms: %w", err)) before returning the
external ErrorInternalServerError, ensuring the original err from client.SendSMS
is not lost.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0e524f2f-972b-4f08-bc7c-9db6176f2fbd

📥 Commits

Reviewing files that changed from the base of the PR and between 477e8d4 and 801c02b.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/notification/notificationmock/SMSSenderServiceInterface_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (11)
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/init.go
  • backend/internal/flow/executor/sms_executor.go
  • backend/internal/flow/executor/sms_executor_test.go
  • backend/internal/notification/SMSSenderServiceInterface_mock_test.go
  • backend/internal/notification/init.go
  • backend/internal/notification/init_test.go
  • backend/internal/notification/sms_sender_service.go
  • backend/internal/notification/sms_sender_service_test.go

@Dilusha-Madushan Dilusha-Madushan force-pushed the feature/generic-sms-executor branch from 801c02b to bc03c19 Compare April 2, 2026 09:18
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
backend/internal/flow/executor/sms_executor.go (1)

32-121: ⚠️ Potential issue | 🟠 Major

🔴 Documentation Required: This PR introduces a user-facing change (e.g., new/modified API endpoint, configuration option, authentication flow, or SDK behavior) but does not include corresponding documentation updates under docs/. Please update the relevant documentation before merging.**

Please document the new SMSExecutor flow node behavior: required node properties (senderId, messageBody), recipient resolution order (UserInputs.mobileNumber then RuntimeData.mobileNumber), and runtime outputs/failure semantics (smsSent, no-op when SMS service is unavailable, and ExecFailure on client errors).
Suggested location: docs/content/guides/ (existing flow-executor guide or a dedicated SMS executor page).

As per coding guidelines: If ANY of the above are detected and the PR does NOT include corresponding updates under docs/, flag this as a major issue.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/internal/flow/executor/sms_executor.go` around lines 32 - 121, The PR
adds a new SMSExecutor flow node (types smsExecutor and method executeSend) but
lacks docs; add a documentation page or update the existing flow-executor guide
under docs/content/guides/ describing: required node properties
propertyKeySMSSenderID (senderId) and propertyKeySMSMessage (messageBody);
recipient resolution order implemented by resolveRecipientMobile
(UserInputs.mobileNumber then RuntimeData.mobileNumber); runtime outputs and
semantics including common.DataSMSSent values (true/false), no-op behavior when
smsSenderService is nil, and failure semantics (ExecFailure when recipient
missing or when service returns a client error, and propagated error for other
service errors). Include examples of node JSON config, expected runtime outputs,
and troubleshooting notes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@backend/internal/flow/executor/sms_executor.go`:
- Around line 32-121: The PR adds a new SMSExecutor flow node (types smsExecutor
and method executeSend) but lacks docs; add a documentation page or update the
existing flow-executor guide under docs/content/guides/ describing: required
node properties propertyKeySMSSenderID (senderId) and propertyKeySMSMessage
(messageBody); recipient resolution order implemented by resolveRecipientMobile
(UserInputs.mobileNumber then RuntimeData.mobileNumber); runtime outputs and
semantics including common.DataSMSSent values (true/false), no-op behavior when
smsSenderService is nil, and failure semantics (ExecFailure when recipient
missing or when service returns a client error, and propagated error for other
service errors). Include examples of node JSON config, expected runtime outputs,
and troubleshooting notes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0e8115bd-7d37-41bb-89a4-2c1ffa480fa7

📥 Commits

Reviewing files that changed from the base of the PR and between 801c02b and bc03c19.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/notification/notificationmock/SMSSenderServiceInterface_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (11)
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/init.go
  • backend/internal/flow/executor/sms_executor.go
  • backend/internal/flow/executor/sms_executor_test.go
  • backend/internal/notification/SMSSenderServiceInterface_mock_test.go
  • backend/internal/notification/init.go
  • backend/internal/notification/init_test.go
  • backend/internal/notification/sms_sender_service.go
  • backend/internal/notification/sms_sender_service_test.go
✅ Files skipped from review due to trivial changes (4)
  • backend/internal/notification/init_test.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/notification/SMSSenderServiceInterface_mock_test.go
  • backend/internal/flow/executor/sms_executor_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • backend/internal/flow/executor/init.go
  • backend/internal/notification/sms_sender_service.go
  • backend/internal/notification/init.go

@Dilusha-Madushan Dilusha-Madushan force-pushed the feature/generic-sms-executor branch from bc03c19 to 6eb023d Compare April 2, 2026 09:42
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
backend/internal/flow/executor/sms_executor.go (1)

40-57: ⚠️ Potential issue | 🟠 Major

🔴 Documentation Required: This PR introduces a user-facing change (e.g., new/modified API endpoint, configuration option, authentication flow, or SDK behavior) but does not include corresponding documentation updates under docs/. Please update the relevant documentation before merging.

Please document the new SMSExecutor utility node, its required senderId and messageBody properties, the mobileNumber resolution order, and the smsSent / no-op behavior. Updating the flow-executor guide under docs/content/guides/ or adding a dedicated SMS executor page there would cover the missing docs.

As per coding guidelines: If ANY of the above are detected and the PR does NOT include corresponding updates under docs/, flag this as a major issue.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/internal/flow/executor/sms_executor.go` around lines 40 - 57, Add
documentation for the new SMSExecutor utility node introduced by
newSMSExecutor/smsExecutor: create or update a guide under docs/content/guides/
(or a dedicated SMS executor page) that documents the required senderId and
messageBody properties, the mobileNumber resolution order (how
userAttributeMobileNumber is resolved), the runtime behavior including smsSent
event vs no-op when smsSenderService is nil, and example flow snippets showing
configuration and expected outputs; ensure the docs reference the
ExecutorNameSMSExecutor and the inputs/outputs used by the executor.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/internal/flow/executor/constants.go`:
- Around line 92-97: The constants file only defines propertyKeySMSSenderID and
a package-level smsDefaultMessage, so flows cannot supply message content; add a
new constant propertyKeySMSMessageBody (e.g., propertyKeySMSMessageBody =
"messageBody") to backend/internal/flow/executor/constants.go and remove/avoid
relying on the hardcoded smsDefaultMessage for real messages; then update the
executor to resolve propertyKeySMSMessageBody in
backend/internal/flow/executor/sms_executor.go before calling SendSMS (fall back
to smsDefaultMessage only if the resolved property is empty) so flow authors can
provide per-message content.

In `@backend/internal/flow/executor/sms_executor.go`:
- Around line 103-107: The handler for service errors uses svcErr.Error which
can expose a terse/internal value; update the branch that detects
serviceerror.ClientErrorType to set execResp.FailureReason to the client-facing
text by using svcErr.ErrorDescription.DefaultValue with a safe fallback (e.g.,
if ErrorDescription or DefaultValue is empty, fall back to svcErr.Error or a
generic message) in the function handling the response (where svcErr is checked
and execResp is populated).

In `@backend/internal/notification/sms_sender_service.go`:
- Around line 47-65: SendSMS currently calls client.SendSMS without passing ctx
and collapses all provider errors into ErrorInternalServerError; update the call
chain so the context is propagated and provider errors can be classified: change
the usage of GetMessageClient/SendSMS so SendSMS receives the incoming ctx
(i.e., call client.SendSMS(ctx, common.SMSData{...})), update any message client
implementations/signatures as needed to accept context, and replace the blanket
return of &ErrorInternalServerError with error mapping that converts provider
validation or client-returned client errors into the repository's
ClientErrorType/ExecFailure responses while keeping true unexpected failures as
ErrorInternalServerError. Ensure you modify SendSMS, the call to client.SendSMS,
and any concrete client implementations returned by GetMessageClient to accept
and honor context.

---

Duplicate comments:
In `@backend/internal/flow/executor/sms_executor.go`:
- Around line 40-57: Add documentation for the new SMSExecutor utility node
introduced by newSMSExecutor/smsExecutor: create or update a guide under
docs/content/guides/ (or a dedicated SMS executor page) that documents the
required senderId and messageBody properties, the mobileNumber resolution order
(how userAttributeMobileNumber is resolved), the runtime behavior including
smsSent event vs no-op when smsSenderService is nil, and example flow snippets
showing configuration and expected outputs; ensure the docs reference the
ExecutorNameSMSExecutor and the inputs/outputs used by the executor.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 68ccc3ec-b587-4203-a304-400c67f74baf

📥 Commits

Reviewing files that changed from the base of the PR and between bc03c19 and 6eb023d.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/notification/notificationmock/SMSSenderServiceInterface_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (11)
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/init.go
  • backend/internal/flow/executor/sms_executor.go
  • backend/internal/flow/executor/sms_executor_test.go
  • backend/internal/notification/SMSSenderServiceInterface_mock_test.go
  • backend/internal/notification/init.go
  • backend/internal/notification/init_test.go
  • backend/internal/notification/sms_sender_service.go
  • backend/internal/notification/sms_sender_service_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • backend/internal/flow/executor/init.go
  • backend/internal/notification/init.go
  • backend/internal/notification/init_test.go
  • backend/internal/flow/executor/sms_executor_test.go

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
backend/internal/flow/executor/sms_executor.go (1)

60-117: ⚠️ Potential issue | 🟠 Major

🔴 Documentation Required: This PR introduces a user-facing change (e.g., new/modified API endpoint, configuration option, authentication flow, or SDK behavior) but does not include corresponding documentation updates under docs/. Please update the relevant documentation before merging.**

Please document the new SMSExecutor flow node, the senderId configuration, mobileNumber resolution (UserInputs first, then RuntimeData), the smsSent output, the no-op behavior when no SMS sender service is configured, and the current fixed message-body limitation until #1928. docs/content/guides/ is the most likely place for this.

As per coding guidelines: If ANY of the above are detected and the PR does NOT include corresponding updates under docs/, flag this as a major issue.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/internal/flow/executor/sms_executor.go` around lines 60 - 117, Add
documentation for the new SMSExecutor flow node: describe
smsExecutor/SMSExecutor behavior, the senderId node property
(propertyKeySMSSenderID) configuration, how mobileNumber resolution works
(resolveRecipientMobile: UserInputs first then RuntimeData), the smsSent output
flag (common.DataSMSSent), that the executor is a no-op when smsSenderService is
nil, and note the current fixed message body (smsDefaultMessage) limitation with
a pointer to issue `#1928`; place this content under docs/content/guides/ and
include examples for configuring senderId, user inputs vs runtime data for
mobileNumber, and expected outputs.
🧹 Nitpick comments (2)
backend/internal/notification/sms_sender_service_test.go (1)

86-88: Match the resolved sender/request instead of mock.Anything.

These expectations only prove the calls happened. They won't catch regressions where smsSenderService passes the wrong sender into GetMessageClient or builds the wrong outbound SMS. Using mock.MatchedBy here would make the suite validate the actual contract.

Also applies to: 130-132

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/internal/notification/sms_sender_service_test.go` around lines 86 -
88, Replace the broad mock.Anything matchers with predicate matchers so the test
validates the actual sender and outbound SMS payload: change the
mm.EXPECT().SendSMS(mock.Anything) to
mm.EXPECT().SendSMS(mock.MatchedBy(func(req /* type of outbound SMS request */)
bool { return /* check fields (From/To/Body/other) match expected values */ }))
and change suite.mockClientProvider.EXPECT().GetMessageClient(mock.Anything) to
suite.mockClientProvider.EXPECT().GetMessageClient(mock.MatchedBy(func(sender /*
sender type */) bool { return /* check sender ID/credentials/fields equal the
resolved sender used by smsSenderService */ })). Apply the same replacement
pattern for the second occurrence around the 130-132 block so both SendSMS and
GetMessageClient expectations validate the actual objects instead of using
mock.Anything.
backend/internal/flow/executor/sms_executor.go (1)

32-33: Align the comments with the current implementation.

These comments still say the executor reads the message body from node properties, but the code always sends smsDefaultMessage. Please describe the current temporary behavior here so the file does not advertise a contract it does not implement.

📝 Suggested comment update
-// smsExecutor sends an SMS message using the configured sender and message body from node properties.
+// smsExecutor sends an SMS message using the configured sender and a temporary default message body.
 // When smsSenderService is nil, it completes as a no-op with smsSent=false.
@@
-// executeSend resolves the recipient, sender ID, and message body from node properties, then sends the SMS.
+// executeSend resolves the recipient and sender ID, then sends the SMS using the temporary default message body.
 // If the SMS sender service is not configured, it completes without sending (no-op).

Based on learnings: smsDefaultMessage is intentionally hardcoded for the initial SMSExecutor PR, and template-based messageBody support is deferred to issue #1928.

Also applies to: 70-71

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/internal/flow/executor/sms_executor.go` around lines 32 - 33, Update
the top-of-file comments to reflect the current behavior: state that smsExecutor
always sends the hardcoded smsDefaultMessage (not a message read from node
properties) and that when smsSenderService is nil it is a no-op returning
smsSent=false; mention that template-based messageBody support is intentionally
deferred to issue `#1928`. Reference smsExecutor, smsSenderService, and
smsDefaultMessage so reviewers can locate the implementation to keep comments
aligned with the code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@backend/internal/flow/executor/sms_executor.go`:
- Around line 60-117: Add documentation for the new SMSExecutor flow node:
describe smsExecutor/SMSExecutor behavior, the senderId node property
(propertyKeySMSSenderID) configuration, how mobileNumber resolution works
(resolveRecipientMobile: UserInputs first then RuntimeData), the smsSent output
flag (common.DataSMSSent), that the executor is a no-op when smsSenderService is
nil, and note the current fixed message body (smsDefaultMessage) limitation with
a pointer to issue `#1928`; place this content under docs/content/guides/ and
include examples for configuring senderId, user inputs vs runtime data for
mobileNumber, and expected outputs.

---

Nitpick comments:
In `@backend/internal/flow/executor/sms_executor.go`:
- Around line 32-33: Update the top-of-file comments to reflect the current
behavior: state that smsExecutor always sends the hardcoded smsDefaultMessage
(not a message read from node properties) and that when smsSenderService is nil
it is a no-op returning smsSent=false; mention that template-based messageBody
support is intentionally deferred to issue `#1928`. Reference smsExecutor,
smsSenderService, and smsDefaultMessage so reviewers can locate the
implementation to keep comments aligned with the code.

In `@backend/internal/notification/sms_sender_service_test.go`:
- Around line 86-88: Replace the broad mock.Anything matchers with predicate
matchers so the test validates the actual sender and outbound SMS payload:
change the mm.EXPECT().SendSMS(mock.Anything) to
mm.EXPECT().SendSMS(mock.MatchedBy(func(req /* type of outbound SMS request */)
bool { return /* check fields (From/To/Body/other) match expected values */ }))
and change suite.mockClientProvider.EXPECT().GetMessageClient(mock.Anything) to
suite.mockClientProvider.EXPECT().GetMessageClient(mock.MatchedBy(func(sender /*
sender type */) bool { return /* check sender ID/credentials/fields equal the
resolved sender used by smsSenderService */ })). Apply the same replacement
pattern for the second occurrence around the 130-132 block so both SendSMS and
GetMessageClient expectations validate the actual objects instead of using
mock.Anything.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d6a26436-016b-4ffb-8738-16d05abd4a13

📥 Commits

Reviewing files that changed from the base of the PR and between 6eb023d and b3e51b5.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/notification/notificationmock/SMSSenderServiceInterface_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (11)
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/init.go
  • backend/internal/flow/executor/sms_executor.go
  • backend/internal/flow/executor/sms_executor_test.go
  • backend/internal/notification/SMSSenderServiceInterface_mock_test.go
  • backend/internal/notification/init.go
  • backend/internal/notification/init_test.go
  • backend/internal/notification/sms_sender_service.go
  • backend/internal/notification/sms_sender_service_test.go
🚧 Files skipped from review as they are similar to previous changes (6)
  • backend/internal/flow/executor/init.go
  • backend/internal/flow/common/constants.go
  • backend/internal/notification/init_test.go
  • backend/internal/notification/sms_sender_service.go
  • backend/internal/flow/executor/sms_executor_test.go
  • backend/internal/notification/init.go

@ThaminduDilshan ThaminduDilshan linked an issue Apr 3, 2026 that may be closed by this pull request
@Dilusha-Madushan Dilusha-Madushan force-pushed the feature/generic-sms-executor branch from b3e51b5 to c9970b8 Compare April 3, 2026 07:10
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
backend/internal/flow/executor/init.go (1)

47-47: ⚠️ Potential issue | 🟠 Major

Missing docs update for newly registered SMSExecutor flow capability.

🔴 Documentation Required: This PR introduces a user-facing change (e.g., new/modified API endpoint, configuration option, authentication flow, or SDK behavior) but does not include corresponding documentation updates under docs/. Please update the relevant documentation before merging.

Please document the new SMSExecutor utility node behavior (required senderId, recipient resolution order, smsSent output/no-op semantics) in docs/content/guides/ (or the existing flow-executor guide) before merge.

As per coding guidelines: "If ANY of the above are detected and the PR does NOT include corresponding updates under docs/, flag this as a major issue."

Also applies to: 101-101

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/internal/flow/executor/init.go` at line 47, The PR added a new flow
capability SMSExecutor but did not update docs; add documentation under
docs/content/guides/ (or update the existing flow-executor guide) describing the
SMSExecutor utility node: required configuration field senderId, how recipients
are resolved (explicit recipient param -> flow context lookup -> default/group
fallback), the semantics of the smsSent output (true on send, no-op behavior
when SMS service disabled or rate-limited, and error conditions), and any
auth/configuration steps for notification.SMSSenderServiceInterface; ensure
examples and schema snippets for the node inputs/outputs are included so users
can configure senderId and interpret smsSent.
🧹 Nitpick comments (1)
backend/internal/notification/sms_sender_service_test.go (1)

75-77: Prefer Twilio property-key constants in test fixtures.

Using common.TwilioPropKeyAccountSID, common.TwilioPropKeyAuthToken, and common.TwilioPropKeySenderID here will keep tests aligned with production constants and avoid drift.

♻️ Suggested refactor
-			createTestProperty("account_sid", "AC00112233445566778899aabbccddeeff", true),
-			createTestProperty("auth_token", "test-token", true),
-			createTestProperty("sender_id", "+15551234567", false),
+			createTestProperty(common.TwilioPropKeyAccountSID, "AC00112233445566778899aabbccddeeff", true),
+			createTestProperty(common.TwilioPropKeyAuthToken, "test-token", true),
+			createTestProperty(common.TwilioPropKeySenderID, "+15551234567", false),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/internal/notification/sms_sender_service_test.go` around lines 75 -
77, Replace hard-coded Twilio property key strings in the test fixtures with the
production constants: use common.TwilioPropKeyAccountSID,
common.TwilioPropKeyAuthToken, and common.TwilioPropKeySenderID when calling
createTestProperty in sms_sender_service_test.go so the test uses the same keys
as production and avoids drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/internal/flow/executor/sms_executor.go`:
- Around line 70-71: The function comment for executeSend is inaccurate: it
claims the message body is resolved from node properties but the implementation
sends the smsDefaultMessage; update the comment on executeSend to state that it
resolves recipient and sender ID from node properties but uses smsDefaultMessage
as the message body, and retain the note that if the SMS sender service is not
configured the function completes as a no-op; reference executeSend and
smsDefaultMessage when editing the comment.

---

Duplicate comments:
In `@backend/internal/flow/executor/init.go`:
- Line 47: The PR added a new flow capability SMSExecutor but did not update
docs; add documentation under docs/content/guides/ (or update the existing
flow-executor guide) describing the SMSExecutor utility node: required
configuration field senderId, how recipients are resolved (explicit recipient
param -> flow context lookup -> default/group fallback), the semantics of the
smsSent output (true on send, no-op behavior when SMS service disabled or
rate-limited, and error conditions), and any auth/configuration steps for
notification.SMSSenderServiceInterface; ensure examples and schema snippets for
the node inputs/outputs are included so users can configure senderId and
interpret smsSent.

---

Nitpick comments:
In `@backend/internal/notification/sms_sender_service_test.go`:
- Around line 75-77: Replace hard-coded Twilio property key strings in the test
fixtures with the production constants: use common.TwilioPropKeyAccountSID,
common.TwilioPropKeyAuthToken, and common.TwilioPropKeySenderID when calling
createTestProperty in sms_sender_service_test.go so the test uses the same keys
as production and avoids drift.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7829e374-a35a-4c43-baef-70a8e5035301

📥 Commits

Reviewing files that changed from the base of the PR and between b3e51b5 and c9970b8.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/notification/notificationmock/SMSSenderServiceInterface_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (11)
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/init.go
  • backend/internal/flow/executor/sms_executor.go
  • backend/internal/flow/executor/sms_executor_test.go
  • backend/internal/notification/SMSSenderServiceInterface_mock_test.go
  • backend/internal/notification/init.go
  • backend/internal/notification/init_test.go
  • backend/internal/notification/sms_sender_service.go
  • backend/internal/notification/sms_sender_service_test.go
✅ Files skipped from review due to trivial changes (2)
  • backend/internal/flow/common/constants.go
  • backend/internal/notification/init_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • backend/cmd/server/servicemanager.go
  • backend/internal/notification/init.go
  • backend/internal/notification/sms_sender_service.go
  • backend/internal/flow/executor/sms_executor_test.go

@Dilusha-Madushan Dilusha-Madushan force-pushed the feature/generic-sms-executor branch from c9970b8 to 47e8d33 Compare April 3, 2026 08:51
@asgardeo asgardeo deleted a comment from coderabbitai bot Apr 5, 2026
@asgardeo asgardeo deleted a comment from coderabbitai bot Apr 5, 2026
@Dilusha-Madushan Dilusha-Madushan force-pushed the feature/generic-sms-executor branch from 47e8d33 to ed0bd85 Compare April 5, 2026 15:54
@Dilusha-Madushan Dilusha-Madushan force-pushed the feature/generic-sms-executor branch 2 times, most recently from d30fffa to a8a92f5 Compare April 6, 2026 04:55
@Dilusha-Madushan Dilusha-Madushan force-pushed the feature/generic-sms-executor branch from a8a92f5 to 3295abe Compare April 6, 2026 07:45
Signed-off-by: Dilusha-Madushan <dilushamadushan9912@gmail.com>
@Dilusha-Madushan Dilusha-Madushan force-pushed the feature/generic-sms-executor branch from 3295abe to 4699cbd Compare April 6, 2026 08:07
@ThaminduDilshan ThaminduDilshan added this pull request to the merge queue Apr 6, 2026
Merged via the queue into asgardeo:main with commit 70ba059 Apr 6, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement a new SMS executor for generic SMS delivery

3 participants