Enrolment hands out the broker CA, and now the PC keeps it

The server has always sent the broker's CA certificate in the enrolment
response, precisely so it never has to ship in an installer. Nothing on
the receiving end wrote it anywhere: the agent read the field under the
wrong name (ca_pem, the server says ca_cert) and the desktop app read it
correctly and dropped it. Every claimed PC therefore dialled
tls://mcp.loyaly.ai:8883 with the system trust store, the private CA
failed verification, and the agent reported 'the broker did not accept
this PC' - a TLS failure is indistinguishable from a refusal at that
layer. No real site could ever have published a visit.

Found by claiming this Mac as a real shop against production; fixed by
writing the CA to broker-ca.crt beside agent.json on both claim paths.
Verified: broker connected over TLS, camera pushed from head office,
engine streaming it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KGcjxF1cNLcuwc3DAPcnfj
This commit is contained in:
2026-09-18 12:16:43 +05:30
parent a74cb899b4
commit 5f83a1077d
5 changed files with 39 additions and 3 deletions

View File

@@ -57,8 +57,11 @@ func InstallRoot() string {
}
func AgentConfig() string { return filepath.Join(StateRoot(), "agent.json") }
func SpoolDir() string { return filepath.Join(StateRoot(), "spool") }
func EngineLog() string { return filepath.Join(StateRoot(), "engine.log") }
// BrokerCA is the broker's CA certificate, written at enrolment.
func BrokerCA() string { return filepath.Join(StateRoot(), "broker-ca.crt") }
func SpoolDir() string { return filepath.Join(StateRoot(), "spool") }
func EngineLog() string { return filepath.Join(StateRoot(), "engine.log") }
// APICredentials is the file the engine writes when it generates its own
// Basic credentials. The agent reads it rather than storing a second copy,