package provider import ( "context" "fmt" "sync" "github.com/kami/hexis/internal/domain" ) type Provider interface { Name() string // Execute performs the capability's side effect. The context carries the // capability's timeout: implementations MUST propagate it into every // blocking call they make so that a timed-out execution is genuinely // cancelled rather than abandoned to run on in the background. Execute(ctx context.Context, capability *domain.Capability, req *domain.ExecuteRequest) (map[string]any, error) } type Registry struct { mu sync.RWMutex providers map[string]Provider } func NewRegistry() *Registry { return &Registry{ providers: make(map[string]Provider), } } func (r *Registry) Register(p Provider) { r.mu.Lock() defer r.mu.Unlock() r.providers[p.Name()] = p } func (r *Registry) Get(name string) (Provider, error) { r.mu.RLock() defer r.mu.RUnlock() p, ok := r.providers[name] if !ok { return nil, fmt.Errorf("provider %q not found", name) } return p, nil }