Architecture overview
Continuous Control is two native halves and one wire. On Salesforce: Lightning components, Apex payload builders, and queueable workers. On NetSuite: a single RESTlet endpoint, three engine Suitelets, and the custom record model. Between them: signed HTTPS calls carrying whole graphs, never record-by-record chatter.
The full picture
Salesforce components
The Salesforce half is an unlocked package with no triggers. Every sync starts one of three ways: a user clicks a card, a Flow calls an invocable action, or a schedule fires. Here are the moving parts.
| Layer | Key classes | Responsibility |
|---|---|---|
| UI | ccNetSuiteSyncCall, ccContractRevenue, ccNsConnectionSetup, ccNsMappingEditor, ccNsSyncRuns | Cards, wizard, mapping editor, dashboard |
| Controllers | CcNsSyncCallController, CcNsConnectionSetupController, CcNsMappingAdminController, CcNsSyncRunDashController, CcContractRevenueController | Summaries, previews, start actions, polling |
| Run lifecycle | CcNsSyncRunService | In-flight guards, credential fail-fast, payload build + store, enqueue, the done-status set (DONE_STATUSES: Completed / Completed with warnings) |
| Payload assembly | CcNsPayloadBuilder, CcNsInvoicePayloadBuilder, CcNsOrderLinePayloadBuilder, selectors, CcNsMappingService | SOQL → one JSON document per call |
| Async workers | CcNsBookOrderQueueable, CcNsSyncOrderLinesQueueable, CcNsSyncInvoicesQueueable, CcNsEngineQueueable, CcNsSyncFilesQueueable | The callouts, chunking, chaining |
| Wire + writeback | CcNsRestClient, CcNsEndpointRegistry, CcNsSourceOrg, CcNsWritebackService | OAuth 1.0a signing via postRestletTo(script, deploy, body); the entry endpoint row, ENTRY_SCRIPT_ID and ENTRY_DEPLOY_ID; the Source Org stamp, orgId, host, and label; and id stamping |
NetSuite components
| Component | Kind | Responsibility |
|---|---|---|
cc_control_rl | RESTlet | The single integration endpoint. It dispatches on the payload's action field and writes nothing itself. See Inside the RESTlet |
cc_action_* + cc_control_ctx | Script libraries | One module per action behind the endpoint, sharing a context that carries the Source Org stamp (sourceOrg / setSourceOrg / stampSourceOrg / sourceOrgFamily). No script records of their own |
cc_pob_update / cc_rev_plan / cc_rev_rec_run | Suitelets | Update POBs (always runs) and the two Continuous Revenue Engine processes. See The engine Suitelets |
cc_settings_lib | Script library | The one reader of the Continuous Revenue Settings record (engine and native Sales Order switches, default rule, auto-recognize), read at point of use by every script. No script record of its own |
cc_native_so + cc_native_so_lib | Suitelet + library | The cumulative native Sales Order per contract (the contract button and the booking-time generator) |
cc_form_visuals_ue (+ client scripts) | User Event | Renders the contract/POB visuals and adds the engine buttons |
cc_engine_sched / cc_engine_run_now | Map/Reduce + Suitelet | Portfolio-wide scheduled close and its run-now trigger |
cc_invoice_guard_ue | User Event | Blocks double-billing paths flagged do-not-bill |
cc_gl_impact_ue | User Event | Lists a posted transaction's GL lines on its GL Impact tab |
cc_make_search | Suitelet | Maintenance utility that creates any missing customsearch_cc_* saved search (idempotent on scriptid). It's the headless twin of the setup wizard's postinstall search step |
| 12 record types, 11 scripts, 18 saved searches | Records | The data model and its sublists/KPIs |
The wire between them
Salesforce always makes the call, even when it's pulling data. It asks, and NetSuite answers. There are two call shapes.
- RESTlet POSTs handle every data sync. Each call sends one JSON document, dispatched by its
actionfield, and is signed with OAuth 1.0a HMAC-SHA256 including the query parameters. - Signed Suitelet GETs run the automatic engine legs. After a sync, NetSuite calls Update POBs for every affected contract, and calls Update Revenue Plans too when the Continuous Revenue Engine is on.
The Open in NetSuite links in the UI are plain browser URLs built from environment metadata. They carry no credentials. See Security model for the full trust story.