Trust Boundary
| Side of the boundary | What lives there |
|---|---|
| Inside the Org | All Apex classes, Custom Metadata, Permission Sets, Lightning Web Components, custom objects, and the signing secret. |
| On the wire | One HTTPS request per send, signed with HMAC-SHA256. Payload is JSON; transport is TLS 1.2+. |
| Outside the Org | The Chert messaging service at console.trychert.com. Receives signed requests, dispatches to delivery infrastructure, surfaces replies through the inbound REST resource. |
Authentication
Outbound (Org → Chert)
Every outbound request carries:<unix-ts>is the seconds-since-epoch at which the request was signed.<hex>isHMAC-SHA256(<unix-ts>.<raw-body>, signing_secret)rendered as lowercase hex.
<unix-ts>is more than 5 minutes in the past (replay window).<unix-ts>is more than 5 minutes in the future (clock-skew tolerance).- The HMAC does not match.
Inbound (Chert → Org)
Reply notifications POST to theChertInboundRest REST resource on the
Org. The resource requires:
ingest_token is generated by you, stored in
Chert_Tenant__mdt.Ingest_Token__c, and shared with Chert. It is not
the same value as the outbound signing secret; the two are
independently rotatable.
Authorization
Apex Sharing
Every callable Apex class declares its sharing posture explicitly:| Class | Sharing | Rationale |
|---|---|---|
ChertSendIMessage | with sharing | Runs in the calling user’s context. Honours record sharing. |
ChertBridge | with sharing | LWC data layer. Honours record sharing. |
ChertEnrichService | with sharing | Phone enrichment under the calling user’s grants. |
ChertEnrichScheduler | with sharing | Scheduled job; honours sharing of the scheduled-job owner. |
ChertEnrichmentRunNowRest | with sharing | REST resource invoked by authenticated users. |
ChertEnrichResultRest | with sharing | REST resource for enrichment callbacks; bearer-authenticated. |
ChertInboundRest | with sharing | REST resource for reply ingestion; bearer-authenticated. |
ChertContactsRest | without sharing | Site-exposed REST resource gated by bearer token. Documented and bounded — see below. |
ChertContactsRest is the only without sharing class in the package.
Its scope is read-only on a fixed projection of Contact fields and an
edit on a single mutable field. The bearer-token check runs before any
SOQL or DML, and the field allowlist is enforced server-side. If your
deployment does not need the live-Contacts surface, remove the
Permission Set’s class access and disable the Site that exposes it.
Field-Level Security
The package never bypasses CRUD or FLS. Apex DML on standard objects runs under the calling user’s profile and Permission Set grants. The Lightning Web Components route every read and write through Apex classes that honourWITH USER_MODE semantics.
Permission Set Scope
Chert Messaging User grants only what end users need:
- Read on the conversation pane’s Contact and Lead fields.
- Edit on
Contact.MobilePhoneand the Chert-prefixed enrichment fields. - Read and Create on
Chert_Message__c. No Edit, no Delete, no View All, no Modify All. - Apex class access for the eight package classes.
- Named Credential access to
Chert_Endpoint.
View All Data, Modify All Data, or any custom user permission.
Data Handling
What Crosses the Wire on a Send
| Field | Direction | Purpose |
|---|---|---|
tenant_slug | Out | Identifies your Org. |
phone | Out | The recipient’s E.164 number. |
message | Out | The iMessage body. |
idempotency_key | Out | Deterministic dedup key. |
salesforce_record_id | Out | The Lead, Contact, or Account ID. Used for traceability and inbound reply correlation. |
lead.name, lead.company, lead.custom_fields | Out, optional | Used to personalize the message body server-side. Pass only if you opt in. |
What Crosses on an Inbound Reply
| Field | Direction | Purpose |
|---|---|---|
phone | In | The sender’s number. |
message | In | The reply body. |
received_at | In | Carrier-side timestamp. |
salesforce_record_id | In | Correlated to the Salesforce parent record from the original send. |
Retention
Chert retains conversation data for the duration of the customer contract plus 30 days for operational continuity, after which it is purged. Data residency and retention overrides are negotiated through the Chert master service agreement.Sub-Processors
The Chert messaging service depends on a small set of named sub-processors for delivery, hosting, and observability. The current list is published atconsole.trychert.com/legal/sub-processors and
is the authoritative source.
Cryptography
| Property | Value |
|---|---|
| Signature algorithm | HMAC-SHA256 |
| Signature input | <unix-ts>.<raw-body> |
| Signature encoding | Lowercase hex |
| Replay window | 5 minutes |
| Transport | TLS 1.2+ enforced by Chert |
| Secret rotation | Rotate the Custom Metadata field; the next signed request uses the new secret. Coordinate with Chert support to overlap windows during rotation. |
Vulnerability Disclosure
Report security issues tocontact@trychert.com. Chert’s disclosure
policy is 90 days from acknowledgement to public publication.
Deployment Topology — Hardening Roadmap
The current reference topology exposes the live-Contacts read surface (ChertContactsRest) through a public Salesforce Site, gated by the
bearer ingest token. This is appropriate for Org-internal pilots where
the bearer token is the authentication boundary and the field
projection is intentionally narrow (no Account lookup, no Email,
write access scoped to MobilePhone only).
The recommended path for production-scale customer deployments is:
- Replace the public Site with a Connected App configured for the OAuth 2.0 Client Credentials Flow. Chert obtains an access token per request rather than presenting a static bearer.
- Revoke the Site Guest User’s access to
ChertContactsRest. - Rotate the bearer ingest token to invalidate any cached value.
See Also
- ARCHITECTURE for the call-graph and async behavior.
- LIMITS AND CONSIDERATIONS for governor-limit math and Shield Platform Encryption support.
- Salesforce Well-Architected — Trusted / Secure

