I think this is a good question to which I don't have a straight forward answer. In short, I think the meta-data/payload distinction is incomplete.
Data, Data ... and Data
The analogy to HTTP (see VoiceOfUnreason's answer) is a good starting point and quite helpful in understanding the concept of meta data: the data that's relevant to your app is in the message body. To make the communication work, the web browser and server exchange some additional data about the message in the headers.
That's not exactly accurate, especially with today's frontends but for the purposes of data vs. meta data I think we can get away with this simplification.
At first, it seems easy to translate this into event sourcing: clearly our domain data will go into the payload, while the event number and stream id constitute meta data. After all, they essentially just exist for the infrastructure.
In practice, however, you may want to store application data, which isn't required for the ES infrastucture to work, but also doesn't affect the domain logic. Classic examples are when something happened, who initiated it, etc. So we now have three kinds of data.
Just to keep things interesting, those three classes are not necessarily always disjoint. For example, while you may want to always store who caused an event, for some events, this may actually be relevant to your domain.
Finally, your event storage & distribution infrastructure might provide special meta data fields (with additional features) for some, but not all of your application data.
As I mentioned, I do not have a fully worked out solution. I'll describe my current philoshophy below as a potential starting point.
I have found it useful to model an event as three separate data sections as discussed above.
The domain model only deals with the domain part, the application layer adds application data and then publishes the events to the ES module, which adds the stream id & event numbers before storing the whole thing.
In CQRS, the read side may combine data from all data sections, e.g. to filter by 'who' or 'when'.
Combining data, even from different streams, is kind of the point of the read side, so I don't see a problem here.
An event may contain duplicate data in some cases.
For example, like all events, the
PostAnswerEvent has an application data field
caused_by with the username. Unlike many other events, it also has a domain data field
author with the same user - which might be relevant in the domain for edit/voting logic.
Now we can store exactly the domain data we actually need, but still create a generic query over everything a particular user is responsible for.
Note however, that there could be a subtle difference between the fields. Your app logic might allow user X to create a post with author Y, if you're into that kind of thing. If not, you'd have to enforce this somehow.
Your event store module might further duplicate or split data to take advantage of any features your underlying ES infrastructure provides.
That's not something the rest of your app has to be aware of.
Essentially, if your framework has a meta-data field for
user that you would like to use, move or copy the
caused_by data there. Ignore whether it is called 'meta data' in your app and just use is at application data.