Skip to content

Connector-centric registry: one place to add an integration #22

Description

@alexeygrigorev

Full analysis in docs/architecture-review.md. The trigger→action engine is sound; what doesn't scale is that connector knowledge lives in four hand-maintained registries across two languages.

Problem

Adding one action today touches:

  1. src/dapier/engine/actions/<x>.py
  2. the run_x import + if/elif dispatch in src/dapier/engine/__init__.py
  3. ACTION_SPECS validation in src/dapier/triggers/email_triggers.py
  4. the hand-mirrored designer/src/catalog.ts (comment says "Mirrors the run_* dispatch")

Adding one trigger source touches:

  1. worker.normalize_payload branches
  2. template.yaml (per-source queue/table/env)
  3. api/router.py hook routing
  4. a load_workflows() hook in matching.all_workflows

Nothing links these copies; they drift silently. Related structural limits: no data flow between steps (blocks #6, #7, #12), O(all-workflows) resolution per event (published-table scan capped at 200, silently), and per-action auth folklore (credential_id vs connection_id vs auth_secret_id).

Proposal

  • src/dapier/connectors/<name>/ — one package per integration: a manifest (label, events, actions + field schema), normalize(raw) -> event per ingress it owns, and run(action, ctx) per action. A connectors/registry.py replaces the dispatch chain, ACTION_SPECS, and the trigger-load hooks.
  • GET /api/catalog — serve the manifests as JSON; the designer renders palette/inspector from it (keep catalog.ts as a dev fallback). One registry, three consumers: engine dispatch, validation, UI.
  • ActionContext — ctx.connection(name) → live token (auto-refreshed), plus event, workflow, run id, and a steps namespace so later steps can template earlier outputs (first enabler for Step-to-step data mapping + Formatter #6).
  • One workflows table with a connector#event GSI — merge the published/email/hook/schedule stores; matching becomes a query per event instead of four scans + a linear pass. Instant-publish semantics unchanged.
  • Generic ingress — a route/queue/source → connector mapping with one ingress handler; per-connector queues become declared resources instead of template.yaml surgery.

Migration order (incremental, no big bang)

  1. Registry wrapping the existing run_* functions; dispatch reads the registry. Tests keep passing.
  2. Move normalize_payload branches into connectors; keep the SQS contract.
  3. /api/catalog; designer consumes it; delete the TS mirror and ACTION_SPECS duplication.
  4. ActionContext + steps + unified connection_id (keep credential_id/auth_secret_id as deprecated aliases).
  5. Single workflows table + trigger GSI.
  6. Then Step-to-step data mapping + Formatter #6/In-workflow logic: filter steps, branching, delays, loops #7/Test-before-publish: run a workflow against a sample event #10 become small changes on top instead of structural ones.

The 23 src/*.py back-compat shims are already removed (2026-09-25); make test was 426 passing at filing time.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions