Summary for handing control of the project over to the Unicity team. Explains what was built, how data persists, what's resolved, and what's still open — without needing to read the code line by line.
A small service (the "bridge") that sits between Intercom and RingCentral. When Fin (Intercom's AI agent) can't resolve something and escalates the conversation to a human, this service translates messages between the two systems so the customer sees one continuous conversation, without ever knowing the system changed behind the scenes.
POST /internal/escalate) with that conversation's data.POST /webhooks/ringcentral), and the bridge injects that reply into the original Intercom conversation.POST /webhooks/intercom), and the bridge forwards it to RingCentral. Steps 4-5 repeat for as long as the conversation with the agent continues.The core piece of data the bridge needs to remember is the "Intercom conversation ↔ RingCentral thread" mapping. Without it, it wouldn't know where to forward each new message.
| Partition key (pk) | Content | What it's for |
|---|---|---|
| conv:<intercom_conv_id> | { ringcentral_thread_id } | When a new message arrives from the customer in Intercom, we look this up to know where to forward it |
| rc:<ringcentral_thread_id> | { intercom_conversation_id } | When the agent replies in RingCentral, we look this up to know which Intercom conversation to inject the reply into |
| evt:<intercom_event_id> | { ttl } | Record of "this event was already processed" — prevents duplicates if Intercom retries a webhook |
If the server restarts (a deploy, a crash, a scheduled restart), a process's memory is wiped entirely. With DynamoDB the mapping survives restarts, and if the service ever runs on more than one instance to spread load, they all share the same source of truth instead of each keeping its own inconsistent copy.
evt:* records (duplicate control) carry a ttl attribute — DynamoDB deletes them automatically after 24 hours, no manual cleanup needed. Mapping records (conv:* and rc:*) aren't auto-deleted today; cleaning up old conversations is a pending task to define, based on how long Unicity wants to retain mapping history.
| Channel | How it's protected |
|---|---|
| Intercom → bridge | Cryptographic signature (HMAC-SHA1) sent by Intercom on every request; the bridge recomputes and compares it. If it doesn't match, it rejects with 401. |
| RingCentral → bridge | A token Unicity chooses when creating the subscription, returned by RingCentral on every subsequent notification. |
| Intercom Workflow → bridge | A separate secret stored as an "Authentication Token" in the Intercom Data Connector (encrypted on Intercom's side, never visible as plain text). |
| bridge → Intercom / RingCentral | Auth tokens in the Authorization header, never in the URL. |
All secret comparisons use a timing-attack-safe method (crypto.timingSafeEqual), the minimum standard for this kind of validation.
One-time, on first deploy:
Recurring, once RingCentral info arrives:
Everything below is not pending work on our side — it's information only Unicity can confirm. With these 4 pieces of info, two specific code files get completed; nothing else in the system needs to change.
For any question about the bridge's business logic (not infrastructure), the point of contact remains Matias Gema (EscalateOps) until RingCentral's information is confirmed and that last piece is closed.