--- status: open opened: 2026-09-26 located-in: [mesh-controller, mesh-catalog step-ca] --- # 129 — nothing makes a machine trust the mesh's own certificate authority ## What was observed On an enrolled, adopted workstation — on the private network, resolving the mesh's names through the mesh's resolver — every HTTPS name the mesh serves internally fails verification: ``` curl https:/// curl: (60) SSL certificate OpenSSL verify result: unable to get local issuer certificate (20) ``` The route proxy presents a certificate issued by the mesh's internal authority (step-ca, the `internal-acme-ca` provision). The machine's trust store holds the **predecessor's** authority and a developer tool's local root, and nothing of the mesh's. No module installs the mesh's root, and no fact carries it: step-ca's only consumers are proxies, which obtain certificates over ACME and never need the root on the machine they run on. [Issue 048](../048-nothing-makes-a-machine-trust-the-mesh-registry/00-report.md) found the same shape for the mesh's registry and resolved it by treating the private network as the transport security ([ADR 0082](../../02-DECISIONS/0082-the-registry-is-reached-by-name-and-trusted-by-the-overlay.md)): the runtime pulls in the clear, over the tunnel. That answer does not carry over. A browser, git over HTTPS, a package manager and every TLS client a person or a module uses verify the certificate chain, and there is no "insecure registries" for them — nor should there be. Consequences today, all silent until someone tries: - a person on a workstation cannot open any internal HTTPS name without a warning; - git over HTTPS to the mesh's forge fails, so the working clone URL is ssh-only; - a module on a non-hub machine that calls another module's internal HTTPS name fails verification unless its image happens to carry the root; - the predecessor's authority cannot be retired from any machine while anything there still speaks TLS to a mesh name, because it is the only authority those machines trust. ## What would have prevented it - A **mesh fact carrying the internal authority's root** (public material; the controller or the step-ca module is its source), written onto every machine on the private network — the same reasoning that has the private network write the registry trust and the names: being on the network is what makes a machine one that speaks to the mesh's names. - A resource that puts it where the machine's TLS clients look — on Arch, `/etc/ca-certificates/trust-source/anchors/` — and **refreshes the extracted bundles** (`update-ca-trust`). The refresh is the open design question: it is a command, and the link may not carry an action ([ADR 0005](../../02-DECISIONS/0005-the-node-host.md)). A declared one-shot unit, or a host primitive for "trust this anchor", are the obvious candidates. - Removal symmetric to arrival: undeclared, the anchor goes and the bundles are refreshed again, so a machine leaving the mesh stops trusting it. ## Evidence to carry into diagnosis - `step-ca` module: provides `acme-ca` / `internal-acme-ca`, listens on 9000 for proxies; no resource writes its root anywhere but its own state directory. - The private network's generator writes `/etc/hosts` and the registry trust, and nothing about certificates. - On the workstation, the trust anchors present are the predecessor's authority and a local development root; `trust list` shows no entry for the mesh.