Integration Architecture Pattern: Temporal-Based Durable Transactions
Date: March 6, 2026
Status: ESTABLISHED PATTERN
Safety Level: CRITICAL
Executive Summary
Section titled βExecutive SummaryβAll third-party ERP integrations should follow the Temporal-based durable transaction pattern:
- Read Operations (GET) β Temporal activities (cacheable reference data) + Dagster batch jobs
- Write Operations (POST/PATCH/DELETE) β Temporal workflows with retry logic, audit trails, and rollback capability
- Rationale: Ensures reliability, traceability, and atomicity across network boundaries
This document establishes the pattern once and prevents reinventing the wheel for P21, NetSuite, SAP, etc.
Pattern Overview
Section titled βPattern Overviewβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ WEBAPP USER ACTION ββ (e.g., "Submit Order to P21") βββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ β βΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ TEMPORAL WORKFLOW (Durable Transaction) ββ ββ 1. Fetch live data from ERP API (GET) ββ 2. Validate against local rules ββ 3. Calculate adjustments (pricing, discounts, etc) ββ 4. Show user confirmation ββ 5. On approval: ββ ββ Begin transaction ββ ββ Send POST/PATCH to ERP ββ ββ Retry on failure (exponential backoff) ββ ββ Rollback if failed ββ ββ Log audit trail ββ 6. Return result (success/failure) ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β βββββββββββββΌββββββββββββ βΌ βΌ βΌ SUCCESS FAILURE AUDIT LOG (return) (retry) (store)Why Temporal?
Section titled βWhy Temporal?β| Aspect | Temporal Advantage |
|---|---|
| Durability | Survives network failures, worker crashes |
| Retry Logic | Exponential backoff with configurable limits |
| Audit Trail | Every step logged for compliance |
| Rollback | Can reverse failed writes (compensating transactions) |
| Timeout Handling | Wonβt hang indefinitely on bad connections |
| Ordering | Guarantees steps execute in order |
| Idempotency | Safe to replay without side effects |
CK POC: WhereFour Integration Plan (APPROVED)
Section titled βCK POC: WhereFour Integration Plan (APPROVED)βStatus: β READY FOR IMPLEMENTATION
Architecture
Section titled βArchitectureβWEBAPP ββ User submits order β βΌ TEMPORAL WORKFLOW: submit_order_to_wherefour β ββ Activity 1: fetch_order_from_api(order_id) β ββ GET /orders/{id} β ββ Returns: order_items[], custom_line_items[], pricing β ββ Activity 2: get_pricing_tiers_from_cache() β ββ Read Redis (24h TTL, synced by Dagster) β ββ Activity 3: validate_order(order, tiers) β ββ Pure Python: validate products + custom items β ββ Activity 4: calculate_discount(order, validation) β ββ Apply tier discounts + allowances β ββ Return discount chip data β ββ (User confirms in UI) β ββ Activity 5: submit_to_wherefour(order) β ββ β οΈ ONLY on Sandbox account (when available) β ββ BLOCKED for production until sandbox exists β ββ Activity 6: audit_log(workflow_id, status) ββ Store in PostgreSQL audit_trail tableData Sources
Section titled βData Sourcesβ| Data | Operation | Source | Where |
|---|---|---|---|
| Orders | GET | API | Temporal (on-submit) |
| Order Items | GET | API | Temporal (on-submit) |
| Custom Line Items | GET | API | Temporal (on-submit) |
| Pricing Tiers | GET | Scraper | Redis (Dagster daily) |
| Customers | GET | API | Redis (Dagster daily) |
| Inventory | GET | API | PostgreSQL (Dagster daily) |
β οΈ CRITICAL SAFETY BOUNDARY: NO WRITES TO PRODUCTION
Section titled ββ οΈ CRITICAL SAFETY BOUNDARY: NO WRITES TO PRODUCTIONβ# ALLOWED (GET only)β
fetch_order_from_api(order_id)β
get_customers_list()β
get_inventory_catalog()
# BLOCKED (POST/PATCH/DELETE)β submit_to_wherefour() # β Wait for sandbox accountβ update_order_status() # β Wait for sandbox accountβ create_invoice() # β Wait for sandbox accountRULE: If operation requires POST, PATCH, or DELETE, it MUST target sandbox account first.
STATUS: Sandbox account NOT YET AVAILABLE.
IMPLICATION: CK POC cannot test write operations until sandbox confirmed.
Project: P21 (Epicor Prophet21) Integration Refactor
Section titled βProject: P21 (Epicor Prophet21) Integration RefactorβStatus: PLANNED (Q2/Q3 2026)
Scope: Refactor existing P21 integration to use Temporal pattern
Current State Analysis (To Be Completed)
Section titled βCurrent State Analysis (To Be Completed)β- Identify all P21 API calls in codebase
- Classify: GET (read) vs POST (write)
- Document current error handling
- Identify silent failure points
Desired State (Temporal-based)
Section titled βDesired State (Temporal-based)βTemporal Workflow: submit_order_to_p21 ββ Activity: fetch_p21_customer(customer_id) β ββ GET /customers/{id} from P21 API β ββ Activity: validate_p21_sku_mapping(order_items) β ββ Check SKU translations β ββ Activity: submit_p21_purchase_order(order_data) β ββ POST /purchase-orders to P21 (with retry) β ββ Activity: confirm_p21_receipt(po_id) β ββ PATCH /purchase-orders/{id}/confirm β ββ Activity: log_audit_trail(workflow_id, p21_po_id) ββ Store in PostgreSQLImplementation Plan (Rough)
Section titled βImplementation Plan (Rough)β- Phase 1: Extract P21 API client library (if doesnβt exist)
- Phase 2: Create Temporal activities for core operations
- Phase 3: Create Temporal workflows (submit order, confirm, cancel, etc)
- Phase 4: Integrate with webapp (replace direct P21 calls)
- Phase 5: Add retry logic + exponential backoff
- Phase 6: Add audit logging + dashboard
Other Integrations: Project Plans to Update
Section titled βOther Integrations: Project Plans to UpdateβApply same pattern to:
NetSuite Integration
Section titled βNetSuite IntegrationβTemporal Workflows: ββ submit_order_to_netsuite ββ sync_inventory_from_netsuite ββ pull_customer_data
Read operations (Dagster): ββ Fetch customers daily ββ Fetch tax codes daily ββ Fetch item catalog dailySAP Integration
Section titled βSAP IntegrationβTemporal Workflows: ββ submit_sto_to_sap ββ confirm_receipt ββ sync_shipment_status
Read operations (Dagster): ββ Fetch material master data ββ Fetch cost centers ββ Fetch plant dataQuickBooks Integration
Section titled βQuickBooks IntegrationβTemporal Workflows: ββ create_invoice_in_qb ββ record_payment ββ sync_estimates
Read operations (Dagster): ββ Fetch customers ββ Fetch items ββ Fetch payment methodsDagster Role: Reference Data Sync (Not Transactions)
Section titled βDagster Role: Reference Data Sync (Not Transactions)βDagster jobs handle read-only, batch operations ONLY:
@jobdef wherefour_sync_daily(): """Sync reference data (NOT transactional)."""
# Fetch reference data tiers = scrape_pricing_tiers() # Playwright scraper customers = fetch_customers_from_api() # GET /customers inventory = fetch_inventory_from_api() # GET /inventory vendors = fetch_vendors_from_api() # GET /vendors
# Cache in Redis + PostgreSQL cache_pricing_tiers(tiers) # Redis 24h TTL cache_customers(customers) # Redis 24h TTL store_inventory(inventory) # PostgreSQL 7d retention store_vendors(vendors) # PostgreSQL 7d retentionNEVER use Dagster for writes (POST/PATCH/DELETE). Use Temporal instead.
Safety Rules (CRITICAL)
Section titled βSafety Rules (CRITICAL)βRule 1: GET Only in Dagster
Section titled βRule 1: GET Only in Dagsterββ
OK: GET /customers, GET /inventory, GET /ordersβ NO: POST /invoices, PATCH /status, DELETE /ordersRule 2: Writes Only in Temporal Workflows
Section titled βRule 2: Writes Only in Temporal Workflowsββ
OK: Temporal activity submits POST to sandboxβ NO: Direct httpx.post() in main codeβ NO: Direct requests.post() in webappRule 3: Sandbox First for New Write Operations
Section titled βRule 3: Sandbox First for New Write OperationsβBefore testing ANY POST/PATCH/DELETE: 1. Request sandbox account from vendor 2. Verify credentials work 3. Run test against sandbox 4. Document test results 5. ONLY then: enable production writesRule 4: All Writes Must Be Audited
Section titled βRule 4: All Writes Must Be AuditedβEvery POST/PATCH/DELETE must: ββ Log to PostgreSQL audit_trail ββ Include workflow_id + timestamp ββ Include full request payload ββ Include full response payload ββ Be queryable for complianceAudit Trail Schema (PostgreSQL)
Section titled βAudit Trail Schema (PostgreSQL)βCREATE TABLE integration_audit_trail ( id BIGSERIAL PRIMARY KEY, workflow_id UUID NOT NULL, -- Temporal workflow ID integration_name VARCHAR(50), -- "wherefour", "p21", "netsuite" operation VARCHAR(20), -- "GET", "POST", "PATCH", "DELETE" endpoint VARCHAR(255), -- "/orders", "/customers/123" status VARCHAR(20), -- "SUCCESS", "FAILURE", "RETRY" request_payload JSONB, -- What we sent response_payload JSONB, -- What we got back error_message TEXT, -- If failed attempted_at TIMESTAMP, completed_at TIMESTAMP, created_at TIMESTAMP DEFAULT NOW());
CREATE INDEX idx_audit_workflow_id ON integration_audit_trail(workflow_id);CREATE INDEX idx_audit_integration ON integration_audit_trail(integration_name);CREATE INDEX idx_audit_timestamp ON integration_audit_trail(created_at DESC);WhereFour Integration: Documentation (COMPLETE)
Section titled βWhereFour Integration: Documentation (COMPLETE)βEndpoints Used
Section titled βEndpoints Usedβ| Endpoint | Method | Purpose | Where Used | Cache TTL |
|---|---|---|---|---|
/customers?limit=100 | GET | Customer list | Dagster job | 24h |
/customers/{id} | GET | Customer details | Temporal (on-demand) | 24h |
/orders?limit=100 | GET | Orders list | Dagster snapshot | - |
/orders/{id} | GET | Order details + items | Temporal (on-submit) | 5min |
/inventory?limit=100 | GET | Inventory catalog | Dagster job | 7d |
/inventory/search?q=X | GET | Search products | Webapp route | - |
/vendors?limit=100 | GET | Vendor list | Dagster job | 7d |
/settings/price_tiers | WEB SCRAPE | Pricing tiers | Dagster + Playwright | 24h |
No Write Operations
Section titled βNo Write Operationsβ- β POST to
/orders - β PATCH to
/order/{id} - β DELETE to
/order/{id}
Reason: No sandbox account available. Production data protection.
Testing Status
Section titled βTesting Statusβ- β All GET endpoints verified (11/11 passing)
- β Order structure validated (order_items + custom_line_items)
- β Pricing data verified (subtotal, discount, total)
- β Search endpoints confirmed working
- β Write operations: NOT TESTED (blocked by safety rule)
Summary: Temporal Pattern Benefits
Section titled βSummary: Temporal Pattern Benefitsβ| Scenario | Without Temporal | With Temporal |
|---|---|---|
| Network fails mid-submit | β Data lost | β Retry automatically |
| Worker crashes | β Workflow lost | β Resumed on recovery |
| Invalid data submitted | β Silent failure | β Logged + auditable |
| Need to replay transaction | β Manual intervention | β Replay from workflow ID |
| Compliance audit | β No trail | β Full audit log |
| Production issue | β Hard to debug | β Queryable workflow history |
Next Steps (Priority Order)
Section titled βNext Steps (Priority Order)β- β WhereFour CK POC: Implement Temporal workflow for order submission (GET only)
- π² P21 Refactor: Create detailed project plan using this pattern (Q2/Q3)
- π² NetSuite: Update project plan to use Temporal (when started)
- π² SAP: Update project plan to use Temporal (when started)
- π² QuickBooks: Update project plan to use Temporal (when started)
Do not start P21/NetSuite/SAP refactors yet. This establishes the pattern for when you do.
Compliance & Safety Checklist
Section titled βCompliance & Safety ChecklistβBefore implementing any integration write operations:
- Sandbox account requested and confirmed
- Test data loaded into sandbox
- Temporal workflow created with retry logic
- Audit trail table created
- Rollback strategy documented
- Error handling tested
- Production credentials secured (1Password / Infisical)
- Approval from product owner
- Gradual rollout plan created (5% β 25% β 100%)
FINAL WARNING:
π¨ NO WRITES TO WHEREFOUR PRODUCTION π¨
Sandbox account only. GET operations only. Await explicit approval before enabling POST/PATCH/DELETE.