According to the source code of openssh-portable, the
-h flag modifies the certificate type and selects permitted options to None.
Here is the relevant source code:
/* Key type when certifying */
static u_int cert_key_type = SSH2_CERT_TYPE_USER; // L105
/* If -h is set, set certificate type to Host and set cert flags to none. */
case 'h': // L2573
cert_key_type = SSH2_CERT_TYPE_HOST;
certflags_flags = 0;
/* Set the certificate type to whatever value was set before */
public->cert->type = cert_key_type; // L1744
As you can see, that's all the magic.
If you used the wrong certificate type, then the verifying end will refuse to accept the certificate, as it was not signed for that purpose. You can't use a client certificate to identify as server, and you can't use a server certificate to authenticate as client. You can however use the same key to create both a client and a server certificate.
As it turns out, you can indeed use a client certificate for purposes of host identification, and vice versa. This seems to me like a bug.