Skip to main content

Executive Summary

As CONA scales to support 100+ e-commerce and payment integrations, we need a more maintainable architecture. This RFC proposes an Adapter Pattern that separates integration-specific transformation logic from shared workflow orchestration, reducing code duplication while preserving the unique business logic each integration requires. Key Goals:
  • Reduce time-to-implement new integrations from ~2 weeks to ~2-3 days
  • Minimize code duplication across similar integration workflows
  • Maintain flexibility for integrations with unique business logic (Shopify refunds, PayPal fees, Amazon settlements)
  • Provide clear contracts for integration developers
  • Enable easier testing and maintenance
  • Establish a fixture-based approach for test data and schema discovery
Not Goals:
  • Forcing all integrations into a single generic workflow
  • Removing integration-specific business logic
  • Breaking existing integrations during migration

Problem Statement

Current Architecture

Each integration currently has its own complete Temporal workflow:

Problems at Scale

Integration Complexity Matrix

Each integration has unique requirements that cannot be abstracted away:

Proposed Solution: Integration Adapter Pattern

Core Concept

An adapter is a translator that converts data from one format (Shopify, PayPal, Amazon) into a common format (CONA documents). It separates:
  1. “What data to transform” → Integration Adapter (unique per integration)
  2. “How to process documents” → Generic Workflow Orchestrator (shared)

Adapter Interface

Example: Shopify Orders Adapter

Example: PayPal Payments Adapter

Generic Workflow Orchestrator


Directory Structure


Migration Strategy

Phase 1: Define Adapter Interface (Week 1)

  • Create packages/temporal-workflows/src/adapters/types.ts
  • Create adapter registry
  • No changes to existing workflows

Phase 2: Extract PayPal Adapter (Week 2)

  • Create paypal-payments-adapter.ts
  • PayPal is simplest (no refund tracking, no document connections)
  • Run both old workflow and new adapter-based workflow in parallel
  • Compare outputs for parity

Phase 3: Extract Shopify Orders Adapter (Weeks 3-4)

  • Create shopify-orders-adapter.ts
  • Reuse existing helper functions (no rewrite needed)
  • Handle unique Shopify logic (refunds, connections) in postProcess
  • Validate with real Shopify data

Phase 4: Extract Amazon Orders Adapter (Week 5)

  • Create amazon-orders-adapter.ts
  • Amazon Settlements stays as custom workflow (too unique)

Phase 5: New Integrations Use Adapter Pattern (Ongoing)

  • Etsy, WooCommerce, Stripe → implement adapter only
  • Estimated: 2-3 days per integration

Phase 6: Deprecate Old Workflows (After Validation)

  • Mark old workflows as deprecated
  • Eventually remove after 3+ months of adapter stability

Trade-offs & Risks

Benefits

Risks & Mitigations

When NOT to Use an Adapter

Some integrations are too unique for the generic workflow:
  1. Amazon Settlements - Settlement as virtual bank, complex payout tracking
  2. QuickBooks Sync - Two-way sync with conflict resolution
  3. Bank statement reconciliation - Fundamentally different flow
These should keep custom workflows. The registry supports both:

Success Metrics


Test Data & Schema Discovery Strategy

One of the hardest parts of building integrations is understanding incoming data schemas and obtaining realistic test data. This section defines our approach.

The Core Challenge

Fixture Directory Structure

Approaches by Data Source Type

Fixture Capture Script

Schema Contract Testing

Use Zod schemas to define the MINIMUM fields we expect from each API:

Integration Testing Against Fixtures

Discovery Documentation

For each integration, create a DISCOVERY.md file:

Test Data Workflow

Data Anonymization Strategy

Always redact sensitive information in test fixtures before committing to git. This is critical for CONA since we handle financial and customer data.

What to Redact vs. Preserve

Anonymization Utility

Capture Script with Auto-Anonymization

Fixture Storage Layers

CI PII Detection Job

Quick Reference: Platform Sandbox Access


Decisions Made

1. Continue-as-New Handling

Decision: The generic workflow handles continue-as-new automatically using Temporal’s built-in suggestion. The shouldContinueAsNew() utility checks workflowInfo().continueAsNewSuggested which Temporal sets when the workflow history is getting too large. This is adapter-agnostic and requires no configuration.
Usage in generic workflow:
Why this approach:
  • No adapter configuration needed
  • Temporal knows best when history is too large
  • Consistent behavior across all integrations
  • Test hook available for CI testing (testContinueAsNew: true)

2. Adapter Packaging Strategy

Decision: Adapters are NOT separate npm packages. They live in the monorepo. All adapters will be co-located in packages/core/src/integrations/adapters/:
Why this approach:
  • Simpler dependency management - No version mismatches between adapters
  • Faster iteration - Change adapter + workflow in one PR
  • Shared utilities - Adapters can easily share common transformation helpers
  • Unified testing - Run all adapter tests in one CI job
  • Build time is acceptable - With tree-shaking, unused adapters don’t bloat bundles
When to reconsider:
  • If build times exceed 5+ minutes due to adapter count
  • If external teams need to contribute adapters without monorepo access
  • If adapters need independent release cycles

Open Questions

  1. Where should fixtures live?
    • Option A: packages/core/src/integrations/adapters/{integration}/fixtures/ (close to code)
    • Option B: Separate packages/test-fixtures/ package (shared across packages)
    • Option C: Top-level fixtures/ directory in monorepo root
  2. How do we keep fixtures up-to-date when APIs change?
    • Scheduled CI job to validate fixtures against live sandbox
    • Contract tests that fail on schema drift
    • Manual review during integration maintenance

References


Appendix A: Full Adapter Interface

See the complete TypeScript interface in the “Adapter Interface” section above.

Appendix B: Example Adapters

Complete example adapters for Shopify and PayPal are provided in the “Example” sections above.