To extend on that, I can give list the lessons I learned from actually running a similar scheme internally in production for a while now:
1. Give developers the minimum amount of knobs. If they need to choose between 'auth', 'enc', 'seal' and 'sign' it's still going to be confusing. In my case they can personally come to me and ask "Which version should I use? Which type should I use?", but it's not clear.
I'm still undecided whether supporting an unencrypted authenticated token is useful, but 'enc' should ideally be the default, with users going a little bit more out of their way to do anything else.
2. Asymmetrically signed payloads with an expiry are this strange bird that looks like a duck, quacks like a duck but unfortunately _are not a duck_. They're certainly useful, but when I was calling them 'tokens', my users were confused whether they should use them as access tokens.
It's great to have a simple and robust encoding format for packaging payloads with an Ed25519 signature, but it's better to clearly call it something other than 'token', or you'll end up with users deciding they should use asymmetric access tokens just because it makes the key more secure.
3. You want to have some mechanism to specify key ID or key version in the wrapper, because this allows you to do automatic key rotation gracefully. You can use the optional (AEAD) payload for that, but that wouldn't be entirely clear to the users how.
Let's say you want to rotate the key every week, but your longest token has a TTL of 24 hours: you will need to have a window where you would support two different encryption keys. In other rotation scenarios (e.g. rotating every 24 hours with longest token TTL being 30 days) you can have many more encryption keys supported concurrently.
You can iterate and try all possible keys of course, but having key ID/version is much cleaner.