Skip to content

Native HNS HTTPS (DANE/TLSA)

HeadlessDomains serves .agent, .chatbot and .boss domains over native Handshake HTTPS, validated with DANE rather than a public certificate authority. This page describes how an agent discovers and verifies that state.

There is no public CA in this path. A Handshake name cannot be validated by the WebPKI, so each domain uses a self-signed certificate whose public key is pinned in DNS as a TLSA 3 1 1 record. A client validates by comparing the SubjectPublicKeyInfo of the served certificate against the published hash.

Discovering the state

Two read-only surfaces expose the same information.

1. Agent manifest

https://headlessdomains.com/manifests/<domain>.json includes a transport block:

{
  "transport": {
    "native_https": {
      "status": "active",
      "certificate_model": "self_signed_per_domain",
      "validation": "dane-tlsa",
      "certificate_valid_from": "Sep  1 04:50:03 2026 GMT",
      "certificate_valid_to": "Aug 29 04:50:03 2036 GMT",
      "tlsa": {
        "name": "_443._tcp.0.agent",
        "usage": 3,
        "selector": 1,
        "matching_type": 1,
        "spki_sha256": "28874f2c8973687869a1d6fe1801f87cb6e0777e5111c5a94b864b4d0280e067"
      },
      "status_endpoint": "https://0.agent/status",
      "documentation": "https://docs.headlessdomains.com/specs/native-hns-https/"
    },
    "fallback_https": "https://profiles.host.limo/0.agent",
    "native_http": "http://0.agent"
  }
}

status is active when a certificate is provisioned, or planned when the domain is eligible but not yet set up. The tlsa and certificate fields are present only when status is active.

2. Status endpoint

https://<domain>/status, also reachable at https://profiles.host.limo/<domain>/status, returns the same state plus the live serving status of each transport:

{
  "status": "active",
  "agent_domain": "0.agent",
  "native_http": "active",
  "webpki_fallback_https": "active",
  "native_hns_https": {
    "status": "active",
    "managed": true,
    "certificate_valid_to": "Aug 29 04:50:03 2036 GMT",
    "tlsa_record": { "name": "_443._tcp.0.agent", "usage": 3,
                     "selector": 1, "matching_type": 1,
                     "spki_sha256": "28874f2c…" }
  }
}

Verifying it yourself

Do not trust the published metadata alone. Compare it against what the server actually serves:

# hash the public key of the served certificate
echo | openssl s_client -connect <domain>:443 -servername <domain> 2>/dev/null \
  | openssl x509 -pubkey -noout \
  | openssl pkey -pubin -outform der \
  | openssl dgst -sha256

# the TLSA record it must match
dig +short _443._tcp.<domain> TLSA

The two hashes must be identical. Query TLSA through a DNSSEC-validating Handshake resolver, and check the AD flag is set. A resolver that cannot answer TLSA queries, or that returns AD=false, cannot be used to validate DANE.

Three transports, and when each applies

Transport URL Who it is for
Native HNS HTTPS https://<domain> Handshake clients that validate DANE
Native HNS HTTP http://<domain> Handshake clients without DANE support
WebPKI fallback https://profiles.host.limo/<domain> Ordinary browsers

The fallback carries a normal publicly-trusted certificate and works everywhere. Native HTTPS fails closed in a correct client if the certificate stops matching the TLSA record, which is the intended behaviour.

What is not exposed

Neither surface returns private keys or secrets, and neither accepts a write. Everything published is already public: the SPKI hash is in DNS, and the validity dates are readable from the served certificate by any client that connects.