@app-connect/core 1.7.21 → 1.7.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +8 -1
  2. package/connector/developerPortal.js +4 -4
  3. package/docs/README.md +50 -0
  4. package/docs/architecture.md +93 -0
  5. package/docs/connectors.md +117 -0
  6. package/docs/handlers.md +125 -0
  7. package/docs/libraries.md +101 -0
  8. package/docs/models.md +144 -0
  9. package/docs/routes.md +115 -0
  10. package/docs/tests.md +73 -0
  11. package/handlers/admin.js +22 -2
  12. package/handlers/auth.js +51 -10
  13. package/handlers/log.js +4 -4
  14. package/handlers/managedAuth.js +446 -0
  15. package/index.js +264 -34
  16. package/lib/jwt.js +1 -1
  17. package/mcp/tools/createCallLog.js +5 -1
  18. package/mcp/tools/createContact.js +5 -1
  19. package/mcp/tools/createMessageLog.js +5 -1
  20. package/mcp/tools/findContactByName.js +5 -1
  21. package/mcp/tools/findContactByPhone.js +6 -2
  22. package/mcp/tools/getCallLog.js +5 -1
  23. package/mcp/tools/rcGetCallLogs.js +6 -2
  24. package/mcp/tools/updateCallLog.js +5 -1
  25. package/mcp/ui/App/lib/developerPortal.ts +1 -1
  26. package/package.json +72 -72
  27. package/releaseNotes.json +8 -0
  28. package/test/handlers/admin.test.js +34 -0
  29. package/test/handlers/auth.test.js +402 -6
  30. package/test/handlers/managedAuth.test.js +458 -0
  31. package/test/index.test.js +105 -0
  32. package/test/lib/jwt.test.js +15 -0
  33. package/test/mcp/tools/createCallLog.test.js +11 -0
  34. package/test/mcp/tools/createContact.test.js +58 -0
  35. package/test/mcp/tools/createMessageLog.test.js +15 -0
  36. package/test/mcp/tools/findContactByName.test.js +12 -0
  37. package/test/mcp/tools/findContactByPhone.test.js +12 -0
  38. package/test/mcp/tools/getCallLog.test.js +12 -0
  39. package/test/mcp/tools/rcGetCallLogs.test.js +56 -0
  40. package/test/mcp/tools/updateCallLog.test.js +14 -0
  41. package/test/routes/managedAuthRoutes.test.js +132 -0
  42. package/test/setup.js +2 -0
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Core package for RingCentral App Connect project providing modular APIs for CRM integration, authentication, contact management, and call logging.
4
4
 
5
+ For maintainer-facing internal docs about the package internals, see [`docs/README.md`](./docs/README.md). That docs set covers the non-MCP code under `packages/core`.
6
+
5
7
  ## Features
6
8
 
7
9
  - **Modular API Design**: Flexible Express app setup with customizable middleware and routes
@@ -286,6 +288,7 @@ const logHandler = require('@app-connect/core/handlers/log');
286
288
  const adminHandler = require('@app-connect/core/handlers/admin');
287
289
  const userHandler = require('@app-connect/core/handlers/user');
288
290
  const dispositionHandler = require('@app-connect/core/handlers/disposition');
291
+ const managedAuthHandler = require('@app-connect/core/handlers/managedAuth');
289
292
 
290
293
  // Available handlers:
291
294
  // authHandler - Authentication operations
@@ -294,6 +297,7 @@ const dispositionHandler = require('@app-connect/core/handlers/disposition');
294
297
  // adminHandler - Admin operations
295
298
  // userHandler - User management
296
299
  // dispositionHandler - Call disposition
300
+ // managedAuthHandler - Shared API-key auth field operations
297
301
  ```
298
302
 
299
303
  #### Models
@@ -332,6 +336,7 @@ The core package provides the following API endpoints:
332
336
  - `GET /authValidation` - Validate user authentication
333
337
  - `GET /oauth-callback` - OAuth callback handler
334
338
  - `POST /apiKeyLogin` - API key authentication
339
+ - `GET /apiKeyManagedAuthState` - Get managed-auth required-field readiness for API-key logins
335
340
  - `POST /unAuthorize` - Logout user
336
341
 
337
342
  ### Contact Management
@@ -356,11 +361,13 @@ The core package provides the following API endpoints:
356
361
  - `POST /admin/settings` - Update admin settings
357
362
  - `GET /admin/serverLoggingSettings` - Get server logging settings
358
363
  - `POST /admin/serverLoggingSettings` - Update server logging settings
364
+ - `GET /admin/managedAuth` - Get managed-auth field definitions and masked stored values
365
+ - `POST /admin/managedAuth` - Update org-level or user-level managed auth field values
359
366
 
360
367
  ### System
361
368
  - `GET /releaseNotes` - Get release notes
362
369
  - `GET /crmManifest` - Get CRM manifest
363
- - `GET /is-alive` - Health check
370
+ - `GET /isAlive` - Health check
364
371
  - `GET /serverVersionInfo` - Get server version
365
372
  - `GET /hostname` - Get user hostname
366
373
  - `GET /userInfoHash` - Get hashed user info
@@ -22,11 +22,11 @@ async function getPrivateConnectorList() {
22
22
  }
23
23
  }
24
24
 
25
- async function getConnectorManifest({connectorId, isPrivate = false}) {
25
+ async function getConnectorManifest({ connectorId, isPrivate = false }) {
26
26
  try {
27
27
  let response = null;
28
- if(isPrivate) {
29
- response = await axios.get(`https://appconnect.labs.ringcentral.com/public-api/connectors/${connectorId}/manifest?type=internal&accountId=${process.env.RC_ACCOUNT_ID}`);
28
+ if (isPrivate) {
29
+ response = await axios.get(`https://appconnect.labs.ringcentral.com/public-api/connectors/${connectorId}/manifest?access=internal&type=connector&accountId=${process.env.RC_ACCOUNT_ID}`);
30
30
  }
31
31
  else {
32
32
  response = await axios.get(`https://appconnect.labs.ringcentral.com/public-api/connectors/${connectorId}/manifest`);
@@ -36,7 +36,7 @@ async function getConnectorManifest({connectorId, isPrivate = false}) {
36
36
  logger.error('Error getting connector manifest:', error);
37
37
  return null;
38
38
  }
39
- }
39
+ }
40
40
 
41
41
  exports.getPublicConnectorList = getPublicConnectorList;
42
42
  exports.getPrivateConnectorList = getPrivateConnectorList;
package/docs/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # App Connect Core Docs
2
+
3
+ This docs set explains the maintained code under `packages/core`, excluding the `mcp/` subsystem.
4
+
5
+ Use it when you need to change shared backend behavior, trace a request through the framework, or understand which module owns a feature.
6
+
7
+ ## Scope
8
+
9
+ Included:
10
+
11
+ - root package entrypoints and route assembly
12
+ - connector infrastructure
13
+ - handlers
14
+ - models, including DynamoDB-backed schemas used outside MCP
15
+ - shared libraries
16
+ - tests that cover the non-MCP package surface
17
+
18
+ Excluded:
19
+
20
+ - `mcp/`
21
+ - generated output such as `coverage/`
22
+ - vendored dependencies such as `node_modules/`
23
+
24
+ ## Reading Order
25
+
26
+ 1. [Architecture](architecture.md) for the runtime shape and request flow
27
+ 2. [Routes](routes.md) for the HTTP surface in `index.js`
28
+ 3. [Handlers](handlers.md) for shared business logic
29
+ 4. [Connectors](connectors.md) for registration, proxy behavior, and developer-portal helpers
30
+ 5. [Models](models.md) for persistence
31
+ 6. [Libraries](libraries.md) for shared helpers and infrastructure code
32
+ 7. [Tests](tests.md) for current automated coverage
33
+
34
+ ## File Map
35
+
36
+ | Area | Files |
37
+ | --- | --- |
38
+ | Package root | `index.js`, `package.json`, `README.md`, `releaseNotes.json`, `jest.config.js` |
39
+ | Connectors | `connector/registry.js`, `connector/developerPortal.js`, `connector/mock.js`, `connector/proxy/index.js`, `connector/proxy/engine.js` |
40
+ | Handlers | `handlers/admin.js`, `handlers/auth.js`, `handlers/calldown.js`, `handlers/contact.js`, `handlers/disposition.js`, `handlers/log.js`, `handlers/plugin.js`, `handlers/managedAuth.js`, `handlers/user.js` |
41
+ | Sequelize models | `models/accountDataModel.js`, `models/adminConfigModel.js`, `models/cacheModel.js`, `models/callDownListModel.js`, `models/callLogModel.js`, `models/llmSessionModel.js`, `models/messageLogModel.js`, `models/sequelize.js`, `models/userModel.js` |
42
+ | DynamoDB models | `models/dynamo/connectorSchema.js`, `models/dynamo/lockSchema.js`, `models/dynamo/noteCacheSchema.js` |
43
+ | Libraries | `lib/analytics.js`, `lib/authSession.js`, `lib/callLogComposer.js`, `lib/constants.js`, `lib/debugTracer.js`, `lib/encode.js`, `lib/errorHandler.js`, `lib/generalErrorMessage.js`, `lib/jwt.js`, `lib/logger.js`, `lib/oauth.js`, `lib/ringcentral.js`, `lib/s3ErrorLogReport.js`, `lib/sharedSMSComposer.js`, `lib/util.js` |
44
+ | Tests | `test/setup.js`, `test/connector/**`, `test/handlers/**`, `test/lib/**`, `test/models/**`, `test/routes/**` excluding `test/mcp/**` |
45
+
46
+ ## Relationship To The Package README
47
+
48
+ The package [README.md](../README.md) is still the best public-facing quick start.
49
+
50
+ This docs set is the maintainer-oriented reference for the internals behind that API surface.
@@ -0,0 +1,93 @@
1
+ # Core Architecture
2
+
3
+ This package is the reusable backend framework behind App Connect server deployments.
4
+
5
+ Its job is to expose a stable HTTP surface, persist shared state, and delegate CRM-specific work to registered connectors.
6
+
7
+ ## Main Entry Points
8
+
9
+ `index.js` exports the package assembly surface:
10
+
11
+ | Export | Purpose |
12
+ | --- | --- |
13
+ | `createCoreApp(options)` | Builds an Express app, installs middleware, and mounts the shared router |
14
+ | `createCoreMiddleware()` | Returns the common JSON, XML, and CORS middleware stack |
15
+ | `createCoreRouter()` | Creates the shared route layer without creating a full app |
16
+ | `initializeCore(options)` | Initializes analytics and database synchronization |
17
+ | `connectorRegistry` | Global registry for manifests, release notes, connectors, and interface composition |
18
+ | `proxyConnector` | Proxy-driven connector implementation used for config-based integrations |
19
+ | `DebugTracer` | Request-level debug tracing helper |
20
+
21
+ ## Runtime Responsibilities
22
+
23
+ `index.js` owns the framework assembly:
24
+
25
+ - configures local DynamoDB support when `DYNAMODB_LOCALHOST` is set
26
+ - installs an axios interceptor in local-style environments
27
+ - syncs Sequelize models on startup unless `DISABLE_SYNC_DB_TABLE` or `skipDatabaseInit` disables it
28
+ - adds the `hashedRcExtensionId` column to `users` if an older schema is missing it
29
+ - mounts all shared HTTP routes
30
+ - exposes dev-only mock routes when `IS_PROD === 'false'`
31
+
32
+ ## Request Flow
33
+
34
+ The non-MCP request path is:
35
+
36
+ 1. Express receives a request through `createCoreApp()` or `createCoreRouter()`.
37
+ 2. Core middleware parses JSON or XML and applies CORS defaults.
38
+ 3. Route handlers in `index.js` decode JWTs, gather analytics metadata, and call a shared handler.
39
+ 4. Handlers load the current user and connector, refresh auth if needed, and call the connector operation.
40
+ 5. Models persist linkage data such as user sessions, call log ids, cached account data, and plugin task state.
41
+ 6. Libraries compose payloads, normalize errors, emit analytics, and handle logging.
42
+
43
+ ## Connector-Centered Design
44
+
45
+ The package keeps route shapes and handler logic shared across platforms by pushing CRM-specific behavior behind the connector interface.
46
+
47
+ Important consequences:
48
+
49
+ - handlers decide when to load a connector and how to authenticate against it
50
+ - connectors decide how to talk to a CRM
51
+ - proxy connectors make many integrations data-driven instead of code-driven
52
+ - registry-level interface composition lets a platform add methods without mutating the original connector object
53
+
54
+ ## Persistence Layers
55
+
56
+ There are two storage styles in this package:
57
+
58
+ - Sequelize models for relational/shared application state
59
+ - Dynamoose models for selected operational state such as proxy connector definitions, distributed locks, and note cache entries
60
+
61
+ `AccountDataModel` also stores encrypted shared API-key auth values. Shared auth intentionally stays separate from `AdminConfigModel.userMappings`:
62
+
63
+ - `managed-auth-org` stores account-scoped encrypted auth field values
64
+ - `managed-auth-user` stores per-extension encrypted auth field values
65
+ - server-side logging user mapping continues to live in admin config and is not reused for managed auth
66
+
67
+ ## Cross-Cutting Concerns
68
+
69
+ Several concerns are applied in multiple modules:
70
+
71
+ - OAuth refresh via `lib/oauth.js`
72
+ - RingCentral admin and reporting helpers via `lib/ringcentral.js`
73
+ - response-safe error shaping via `lib/errorHandler.js`
74
+ - analytics events via `lib/analytics.js`
75
+ - opt-in debug traces via `lib/debugTracer.js`
76
+ - structured server logging via `lib/logger.js`
77
+
78
+ ## Important Environment Variables
79
+
80
+ | Variable | Why it matters |
81
+ | --- | --- |
82
+ | `DATABASE_URL` | Sequelize connection string |
83
+ | `DISABLE_SYNC_DB_TABLE` | Skips model sync in `initDB()` |
84
+ | `MIXPANEL_TOKEN` | Enables analytics tracking |
85
+ | `APP_SERVER_SECRET_KEY` | Signs and verifies JWTs and encrypts stored managed auth values |
86
+ | `HASH_KEY` | Hashes RingCentral account and extension identifiers |
87
+ | `DYNAMODB_LOCALHOST` | Points Dynamoose to a local endpoint |
88
+ | `IS_PROD` | Enables local-only logging and mock routes when set to `'false'` |
89
+ | `OVERRIDE_APP_SERVER` | Overrides manifest server URL in `GET /crmManifest` |
90
+ | `OVERRIDE_SERVER_SIDE_LOGGING_SERVER` | Overrides manifest server-side logging URL in `GET /crmManifest` |
91
+ | `RINGCENTRAL_SERVER` | Used by RingCentral OAuth and reporting helpers |
92
+ | `RINGCENTRAL_CLIENT_ID` | Used by RingCentral OAuth and reporting helpers |
93
+ | `RINGCENTRAL_CLIENT_SECRET` | Used by RingCentral OAuth and reporting helpers |
@@ -0,0 +1,117 @@
1
+ # Connectors
2
+
3
+ Connectors are the extension seam that lets the shared framework support multiple CRMs.
4
+
5
+ ## Registry
6
+
7
+ `connector/registry.js` exports a singleton `ConnectorRegistry`.
8
+
9
+ ### Responsibilities
10
+
11
+ - register connector implementations by platform name
12
+ - store manifests by platform
13
+ - store release notes
14
+ - register extra interface methods per platform
15
+ - compose registered interfaces onto a connector at read time
16
+ - fall back to the `proxy` connector when a platform-specific connector is missing
17
+
18
+ ### Important behavior
19
+
20
+ | Method | Notes |
21
+ | --- | --- |
22
+ | `registerConnector()` | Validates that the connector implements `createCallLog` and `updateCallLog` |
23
+ | `getConnector()` | Returns the original connector, an interface-only connector, a composed connector, or the proxy connector fallback |
24
+ | `registerConnectorInterface()` | Adds methods without mutating the original connector object |
25
+ | `getManifest(platform, fallbackToDefault)` | Throws if no manifest exists |
26
+ | `getConnectorCapabilities()` | Summarizes original methods, composed methods, registered interfaces, and auth type |
27
+
28
+ ## Proxy Connector
29
+
30
+ The proxy connector makes integrations configurable through stored connector metadata instead of custom connector code.
31
+
32
+ ### Files
33
+
34
+ | File | Role |
35
+ | --- | --- |
36
+ | `connector/proxy/index.js` | User-facing connector implementation for auth, contacts, call logs, message logs, dispositions, and logout |
37
+ | `connector/proxy/engine.js` | Low-level request templating, auth header creation, and response mapping |
38
+
39
+ ### What `proxy/index.js` does
40
+
41
+ - loads proxy config from `models/dynamo/connectorSchema.js`
42
+ - resolves auth type from config, defaulting to `apiKey`
43
+ - builds `getOauthInfo()` for OAuth-style proxy integrations
44
+ - performs `getUserInfo()`, `findContact()`, `createContact()`, `findContactWithName()`, `createCallLog()`, `getCallLog()`, `updateCallLog()`, `createMessageLog()`, `updateMessageLog()`, `upsertCallDisposition()`, and `getUserList()`
45
+ - clears stored tokens in `unAuthorize()`
46
+ - exposes connector-specific log format through `meta.logFormat`
47
+
48
+ ### What `proxy/engine.js` does
49
+
50
+ - resolves dot-path expressions with `getByPath()`
51
+ - renders template strings like `{{ user.accessToken }}`
52
+ - recursively renders query params, headers, and bodies
53
+ - composes auth headers from operation-specific or global auth config
54
+ - performs axios requests from the rendered config
55
+ - maps contact and call-log responses into App Connect's shared shape
56
+
57
+ ## Developer Portal Helpers
58
+
59
+ `connector/developerPortal.js` wraps public API calls to the App Connect Developer Portal.
60
+
61
+ Exports:
62
+
63
+ - `getPublicConnectorList()`
64
+ - `getPrivateConnectorList()`
65
+ - `getConnectorManifest()`
66
+
67
+ These functions are small fetch helpers and return `null` on failure after logging.
68
+
69
+ ## Mock Connector Helpers
70
+
71
+ `connector/mock.js` is not a full connector implementation. It is a development helper used by the dev-only mock routes.
72
+
73
+ Exports:
74
+
75
+ - `createUser()`
76
+ - `deleteUser()`
77
+ - `getCallLog()`
78
+ - `createCallLog()`
79
+ - `cleanUpMockLogs()`
80
+
81
+ ## Connector Contract In Practice
82
+
83
+ The shared framework expects these methods most often:
84
+
85
+ - `getAuthType()`
86
+ - `getOauthInfo()` or `getBasicAuth()`
87
+ - `getUserInfo()`
88
+ - `authValidation()`
89
+ - `createCallLog()`
90
+ - `updateCallLog()`
91
+ - `getCallLog()`
92
+ - `createMessageLog()`
93
+ - `updateMessageLog()`
94
+ - `findContact()`
95
+ - `createContact()`
96
+ - `findContactWithName()`
97
+ - `unAuthorize()`
98
+ - optional methods such as `getUserList()`, `getLicenseStatus()`, `upsertCallDisposition()`, `getServerLoggingSettings()`, `updateServerLoggingSettings()`, and `onUpdateUserSettings()`
99
+
100
+ ## API-Key Managed Auth Fields
101
+
102
+ `apiKey` connector manifests can now annotate auth fields in `platform.auth.apiKey.page.content[]` with:
103
+
104
+ - `managed?: boolean`
105
+ - `managedScope?: 'account' | 'user'`
106
+ - `hidden?: boolean`
107
+
108
+ Behavior:
109
+
110
+ - `managed: true` marks a field as eligible for admin-managed storage and server-side auto-fill
111
+ - `managedScope: 'account'` stores one encrypted value per RingCentral account
112
+ - `managedScope: 'user'` stores encrypted values per RingCentral extension inside that account
113
+ - `hidden: true` hides input field from users
114
+ - stored managed auth values are encrypted at rest by default
115
+
116
+ This does not change the connector runtime contract. `handlers/auth.onApiKeyLogin()` still resolves the manifest-driven auth payload and passes the final field map through `additionalInfo` into connector `getUserInfo()`. Existing connectors like Redtail that already read extra API-key fields from `additionalInfo` remain compatible.
117
+
@@ -0,0 +1,125 @@
1
+ # Handlers
2
+
3
+ Handlers contain the shared business workflows behind the route layer.
4
+
5
+ ## Handler Overview
6
+
7
+ | File | Responsibility | Main exports |
8
+ | --- | --- | --- |
9
+ | `handlers/auth.js` | Connector login, OAuth callback handling, user persistence, and auth validation | `onOAuthCallback`, `onApiKeyLogin`, `authValidation`, `getLicenseStatus`, `onRingcentralOAuthCallback` |
10
+ | `handlers/contact.js` | Contact search, creation, and account-data caching | `findContact`, `createContact`, `findContactWithName` |
11
+ | `handlers/log.js` | Call logging, message logging, plugin execution, call-log lookup, and note cache writes | `createCallLog`, `updateCallLog`, `createMessageLog`, `getCallLog`, `saveNoteCache` |
12
+ | `handlers/admin.js` | Admin settings, RingCentral reporting, server logging settings, and user mapping | `validateAdminRole`, `upsertAdminSettings`, `getAdminSettings`, `updateAdminRcTokens`, `getServerLoggingSettings`, `updateServerLoggingSettings`, `getAdminReport`, `getUserReport`, `getUserMapping`, `reinitializeUserMapping` |
13
+ | `handlers/user.js` | User setting reads, admin/user setting merge, and updates | `getUserSettingsByAdmin`, `getUserSettings`, `updateUserSettings` |
14
+ | `handlers/disposition.js` | Call-disposition writes against an existing log | `upsertCallDisposition` |
15
+ | `handlers/calldown.js` | User-owned call-down scheduling | `schedule`, `list`, `remove`, `markCalled`, `update` |
16
+ | `handlers/plugin.js` | Async plugin task polling and cleanup | `getPluginAsyncTasks` |
17
+ | `handlers/managedAuth.js` | Shared API-key auth field discovery, secure storage, and login-time field resolution | `getManagedAuthAdminSettings`, `getManagedAuthState`, `resolveApiKeyLoginFields`, `upsertOrgManagedAuthValues`, `upsertUserManagedAuthValues` |
18
+
19
+ ## Common Execution Pattern
20
+
21
+ Most connector-backed handlers follow the same sequence:
22
+
23
+ 1. Load the current `UserModel` row.
24
+ 2. Derive `proxyId` and optional proxy configuration from `platformAdditionalInfo`.
25
+ 3. Resolve the connector from `connectorRegistry`.
26
+ 4. Ask the connector for its auth type.
27
+ 5. Refresh OAuth tokens through `lib/oauth.js` or build API-key auth.
28
+ 6. Call the connector method with normalized inputs.
29
+ 7. Return a shared `successful` plus `returnMessage` shape.
30
+
31
+ ## `auth.js`
32
+
33
+ Key behavior:
34
+
35
+ - `onOAuthCallback()` completes the external OAuth code exchange, calls `getUserInfo()`, and persists the user through `saveUserInfo()`.
36
+ - `onApiKeyLogin()` uses connector-provided basic-auth construction and the same user persistence path.
37
+ - `onApiKeyLogin()` resolves shared API-key fields from `handlers/managedAuth.js`, ignores end-user overrides for shared fields, and returns `missingRequiredFieldConsts` when required fields are missing.
38
+ - `saveUserInfo()` updates or creates `UserModel`, preserving existing `platformAdditionalInfo` keys and adding `proxyId`.
39
+ - `authValidation()` refreshes OAuth tokens when needed, then delegates session validation to the connector.
40
+ - `getLicenseStatus()` is connector-defined and only wrapped here.
41
+ - `onRingcentralOAuthCallback()` stores admin RingCentral tokens in `AdminConfigModel`.
42
+
43
+ ## `contact.js`
44
+
45
+ Key behavior:
46
+
47
+ - `findContact()` checks `AccountDataModel` cache first using `contact-${phoneNumber}` as the data key.
48
+ - Found contacts are cached per `rcAccountId` and `platformName`.
49
+ - Cache refresh can be forced with `isForceRefreshAccountData`.
50
+ - Missing or expired users return warning-style response objects rather than throwing.
51
+ - `findContactWithName()` mirrors the phone lookup path without the account-data cache.
52
+
53
+ Known caveat called out in code:
54
+
55
+ - account-data contact caching assumes one RingCentral account does not need separate caches for multiple CRM platforms at the same time
56
+
57
+ ## `log.js`
58
+
59
+ This is the heaviest handler in the package.
60
+
61
+ Key responsibilities:
62
+
63
+ - prevents duplicate call-log creation by checking `CallLogModel` on `sessionId`
64
+ - loads note cache from DynamoDB when `USE_CACHE` and server-side call logging are enabled
65
+ - runs configured plugins before creating or updating logs
66
+ - composes log body content with `composeCallLog()` or `composeSharedSMSLog()`
67
+ - stores local mappings between telephony ids and CRM log ids
68
+ - handles normal SMS, fax, group SMS, and shared SMS cases
69
+ - enriches tracking metadata for analytics callers
70
+
71
+ Important persistence behavior:
72
+
73
+ - `CallLogModel` stores the App Connect to CRM mapping for call logs
74
+ - `MessageLogModel` stores the App Connect to CRM mapping for message logs
75
+ - `CacheModel` stores async plugin task state
76
+ - `NoteCache` stores temporary notes keyed by session id
77
+
78
+ ## `admin.js`
79
+
80
+ Key responsibilities:
81
+
82
+ - validates RingCentral admin role from the current extension token
83
+ - validates arbitrary RingCentral user tokens with `validateRcUserToken()`
84
+ - stores and reads account-level admin configuration
85
+ - stores admin OAuth tokens used for RingCentral reporting
86
+ - fetches call aggregation and user activity metrics from RingCentral
87
+ - delegates server-side logging settings to connector-specific methods when available
88
+ - builds CRM user to RingCentral extension mappings through `getUserList()`
89
+
90
+ ## `user.js`
91
+
92
+ This module is mainly about merging account-level policy with per-user preferences.
93
+
94
+ Rules implemented here:
95
+
96
+ - if no admin settings exist, return user settings directly
97
+ - admin settings can override or hide user settings
98
+ - plugin settings merge at both the plugin level and nested config-field level
99
+ - connectors can intercept setting updates with `onUpdateUserSettings()`
100
+
101
+ ## Smaller Handler Modules
102
+
103
+ `disposition.js`:
104
+
105
+ - requires an existing local call-log mapping before writing disposition data
106
+
107
+ `calldown.js`:
108
+
109
+ - decodes the JWT directly
110
+ - keeps operations scoped to the authenticated user
111
+ - supports schedule, list, remove, mark-as-called, and partial update flows
112
+
113
+ `plugin.js`:
114
+
115
+ - returns cached async task status
116
+ - deletes terminal task cache records after the client reads them
117
+
118
+ `managedAuth.js`:
119
+
120
+ - reads API-key field definitions from either the developer portal manifest or the connector registry manifest
121
+ - isolates managed field definitions with `managed: true` and `managedScope` (`account` or `user`)
122
+ - encrypts managed auth values before writing to `AccountDataModel`
123
+ - provides admin views with stored values using `{ hasValue, value }` while keeping database values encrypted at rest
124
+ - resolves login fields by merging stored managed values and non-managed end-user inputs
125
+
@@ -0,0 +1,101 @@
1
+ # Libraries
2
+
3
+ The `lib/` directory contains cross-cutting helpers used by routes, handlers, and connectors.
4
+
5
+ ## Infrastructure And Security
6
+
7
+ | File | Responsibility |
8
+ | --- | --- |
9
+ | `lib/jwt.js` | Signs and verifies long-lived JWTs with `APP_SERVER_SECRET_KEY` |
10
+ | `lib/oauth.js` | Builds OAuth clients and refreshes access tokens with lock protection |
11
+ | `lib/authSession.js` | Stores and updates auth-session records used by auth flows |
12
+ | `lib/encode.js` | Small encoding and decoding helpers for encrypted values |
13
+ | `lib/errorHandler.js` | Normalizes API and database errors and exports Express error middleware |
14
+ | `lib/logger.js` | Structured logger plus exported `Logger` class and log-level constants |
15
+ | `lib/debugTracer.js` | Request-scoped trace collector used when debug mode is enabled |
16
+ | `lib/s3ErrorLogReport.js` | S3 bucket setup and presigned upload URL generation for debug reports |
17
+
18
+ ## RingCentral And Analytics Helpers
19
+
20
+ | File | Responsibility |
21
+ | --- | --- |
22
+ | `lib/ringcentral.js` | RingCentral API wrapper plus token-validity helpers |
23
+ | `lib/analytics.js` | Mixpanel initialization and event tracking |
24
+ | `lib/generalErrorMessage.js` | Shared user-facing warning messages for auth and rate-limit cases |
25
+
26
+ ## Formatting And Utility Helpers
27
+
28
+ | File | Responsibility |
29
+ | --- | --- |
30
+ | `lib/callLogComposer.js` | Builds plain text, HTML, or Markdown call-log bodies |
31
+ | `lib/sharedSMSComposer.js` | Builds shared-SMS conversation log content |
32
+ | `lib/constants.js` | Defines `LOG_DETAILS_FORMAT_TYPE` values |
33
+ | `lib/util.js` | Hashing, timezone lookup, media-reader links, plugin setting extraction, and date helpers |
34
+
35
+ ## Notes By File
36
+
37
+ ### `lib/analytics.js`
38
+
39
+ - no-op unless `MIXPANEL_TOKEN` is present
40
+ - attaches package version, app name, connector name, browser, OS, device, and caller metadata to events
41
+ - requires `extensionId` to emit an event
42
+
43
+ ### `lib/jwt.js`
44
+
45
+ - `generateJwt()` signs with a very long expiration window
46
+ - `decodeJwt()` logs and returns `null` on verification failure instead of throwing
47
+
48
+ ### `lib/errorHandler.js`
49
+
50
+ Exports:
51
+
52
+ - `handleApiError()`
53
+ - `handleDatabaseError()`
54
+ - `asyncHandler()`
55
+ - `errorMiddleware()`
56
+ - `getOperationErrorMessage()`
57
+
58
+ Notable behavior:
59
+
60
+ - HTTP 429 becomes a rate-limit warning
61
+ - HTTP 4xx up to 409 becomes an authorization-style warning
62
+ - everything else becomes an operation-specific warning response
63
+
64
+ ### `lib/callLogComposer.js`
65
+
66
+ This module centralizes log-body generation for call logs.
67
+
68
+ It supports:
69
+
70
+ - plain text
71
+ - HTML
72
+ - Markdown
73
+ - note insertion
74
+ - session id, subject, duration, result, recording, and timestamp formatting
75
+ - transcript and AI note insertion
76
+ - leg journey formatting
77
+ - RingSense transcript, summary, score, bullet summary, and deep link sections
78
+
79
+ ### `lib/sharedSMSComposer.js`
80
+
81
+ This module formats shared SMS conversations for CRM logging.
82
+
83
+ It handles:
84
+
85
+ - message, note, and assignment entities
86
+ - owner and assignee metadata
87
+ - per-format output generation
88
+ - summary counts and formatted timeline entries
89
+
90
+ ### `lib/util.js`
91
+
92
+ Exports:
93
+
94
+ - `getTimeZone()`
95
+ - `getHashValue()`
96
+ - `secondsToHoursMinutesSeconds()`
97
+ - `getMostRecentDate()`
98
+ - `getMediaReaderLinkByPlatformMediaLink()`
99
+ - `getPluginsFromUserSettings()`
100
+
101
+ `getPluginsFromUserSettings()` is especially important because logging handlers use it to discover which plugins should run for call, SMS, or fax workflows.