Hub / Topics / End-to-end encryption

End-to-End Encryption of Case Content

Connect can now carry case text that only the two members on the case can read. The sending connector encrypts and signs it before the API call, the receiving connector verifies and decrypts it after the fetch, and the platform in between stores it without holding a key. What exists today is an API contract on every environment and one proof-of-concept connector. This page covers both, and the sharp edges already found.

Topic Case content confidentiality Grounded in The served API spec + the Dynamics PoC source Audience Members evaluating or building E2EE Updated 2026-10-28

The model

What the Platform Can and Cannot Read

Without E2EE, case content is encrypted in transit and readable by the platform: Connect renders it in the web app, sanitizes it, and stores it as text. End-to-end encryption removes the platform's ability to read a named set of fields. The keys live at each member's own connector. Connect's part is to store two extra fields, return everything exactly as it was submitted, and stay out of the cryptography.

Sending connector encrypts protected fields signs one manifest private keys stay here the member's own key store create · add note ciphertext + JWS TSANet Connect stores manifest + encrypted returns values as submitted parses nothing, holds no keys routing fields stay readable fetch by token returned as sent Receiving connector verifies the manifest checks every digest decrypts, or refuses no plaintext fallback Each member publishes its public keys as a JWKS at a URL it hosts, and partners fetch them directly. No key passes through Connect. In the Dynamics PoC: RSA-OAEP-256 keys for encryption, ES256 keys for signing
Connect is a courier for ciphertext. It still has to route the case, so everything it needs for that stays in the clear.
EncryptedLeft in the clear
problemSummary and problemDescription on the request
each customFields[].value
note summary and description
Who the case is from and to, the form, priority and status
contact details and both internal case numbers
the notes Connect writes itself (Case Created, approval, rejection, closure)
attachments, which travel by file delivery and are not covered
webhook events, which carry only tokens on v2

The field list above is what the one implementation protects. A draft specification from the TSANet E2EE workgroup defines the authoritative list, the encryption and manifest profile, a per-relationship opt-in model, and test vectors. It is not public, so this page is read from the implementation and the API, which are.

The API contract

Two Fields, Stored and Never Read

The platform's whole contribution is two optional fields on collaboration requests and notes. manifest is an opaque Compact JWS that the receiving connector uses to verify what it got. encrypted says whether the content is encrypted. Connect stores both and returns them exactly as submitted. It never parses or changes them, and it does no cryptography.

Schemamanifestencrypted
CollaborationRequestDTO (create)optional stringboolean, default: false
CollaborationRequestStatusDTO (read)left out when unsetalways true or false
CaseNoteTemplateDTO (create note)optional stringboolean, default: false
CaseNoteDTO (read note)left out when unsetalways true or false
EnvironmentStatusEvidence
DevelopmentliveRound trip probed by TSANet's contract-test harness on 2026-10-12 and 2026-10-13, including the full case lifecycle.
BetaliveIn the served spec since 2026-10-19. The harness's API-level E2EE checks pass 10/10 there (reported 2026-10-20).
Productionin the specThe served spec carries both fields since 2026-10-26, identical to Beta's. Spec-read; not probed by the hub.

The one implementation

How the Dynamics PoC Encrypts, Signs and Verifies

The Dynamics connector carries the only working implementation, in TSANETBasePlugins/E2ee. It names its profile tsanet-e2ee-1. Read here at main 0586c96 as a worked example of the shape, not as the specification.

// manifest claims, decoded (values illustrative)
{
  "ver": "tsanet-e2ee-1",
  "iss": "<sending member>",   "aud": "<receiving member>",
  "jti": "<unique per request or note>",  "iat": 1761600000,
  "ref": "<sender's case number>",
  "fields": [
    { "name": "problemSummary",     "alg": "S256", "dig": "<base64url>" },
    { "name": "problemDescription", "alg": "S256", "dig": "<base64url>" }
  ]
}

Keys. The private keys live in Azure Key Vault. The plugin asks the vault to sign and to unwrap, so the private key material never enters Dynamics. The two key ids are set as the environment variables ap_SigningKeyId and ap_UnwrapKeyId. Partners' public keys come from their JWKS URLs, configured as settings: one encryptedRecipient for the partner it encrypts to, and a signingKeyCounterParty for each sender it accepts.

Its failure reasons give a checklist for any receiver you build: ManifestMissing, SignatureInvalid, BindingMismatch, FieldSetMismatch, FingerprintMismatch, NoMatchingRecipient, AeadFailure, HeaderBindingMismatch.

Adoption

Where Each Connector Stands

Both members on a case need E2EE support for it to work. Nothing in the platform checks that the receiver can decrypt before an encrypted case is sent.

ConnectorStatusDetail
DynamicsPoCv2.14.0.0's release notes list an "End to End Encryption PoC". That release encrypts requests and custom fields. Note encryption followed on main on 2026-10-20 and is not in a release yet.
Connect SDKnot yetconnect-library does not expose either field, so nothing built on it can send or read them. Tracked in Connect_SDK#137, which also requires the library never to trim or re-serialize the manifest.
Connect Gateway · Fin / Intercomnot yetThe engine sends encrypted: false on every create and waits on the SDK. One open question is policy, not code: on a TSANet-hosted adapter, TSANet would hold the member's private key. Until the workgroup decides on that, E2EE on a gateway adapter is a self-hosting feature.
Zendesk · SalesforcenoneNo code in either repository reads encrypted or manifest. An encrypted case sent to one of them would show its JWE JSON in place of the summary and description. That follows from the design and has not been observed.
Direct RESTopenAny integration can send and read the two fields today. The cryptography, the keys and the partner agreement are yours.

Sharp edges

What Breaks First

E2EE is a bilateral arrangement between two members, built on a contract the platform only carries. Before planning one, agree keys, fields and failure handling with the partner, and test both directions on Beta. Questions and pilot interest belong in Community.

Verified against

Sources, with the Dates That Were Read

Read onSourceUsed for
2026-10-28openapi.yaml as Beta and Production serve it (last modified 2026-10-19 and 2026-10-26; identical)The four schemas, the defaults, the field length limits, the per-environment status
2026-10-28webhook-asyncapi.yaml on the API source's Beta branch (private repository)v2 event payloads carry tokens only
2026-10-28MS_Power_App TSANETBasePlugins/E2ee at main 0586c96, and the v2.14.0.0 release notesAlgorithms, header and manifest claims, key custody, failure reasons, the single-recipient setting, the decode workaround
2026-10-28Connect_SDK#137The SDK's status; the Beta 10/10 harness result
2026-10-12 to 2026-10-23TSANet contract-test harness results on Development, as reported to the API team; not re-run by the hubRound trip, lifecycle, the 400 on a non-boolean flag, the sanitizer rewrite, the 1,237-character summary
2026-10-28Source search of Zendesk_App and SFDC_AppNeither handles the fields
not readThe workgroup's draft specificationReferenced only; the authoritative field list and test vectors