I'm a little confused about
- commands role in event sourcing
 - distinction between domain and external events
 
If my understanding is right
- a command represents an action initiated by an actor in terms of the domain
 - a domain event is an event can be consumed and produced by aggregate roots
 - an external event is just like a DTO - a data contract and it needs to be translated to either a domain event or a command
 
Example
I have a Product aggregate root. A product can have multiple active special offers. In order to manage it's SpecialOffers, the product accepts 2 domain events:
- SpecialOfferActivated
 - SpecialOfferDeactivated
 
So it's public interface is just 2 overloaded Apply methods:
class Product{
    ...
    Apply(SpecialOfferActivated){...}
    Apply(SpecialOfferDeactivated){...}
}
1st case: The request comes form front-end to the api
So a Controller is first in the line. It basically translates caller intention from data contract (DTO) to the domain language (command):
class ProductController{
    Post(SpecialOfferDto dto){
        ActivateSpecialOfferCommand command = Map(dto)
        _commandBus.Send(command)
    }
}
Command sent, now we need a command handler
class ActivateSpecialOfferCommandHandler{
    Handle(ActivateSpecialOfferCommand command){
        SpecialOfferActivated domainEvent = Map(command)
        _eventBus.Publish(domainEvent)
    }
}
Event published, now time for the event handler
class SpecialOfferActivatedDomainEventHandler{
    Handle(SpecialOfferActivated domainEvent){
        var product = GetFromDatabase()
        product.Apply(domainEvent)
        Save(product)
    }
}
Done.
2nd case: The process is initiated by an external event published to the service bus.
This time NewPromotionExternalEvent is the data contract (ExternalEvent) and again we need to translate it to the domain language (Command)
class NewPromotionExternalEventHandler{
    Handle(NewPromotionExternalEvent extenalEvent){
        ActivateSpecialOfferCommand command = Map(extenalEvent)
        _commandBus.Send(command)
    }
}
And then it falls back to the ActivateSpecialOfferCommandHandler from the fist case. So it's the same case as the first one basically.
3rd case: Skip the domain events layer (variation of either the 1st or the 2nd case)
So either by an api or an external event a command was produced. We simply create a domain event in order to apply it to the aggregate root. We do not publish the event to the service bus.
class ActivateSpecialOfferCommandHandler{
    Handle(ActivateSpecialOfferCommand command){
        SpecialOfferActivated domainEvent = Map(command)
        var product = GetFromDatabase()
        product.Apply(domainEvent )
        Save(product)
    }
}
Done.
4th case: Skip the commands layer (variation of the 1st case)
We can easily skip the commands layer
class ProductController{
    Post(SpecialOfferDto dto){
        SpecialOfferActivated domainEvent = Map(dto)
        _eventBus.Publish(domainEvent)
    }
}
and fallback to the SpecialOfferActivatedDomainEventHandler
5th case: Aggregate root creation.
So either by an api or an external event a command CreateNewProductCommand was produced. And we need another handler:
CreateNewProductCommandHandler{
    Handle(CreateNewProductCommand command){
        var product = Map(command)
        SaveToDatabase(product)
        NewProductCreated domainEvent = Map(product)
        _eventBus.Publish(domainEvent) // in case somebody is interested
    }
}
In this case there's really no place to stick the domain events layer.
6th case: Domain event produced by Product (aggregate root)
class Product{
    Apply(SpecialOfferActivated domainEvent){
        var specialOffer = Map(domainEvent)
        _specialOffers.Add(specialOffer)
        if(...){
            // For simplicity sake, assume the aggregate root can access _eventBus
            _eventBus.Publish(new ProductReceivedTooManySpromotionsDomainEvent(this.Id))
        }
    }
}
Questions
- The events layer is cool, it allows us to distribute jobs across multiple instances or other microservices. However, what's the point of the command layer? I could easily produce domain events right away (in a controller or external an event handler - 4th case).
 - Is 3rd case legit (create a domain event just to apply it to the aggregate root, without publishing it)?
 - Does command layer only make sense in 5th case where it gives us the benefit of delegating product creation to another microservice while domain events layer is not applicable?
 - Where is the line between external and domain events? Is 
NewPromotionExternalEventfrom the 2nd really an external event or is it rather a domain event? - Who can produce domain events? Aggregate root? Command handler? Domain event handler? External event handler? Another microservice? All of them?
 - Can domain events be dispatched to another micro-service or would it become an external event then?
 - What is the proper way of handling product creation and special offer activation when it the request comes form controller or external event?