Skip to content

https://mobileaws.atlassian.net/browse/CLOUD-2712#1

Open
dlopezallcode wants to merge 1 commit intomainfrom
CLOUD-2712
Open

https://mobileaws.atlassian.net/browse/CLOUD-2712#1
dlopezallcode wants to merge 1 commit intomainfrom
CLOUD-2712

Conversation

@dlopezallcode
Copy link
Copy Markdown

PR Summary — Node.js SDK (ccai-node)

Overview

The Node.js/TypeScript SDK has been brought to complete parity with the reference Java SDK. Critical bugs with hardcoded URLs, hardcoded accountId, and verifySignature placeholder were fixed. Contact Service and MD5 caching in MMS were added. The SDK compiles without TypeScript errors and passes 21/21 integration tests.


Implemented Changes

1. Hardcoded Base URL Fix in CCAI Client (src/ccai.ts) 🔴

Before: the default of baseUrl pointed to https://core-test-cloudcontactai.allcode.com/api (test environment).

After: the default now points to https://core.cloudcontactai.com/api (production).

Intentional breaking change: Users who instantiate new CCAI({ clientId, apiKey }) without useTestEnvironment: true now send to production automatically.


2. Hardcoded URL Fix in Email Service (src/email/email.ts) 🔴

Before: the service had a hardcoded baseUrl constant pointing to the test environment.

After: uses this.ccai.getEmailBaseUrl() from Config dynamically. Also added the method send(accounts, subject, message, senderEmail, replyEmail, senderName, title?, options?) compatible with Java.


3. Hardcoded accountId Fix in Email (src/email/email.ts) 🔴

Before: email headers had hardcoded 'accountId': '1223'.

After: uses this.ccai.getClientId() dynamically in headers AccountId and ClientId.


4. verifySignature Fix — Security Bug (src/webhook/webhook.ts) 🔴

Before: placeholder implementation (always returned true or did not verify correctly).

After: real implementation with HMAC-SHA256 using Node.js native crypto module:

  • createHmac('sha256', secret).update(body).digest('hex')
  • timingSafeEqual() for constant-time comparison (prevents timing attacks)
  • Support for sha256= prefix in signature
  • Added parseEvent(payload: string) to parse JSON payloads

5. Multi-URL Support and Test/Prod Environment (src/ccai.ts)

CCAIConfig now supports:

  • useTestEnvironment?: boolean (default: false)
  • baseUrl?: string, emailBaseUrl?: string, filesBaseUrl?: string
  • Resolution by priority: explicit parameter > environment variable > default test/prod
  • Environment variables: CCAI_BASE_URL, CCAI_EMAIL_BASE_URL, CCAI_FILES_BASE_URL
  • Getters: getBaseUrl(), getEmailBaseUrl(), getFilesBaseUrl(), isTestEnvironment()

6. MD5 Cache in MMS (src/sms/mms.ts)

Before: sendWithImage() always uploaded the image without checking for duplicates.

After:

  • md5File(filePath) private — uses crypto.createHash('md5') with file streaming
  • checkFileUploaded(fileKey) public — queries GET /clients/{clientId}/storedUrl?fileKey={fileKey}
  • sendWithImage() rewritten: computes MD5 → constructs {clientId}/campaign/{md5}.{ext} → checks if exists → if yes, skips upload → sends
  • Bonus fix: getSignedUploadUrl() now uses client.getFilesBaseUrl() instead of hardcoded URL

7. New Service: Contact (src/contact/contact.ts)

Before: the SDK had no contact management support.

After:

  • setDoNotText(doNotText: boolean, contactId?: string, phone?: string): Promise<SetDoNotTextResponse> — SMS opt-out / opt-in

Endpoint: PUT /account/do-not-text

Registered in ccai.ts as public contact: Contact and exported from src/index.ts.


8. Next.js Webhook Handler (src/webhook/nextjs.ts)

Exclusive utility of Node.js SDK to integrate CCAI webhooks in Next.js App Router routes:

export function createCCAIWebhookHandler(handlers: WebhookHandlers, options?: WebhookHandlerOptions)

Automatically verifies signature and dispatches to the corresponding handler (onMessageSent, onMessageReceived).


9. Real Integration Test (src/test_real.ts)

File created with 18+ integration tests: SMS (1-2), MMS (3-7, 7b, 7c), Email (8-9), Webhook (11-16), Contact (17-18). Loads .env with dotenv.


Compatibility Notes

  • The URL default change (test → production) is an intentional breaking change. Must be communicated in changelog.
  • The accountId fix may affect integrations that relied on the hardcoded value.
  • verifySignature no longer accepts any signature — intentional security breaking change.
  • setDoNotText is a new method and does not break anything existing.

@gitguardian
Copy link
Copy Markdown

gitguardian Bot commented Apr 16, 2026

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
While these secrets were previously flagged, we no longer have a reference to the
specific commits where they were detected. Once a secret has been leaked into a git
repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@dlopezallcode dlopezallcode force-pushed the CLOUD-2712 branch 4 times, most recently from 5278353 to 5cd2656 Compare April 16, 2026 18:58
@dlopezallcode dlopezallcode marked this pull request as ready for review April 16, 2026 19:09
@dlopezallcode dlopezallcode force-pushed the CLOUD-2712 branch 4 times, most recently from 5b7e022 to 1b2547c Compare April 20, 2026 15:46
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.

2 participants