Status: Accepted Date: 2025-12-01 Supersedes: N/A Superseded by: N/A

Context

AWF supports plugin operations (GitHub, notifications, HTTP) that extend workflow capabilities. Operations need registration, discovery, and execution. The question is where the registry lives: domain (pure, testable) or infrastructure (concrete, direct access to adapters).

Both registries serve different lifecycle concerns: domain owns the contract, infrastructure owns the wiring.

Candidates

OptionProsCons
Domain registry onlyPure, testable, no infra dependencyCan’t auto-discover infrastructure plugins
Infrastructure registry onlyDirect access to adapters, auto-wiringDomain depends on infrastructure, untestable
Composite (domain + infrastructure)Separation of concerns, testable domain, flexible infraTwo registries to maintain, routing complexity

Decision

Implement OperationRegistry in domain layer implementing ports.OperationProvider. Infrastructure maintains its own plugin registry for lifecycle management (init, cleanup). A CompositeOperationProvider in application layer merges both.

Rules:

  • Domain registry: pure Go, no external deps, implements port directly on domain type
  • Infrastructure registry: manages concrete adapters (HTTP providers, etc.)
  • Application layer wires both via CompositeOperationProvider
  • Preserve both registries — never collapse into one

Consequences

What becomes easier:

  • Unit testing operations without infrastructure
  • Adding pure-domain operations (validators, transformers)
  • Infrastructure plugins have independent lifecycle (init/cleanup)

What becomes harder:

  • Operation lookup traverses two registries
  • New contributors must understand the composite pattern

Constitution Compliance

PrincipleStatusJustification
Hexagonal ArchitectureCompliantDomain defines port, infrastructure implements adapter
Go IdiomsCompliantInterface in consumer (domain), struct in provider (infrastructure)
Minimal AbstractionCompliantComposite justified by two concrete lifecycle needs