Skip to content

Migrate Telegram, Modica, and Line custom channels to account-scoped lambda#3962

Open
Copilot wants to merge 6 commits intomasterfrom
copilot/migrate-custom-channels-lambda
Open

Migrate Telegram, Modica, and Line custom channels to account-scoped lambda#3962
Copilot wants to merge 6 commits intomasterfrom
copilot/migrate-custom-channels-lambda

Conversation

Copy link
Contributor

Copilot AI commented Feb 26, 2026

Migrates Telegram, Modica, and Line custom channel webhook handlers from the serverless repo into the account-scoped lambda, following the existing Instagram pattern. Only Twilio Conversations API is supported (no Programmable Chat).

Description

New channel handlers (src/customChannels/{telegram,modica,line}/):

  • telegramToFlex / flexToTelegram — validates X-Telegram-Bot-Api-Secret-Token header; sends via Telegram Bot API
  • modicaToFlex / flexToModica — no inbound auth (Modica doesn't provide one); sends via Basic Auth REST API with E.164 phone number sanitization
  • lineToFlex / flexToLine — validates x-line-signature HMAC SHA256 (with emoji Unicode escaping); handles batched events; sends via Line Messaging API with Bearer token + per-message X-Line-Retry-Key

Configuration (configuration.ts):

  • Added SSM lookups for all new channel credentials using the channel-scoped naming convention: /${NODE_ENV}/{channel}/${accountSid}/<param> (e.g. /development/telegram/{accountSid}/bot_api_secret_token, /development/modica/{accountSid}/app_name, /development/line/{accountSid}/channel_secret)

Router (router.ts):

  • Registered 6 new routes; inbound routes have empty pipeline, outbound routes use validateWebhookRequest — same pattern as Instagram

Tests: Unit tests for all 6 handlers covering auth validation, missing parameters, ignored events, correct external API calls, and testSessionId routing behaviour.

Logging: Added console.debug logging at key processing points in all 6 handlers (validated event body, computed identifiers, result status). "Received event" logs are at debug level to avoid noise in info logs.

Integration test support (testSessionId): All 3 migrated channels now include the same testSessionId support as the Instagram channel:

  • Inbound handlers (telegramToFlex, modicaToFlex, lineToFlex): testSessionId is accepted in the request body and forwarded to sendConversationMessageToFlex, where it is stored in conversation attributes and used to redirect outbound messages during integration tests.
  • Outbound handlers (flexToTelegram, flexToLine): already supported testSessionId via the shared redirectConversationMessageToExternalChat helper.
  • flexToModica: updated sendModicaMessage to accept testSessionId; when set, messages are redirected to TEST_SEND_URL and the x-webhook-receiver-session-id header is included.

Checklist

  • Corresponding issue has been opened
  • New tests added
  • Feature flags added
  • Strings are localized
  • Tested for chat contacts
  • Tested for call contacts

Other Related Issues

None

Verification steps

Deploy the account-scoped lambda and configure SSM parameters for each channel using the channel-scoped path convention:

  • Telegram: /{env}/telegram/{accountSid}/bot_api_secret_token, /{env}/telegram/{accountSid}/flex_bot_token
  • Modica: /{env}/modica/{accountSid}/app_name, /{env}/modica/{accountSid}/app_password
  • Line: /{env}/line/{accountSid}/channel_secret, /{env}/line/{accountSid}/channel_access_token

Point each channel's webhook URL at the corresponding customChannels/{channel}/{channel}ToFlex endpoint and verify end-to-end message flow.

AFTER YOU MERGE

  1. Cut a release tag using the Github workflow. Wait for it to complete and notify in the #aselo-deploys Slack channel.
  2. Comment on the ticket with the release tag version AND any additional instructions required to configure an environment to test the changes.
  3. Only then move the ticket into the QA column in JIRA

You are responsible for ensuring the above steps are completed. If you move a ticket into QA without advising what version to test, the QA team will assume the latest tag has the changes. If it does not, the following confusion is on you! :-P

Original prompt

This section details on the original issue you should resolve

<issue_title>Migrate remaining custom channels from serverless</issue_title>
<issue_description>## Description

Migrate the Telegram, Modica and Line custom channels which have implementations in the https://github.com/techmatters/serverless/tree/master/functions/webhooks directory into the account-scoped lambda in this repository

Do not migrate any support for running these channels over the Twilio Programmable Chat API, only support for running them over the Twilio Conversations API is required in the migrated implementation

Provide unit test coverage for all migrated channels

Additional context

The Instagram custom channel has already been migrated to account-scoped lambda, use this implementation as a guide for migrating the remaining 3 channels
</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…lambda

Co-authored-by: stephenhand <1694716+stephenhand@users.noreply.github.com>
Copilot AI changed the title [WIP] Migrate remaining custom channels to account-scoped lambda Migrate Telegram, Modica, and Line custom channels to account-scoped lambda Feb 26, 2026
Copy link
Collaborator

@stephenhand stephenhand left a comment

Choose a reason for hiding this comment

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

Add extra logging to each of these channels to assist debugging

accountSid: AccountSID,
) => {
console.info('==== FlexToLine handler ====');
console.info('Received event:', event);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be a debug log

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to console.debug in 3fc1425.

accountSid: AccountSID,
) => {
console.info('==== FlexToModica handler ====');
console.info('Received event:', event);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be a debug log

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to console.debug in 3fc1425.

accountSid: AccountSID,
) => {
console.info('==== ModicaToFlex handler ====');
console.info('Received event:', body);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be a debug log

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to console.debug in 3fc1425.

accountSid: AccountSID,
) => {
console.info('==== FlexToTelegram handler ====');
console.info('Received event:', event);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be a debug log

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to console.debug in 3fc1425.

…ed event logs to debug level

Co-authored-by: stephenhand <1694716+stephenhand@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 26, 2026

Add extra logging to each of these channels to assist debugging

Added extra console.debug logging at key processing points in all 6 new channel handlers in 3fc1425 — logs validated event body, computed identifiers (uniqueUserName, studioFlowSid, recipientId), and result status for each handler.

@stephenhand stephenhand marked this pull request as ready for review February 26, 2026 18:05
getSsmParameter(
`/${process.env.NODE_ENV}/twilio/${accountSid}/${channelName}_studio_flow_sid`,
);

Copy link
Collaborator

Choose a reason for hiding this comment

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

These SSM parameter names are all wrong, see https://github.com/techmatters/serverless/blob/master/.github/actions/custom-actions/aselo_development_custom/action.yml for examples of correct naming for these parameters

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 6d0d0b1. The SSM paths now use the channel name as the service segment (e.g. /development/telegram/{accountSid}/bot_api_secret_token, /development/modica/{accountSid}/app_name, /development/line/{accountSid}/channel_secret) matching the pattern in the serverless action.yml.

…tch serverless naming convention

Co-authored-by: stephenhand <1694716+stephenhand@users.noreply.github.com>
Copy link
Collaborator

@stephenhand stephenhand left a comment

Choose a reason for hiding this comment

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

Fix the linter errors from the last run

Co-authored-by: stephenhand <1694716+stephenhand@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 26, 2026

Fix the linter errors from the last run

Fixed in 03aa1df. The CI's prettier (printWidth: 90) wanted the 3 functions with shorter SSM paths (getTelegramBotApiSecretToken, getTelegramFlexBotToken, getLineChannelAccessToken) collapsed to single lines. The --fix had been applied locally but not committed.

Copy link
Collaborator

@stephenhand stephenhand left a comment

Choose a reason for hiding this comment

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

include the same support for testSessionId that the instagram custom channel supports in the 3 channels being migrated in this PR

Co-authored-by: stephenhand <1694716+stephenhand@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 27, 2026

include the same support for testSessionId that the instagram custom channel supports in the 3 channels being migrated in this PR

Done in 2c8a806. Changes made:

  • Inbound (telegramToFlex, modicaToFlex, lineToFlex): Added testSessionId?: string to each Body type and pass event.testSessionId to sendConversationMessageToFlex (same as Instagram)
  • Outbound flexToModica: Added testSessionId?: string parameter to sendModicaMessage, uses TEST_SEND_URL when set and adds x-webhook-receiver-session-id header (same pattern as flexToTelegram and flexToLine which already had this)
  • Added a new test in flexToModica.test.ts verifying the TEST_SEND_URL + header path when testSessionId is present in conversation attributes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate remaining custom channels from serverless

3 participants