logicspike/docs

Communication

ADR 002: Universal Provider Adaptor (The Plugin System)

Context

This service must be able to use ANY provider:

  • System Default (e.g., LogicSpike Twilio) for free users.
  • Tenant BYOP (e.g., User's Twilio) for pro users.
  • Custom Webhooks (e.g., User's internal API) for enterprise.

Decision

We will expose a Standard Plugin Interface and load implementations dynamically based on config.

Architecture

1. The Interface (The contract)

Every provider must implement this:

interface Provider {
  id: string;
  type: string;
  send(message: MessagePayload): Promise<MessageResult>;
}

2. The Config Table (The Router)

Database configs table stores:

  • tenant_id: "workspace_123"
  • type: "twilio" | "smtp" | "webhook"
  • credentials: Encrypted JSON ({ accountSid: "...", authToken: "..." })

3. The Factory (The Executer)

When a request arrives:

  1. Lookup config for tenant_id.
  2. Decrypt credentials.
  3. Instantiate the correct class: new TwilioProvider(credentials).
  4. Call .send().

Trade-offs

  • Latency: Creating a fresh API client per request adds overhead.
    • Solution: Cache the client instance in-memory for hot tenants.

Status

Accepted.

Communication