4.6 KiB
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.