{"record":{"id":"77c796c65f49f02a","repo":"zeroclaw-labs/zeroclaw","slug":"amqps-requires-ca-cert-to-verify-the-broker","errorCode":null,"errorMessage":"amqps:// requires ca_cert to verify the broker","messagePattern":"amqps:// requires ca_cert to verify the broker","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":16614,"sourceCode":"    /// Checks:\n    /// - `amqp_url` uses a valid scheme (`amqp://` or `amqps://`)\n    /// - `amqps://` connections carry a CA certificate\n    /// - `client_cert` and `client_key` are supplied together (mutual TLS)\n    /// - the exchange is non-empty\n    /// - at least one routing key is bound\n    pub fn validate(&self) -> anyhow::Result<()> {\n        let is_tls = self.amqp_url.starts_with(\"amqps://\");\n        let is_plain = self.amqp_url.starts_with(\"amqp://\");\n\n        if !is_tls && !is_plain {\n            anyhow::bail!(\n                \"amqp_url must start with 'amqp://' or 'amqps://', got: {}\",\n                self.amqp_url\n            );\n        }\n\n        if is_tls && self.ca_cert.is_none() {\n            anyhow::bail!(\"amqps:// requires ca_cert to verify the broker\");\n        }\n\n        match (self.client_cert.is_some(), self.client_key.is_some()) {\n            (true, false) => {\n                anyhow::bail!(\n                    \"client_cert is set but client_key is missing (both are required for mutual TLS)\"\n                )\n            }\n            (false, true) => {\n                anyhow::bail!(\n                    \"client_key is set but client_cert is missing (both are required for mutual TLS)\"\n                )\n            }\n            _ => {}\n        }\n\n        if self.exchange.is_empty() {\n            validation_bail!(RequiredFieldEmpty, \"exchange\", \"exchange must not be empty\");","sourceCodeStart":16596,"sourceCodeEnd":16632,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L16596-L16632","documentation":"For `amqps://` connections the AMQP consumer must verify the broker against a CA certificate; ZeroClaw treats an unverified TLS connection as a misconfiguration rather than silently skipping verification. The validator therefore requires the `ca_cert` path to be set whenever the URL scheme is `amqps://`.","triggerScenarios":"`amqp_url = \"amqps://broker.example.com:5671/zeroclaw\"` with no `ca_cert` key; upgrading a URL from `amqp://` to `amqps://` and forgetting the trust anchor; assuming the system trust store is used implicitly (it is not — an explicit path is required).","commonSituations":"Onboarding to Fedora Messaging or a corporate RabbitMQ over TLS; copying an mTLS example that omits the CA line; the CA existing on disk but never being referenced in config.","solutions":["Set `ca_cert` to the PEM bundle that signed the broker certificate, e.g. `ca_cert = \"/etc/zeroclaw/ca.pem\"`.","For Fedora Messaging, use the CA provided by the project (e.g. `fedora-messaging` CA) at its documented path.","If TLS is not actually required, fall back to `amqp://` on port 5672."],"exampleFix":"# before\namqp_url = \"amqps://broker.example.com:5671/zeroclaw\"\n# no ca_cert\n\n# after\namqp_url = \"amqps://broker.example.com:5671/zeroclaw\"\nca_cert = \"/etc/zeroclaw/ca.pem\"","handlingStrategy":"validation","validationCode":"anyhow::ensure!(\n    !cfg.amqp_url.starts_with(\"amqps://\") || cfg.ca_cert.is_some(),\n    \"amqps:// requires an explicit ca_cert path\"\n);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Whenever you switch the scheme to amqps://, add ca_cert in the same edit.","ZeroClaw does not fall back to the system trust store — the path must be explicit.","Keep the CA bundle versioned alongside the config."],"tags":["amqp","tls","ca-cert","config","zeroclaw"],"backgroundTag":"tls-missing-ca-cert","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}