# Architecture Decision Records > Non-obvious decisions that agents must not undo. > Read during Orient phase every iteration. --- ### ADR-001: Option A (template-based envelope) for createEnvelope() **Date:** 2026-04-09 **Status:** Accepted **Context:** Two approaches were considered for creating a DocuSign eSignature envelope: - Option A: POST with a `templateId` — DocuSign template defines recipients/tabs, Salesforce only passes merge data at send time - Option B: POST with a raw document (download CLM blob, upload as base64) — Salesforce manages all recipient config **Decision:** Use Option A. Simpler implementation, no blob download, recipient config lives in the DocuSign template where it belongs. **Consequences:** ✅ Fewer lines of Apex (no ContentVersion download, no base64 encoding) ✅ Recipient/tab configuration lives in DocuSign where it is maintained ❌ Requires a matching eSignature template to exist in the DocuSign account ❌ If the template does not exist, the API returns a 400 — the operator must set up the template first **Alternatives Considered:** Option B was rejected as unnecessary complexity for this proof-of-concept phase. --- ### ADR-002: Named credentials for all DocuSign API calls **Date:** 2026-04-09 **Status:** Accepted **Context:** All CLM and eSignature API calls must go through Salesforce named credentials. No hardcoded tokens, passwords, or base URLs in Apex. **Decision:** Named credential API name is always sourced from `CLM_Account_Setting__mdt`: - CLM calls use `CLM_API_Named_Credential__c` - eSignature calls use `ESignature_Rest_Named_Credential__c` The `eSignatureAccountId` is also from `CLM_Account_Setting__mdt.ESignature_Account_Id__c`. **Consequences:** ✅ No secrets in source code ✅ Works with Salesforce's credential management (OAuth token refresh, etc.) ❌ Named credentials must be manually configured in each org before the code works --- ### ADR-003: persistEnvelopeResult follows persistDocGenResult pattern **Date:** 2026-04-09 **Status:** Accepted **Context:** The project already has `CLMAdminService.persistDocGenResult()` which writes CLM task results back to the case. The eSignature result persistence should follow the same pattern — not a new approach. **Decision:** `CLMAdminService.persistEnvelopeResult()` is an `@AuraEnabled` static method that takes structured parameters (not a blob or generic map) and writes specific fields to the case via a SOQL update. Same structure as `persistDocGenResult`. **Consequences:** ✅ Consistent code pattern, agent can learn from existing method ✅ Testable with the same approach as `CLMAdminServiceTest` --- ### ADR-004: eSignature tracking fields belong on Appraiser_Case__c **Date:** 2026-04-09 **Status:** Accepted **Context:** The case is the central record. CLM tracking fields already live on `Appraiser_Case__c`. The eSignature tracking fields follow the same pattern. **Decision:** All five eSignature lifecycle fields go on `Appraiser_Case__c`, not on a child record or a separate object. **Consequences:** ✅ Single record for operator to view ✅ Consistent with existing CLM field placement ❌ Only one envelope tracked per case (sufficient for Phase 2) --- ### ADR-005: Operator manually enters template ID in Phase 2 **Date:** 2026-04-09 **Status:** Accepted **Context:** Option: auto-populate the template ID from `CLM_Letter_Definition__mdt` or present a template browser. Both require additional metadata fields or another API call and are out of scope for Phase 2. **Decision:** The operator inputs the eSignature template ID directly into a text field in `clmDocGenWorkbench`. No auto-selection, no browser, no additional metadata field. **Consequences:** ✅ Simpler Phase 2 scope ✅ No new metadata record changes needed ❌ Operator must know the template ID — acceptable for a proof-of-concept **Review after:** Phase 3 could add a `ESignature_Template_Id__c` field to `CLM_Letter_Definition__mdt` and pre-populate the input. --- ### ADR-006: HTTP mocks required for all Apex callout tests **Date:** 2026-04-09 **Status:** Accepted **Context:** Salesforce requires all HTTP callouts in test classes to use `Test.setMock(HttpCalloutMock.class, ...)`. The existing test classes all follow this pattern. **Decision:** All tests for `createEnvelope()` must mock the HTTP response using an inner `MockHttpResponse` class implementing `HttpCalloutMock`. Do not attempt live callouts in test methods. **Consequences:** ✅ Tests run in any Salesforce org without external connectivity ✅ Consistent with existing test class patterns (see `CLMDocGenCalloutTest`) --- _Decisions don't drift if they're written down._