# checker-tls TLS posture checker for happyDomain. Consumes `DiscoveredEndpoint` entries published by service checkers (xmpp, srv, caldav, carddav, …) via `AutoFill: discovered_endpoints`, performs a real TCP dial, optional STARTTLS upgrade, and TLS handshake on each, and exports per-endpoint posture under the observation key `tls_probes`. ## Supported endpoint types | `DiscoveredEndpoint.Type` | Handshake | | --------------------------- | ---------------------------------------------- | | `tls` | Direct TLS on connect | | `starttls-smtp` | ESMTP EHLO + STARTTLS (RFC 3207) | | `starttls-submission` | Same as `starttls-smtp` | | `starttls-imap` | IMAP CAPABILITY + STARTTLS (RFC 3501) | | `starttls-pop3` | POP3 CAPA + STLS (RFC 2595) | | `starttls-xmpp-client` | XMPP c2s stream + `` (RFC 6120) | | `starttls-xmpp-server` | XMPP s2s stream + `` (RFC 6120) | | other `starttls-*` | Rejected with a `handshake_failed` issue | ## Payload shape Observation data under `tls_probes`: ```json { "probes": { "": { "host": "example.net", "port": 5222, "endpoint": "example.net:5222", "type": "starttls-xmpp-client", "sni": "example.net", "tls_version": "TLS1.3", "cipher_suite": "TLS_AES_128_GCM_SHA256", "hostname_match": true, "chain_valid": true, "not_after": "2026-07-01T00:00:00Z", "issuer": "Let's Encrypt", "issues": [] } }, "collected_at": "2026-04-21T12:34:56Z" } ``` Consumers pick their own endpoint from the map via `RelatedObservation.EndpointID`. ## Issues reported - `tcp_unreachable` — dial failed. - `handshake_failed` — TLS handshake or STARTTLS upgrade failed. - `starttls_not_offered` — server didn't advertise STARTTLS (severity depends on `Meta["starttls"]` = `"required"` vs `"opportunistic"`). - `chain_invalid` — leaf does not chain to a system-trusted root. - `hostname_mismatch` — cert SANs don't cover the SNI. - `expired` / `expiring_soon` — cert expiry posture. - `weak_tls_version` — negotiated TLS < 1.2. ## Options | Id | Type | Default | Description | | ----------------- | ------ | ------- | ------------------------------------------------ | | `probeTimeoutMs` | number | 10000 | Per-endpoint dial + handshake timeout in ms. | ## Running ```bash # Plugin (loaded by happyDomain at startup) make plugin # Standalone HTTP server make && ./checker-tls -listen :8080 ```