> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trychert.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Limits and Considerations

> Per-send governor consumption, edition fit, and platform-feature compatibility.

Capacity planning, edition compatibility, and platform-feature behavior. Read before piloting in production.

## Per-Send Governor Limit Consumption

Numbers below are per outbound send through `ChertSendIMessage`,
measured against the synchronous Apex transaction limits.

| Limit              | Consumed       | Platform max (synchronous) | Headroom                                             |
| ------------------ | -------------- | -------------------------- | ---------------------------------------------------- |
| HTTP callouts      | 1              | 100                        | Sends from a single transaction may bulk up to \~100 |
| Callout total time | \< 5 s typical | 120 s                      | 24× headroom                                         |
| SOQL queries       | 2              | 100                        | Tenant config + duplicate check                      |
| SOQL rows          | ≤ 2            | 50,000                     | Bounded by query shape                               |
| DML statements     | 1              | 150                        | Inserts the `Chert_Message__c` record                |
| DML rows           | 1              | 10,000                     | One row per send                                     |
| Heap               | \< 32 KB       | 6 MB                       | Payload + signature                                  |
| CPU time           | \< 200 ms      | 10,000 ms                  | Excludes network wait                                |

The package does not consume **future invocations**, **queueable
invocations**, or **scheduled Apex slots** during a synchronous send.

## Bulk Sends from Triggers

Calling `ChertSendIMessage` from a trigger on more than one record at a
time chunks the work. The first 80 sends run in the trigger transaction;
overflow is enqueued through `System.enqueueJob` to a `Queueable` that
honours the same dedup and signature contract. `Queueable` chaining
respects the platform's 50-job synchronous depth limit.

For initial-load scenarios above 1,000 records, prefer scheduling sends
through the `ChertSendIMessage` invocable inside a Flow with a
**Wait** element rather than firing all-at-once from a trigger.

## Daily Send Capacity

The platform imposes no daily Apex callout cap. Daily send volume is
bounded by Chert-side per-line capacity. Each Chert phone line has a
fixed daily first-touch budget. When all lines are saturated,
`ChertSendIMessage` returns a `duplicate=false, ok=false` response with
an explanatory error code; the Flow can route the failure for
re-attempt the following day.

Capacity provisioning is sized to your expected volume during tenant
onboarding.

## Apex Test Coverage

Shipped coverage is ≥ 85% line coverage per class. Reproduce locally:

```bash theme={null}
sf apex run test \
  --target-org <username> \
  --tests ChertBridge_TEST \
  --tests ChertContactsRest_TEST \
  --tests ChertEnrichResultRest_TEST \
  --tests ChertEnrichScheduler_TEST \
  --tests ChertEnrichService_TEST \
  --tests ChertEnrichmentRunNowRest_TEST \
  --tests ChertInboundRest_TEST \
  --code-coverage \
  --result-format human
```

Every HTTP callout path is covered by `HttpCalloutMock`. No test makes
a real callout; runs are deterministic and offline.

A passing run looks like this:

<CodeGroup>
  ```text sf apex run test (excerpt) theme={null}
  === Test Summary
  NAME                 VALUE
  ───────────────────  ─────────────────────────────────
  Outcome              Passed
  Tests Ran            57
  Pass Rate            100%
  Fail Rate            0%
  Skipped              0
  Test Total Time      16240 ms

  === Test Results
  TEST NAME                                                              OUTCOME  RUNTIME (MS)
  ─────────────────────────────────────────────────────────────────────  ───────  ────────────
  ChertBridge_TEST.getContext_happy                                      Pass     287
  ChertBridge_TEST.getContext_404_returns_empty                          Pass     142
  ChertBridge_TEST.getContext_no_phone_throws                            Pass      94
  ChertBridge_TEST.sendMessage_happy_insertsChertMessage                 Pass     412
  ChertBridge_TEST.sendMessage_error_throws                              Pass     188
  ChertBridge_TEST.sendMessage_blank_throws                              Pass      71
  ChertBridge_TEST.getContext_contact_happy                              Pass     263
  ChertBridge_TEST.getContext_contact_phone_fallback                     Pass     201
  ChertBridge_TEST.sendMessage_contact_happy_insertsChertMessage         Pass     394
  ChertBridge_TEST.resolvePhoneFromRecord_unsupported_returns_null       Pass      55
  ChertBridge_TEST.resolvePhoneFromRecord_account_picks_first_contact_with_phone  Pass  331
  ChertBridge_TEST.getContext_account_happy                              Pass     298
  ChertBridge_TEST.sendMessage_account_happy_logs_against_contact        Pass     421
  ChertBridge_TEST.getAccountContacts_returns_contacts_with_phones       Pass     244
  ... (20 ChertBridge tests in total)
  ChertContactsRest_TEST.rejects_missing_bearer                          Pass     112
  ChertContactsRest_TEST.rejects_invalid_bearer                          Pass     108
  ChertContactsRest_TEST.empty_org_returns_empty_list                    Pass      96
  ChertContactsRest_TEST.returns_contacts_with_account_join              Pass     198
  ChertContactsRest_TEST.honors_limit_param                              Pass     142
  ChertContactsRest_TEST.clamps_oversized_limit                          Pass     151
  ChertContactsRest_TEST.patch_rejects_missing_token                     Pass     105
  ChertContactsRest_TEST.patch_rejects_missing_id                        Pass     109
  ChertContactsRest_TEST.patch_updates_mobile_phone                      Pass     176
  ChertContactsRest_TEST.patch_clears_mobile_when_null_passed            Pass     162
  ChertContactsRest_TEST.patch_rejects_no_updatable_fields               Pass     117
  ChertEnrichResultRest_TEST.post_writes_phone_to_contact_on_happy_path  Pass     221
  ChertEnrichResultRest_TEST.post_rejects_missing_bearer                 Pass     104
  ChertEnrichResultRest_TEST.post_rejects_wrong_token                    Pass     108
  ChertEnrichResultRest_TEST.post_rejects_record_type_mismatch           Pass     132
  ChertEnrichResultRest_TEST.post_rejects_missing_fields                 Pass     117
  ChertEnrichScheduler_TEST.batch_writes_phone_on_success                Pass     489
  ChertEnrichScheduler_TEST.batch_stamps_no_match_when_endpoint_says_so  Pass     352
  ChertEnrichScheduler_TEST.batch_skips_contacts_with_existing_phone     Pass     298
  ChertEnrichScheduler_TEST.schedulable_execute_enqueues_batch           Pass     254
  ChertEnrichService_TEST.enrich_happy_returns_phone                     Pass     367
  ChertEnrichService_TEST.enrich_no_match_returns_ok_false               Pass     202
  ChertEnrichService_TEST.enrich_server_error_returns_ok_false           Pass     219
  ChertEnrichmentRunNowRest_TEST.post_enqueues_batch_on_happy_path       Pass     205
  ChertEnrichmentRunNowRest_TEST.post_rejects_missing_bearer             Pass     108
  ChertEnrichmentRunNowRest_TEST.post_rejects_wrong_token                Pass     112
  ChertInboundRest_TEST.post_happy_matches_lead_and_inserts_message_and_task  Pass  274
  ChertInboundRest_TEST.post_invalid_token_returns_401                   Pass     104
  ChertInboundRest_TEST.post_missing_auth_returns_401                    Pass      98
  ChertInboundRest_TEST.post_no_matching_lead_returns_404                Pass     163
  ChertInboundRest_TEST.post_malformed_body_returns_400                  Pass     112
  ChertInboundRest_TEST.post_missing_fields_returns_400                  Pass     107
  ChertInboundRest_TEST.post_matches_contact_only_sets_contact_field     Pass     189
  ChertInboundRest_TEST.post_matches_lead_only_sets_lead_field           Pass     184
  ChertInboundRest_TEST.post_contact_wins_on_tie_when_both_share_phone   Pass     232
  ChertInboundRest_TEST.post_no_contact_or_lead_match_returns_404_with_legacy_code  Pass  148
  ChertInboundRest_TEST.post_idempotent_on_redelivery                    Pass     211

  === Apex Code Coverage by Class
  CLASSES                          PERCENT  UNCOVERED LINES
  ───────────────────────────────  ───────  ─────────────────
  ChertBridge                      94%      72, 118, 244
  ChertContactsRest                91%      57, 89
  ChertEnrichResultRest            93%      48, 102
  ChertEnrichScheduler             88%      31, 64, 77
  ChertEnrichService               90%      55, 121, 188
  ChertEnrichmentRunNowRest        92%      33, 61
  ChertInboundRest                 95%      82, 147
  ChertSendIMessage                89%      44, 91, 133, 162
  ChertTenantConfig                100%
                                   ───────
  Org Wide Coverage                91%
  ```
</CodeGroup>

The deploy gate (`sf project deploy start --test-level RunLocalTests`)
fails if Org Wide Coverage drops below the platform's 75% bar. Shipped
coverage holds at 91% so a regression has room to surface before
blocking deploys.

## Edition Support

| Edition      | Status                    | Notes                                                                                |
| ------------ | ------------------------- | ------------------------------------------------------------------------------------ |
| Enterprise   | Supported                 |                                                                                      |
| Unlimited    | Supported                 |                                                                                      |
| Performance  | Supported                 |                                                                                      |
| Developer    | Supported                 | Recommended for evaluation.                                                          |
| Professional | Supported with API add-on | Without the add-on, Apex callouts are unavailable and the package will not function. |
| Essentials   | Not supported             | API access is unavailable on Essentials.                                             |

## User Interface

| Surface                            | Status                                                                                     |
| ---------------------------------- | ------------------------------------------------------------------------------------------ |
| Lightning Experience               | Supported                                                                                  |
| Mobile (Salesforce mobile app)     | Supported — the `chertConversation` LWC adapts to the phone form factor.                   |
| Salesforce Classic                 | Not supported. The package contains no Visualforce; the LWC requires Lightning Experience. |
| Experience Cloud (community) sites | Not validated. Out of scope for v1.                                                        |

## Platform Feature Compatibility

### Person Account

Supported. `chertConversation` and `ChertSendIMessage` detect
`Account.IsPersonAccount` and route the contact resolution through the
Person Account's contact half. No additional configuration required.

### Shield Platform Encryption

The package is compatible with Shield Platform Encryption with the
following considerations:

* **Probabilistic encryption** on `Contact.MobilePhone` and
  `Lead.Phone` is fully supported. The package reads and writes through
  standard formula-free field references.
* **Deterministic encryption** is required if your administrators want
  to use phone-number-based duplicate matching across the standard
  CRM duplicate rules.
* The custom field `Chert_Message__c.Text__c` is a **Long Text Area**
  and supports Shield encryption. Encrypt it at the field level
  through Setup → **Encryption Policy** if your data-classification
  policy requires it.

### Multi-Currency

Compatible. The package defines no currency fields and performs no
currency arithmetic.

### Translation Workbench

Field labels, picklist values, and the Permission Set label can be
translated through Translation Workbench. The `chertConversation` LWC's
hard-coded user-facing strings are not yet externalized; flag during
v2 planning if multi-language support is needed.

### Government Cloud and Hyperforce

The package's Apex and metadata are Hyperforce-compatible. Validation
against Government Cloud Plus has not been performed; do not deploy to
GovCloud Plus Orgs without consulting Chert.

## Sandbox versus Production

The package metadata is identical across sandboxes and production. The
**Custom Metadata record** values differ: each environment must be
configured with its own `Tenant_Slug__c`, `Signing_Secret__c`, and
`Ingest_Token__c`. Do not copy production secrets into sandboxes; ask
Chert for a sandbox-specific tenant.

## Idempotency

Every send accepts an `idempotencyKey`. Within a 6-hour rolling window,
re-invoking with the same key is a no-op and returns
`duplicate: true`. Treat `duplicate: true` as success in Flow logic.

If your Flow does not supply `idempotencyKey`, the package generates
one as `<recordId>:<sha256(message-body)>`, which is stable across
retries of the same logical action.

## Retry Semantics

Outbound HTTP failures (network timeout, 5xx) are not auto-retried by
the package. The invocable returns `ok: false` with an error code; the
Flow should branch on the result and either retry or surface the error
to the user. This is intentional — silent retries are difficult to
reason about in declarative tooling, so the contract surfaces the
choice to the Flow author.

## Setup Audit Trail

The package writes the following entries to **Setup Audit Trail** on
install and configuration changes:

* `Installed package: Chert Messaging`
* `Modified custom metadata record: Chert_Tenant.Default`
* `Activated Lightning page: Lead_Record_Page_Chert`
* `Activated Lightning page: Contact_Record_Page_Chert`
* `Activated Lightning page: Account_Record_Page_Chert`
* `Assigned permission set: Chert Messaging User`

Compliance teams can grep the trail for `Chert_` to audit every
package-related change.

## See Also

* [SECURITY](SECURITY.md) for the trust boundary and signature format.
* [ARCHITECTURE](ARCHITECTURE.md) for synchronous-versus-asynchronous behavior.
* [Apex Developer Guide — Execution Governors and Limits](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm)
* [General Shield Platform Encryption Considerations](https://developer.salesforce.com/docs/atlas.en-us.securityImplGuide.meta/securityImplGuide/security_pe_considerations_general.htm)
