#[non_exhaustive]pub enum ControllerMessage {
Show 39 variants
Pong(PongPayload),
Enrolled(EnrolledPayload),
Approved(ApprovedPayload),
Rejected(RejectedPayload),
Certificate(CertificatePayload),
Error(ErrorPayload),
ServiceSettings(ServiceSettingsPayload),
CaBundleUpdated(CaBundleUpdatedPayload),
RequestCertRenewal(RequestCertRenewalPayload),
ServerRestarting(ServerRestartingPayload),
CheckVersions(CheckVersionsPayload),
ExecuteUpdate(Box<ExecuteUpdatePayload>),
ExecuteBatchUpdate(Box<ExecuteBatchUpdatePayload>),
DiscoverSoftware(DiscoverSoftwarePayload),
SetUpdateFreeze(SetUpdateFreezePayload),
UpdateStdinData(UpdateStdinDataPayload),
ResetData,
SoftwareStates(SoftwareStatesPayload),
HostConnectivityUpdated(HostConnectivityUpdatedPayload),
SurfaceActionRequest(SurfaceActionRequest),
SurfaceActionCancel(SurfaceActionCancel),
SurfaceActionResponse(SurfaceActionResponse),
ReportPluginConfigResponse(ReportPluginConfigResponsePayload),
ServiceCredentials(ServiceCredentialsPayload),
ServiceConfigDelivery(ServiceConfigDeliveryPayload),
ServiceConfigAck(ServiceConfigAckPayload),
ServiceConfigUpdated(ServiceConfigUpdatedPayload),
RequestCaRotation(RequestCaRotationPayload),
RequestCrlRenewal(RequestCrlRenewalPayload),
SoftwareStatesChanged(SoftwareStatesChangedPayload),
TokenRevoked(TokenRevokedPayload),
AccessInvalidated(AccessInvalidatedPayload),
BroadcastAdminEvent(BroadcastAdminEventPayload),
WorkloadClaimResult(WorkloadClaimResultPayload),
WorkloadClaimAnnouncement(WorkloadClaimAnnouncementPayload),
WorkloadClaimSyncRequest(WorkloadClaimSyncRequestPayload),
WorkloadClaimSyncResponse(WorkloadClaimSyncResponsePayload),
TestPluginConfig(TestPluginConfigPayload),
Unknown,
}Expand description
Messages sent from the controller to a service (agent or MQTT).
§Forward compatibility
The Unknown variant is a catch-all for message types introduced in newer
controller builds that an older service does not yet recognise. When
encountered, the service logs a warning and continues without closing the
connection, allowing rolling upgrades where services and controllers are not
updated simultaneously.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Pong(PongPayload)
Enrolled(EnrolledPayload)
Approved(ApprovedPayload)
Rejected(RejectedPayload)
Certificate(CertificatePayload)
Error(ErrorPayload)
ServiceSettings(ServiceSettingsPayload)
CaBundleUpdated(CaBundleUpdatedPayload)
RequestCertRenewal(RequestCertRenewalPayload)
ServerRestarting(ServerRestartingPayload)
CheckVersions(CheckVersionsPayload)
ExecuteUpdate(Box<ExecuteUpdatePayload>)
ExecuteBatchUpdate(Box<ExecuteBatchUpdatePayload>)
DiscoverSoftware(DiscoverSoftwarePayload)
SetUpdateFreeze(SetUpdateFreezePayload)
UpdateStdinData(UpdateStdinDataPayload)
Controller → Agent: forward stdin data or a signal to the running update process.
Only sent to agents that advertise the InteractiveUpdates capability
and have an in-flight interactive update matching the update_history_id.
Security: session-targeted, NEVER published to NATS.
ResetData
Controller → Services: reset all tenant-scoped data.
Broadcast to services with the ResetData capability after the
controller has cleared the database. Services should truncate their
local data stores (e.g. SSH host list, Proxmox state).
SoftwareStates(SoftwareStatesPayload)
HostConnectivityUpdated(HostConnectivityUpdatedPayload)
Agent connectivity changed for one or more hosts.
Published to NATS with target_capability = "update_tracking" by the controller
that owns the agent WebSocket connection (on connect and disconnect). The MQTT
service updates its per-tenant connectivity cache and publishes the
{prefix}/hosts/{h}/connectivity/state retained topic.
Safe to publish via NATS — contains no credential material.
SurfaceActionRequest(SurfaceActionRequest)
Proxied surface action invocation from the controller to a service.
Sent to services participating in the surface contract. The service
should process the action and respond with SurfaceActionResponse.
SurfaceActionCancel(SurfaceActionCancel)
Cancellation of an in-flight proxied surface action request.
Session-targeted and never published to NATS.
SurfaceActionResponse(SurfaceActionResponse)
Response to a service-initiated surface action invocation.
Sent by the controller after processing a
ServiceMessage::SurfaceActionRequest.
ReportPluginConfigResponse(ReportPluginConfigResponsePayload)
Response to a ReportPluginConfig request from a service.
Contains the plugin config ID if the operation succeeded, or an error
message if it failed. Idempotent: returns the existing config ID if a
matching (tenant_id, plugin_type, name) already exists.
ServiceCredentials(ServiceCredentialsPayload)
Infrastructure credentials for services that advertise credential capabilities. Fields are populated based on the service’s capability set:
database_access→db_urlis setnats_access→nats_urlis set (if controller has NATS)master_key_access→master_key_hexis set (if encryption enabled)
Security: NEVER published to NATS. Delivered locally via WebSocket only, following the same pattern as MQTT credential messages.
ServiceConfigDelivery(ServiceConfigDeliveryPayload)
Controller → Service: initial delivery of all stored config entries.
Sent once after authentication (after credential delivery if applicable). Security: contains decrypted sensitive values — NEVER published to NATS.
ServiceConfigAck(ServiceConfigAckPayload)
Controller → Service: acknowledgment of a store or delete operation.
Security: NEVER published to NATS — session-targeted.
ServiceConfigUpdated(ServiceConfigUpdatedPayload)
Controller → Service: incremental update pushed to all instances of the
same service_app_name when any instance modifies a config entry.
Security: may contain decrypted sensitive values — NEVER published to NATS.
RequestCaRotation(RequestCaRotationPayload)
Request from an external component (e.g. scheduler) for the controller to
perform CA certificate rotation. Published via NATS to the controller subject;
handled by triggering ca_rotation_trigger.notify_one().
RequestCrlRenewal(RequestCrlRenewalPayload)
Request all controller instances to rebuild the CRL immediately.
Published via NATS to the controller subject by any controller that
revokes a certificate or by the CrlRenewal scheduled task.
Receiving controllers fire revocation_notify.notify_one() so that
CrlManager::run() rebuilds and hot-reloads the TLS configuration.
SoftwareStatesChanged(SoftwareStatesChangedPayload)
Signal that software states have changed for a tenant.
Published to the controller NATS subject by the external scheduler
after a version-check run completes. The receiving controller loads
the states from the database and pushes them to update-tracking services.
TokenRevoked(TokenRevokedPayload)
Token revocation event published by the originating controller to the “controller” NATS subject so that all other instances update their in-memory denylist caches without a per-request DB query.
A message carries either a JTI-level revocation (when jti and exp
are set) or a user-level revocation (when user_id, iat_cutoff, and
purge_after are set). Both kinds may be present in a single message
(e.g. when revoking a specific token and all prior tokens for a user).
Safe to publish via NATS — contains no credential material.
AccessInvalidated(AccessInvalidatedPayload)
Cross-controller access-cache invalidation published by the controller that mutated access grants or role assignments. Controller→controller over NATS only — never sent over the service WebSocket. Receivers flush their whole access cache; the ID lists are diagnostic and forward-compat only (no granular invalidation promise).
Safe to publish via NATS — contains no credential material.
BroadcastAdminEvent(BroadcastAdminEventPayload)
Cross-controller admin event broadcast.
Published via NATS to the controller subject by any controller
instance when it emits an AdminEvent to local SSE subscribers.
Receiving controller instances decode the payload and re-broadcast
to their own local SSE subscribers using send_local /
send_global_local (without re-publishing to NATS to avoid loops).
Safe to publish via NATS — contains no credential material.
WorkloadClaimResult(WorkloadClaimResultPayload)
Controller → Service: grant/reject response for a workload claim.
Sent in response to WorkloadClaim, unsolicited for proactive
re-grants when previously rejected keys become available, or for
revocations during cross-controller conflict resolution.
Session-targeted: NEVER published to NATS.
WorkloadClaimAnnouncement(WorkloadClaimAnnouncementPayload)
Controller → NATS: announce claim state changes for cross-controller sync.
Published to the controller NATS subject after granting or releasing
claims. Other controllers update their global claim registry from this.
Safe to publish via NATS — contains no credential material.
WorkloadClaimSyncRequest(WorkloadClaimSyncRequestPayload)
Controller → NATS: request full claim state from all active controllers.
Published on controller startup. Each active controller responds with
WorkloadClaimSyncResponse.
NATS-only (controller-to-controller).
WorkloadClaimSyncResponse(WorkloadClaimSyncResponsePayload)
Controller → NATS: respond with full local claim state.
Sent in response to WorkloadClaimSyncRequest.
NATS-only (controller-to-controller).
TestPluginConfig(TestPluginConfigPayload)
Controller -> Agent: test a plugin configuration on a specific host.
Sent when a user invokes the config test API endpoint for an agent-side
plugin. The agent executes the test and responds with
ServiceMessage::TestPluginConfigResult.
Security: session-targeted, NEVER published to NATS.
Unknown
Unknown message type from a newer controller build.
Deserialized when the type tag does not match any known variant.
The payload is discarded. The receiver should log a warning and
continue processing other messages.
Security: Never published to NATS — we cannot re-publish a message whose payload has been discarded.
Implementations§
Source§impl ControllerMessage
impl ControllerMessage
Sourcepub fn is_nats_publishable(&self) -> bool
pub fn is_nats_publishable(&self) -> bool
Returns true if this message may be published to NATS JetStream.
Credential-bearing variants (ServiceCredentials) and session-targeted
variants (SurfaceActionRequest, SurfaceActionCancel,
SurfaceActionResponse)
must never be published to NATS — they are delivered exclusively
over authenticated WebSocket connections. All other variants are safe
to broadcast via NATS.
This is the authoritative gate used by [NatsConnection::publish].
Trait Implementations§
Source§impl Clone for ControllerMessage
impl Clone for ControllerMessage
Source§fn clone(&self) -> ControllerMessage
fn clone(&self) -> ControllerMessage
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ControllerMessage
impl Debug for ControllerMessage
Source§impl<'de> Deserialize<'de> for ControllerMessage
impl<'de> Deserialize<'de> for ControllerMessage
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for ControllerMessage
Source§impl PartialEq for ControllerMessage
impl PartialEq for ControllerMessage
Source§impl Serialize for ControllerMessage
impl Serialize for ControllerMessage
impl StructuralPartialEq for ControllerMessage
Source§impl WireValidate for ControllerMessage
impl WireValidate for ControllerMessage
Source§fn wire_validate(&self) -> Result<(), WireValidationError>
fn wire_validate(&self) -> Result<(), WireValidationError>
Auto Trait Implementations§
impl Freeze for ControllerMessage
impl RefUnwindSafe for ControllerMessage
impl Send for ControllerMessage
impl Sync for ControllerMessage
impl Unpin for ControllerMessage
impl UnsafeUnpin for ControllerMessage
impl UnwindSafe for ControllerMessage
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.