A key/value map of metadata can be associated with any group ID or message ID in the local DB. Some clients also need to store metadata for protocol sessions, which requires a hack to associate the session ID with a message ID where the metadata is stored.
We can generalise the current approach by replacing the group ID or message ID with an arbitrary collection ID. However, we still want all metadata to belong to a group so it can be garbage collected if the group is removed. So the metadata structure becomes: group/collection/key/value. To associate metadata with a message, use the message ID as the collection ID. Metadata queries that currently return message IDs will return collection IDs instead.
This change will allow protocol clients to store metadata directly under the session ID. It will also allow settings to be stored as metadata rather than using a separate DB table, and the group and message metadata tables can be merged.
Sub-task of #136 (closed).