asyncapi: 3.0.0
info:
title: Uptrakit Service-Controller Protocol
version: 0.0.3
description: 'Generated from the Rust wire types (uptrakit-wire). Do not edit by hand; regenerate with the golden test in tests.rs (UPDATE_ASYNCAPI=1). Protocol narrative (enrollment lifecycle, CSR issuance, reconnection semantics): docs/api/wire-protocol.md.'
channels:
service:
address: /api/v1/ws/service
messages:
audit_event:
$ref: '#/components/messages/audit_event'
batch_update_result:
$ref: '#/components/messages/batch_update_result'
delete_service_config:
$ref: '#/components/messages/delete_service_config'
disconnecting:
$ref: '#/components/messages/disconnecting'
discovery_results:
$ref: '#/components/messages/discovery_results'
enroll:
$ref: '#/components/messages/enroll'
ping:
$ref: '#/components/messages/ping'
register:
$ref: '#/components/messages/register'
renew_certificate:
$ref: '#/components/messages/renew_certificate'
report_hosts:
$ref: '#/components/messages/report_hosts'
report_plugin_config:
$ref: '#/components/messages/report_plugin_config'
request_certificate:
$ref: '#/components/messages/request_certificate'
service_trigger_host_batch_update:
$ref: '#/components/messages/service_trigger_host_batch_update'
service_trigger_update:
$ref: '#/components/messages/service_trigger_update'
stdin_attention:
$ref: '#/components/messages/stdin_attention'
store_service_config:
$ref: '#/components/messages/store_service_config'
surface_action_request:
$ref: '#/components/messages/surface_action_request'
surface_action_response:
$ref: '#/components/messages/surface_action_response'
surface_registration:
$ref: '#/components/messages/surface_registration'
test_plugin_config_result:
$ref: '#/components/messages/test_plugin_config_result'
update_output:
$ref: '#/components/messages/update_output'
update_result:
$ref: '#/components/messages/update_result'
update_started:
$ref: '#/components/messages/update_started'
version_check_results:
$ref: '#/components/messages/version_check_results'
workload_claim:
$ref: '#/components/messages/workload_claim'
workload_release:
$ref: '#/components/messages/workload_release'
access_invalidated:
$ref: '#/components/messages/access_invalidated'
approved:
$ref: '#/components/messages/approved'
broadcast_admin_event:
$ref: '#/components/messages/broadcast_admin_event'
ca_bundle_updated:
$ref: '#/components/messages/ca_bundle_updated'
certificate:
$ref: '#/components/messages/certificate'
check_versions:
$ref: '#/components/messages/check_versions'
discover_software:
$ref: '#/components/messages/discover_software'
enrolled:
$ref: '#/components/messages/enrolled'
error:
$ref: '#/components/messages/error'
execute_batch_update:
$ref: '#/components/messages/execute_batch_update'
execute_update:
$ref: '#/components/messages/execute_update'
host_connectivity_updated:
$ref: '#/components/messages/host_connectivity_updated'
pong:
$ref: '#/components/messages/pong'
rejected:
$ref: '#/components/messages/rejected'
report_plugin_config_response:
$ref: '#/components/messages/report_plugin_config_response'
request_ca_rotation:
$ref: '#/components/messages/request_ca_rotation'
request_cert_renewal:
$ref: '#/components/messages/request_cert_renewal'
request_crl_renewal:
$ref: '#/components/messages/request_crl_renewal'
reset_data:
$ref: '#/components/messages/reset_data'
server_restarting:
$ref: '#/components/messages/server_restarting'
service_config_ack:
$ref: '#/components/messages/service_config_ack'
service_config_delivery:
$ref: '#/components/messages/service_config_delivery'
service_config_updated:
$ref: '#/components/messages/service_config_updated'
service_credentials:
$ref: '#/components/messages/service_credentials'
service_settings:
$ref: '#/components/messages/service_settings'
set_update_freeze:
$ref: '#/components/messages/set_update_freeze'
software_states:
$ref: '#/components/messages/software_states'
software_states_changed:
$ref: '#/components/messages/software_states_changed'
surface_action_cancel:
$ref: '#/components/messages/surface_action_cancel'
test_plugin_config:
$ref: '#/components/messages/test_plugin_config'
token_revoked:
$ref: '#/components/messages/token_revoked'
update_stdin_data:
$ref: '#/components/messages/update_stdin_data'
workload_claim_announcement:
$ref: '#/components/messages/workload_claim_announcement'
workload_claim_result:
$ref: '#/components/messages/workload_claim_result'
workload_claim_sync_request:
$ref: '#/components/messages/workload_claim_sync_request'
workload_claim_sync_response:
$ref: '#/components/messages/workload_claim_sync_response'
operations:
sendToController:
action: send
channel:
$ref: '#/channels/service'
messages:
- $ref: '#/channels/service/messages/audit_event'
- $ref: '#/channels/service/messages/batch_update_result'
- $ref: '#/channels/service/messages/delete_service_config'
- $ref: '#/channels/service/messages/disconnecting'
- $ref: '#/channels/service/messages/discovery_results'
- $ref: '#/channels/service/messages/enroll'
- $ref: '#/channels/service/messages/ping'
- $ref: '#/channels/service/messages/register'
- $ref: '#/channels/service/messages/renew_certificate'
- $ref: '#/channels/service/messages/report_hosts'
- $ref: '#/channels/service/messages/report_plugin_config'
- $ref: '#/channels/service/messages/request_certificate'
- $ref: '#/channels/service/messages/service_trigger_host_batch_update'
- $ref: '#/channels/service/messages/service_trigger_update'
- $ref: '#/channels/service/messages/stdin_attention'
- $ref: '#/channels/service/messages/store_service_config'
- $ref: '#/channels/service/messages/surface_action_request'
- $ref: '#/channels/service/messages/surface_action_response'
- $ref: '#/channels/service/messages/surface_registration'
- $ref: '#/channels/service/messages/test_plugin_config_result'
- $ref: '#/channels/service/messages/update_output'
- $ref: '#/channels/service/messages/update_result'
- $ref: '#/channels/service/messages/update_started'
- $ref: '#/channels/service/messages/version_check_results'
- $ref: '#/channels/service/messages/workload_claim'
- $ref: '#/channels/service/messages/workload_release'
receiveFromController:
action: receive
channel:
$ref: '#/channels/service'
messages:
- $ref: '#/channels/service/messages/access_invalidated'
- $ref: '#/channels/service/messages/approved'
- $ref: '#/channels/service/messages/broadcast_admin_event'
- $ref: '#/channels/service/messages/ca_bundle_updated'
- $ref: '#/channels/service/messages/certificate'
- $ref: '#/channels/service/messages/check_versions'
- $ref: '#/channels/service/messages/discover_software'
- $ref: '#/channels/service/messages/enrolled'
- $ref: '#/channels/service/messages/error'
- $ref: '#/channels/service/messages/execute_batch_update'
- $ref: '#/channels/service/messages/execute_update'
- $ref: '#/channels/service/messages/host_connectivity_updated'
- $ref: '#/channels/service/messages/pong'
- $ref: '#/channels/service/messages/rejected'
- $ref: '#/channels/service/messages/report_plugin_config_response'
- $ref: '#/channels/service/messages/request_ca_rotation'
- $ref: '#/channels/service/messages/request_cert_renewal'
- $ref: '#/channels/service/messages/request_crl_renewal'
- $ref: '#/channels/service/messages/reset_data'
- $ref: '#/channels/service/messages/server_restarting'
- $ref: '#/channels/service/messages/service_config_ack'
- $ref: '#/channels/service/messages/service_config_delivery'
- $ref: '#/channels/service/messages/service_config_updated'
- $ref: '#/channels/service/messages/service_credentials'
- $ref: '#/channels/service/messages/service_settings'
- $ref: '#/channels/service/messages/set_update_freeze'
- $ref: '#/channels/service/messages/software_states'
- $ref: '#/channels/service/messages/software_states_changed'
- $ref: '#/channels/service/messages/surface_action_cancel'
- $ref: '#/channels/service/messages/surface_action_request'
- $ref: '#/channels/service/messages/surface_action_response'
- $ref: '#/channels/service/messages/test_plugin_config'
- $ref: '#/channels/service/messages/token_revoked'
- $ref: '#/channels/service/messages/update_stdin_data'
- $ref: '#/channels/service/messages/workload_claim_announcement'
- $ref: '#/channels/service/messages/workload_claim_result'
- $ref: '#/channels/service/messages/workload_claim_sync_request'
- $ref: '#/channels/service/messages/workload_claim_sync_response'
components:
schemas:
AttestationStatus:
description: 'Open wire string (unknown values are forward-compatible). Known values: Verified, NotFound, Unverified.'
type: string
BatchUpdateItem:
description: A single software item within a batch update request.
type: object
properties:
host_software_item_id:
description: Host software item entity ID.
type: string
format: uuid
update_history_id:
description: Update history record ID (pre-created by the controller).
type: string
format: uuid
package_identifier:
description: Plugin-specific package identifier (e.g., APT package name).
type: string
to_version:
description: Target version to install.
type: string
release_info:
description: Optional release metadata from the upstream source.
anyOf:
- $ref: '#/components/schemas/ReleaseInfo'
- type: 'null'
required:
- host_software_item_id
- update_history_id
- package_identifier
- to_version
BatchUpdateItemResult:
description: Result of updating a single item within a batch operation.
type: object
properties:
host_software_item_id:
description: Host software item entity ID.
type: string
format: uuid
update_history_id:
description: Update history record ID.
type: string
format: uuid
status:
description: Final status of this item's update.
$ref: '#/components/schemas/UpdateFinalStatus'
output:
description: Accumulated output from the update.
type: string
installed_version:
description: Detected installed version after the update (if detection succeeded).
type:
- string
- 'null'
error:
description: Error message if the update failed.
type:
- string
- 'null'
required:
- host_software_item_id
- update_history_id
- status
- output
Capability:
description: 'Open wire string (unknown values are forward-compatible). Known values: graceful_shutdown, update_tracking, software_discovery, ssh_remote, update_hooks, scheduler, database_access, nats_access, master_key_access, ca_management, system_service, ui_surfaces, interactive_updates, reset_data, workload_claims.'
type: string
ConfigTestKind:
description: The kind of configuration test to perform on the agent.
oneOf:
- description: Execute `detect_installed_version()` and return output + detected version.
type: string
const: version_detection
- description: Validate update_command syntax (sh -n check, do NOT execute).
type: string
const: update_command_validation
- description: Execute pre-update hook with mock context.
type: string
const: pre_update_hook
- description: Execute post-update hook with mock context.
type: string
const: post_update_hook
- description: Test connectivity for controller-side plugins (`fetch_releases`).
type: string
const: connectivity
DisconnectReason:
description: 'Open wire string (unknown values are forward-compatible). Known values: shutdown, restart.'
type: string
DiscoveredSoftware:
description: |-
A piece of software discovered on the local system by a plugin.
`installed_version` is required — plugins that cannot determine a version
must omit the item from results entirely.
This type is the canonical shared definition used in both the agent/plugin
layer and the wire protocol. The `uptrakit-plugin-core` crate re-exports it.
# Discovery targets
The `targets` field drives plugin-config creation and role assignment on the
controller. When non-empty, the controller processes each target generically
(find-or-create plugin config, create role assignments). When empty, the
controller falls back to the `plugin_config_id` on the enclosing
`DiscoveryPluginResult`.
The `extra` field is purely informational metadata (e.g. Docker's container
names) — the controller never interprets it for config synthesis.
# Per-row qualifier
The `qualifier` field selects which `host_software_item` row to create or
reuse. `None` = unqualified (default behaviour, one row per software item per
host). Docker uses the container name here so that each container gets its
own tracking row even when multiple containers run the same image.
# Plugin package identifier
`plugin_package_identifier`, when set, overrides `package_identifier` as the
value stored in `host_software_item_plugin.package_identifier` for plugin
operations. `None` = use `package_identifier` (existing behaviour).
# Pinning
When `featured` is `true`, the controller marks the software item as
featured on first creation so it gets individual MQTT entities and
prominent visibility. Default `false` — item starts unfeatured
(bulk/aggregate view only). The controller only applies `featured: true`
when **creating** a new `software_items` row. Subsequent discoveries do
not override a user's manual feature/unfeature choice.
type: object
properties:
package_identifier:
description: Plugin-specific identifier for this software (e.g., package name, app slug).
type: string
name:
description: Human-readable display name.
type: string
installed_version:
description: Currently installed version (required; plugins omit items with unknown versions).
type: string
targets:
description: |-
Target plugin configurations for managing this item.
Empty = use the discovering plugin's own config for all roles.
type: array
items:
$ref: '#/components/schemas/DiscoveryTarget'
extra:
description: |-
Optional informational metadata (not used for config synthesis).
Example: Docker's `{"containers": ["web-server"]}`.
qualifier:
description: |-
Row discriminator within `host_software_items`.
`None` = unqualified (default). Docker sets this to the container name
so that each container produces its own `host_software_item` row even
when multiple containers run the same image.
type:
- string
- 'null'
plugin_package_identifier:
description: |-
Override for the `package_identifier` stored in
`host_software_item_plugin.package_identifier`.
`None` = use `package_identifier` (existing behaviour).
type:
- string
- 'null'
featured:
description: |-
When `true`, the controller marks the software item as featured on
first creation. Default `false` — item starts unfeatured.
type: boolean
default: false
installed_display_version:
description: |-
Plugin-provided display version for the installed version (e.g. Docker image publish date).
`None` when the plugin cannot determine a display version during discovery.
type:
- string
- 'null'
required:
- package_identifier
- name
- installed_version
DiscoveryPluginAssignment:
description: A single plugin assignment inside a [`DiscoverSoftwarePayload`].
type: object
properties:
plugin_config_id:
description: Pre-existing plugin config ID, or `None` for a default/auto run.
type:
- string
- 'null'
format: uuid
plugin_type:
description: Plugin type to use for discovery.
$ref: '#/components/schemas/PluginTypeId'
config:
description: Plugin-specific configuration (`{}` for default assignments).
required:
- plugin_type
- config
DiscoveryPluginResult:
description: Result for a single plugin inside a [`DiscoveryResultsPayload`].
type: object
properties:
plugin_config_id:
description: |-
Echoed from [`DiscoveryPluginAssignment`] so the controller can route
results to the correct `PluginConfig` row.
type:
- string
- 'null'
format: uuid
plugin_type:
description: Plugin type that produced these results.
$ref: '#/components/schemas/PluginTypeId'
discoveries:
description: Discovered software items (empty on error).
type: array
items:
$ref: '#/components/schemas/DiscoveredSoftware'
error:
description: Plugin-level error message, if discovery failed.
type:
- string
- 'null'
required:
- plugin_type
DiscoveryTarget:
description: |-
A structured target that tells the autodiscovery controller exactly which
plugin config (and role assignments) to create for a discovered software item.
Plugins emit `DiscoveryTarget` values inside [`super::DiscoveredSoftware::targets`]
so that the web-API controller can process them generically — without any
plugin-specific synthesis logic.
# Examples
PHS plugin discovering a GitHub-managed app (fetch releases only; the
`owner/repo` is expressed as the `package_identifier` override):
```
# use uptrakit_shared_types::{DiscoveryTarget, PluginTypeId, PluginRole, plugin_ids};
let target = DiscoveryTarget {
plugin_type: plugin_ids::RELEASES_GITHUB.clone(),
plugin_config: serde_json::json!({
"tag_strip_prefix": "v",
"include_prereleases": false,
}),
plugin_config_name: "GitHub Releases".to_string(),
roles: vec![PluginRole::FetchReleases],
package_identifier: Some("BookLore/BookLore".to_string()),
config_override: None,
execution_site: None,
};
```
type: object
properties:
plugin_type:
description: |-
Target plugin type (may differ from the discovering plugin).
For example, the PHS plugin discovers software but targets
`releases.github` or `package-manager.apt` for tracking.
$ref: '#/components/schemas/PluginTypeId'
plugin_config:
description: |-
Config JSON for find-or-create of the target plugin config.
The controller will search for an existing active plugin config
whose JSON matches this value, or create a new one.
plugin_config_name:
description: Display name for auto-created plugin config (e.g. "BookLore/BookLore").
type: string
roles:
description: |-
Which roles this target covers.
Typically all three: `DetectVersion`, `FetchReleases`, `ExecuteUpdate`.
type: array
items:
$ref: '#/components/schemas/PluginRole'
package_identifier:
description: |-
Package identifier override (None = same as parent `DiscoveredSoftware`).
Used when the target plugin needs a different identifier than the
discovering plugin's slug (e.g. PHS slug → APT package name).
type:
- string
- 'null'
config_override:
description: Per-assignment config override.
execution_site:
description: Execution site hint (`"auto"` | `"agent"` | `"controller"`; None = `"auto"`).
type:
- string
- 'null'
required:
- plugin_type
- plugin_config
- plugin_config_name
- roles
EnrollmentStatus:
description: 'Open wire string (unknown values are forward-compatible). Known values: pending, approved.'
type: string
ErrorCode:
description: 'Open wire string (unknown values are forward-compatible). Known values: bad_request, enrollment_failed, not_approved, forbidden, certificate_error, internal_error, sequence_error.'
type: string
HostConnectivityUpdate:
description: Connectivity status for a single host, used in [`HostConnectivityUpdatedPayload`].
type: object
properties:
host_id:
description: Host UUID.
type: string
format: uuid
online:
description: Whether the agent is currently connected (`true` = online, `false` = offline).
type: boolean
last_seen_at:
description: Timestamp of last agent activity (ISO 8601). `null` when unavailable.
type:
- string
- 'null'
agent_version:
description: Agent binary version. Present on connect; `null` on disconnect.
type:
- string
- 'null'
required:
- host_id
- online
HostInfo:
description: Information about the host machine running the agent.
type: object
properties:
machine_id:
description: |-
Persistent machine identifier (e.g. `/etc/machine-id` on Linux, `IOPlatformUUID` on macOS).
Falls back to `"unknown"` if the identifier cannot be read.
type: string
os_type:
description: Operating system type (e.g. "linux", "macos").
type:
- string
- 'null'
os_version:
description: Operating system version (e.g. "Ubuntu 24.04 LTS").
type:
- string
- 'null'
architecture:
description: CPU architecture (e.g. "x86_64", "aarch64").
type:
- string
- 'null'
hostname:
description: Hostname reported by the agent/host machine.
type:
- string
- 'null'
ip_address:
description: Network address of the host (SSH target address for SSH agent hosts).
type:
- string
- 'null'
agent_host_id:
description: |-
Agent-local UUID assigned to this host at bootstrap time.
When present, the controller uses this as `hosts.id` when creating a
new row, ensuring agent and controller share the same UUID. This is
required for plugin FK operations (e.g. Proxmox host mapping) that
reference `hosts.id` before the controller has generated its own UUID.
type:
- string
- 'null'
format: uuid
features:
description: |-
Agent-probed host features (e.g. `["posix_shell", "privilege_escalation", "systemd"]`).
`None` for legacy agents that predate feature reporting. Uses `Vec<String>`
(not `BTreeSet<HostFeature>`) on the wire for forward-compatibility: if a
newer agent reports a feature the controller doesn't know, it is stored
losslessly and ignored by `HostCapabilities` parsing.
type:
- array
- 'null'
items:
type: string
required:
- machine_id
HostPackageSummary:
description: |-
Per-host aggregate summary of unpinned (unfeatured) software items.
Included in [`SoftwareStatesPayload`] to surface overall update
status per host to Home Assistant via a single `update` entity per host.
type: object
properties:
host_id:
description: Host UUID.
type: string
format: uuid
hostname:
description: Human-readable hostname.
type: string
friendly_name:
description: User-defined display name for the host.
type: string
default: ''
pending_count:
description: Count of items where `installed_version != latest_version` (both known).
type: integer
format: uint32
minimum: 0
security_pending_count:
description: |-
Count of items where `update_category = "security"` AND versions differ.
Used to drive the per-host security updates entity in Home Assistant.
type: integer
format: uint32
minimum: 0
total_count:
description: Total count of enabled, non-deactivated unfeatured items for this host.
type: integer
format: uint32
minimum: 0
update_in_progress:
description: Whether a batch update is currently pending or in progress for this host.
type: boolean
bugfix_count:
description: |-
Count of pending packages where `update_category = "bugfix"`.
Defaults to `0` when absent (older controller that does not compute this field).
type: integer
format: uint32
minimum: 0
default: 0
feature_count:
description: |-
Count of pending packages where `update_category = "feature"`.
Defaults to `0` when absent (older controller that does not compute this field).
type: integer
format: uint32
minimum: 0
default: 0
required:
- host_id
- hostname
- pending_count
- security_pending_count
- total_count
- update_in_progress
HostStateMetadata:
description: |-
Per-host metadata published to MQTT for MQTT-browser visibility and Home Assistant.
Included in [`SoftwareStatesPayload`]. All fields are sourced exclusively
from the shared DB — safe for multi-controller deployments.
Intentionally excludes `ip_address` (network topology risk) and `agent_online`
(must come from the event-driven [`HostConnectivityUpdatedPayload`]).
type: object
properties:
host_id:
description: Host UUID.
type: string
format: uuid
hostname:
description: Hostname as reported by the agent.
type: string
friendly_name:
description: User-defined display name.
type: string
os_type:
description: Operating system type (e.g. `"linux"`, `"macos"`). `null` when unknown.
type:
- string
- 'null'
os_version:
description: Operating system version (e.g. `"Ubuntu 24.04 LTS"`). `null` when unknown.
type:
- string
- 'null'
architecture:
description: CPU architecture (e.g. `"x86_64"`, `"aarch64"`). `null` when unknown.
type:
- string
- 'null'
tags:
description: Organisational tag names assigned to this host (e.g. `["production", "web-server"]`).
type: array
items:
type: string
default: []
agent_version:
description: |-
Agent binary version string (e.g. `"0.2.1"`). `null` when never connected.
Sourced from `services.client_version` for the newest approved, non-deactivated
agent linked to this host.
type:
- string
- 'null'
agent_last_seen_at:
description: |-
ISO 8601 timestamp of when the agent last sent a message.
Sourced from `services.last_seen_at`. `null` when never seen.
type:
- string
- 'null'
required:
- host_id
- hostname
- friendly_name
OutputStreamType:
description: Output stream source for update execution output lines.
type: string
enum:
- stdout
- stderr
- pre_hook
- post_hook
- system
PluginAssignment:
description: A plugin assignment for a specific role in a version check or update.
type: object
properties:
plugin_type:
description: The plugin type (e.g. github_releases, apt, homebrew).
$ref: '#/components/schemas/PluginTypeId'
package_identifier:
description: Package identifier for this role's plugin.
type: string
config:
description: Merged plugin config (base + override).
required:
- plugin_type
- package_identifier
- config
PluginRole:
description: 'Open wire string (unknown values are forward-compatible). Known values: detect_version, fetch_releases, execute_update, pre_update_hook, post_update_hook.'
type: string
PluginTypeId:
description: |-
Opaque plugin type identifier — validated at the catalog boundary.
Uses `Cow<'static, str>` so well-known constants are zero-allocation borrows
while DB/wire values are owned strings. Both are the same type.
This replaces `PluginType` enum. Instead of matching on variants, code looks up
the `PluginTypeId` in the `PluginCatalog` to get a `PluginDescriptor`.
type: string
ReleaseAsset:
description: A downloadable asset attached to a release.
type: object
properties:
name:
description: Asset filename.
type: string
download_url:
description: Direct download URL.
type: string
size:
description: File size in bytes, if known.
type:
- integer
- 'null'
format: uint64
minimum: 0
content_type:
description: MIME content type, if known.
type:
- string
- 'null'
sha256_digest:
description: SHA-256 digest from the release checksums file, if available.
type:
- string
- 'null'
required:
- name
- download_url
ReleaseInfo:
description: |-
Simplified release info for update execution context.
Contains the minimal release metadata needed by plugins to execute updates.
type: object
properties:
tag:
type: string
release_url:
type: string
assets:
type: array
items:
$ref: '#/components/schemas/ReleaseAsset'
attestation_status:
description: |-
Attestation status as determined by the GitHub Attestations API.
Set by the controller from the most recent `fetch_releases` run.
`None` means the check was never performed or the source is not GitHub.
anyOf:
- $ref: '#/components/schemas/AttestationStatus'
- type: 'null'
require_attestation:
description: |-
When `true`, the agent must abort the update if attestation is not `Verified`.
Copied from `GitHubConfig.require_attestation` by the controller at
trigger time.
type: boolean
default: false
required:
- tag
- release_url
ReportPageLimits:
description: Per-page item-count limits for paginated report payloads.
type: object
properties:
report_hosts:
description: Maximum `hosts` items per `report_hosts` page.
type: integer
format: uint32
minimum: 0
version_check_results:
description: Maximum `results` items per `version_check_results` page.
type: integer
format: uint32
minimum: 0
discovery_results:
description: Maximum `results` items per `discovery_results` page.
type: integer
format: uint32
minimum: 0
batch_update_results:
description: Maximum `results` items per `batch_update_result` page.
type: integer
format: uint32
minimum: 0
required:
- report_hosts
- version_check_results
- discovery_results
- batch_update_results
ReportPagination:
required:
- report_id
- page
- total_pages
title: ReportPagination
description: |-
Pagination metadata for a paginated report.
When a service needs to send a report that exceeds the WebSocket frame
limit, it splits the payload into pages. Each page carries the same
`report_id` and a 1-based `page` number out of `total_pages`.
The controller processes each page immediately (no payload buffering) and
defers only lightweight finalization (e.g. notification emission) until the
final page arrives.
type: object
properties:
report_id:
description: Unique identifier grouping all pages of the same logical report.
type: string
format: uuid
page:
description: 1-based page number within the report.
type: integer
format: uint32
minimum: 0
total_pages:
description: Total number of pages in the report (known upfront by the sender).
type: integer
format: uint32
minimum: 0
ServiceConfigEntry:
description: |-
A single stored service config entry, delivered to the service.
Sensitive values are already decrypted by the controller before delivery.
type: object
properties:
tenant_id:
description: Tenant this entry belongs to, or `None` for global entries.
type:
- string
- 'null'
format: uuid
key:
description: Entry key (e.g. `"clients.{uuid}"`).
type: string
value:
description: Entry value (plaintext JSON; controller decrypts before delivery).
required:
- key
- value
ServiceConfigKey:
description: Identifies a service config entry by scope and key (used in delete notifications).
type: object
properties:
tenant_id:
description: Tenant this entry belongs to, or `None` for global entries.
type:
- string
- 'null'
format: uuid
key:
description: Entry key.
type: string
required:
- key
SoftwareStateHostEntry:
description: Per-host version data for a software item.
type: object
properties:
host_id:
description: Host UUID.
type: string
format: uuid
hostname:
description: Human-readable hostname.
type: string
friendly_name:
description: User-defined display name for the host.
type: string
installed_version:
description: Currently installed version, if known.
type:
- string
- 'null'
latest_version:
description: Latest available version, if known.
type:
- string
- 'null'
update_available:
description: Whether an update is available (`latest_version > installed_version`).
type: boolean
update_in_progress:
description: |-
Whether an update is currently pending or in progress for this host-item pair.
Set to `true` when an `update_history` record exists with status
`Pending` or `InProgress`. Cleared to `false` once the update
completes or fails. Defaults to `false` when absent (older controller).
type: boolean
default: false
release_url:
description: URL to the upstream release page (e.g. GitHub release), if available.
type:
- string
- 'null'
release_notes:
description: Release notes or changelog text, if available.
type:
- string
- 'null'
update_category:
description: |-
Classification of the update (e.g. `"security"`, `"bugfix"`, `"feature"`, `"unknown"`).
Sourced from `host_software_item.update_category`. Defaults to `"unknown"` when absent.
type:
- string
- 'null'
release_date:
description: |-
Date when the latest release was published (ISO 8601 date string, e.g. `"2025-01-15"`).
Extracted from `latest_release_metadata.published_at`. `null` when metadata is absent.
type:
- string
- 'null'
last_checked_at:
description: |-
Timestamp when the installed version was last detected (ISO 8601).
Sourced from `host_software_item.installed_version_detected_at`. `null` when never checked.
type:
- string
- 'null'
required:
- host_id
- hostname
- friendly_name
- update_available
SoftwareStateItem:
description: A single software item entry in [`SoftwareStatesPayload`].
type: object
properties:
software_item_id:
description: Software item UUID.
type: string
format: uuid
name:
description: Human-readable software item name.
type: string
icon_url:
description: |-
Optional HTTPS URL to an icon/logo image.
When present, the MQTT service includes this as `entity_picture` in the
Home Assistant discovery config so HA displays it as the entity thumbnail.
Limited to [`crate::limits::MAX_ICON_URL_LEN`] characters.
type:
- string
- 'null'
hosts:
description: Per-host version data for this software item.
type: array
items:
$ref: '#/components/schemas/SoftwareStateHostEntry'
required:
- software_item_id
- name
- hosts
SoftwareStatesPage:
description: |-
Pagination metadata for a [`SoftwareStatesPayload`] message.
All payloads carry a `page` field. For single-page delivery use
`{ page_index: 0, total_pages: 1 }`. Multi-page delivery uses
`page_index` 0…N-1; the last page satisfies `page_index + 1 == total_pages`.
type: object
properties:
page_index:
description: Zero-based index of this page.
type: integer
format: uint32
minimum: 0
total_pages:
description: Total number of pages in this delivery batch.
type: integer
format: uint32
minimum: 0
required:
- page_index
- total_pages
TraceContext:
required:
- trace_id
title: TraceContext
description: |-
Distributed tracing context for correlating messages across service boundaries.
## Wire format
```json
{"trace_id":"0123456789abcdef0123456789abcdef","span_id":"0123456789abcdef"}
```
- `trace_id`: 32 lowercase hex characters (128-bit identifier)
- `span_id`: 16 lowercase hex characters (64-bit identifier), omitted when absent
type: object
properties:
trace_id:
description: 128-bit trace identifier encoded as 32 lowercase hex characters.
type: string
span_id:
description: |-
64-bit span identifier encoded as 16 lowercase hex characters.
`None` when no parent span is active.
type:
- string
- 'null'
UpdateCategory:
description: 'Open wire string (unknown values are forward-compatible). Known values: security, bugfix, feature, unknown.'
type: string
UpdateFinalStatus:
description: 'Open wire string (unknown values are forward-compatible). Known values: completed, failed.'
type: string
VersionCheckAssignment:
description: A single software item to check for installed version and/or latest version.
type: object
properties:
software_item_id:
description: Software item ID.
type: string
format: uuid
name:
description: Human-readable name for logging.
type: string
detect_version:
description: |-
Plugin for the detect_version role.
None if no detect_version plugin is configured for this host-software pair.
anyOf:
- $ref: '#/components/schemas/PluginAssignment'
- type: 'null'
fetch_releases:
description: |-
Plugin for the fetch_releases role — only included for agent-side plugins
(i.e., plugins without ControllerSideFetchReleases or with execution_site = agent).
Controller-side fetch_releases is handled by the scheduler, not sent to the agent.
anyOf:
- $ref: '#/components/schemas/PluginAssignment'
- type: 'null'
host_software_item_id:
description: |-
Host software item ID for routing results to the host_software_items table.
When set, this assignment is for a host-managed software item rather than
a targeted software item.
type:
- string
- 'null'
format: uuid
required:
- software_item_id
- name
VersionCheckResult:
description: Result of a single version check.
type: object
properties:
software_item_id:
description: Software item ID.
type: string
format: uuid
installed_version:
description: Detected installed version, if any.
type:
- string
- 'null'
latest_version:
description: |-
Latest available version from the package index, if resolved locally
by the agent (e.g., Homebrew). Absent for plugins whose latest
version is resolved on the controller side.
type:
- string
- 'null'
error:
description: Error message if detection failed.
type:
- string
- 'null'
update_category:
description: |-
Classification of the available update (e.g. security, bugfix).
Defaults to `Unknown` when the plugin cannot classify the update.
$ref: '#/components/schemas/UpdateCategory'
default: unknown
host_software_item_id:
description: |-
Host software item ID for routing results to the host_software_items table.
Mirrors the value from the corresponding [`VersionCheckAssignment`].
type:
- string
- 'null'
format: uuid
installed_display_version:
description: |-
Human-readable installed version for display when `installed_version`
is opaque (e.g. a Docker SHA256 digest → the image publish date).
Set by the agent from `BatchDetectResult.display_version`.
`None` when the plugin does not provide a display version.
type:
- string
- 'null'
not_ready:
description: |-
When `true`, the agent is not yet ready to report a meaningful version
for this item (e.g. a self-update is in progress and the binary has not
restarted yet). The controller should treat this as "check again later"
rather than clearing the installed version.
`None` / absent means "ready" for wire backward compatibility.
type:
- boolean
- 'null'
required:
- software_item_id
WorkloadClaimSyncEntry:
description: A single entry in a `WorkloadClaimSyncResponse`.
type: object
properties:
service_id:
description: The service that owns this claim.
type: string
format: uuid
tenant_id:
description: The tenant this config key belongs to.
type: string
format: uuid
claimed_at:
description: ISO 8601 timestamp when the claim was granted.
type: string
required:
- service_id
- tenant_id
- claimed_at
access_invalidatedPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: access_invalidated
user_ids:
description: Users whose grant rows or role assignments changed.
type: array
items:
type: string
format: uuid
role_ids:
description: Roles whose grant rows changed.
type: array
items:
type: string
format: uuid
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- user_ids
- role_ids
- protocol_version
- seq
approvedPayload:
type: object
properties:
type:
type: string
const: approved
service_id:
type: string
format: uuid
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- service_id
- protocol_version
- seq
audit_eventPayload:
description: |-
Service -> Controller: forwarded semantic audit event.
The controller re-validates the event and silently drops invalid or
non-forwardable payloads without closing the connection.
type: object
properties:
type:
type: string
const: audit_event
action_type:
description: Semantic action identifier, such as `service.certificate.issue`.
type: string
tenant_id:
description: Tenant UUID as a string when the event is tenant-scoped.
type:
- string
- 'null'
target_type:
description: Optional semantic target type.
type:
- string
- 'null'
target_id:
description: Optional semantic target identifier.
type:
- string
- 'null'
target_display:
description: Optional human-readable target display value.
type:
- string
- 'null'
outcome:
description: Semantic outcome, such as `success` or `denied`.
type: string
details_json:
description: Optional JSON-encoded details payload.
type:
- string
- 'null'
request_id:
description: Optional correlation identifier.
type:
- string
- 'null'
correlation_id:
description: Optional correlation identifier linking events in a workflow chain.
type:
- string
- 'null'
format: uuid
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- action_type
- outcome
- protocol_version
- seq
batch_update_resultPayload:
type: object
properties:
type:
type: string
const: batch_update_result
batch_id:
description: Batch ID matching the request.
type: string
format: uuid
results:
description: Per-item results.
type: array
items:
$ref: '#/components/schemas/BatchUpdateItemResult'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- batch_id
- results
- protocol_version
- seq
broadcast_admin_eventPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: broadcast_admin_event
tenant_id:
description: Target tenant, or `None` for system-wide events.
type:
- string
- 'null'
format: uuid
event_json:
description: JSON-serialised `AdminEvent`.
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- event_json
- protocol_version
- seq
ca_bundle_updatedPayload:
type: object
properties:
type:
type: string
const: ca_bundle_updated
ca_bundle_pem:
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- ca_bundle_pem
- protocol_version
- seq
certificatePayload:
type: object
properties:
type:
type: string
const: certificate
cert_pem:
type: string
not_after:
description: Certificate "not valid after" timestamp.
type: integer
format: int64
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- cert_pem
- not_after
- protocol_version
- seq
check_versionsPayload:
type: object
properties:
type:
type: string
const: check_versions
host_machine_id:
description: |-
The machine_id of the host to check versions on.
For the regular agent (one service = one host), the agent validates that
this matches its own machine_id as a defensive sanity check.
For the SSH agent (one service = N remote hosts), the agent uses this
field to look up the correct SSH credentials and route the operation to
the right remote host.
type: string
assignments:
description: List of software items to check.
type: array
items:
$ref: '#/components/schemas/VersionCheckAssignment'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- host_machine_id
- assignments
- protocol_version
- seq
delete_service_configPayload:
description: |-
Service → Controller: delete a config entry from the controller DB.
The controller deletes, ACKs, and broadcasts `ServiceConfigUpdated`.
type: object
properties:
type:
type: string
const: delete_service_config
request_id:
description: Correlation ID for the `ServiceConfigAck` response.
type: string
tenant_id:
description: Tenant scope. `None` = global scope.
type:
- string
- 'null'
format: uuid
key:
description: Config key to delete.
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- request_id
- key
- protocol_version
- seq
disconnectingPayload:
type: object
properties:
type:
type: string
const: disconnecting
reason:
$ref: '#/components/schemas/DisconnectReason'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- reason
- protocol_version
- seq
discover_softwarePayload:
type: object
properties:
type:
type: string
const: discover_software
host_machine_id:
description: |-
Machine ID of the host to discover software on.
For the regular agent this is validated to match its own machine_id.
For the SSH agent it identifies which remote host to connect to.
type: string
plugins:
description: Per-plugin discovery assignments.
type: array
items:
$ref: '#/components/schemas/DiscoveryPluginAssignment'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- host_machine_id
- plugins
- protocol_version
- seq
discovery_resultsPayload:
type: object
properties:
type:
type: string
const: discovery_results
host_machine_id:
description: Machine ID of the host that was scanned (echoed from the assignment).
type: string
results:
description: Per-plugin results.
type: array
items:
$ref: '#/components/schemas/DiscoveryPluginResult'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- host_machine_id
- results
- protocol_version
- seq
enrollPayload:
type: object
properties:
type:
type: string
const: enroll
hostname:
type: string
friendly_name:
type: string
enrollment_token:
type:
- string
- 'null'
capabilities:
description: |-
Capabilities this service supports.
The controller persists these in the `services.capabilities` column and
derives behavioral defaults from the resulting [`ServiceProfile`](crate::ServiceProfile).
type: array
uniqueItems: true
items:
$ref: '#/components/schemas/Capability'
service_app_name:
description: |-
The binary/crate name of the enrolling service (e.g., `"uptrakit-agent-ssh"`).
Derived from `env!("CARGO_PKG_NAME")` at compile time. Used for UI
display, extension conflict detection, and distinguishing service binaries.
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- hostname
- friendly_name
- capabilities
- service_app_name
- protocol_version
- seq
enrolledPayload:
type: object
properties:
type:
type: string
const: enrolled
service_id:
type: string
format: uuid
enrollment_secret:
type: string
status:
$ref: '#/components/schemas/EnrollmentStatus'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- service_id
- enrollment_secret
- status
- protocol_version
- seq
errorPayload:
type: object
properties:
type:
type: string
const: error
code:
$ref: '#/components/schemas/ErrorCode'
message:
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- code
- message
- protocol_version
- seq
execute_batch_updatePayload:
type: object
properties:
type:
type: string
const: execute_batch_update
host_machine_id:
description: |-
The machine_id of the host to run the batch update on.
For the regular agent (one service = one host) this is validated against
its own machine_id. For the SSH agent this routes to the correct remote host.
type: string
batch_id:
description: Unique identifier for this batch operation.
type: string
format: uuid
plugin_type:
description: Plugin type for all items in this batch.
$ref: '#/components/schemas/PluginTypeId'
plugin_config:
description: Merged plugin configuration.
updates:
description: Individual items to update.
type: array
items:
$ref: '#/components/schemas/BatchUpdateItem'
pre_update_hook_plugins:
description: Pre-update hook plugins to execute before the batch, ordered by priority.
type: array
items:
$ref: '#/components/schemas/PluginAssignment'
post_update_hook_plugins:
description: Post-update hook plugins to execute after the batch, ordered by priority.
type: array
items:
$ref: '#/components/schemas/PluginAssignment'
timeout_seconds:
description: |-
Timeout for the entire batch operation.
Wire field name: `timeout_seconds` (kept for backward compatibility).
type: integer
format: uint32
minimum: 0
default: 7200
interactive:
description: |-
When `true`, the agent allocates a PTY and keeps stdin open for forwarding.
Requires the agent to advertise the `InteractiveUpdates` capability.
Defaults to `false` for backward compatibility with older agents.
type: boolean
default: false
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- host_machine_id
- batch_id
- plugin_type
- plugin_config
- updates
- protocol_version
- seq
execute_updatePayload:
type: object
properties:
type:
type: string
const: execute_update
host_machine_id:
description: |-
The machine_id of the host to run the update on.
For the regular agent (one service = one host), the agent validates that
this matches its own machine_id as a defensive sanity check.
For the SSH agent (one service = N remote hosts), the agent uses this
field to look up the correct SSH credentials and route the operation to
the right remote host.
type: string
update_history_id:
type: string
format: uuid
software_item_id:
type: string
format: uuid
software_item_name:
type: string
to_version:
type: string
detect_version_plugin:
description: |-
Plugin for the detect_version role (for before/after installed-version detection).
Absent when no detect_version plugin is configured for this assignment.
anyOf:
- $ref: '#/components/schemas/PluginAssignment'
- type: 'null'
execute_update_plugin:
description: Plugin for the execute_update role.
$ref: '#/components/schemas/PluginAssignment'
pre_update_hook_plugins:
description: Pre-update hook plugins to execute before the update, ordered by priority.
type: array
items:
$ref: '#/components/schemas/PluginAssignment'
post_update_hook_plugins:
description: Post-update hook plugins to execute after the update, ordered by priority.
type: array
items:
$ref: '#/components/schemas/PluginAssignment'
release_info:
anyOf:
- $ref: '#/components/schemas/ReleaseInfo'
- type: 'null'
timeout_seconds:
description: |-
Timeout for the update execution.
Wire field name: `timeout_seconds` (kept for backward compatibility).
type: integer
format: uint32
minimum: 0
default: 7200
interactive:
description: |-
When `true`, the agent allocates a PTY and keeps stdin open for forwarding.
Requires the agent to advertise the `InteractiveUpdates` capability.
Defaults to `false` for backward compatibility with older agents.
type: boolean
default: false
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- host_machine_id
- update_history_id
- software_item_id
- software_item_name
- to_version
- execute_update_plugin
- protocol_version
- seq
host_connectivity_updatedPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: host_connectivity_updated
tenant_id:
description: Tenant this update belongs to.
type: string
format: uuid
updates:
description: One entry per host whose connectivity changed.
type: array
items:
$ref: '#/components/schemas/HostConnectivityUpdate'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- tenant_id
- updates
- protocol_version
- seq
pingPayload:
type: object
properties:
type:
type: string
const: ping
service_ts:
description: Timestamp when the service sent the ping.
type: integer
format: int64
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- service_ts
- protocol_version
- seq
pongPayload:
type: object
properties:
type:
type: string
const: pong
service_ts:
description: Original timestamp from the service's ping.
type: integer
format: int64
controller_ts:
description: Timestamp when the controller processed the ping.
type: integer
format: int64
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- service_ts
- controller_ts
- protocol_version
- seq
registerPayload:
description: |-
Service declares its capabilities immediately on connect.
Sent from `on_connected` before `ServiceSettings` is processed.
The controller uses this to establish session-level capability flags
without relying on DB-stored values (which may be absent on first connect).
type: object
properties:
type:
type: string
const: register
capabilities:
description: Capabilities declared by this service instance.
type: array
uniqueItems: true
items:
$ref: '#/components/schemas/Capability'
runtime_instance_id:
description: |-
Runtime instance identity for restart-vs-reconnect detection.
Optional for mixed-version compatibility: legacy services omit this
field and are treated as service-scoped (not instance-scoped).
type:
- string
- 'null'
format: uuid
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- protocol_version
- seq
rejectedPayload:
type: object
properties:
type:
type: string
const: rejected
service_id:
type: string
format: uuid
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- service_id
- protocol_version
- seq
renew_certificatePayload:
type: object
properties:
type:
type: string
const: renew_certificate
csr_pem:
description: PEM-encoded Certificate Signing Request with CN=service_id.
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- csr_pem
- protocol_version
- seq
report_hostsPayload:
type: object
properties:
type:
type: string
const: report_hosts
hosts:
description: One or more host machines managed by this service.
type: array
items:
$ref: '#/components/schemas/HostInfo'
agent_version:
description: Agent binary version (e.g., "0.0.1").
type: string
capabilities:
description: |-
Capabilities advertised by this service.
The controller computes the agreed set as the intersection of this set
with its own capabilities, considering only typed (known) variants.
type: array
uniqueItems: true
items:
$ref: '#/components/schemas/Capability'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- hosts
- agent_version
- protocol_version
- seq
report_plugin_configPayload:
description: |-
Service reports a plugin configuration to the controller.
Sent by agents that detect infrastructure (e.g. PVE nodes) during
bootstrap. The controller creates or returns an existing plugin config
matching `(tenant_id, plugin_type, name)` and responds with
`ReportPluginConfigResponse`.
type: object
properties:
type:
type: string
const: report_plugin_config
request_id:
description: Unique request identifier for correlating the response.
type: string
plugin_type:
description: Plugin type string (e.g. `"infrastructure.proxmox"`).
type: string
name:
description: Human-readable name for the config (e.g. `"pve.local"`).
type: string
config:
description: Plugin-specific configuration JSON.
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- request_id
- plugin_type
- name
- config
- protocol_version
- seq
report_plugin_config_responsePayload:
description: |-
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.
type: object
properties:
type:
type: string
const: report_plugin_config_response
request_id:
description: The request ID from the original `ReportPluginConfig` message.
type: string
success:
description: Whether the operation succeeded.
type: boolean
plugin_config_id:
description: The plugin config ID (set on success).
type:
- string
- 'null'
format: uuid
error:
description: Error message (set on failure).
type:
- string
- 'null'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- request_id
- success
- protocol_version
- seq
request_ca_rotationPayload:
description: |-
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()`.
type: object
properties:
type:
type: string
const: request_ca_rotation
reason:
description: Human-readable reason for the rotation request.
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- reason
- protocol_version
- seq
request_cert_renewalPayload:
type: object
properties:
type:
type: string
const: request_cert_renewal
reason:
description: Human-readable reason for the renewal request.
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- reason
- protocol_version
- seq
request_certificatePayload:
type: object
properties:
type:
type: string
const: request_certificate
csr_pem:
description: PEM-encoded Certificate Signing Request.
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- csr_pem
- protocol_version
- seq
request_crl_renewalPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: request_crl_renewal
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- protocol_version
- seq
reset_dataPayload:
description: |-
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).
type: object
properties:
type:
type: string
const: reset_data
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- protocol_version
- seq
server_restartingPayload:
type: object
properties:
type:
type: string
const: server_restarting
reason:
description: Human-readable reason for the restart.
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- reason
- protocol_version
- seq
service_config_ackPayload:
description: |-
Controller → Service: acknowledgment of a store or delete operation.
**Security**: NEVER published to NATS — session-targeted.
type: object
properties:
type:
type: string
const: service_config_ack
request_id:
description: Correlation ID matching the request.
type: string
success:
description: '`true` if the operation succeeded.'
type: boolean
error:
description: Error message when `success` is `false`.
type:
- string
- 'null'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- request_id
- success
- protocol_version
- seq
service_config_deliveryPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: service_config_delivery
entries:
description: All config entries stored for this `service_app_name`.
type: array
items:
$ref: '#/components/schemas/ServiceConfigEntry'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- entries
- protocol_version
- seq
service_config_updatedPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: service_config_updated
changed:
description: Entries that were inserted or updated (with decrypted values).
type: array
items:
$ref: '#/components/schemas/ServiceConfigEntry'
deleted:
description: Keys that were deleted.
type: array
items:
$ref: '#/components/schemas/ServiceConfigKey'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- protocol_version
- seq
service_credentialsPayload:
description: |-
Infrastructure credentials for services that advertise credential
capabilities. Fields are populated based on the service's capability set:
- `database_access` → `db_url` is set
- `nats_access` → `nats_url` is set (if controller has NATS)
- `master_key_access` → `master_key_hex` is set (if encryption enabled)
**Security**: NEVER published to NATS. Delivered locally via WebSocket only,
following the same pattern as MQTT credential messages.
type: object
properties:
type:
type: string
const: service_credentials
db_url:
description: Database connection URL. Present when the service has `database_access`.
type:
- string
- 'null'
master_key_hex:
description: |-
Master encryption key as 64-char hex. Present when the service has
`master_key_access` and encryption is enabled on the controller.
type:
- string
- 'null'
nats_url:
description: |-
NATS server URL. Present when the service has `nats_access` and
NATS is configured on the controller.
type:
- string
- 'null'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- protocol_version
- seq
service_settingsPayload:
type: object
properties:
type:
type: string
const: service_settings
renewal_window_hours:
type: integer
format: uint16
minimum: 0
maximum: 65535
ca_bundle_hash:
type: string
default: ''
capabilities:
description: |-
Capabilities advertised by the controller.
The service computes the agreed set as the intersection of this set
with its own capabilities, considering only typed (known) variants.
type: array
uniqueItems: true
items:
$ref: '#/components/schemas/Capability'
report_page_limits:
description: |-
Per-page item-count limits for paginated service-to-controller reports.
Services must honor these limits when splitting large `report_hosts`,
`discovery_results`, `version_check_results`, and
`batch_update_result` payloads across pages.
$ref: '#/components/schemas/ReportPageLimits'
shutdown_timeout_seconds:
description: |-
Maximum time to wait for in-flight operations during shutdown.
Present for agents, absent for MQTT services.
Wire field name: `shutdown_timeout_seconds` (kept for backward compatibility).
type:
- integer
- 'null'
format: uint32
minimum: 0
ping_interval:
description: |-
How often the service should send ping messages.
Controller-managed; derived from per-service DB override or service-type default.
type: integer
format: uint32
minimum: 0
tenant_id:
description: |-
Tenant UUID that this service belongs to.
`None` for system services (MQTT, scheduler) which are not
tenant-scoped. Present for tenant-scoped agents so they can
include the tenant identity in external provisioning operations
(e.g. PVE API credential naming).
type:
- string
- 'null'
format: uuid
trust_domain:
description: |-
SPIFFE trust domain for Service identity URIs.
Empty string when the Controller has no trust domain configured.
Agent falls back to the dialed hostname for SPIFFE SAN generation.
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- renewal_window_hours
- ping_interval
- protocol_version
- seq
service_trigger_host_batch_updatePayload:
description: |-
Service → Controller: trigger a batch update of all outdated software items on a host.
Sent when a Home Assistant user presses "Install" on a host update entity.
type: object
properties:
type:
type: string
const: service_trigger_host_batch_update
tenant_id:
description: Tenant UUID (for validation).
type: string
format: uuid
host_id:
description: Host whose items should be updated.
type: string
format: uuid
actor_service_id:
description: Service instance UUID that initiated the trigger (used as actor_id).
type: string
format: uuid
security_only:
description: When `true`, only items with `update_category = "security"` are updated.
type: boolean
default: false
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- tenant_id
- host_id
- actor_service_id
- protocol_version
- seq
service_trigger_updatePayload:
type: object
properties:
type:
type: string
const: service_trigger_update
tenant_id:
description: Tenant UUID (for validation).
type: string
format: uuid
software_item_id:
description: Software item to update.
type: string
format: uuid
host_id:
description: Host to update on.
type: string
format: uuid
to_version:
description: Target version to install.
type: string
actor_service_id:
description: Service instance UUID that initiated the trigger (used as actor_id).
type: string
format: uuid
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- tenant_id
- software_item_id
- host_id
- to_version
- actor_service_id
- protocol_version
- seq
set_update_freezePayload:
type: object
properties:
type:
type: string
const: set_update_freeze
enabled:
description: Whether to enable (`true`) or disable (`false`) the freeze.
type: boolean
reason:
description: Optional human-readable reason for the freeze (audit trail).
type:
- string
- 'null'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- enabled
- protocol_version
- seq
software_statesPayload:
type: object
properties:
type:
type: string
const: software_states
tenant_id:
description: Tenant this state belongs to.
type: string
format: uuid
items:
description: All active software items for the tenant with per-host version data.
type: array
items:
$ref: '#/components/schemas/SoftwareStateItem'
host_summaries:
description: |-
Per-host aggregate summary of unpinned (unfeatured) software items.
Each entry summarises all enabled, non-deactivated unfeatured items for
one host. Only hosts with at least one such item are included.
Defaults to an empty list on deserialization for backward compatibility
with older MQTT services.
type: array
items:
$ref: '#/components/schemas/HostPackageSummary'
default: []
hosts:
description: |-
Per-host metadata for all hosts referenced in `items` or `host_summaries`.
Includes OS info, tags, and agent last-seen data. Sourced exclusively from DB.
Defaults to an empty list for backward compatibility with older MQTT services.
type: array
items:
$ref: '#/components/schemas/HostStateMetadata'
default: []
page:
description: Pagination metadata indicating which page this payload represents.
$ref: '#/components/schemas/SoftwareStatesPage'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- tenant_id
- items
- page
- protocol_version
- seq
software_states_changedPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: software_states_changed
tenant_id:
type: string
format: uuid
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- tenant_id
- protocol_version
- seq
stdin_attentionPayload:
description: |-
Agent → Controller: the update process appears to be waiting for stdin input.
Sent when the agent detects that the process has produced no output for
a sustained period while still running (heuristic: ~10 seconds of silence).
The controller broadcasts this to interactive session subscribers and may
trigger notifications.
type: object
properties:
type:
type: string
const: stdin_attention
update_history_id:
description: The update history record that needs attention.
type: string
format: uuid
hint:
description: Optional hint about what the process might be waiting for.
type:
- string
- 'null'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- update_history_id
- protocol_version
- seq
store_service_configPayload:
description: |-
Service → Controller: upsert a config entry in the controller DB.
The controller encrypts sensitive values at rest, ACKs, and broadcasts
`ServiceConfigUpdated` to all connected instances of the same service app.
type: object
properties:
type:
type: string
const: store_service_config
request_id:
description: Correlation ID for the `ServiceConfigAck` response.
type: string
tenant_id:
description: Tenant scope. `None` = global scope.
type:
- string
- 'null'
format: uuid
key:
description: Config key (e.g. `"clients.{uuid}"`).
type: string
value:
description: Config value (plaintext JSON; controller encrypts at rest if `sensitive`).
sensitive:
description: When `true`, the controller stores the value using `EncryptedString`.
type: boolean
default: false
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- request_id
- key
- value
- protocol_version
- seq
surface_action_cancelPayload:
description: |-
Cancellation of an in-flight proxied surface action request.
Session-targeted and never published to NATS.
type: object
properties:
type:
type: string
const: surface_action_cancel
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- protocol_version
- seq
surface_action_requestPayload:
description: |-
Service requests a surface action invocation from the controller.
Enables services to call surface actions via the wire protocol and
receive the correlated `ControllerMessage::SurfaceActionResponse`.
type: object
properties:
type:
type: string
const: surface_action_request
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- protocol_version
- seq
surface_action_responsePayload:
description: |-
Response to a proxied surface action invocation.
Sent by the service after processing a `SurfaceActionRequest` from the
controller.
type: object
properties:
type:
type: string
const: surface_action_response
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- protocol_version
- seq
surface_registrationPayload:
description: |-
Service declares its surfaces after connecting.
Sent once after connection setup by services that participate in the
surface contract.
type: object
properties:
type:
type: string
const: surface_registration
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- protocol_version
- seq
test_plugin_configPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: test_plugin_config
request_id:
description: Unique request ID for correlation (UUID v7).
type: string
host_machine_id:
description: Target host machine ID on the agent.
type: string
test_kind:
description: What to test.
$ref: '#/components/schemas/ConfigTestKind'
plugin_type:
description: The plugin type to test.
type: string
config:
description: The plugin configuration JSON to test.
package_identifier:
description: Package identifier for testing (required for version detection).
type:
- string
- 'null'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- request_id
- host_machine_id
- test_kind
- plugin_type
- config
- protocol_version
- seq
test_plugin_config_resultPayload:
description: |-
Agent -> Controller: result of a plugin configuration test.
Sent after the agent completes a config test request. The controller
uses `request_id` to correlate with the pending REST API request.
type: object
properties:
type:
type: string
const: test_plugin_config_result
request_id:
description: Correlation ID matching the original request.
type: string
success:
description: Whether the test passed.
type: boolean
output:
description: Command output or connectivity response.
type:
- string
- 'null'
error:
description: Error message if the test failed.
type:
- string
- 'null'
detected_version:
description: Detected version (for version detection tests).
type:
- string
- 'null'
duration_ms:
description: Test duration in milliseconds.
type: integer
format: uint64
minimum: 0
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- request_id
- success
- duration_ms
- protocol_version
- seq
token_revokedPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: token_revoked
jti:
description: JWT ID to deny (`exp` must also be set for JTI-level revocations).
type:
- string
- 'null'
exp:
description: Token expiry unix timestamp (seconds). Required when `jti` is set.
type:
- integer
- 'null'
format: int64
user_id:
description: User UUID for user-level revocations.
type:
- string
- 'null'
format: uuid
iat_cutoff:
description: Deny tokens with `iat < iat_cutoff`. Required when `user_id` is set.
type:
- integer
- 'null'
format: int64
purge_after:
description: Remove the user entry after this unix timestamp.
type:
- integer
- 'null'
format: int64
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- protocol_version
- seq
update_outputPayload:
type: object
properties:
type:
type: string
const: update_output
update_history_id:
type: string
format: uuid
output:
type: string
stream:
$ref: '#/components/schemas/OutputStreamType'
default: stdout
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- update_history_id
- output
- protocol_version
- seq
update_resultPayload:
type: object
properties:
type:
type: string
const: update_result
update_history_id:
type: string
format: uuid
status:
$ref: '#/components/schemas/UpdateFinalStatus'
from_version:
type:
- string
- 'null'
to_version:
type:
- string
- 'null'
output:
type: string
error:
type:
- string
- 'null'
resumable:
description: |-
When `true`, the agent signals that this update can be resumed after
a restart (e.g. the update script supports idempotent re-entry or the
agent is mid-self-update and will re-attach on reconnect).
`None` / absent means "not resumable" for wire backward compatibility.
type:
- boolean
- 'null'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- update_history_id
- status
- output
- protocol_version
- seq
update_startedPayload:
type: object
properties:
type:
type: string
const: update_started
update_history_id:
type: string
format: uuid
from_version:
type:
- string
- 'null'
interactive:
description: |-
Whether this update was dispatched in interactive mode and the agent's
executor supports PTY allocation (dispatch intent). The PTY itself is
allocated when the update command starts; on reconnect replay the agent
reports live reality instead (channels resolved). Old agents that do
not send this field will deserialize as `false`.
type: boolean
default: false
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- update_history_id
- protocol_version
- seq
update_stdin_dataPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: update_stdin_data
update_history_id:
description: The update history record this stdin data belongs to.
type: string
format: uuid
data:
description: 'Raw bytes encoded as base64 (supports binary: Ctrl+C = \x03, etc.).'
type: string
signal:
description: |-
When set, send this signal to the process group instead of writing stdin.
Values: 2 = SIGINT, 15 = SIGTERM.
type:
- integer
- 'null'
format: int32
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- update_history_id
- data
- protocol_version
- seq
version_check_resultsPayload:
type: object
properties:
type:
type: string
const: version_check_results
results:
description: Results for each checked software item.
type: array
items:
$ref: '#/components/schemas/VersionCheckResult'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- results
- protocol_version
- seq
workload_claimPayload:
description: |-
Service → Controller: request exclusive ownership of config keys.
Sent after `ServiceConfigDelivery` is processed and whenever the
desired config set changes. Uses full replacement semantics.
Requires the `WorkloadClaims` capability.
type: object
properties:
type:
type: string
const: workload_claim
claims:
description: Map of `config_key → tenant_id` representing the full desired set.
type: object
additionalProperties:
type: string
format: uuid
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- claims
- protocol_version
- seq
workload_claim_announcementPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: workload_claim_announcement
service_id:
description: The service that owns these claims.
type: string
format: uuid
controller_id:
description: The controller that granted these claims.
type: string
format: uuid
claimed:
description: 'Newly claimed keys: `config_key → tenant_id`.'
type: object
additionalProperties:
type: string
format: uuid
released:
description: Keys that were released.
type: array
uniqueItems: true
items:
type: string
claimed_at:
description: ISO 8601 timestamp when the claims were granted (for conflict resolution).
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- service_id
- controller_id
- claimed_at
- protocol_version
- seq
workload_claim_resultPayload:
description: |-
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.
type: object
properties:
type:
type: string
const: workload_claim_result
granted:
description: Config keys that were granted (exclusive ownership).
type: array
uniqueItems: true
items:
type: string
rejected:
description: Config keys that were rejected (already claimed by another service).
type: array
uniqueItems: true
items:
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- protocol_version
- seq
workload_claim_sync_requestPayload:
description: |-
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).
type: object
properties:
type:
type: string
const: workload_claim_sync_request
controller_id:
description: The requesting controller's ID.
type: string
format: uuid
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- controller_id
- protocol_version
- seq
workload_claim_sync_responsePayload:
description: |-
Controller → NATS: respond with full local claim state.
Sent in response to `WorkloadClaimSyncRequest`.
**NATS-only** (controller-to-controller).
type: object
properties:
type:
type: string
const: workload_claim_sync_response
controller_id:
description: The responding controller's ID.
type: string
format: uuid
claims:
description: 'Full local claim state: `config_key → (service_id, tenant_id)`.'
type: object
additionalProperties:
$ref: '#/components/schemas/WorkloadClaimSyncEntry'
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
required:
- type
- controller_id
- claims
- protocol_version
- seq
workload_releasePayload:
description: |-
Service → Controller: voluntarily release config keys.
Sent when a service no longer wants to serve certain configs.
Requires the `WorkloadClaims` capability.
type: object
properties:
type:
type: string
const: workload_release
keys:
description: Config keys to release.
type: array
uniqueItems: true
items:
type: string
protocol_version:
type: integer
format: uint32
minimum: 0
seq:
type: integer
format: uint64
minimum: 0
trace_context:
$ref: '#/components/schemas/TraceContext'
pagination:
$ref: '#/components/schemas/ReportPagination'
required:
- type
- keys
- protocol_version
- seq
messages:
access_invalidated:
name: access_invalidated
payload:
$ref: '#/components/schemas/access_invalidatedPayload'
approved:
name: approved
payload:
$ref: '#/components/schemas/approvedPayload'
audit_event:
name: audit_event
payload:
$ref: '#/components/schemas/audit_eventPayload'
batch_update_result:
name: batch_update_result
payload:
$ref: '#/components/schemas/batch_update_resultPayload'
broadcast_admin_event:
name: broadcast_admin_event
payload:
$ref: '#/components/schemas/broadcast_admin_eventPayload'
ca_bundle_updated:
name: ca_bundle_updated
payload:
$ref: '#/components/schemas/ca_bundle_updatedPayload'
certificate:
name: certificate
payload:
$ref: '#/components/schemas/certificatePayload'
check_versions:
name: check_versions
payload:
$ref: '#/components/schemas/check_versionsPayload'
delete_service_config:
name: delete_service_config
payload:
$ref: '#/components/schemas/delete_service_configPayload'
disconnecting:
name: disconnecting
payload:
$ref: '#/components/schemas/disconnectingPayload'
discover_software:
name: discover_software
payload:
$ref: '#/components/schemas/discover_softwarePayload'
discovery_results:
name: discovery_results
payload:
$ref: '#/components/schemas/discovery_resultsPayload'
enroll:
name: enroll
payload:
$ref: '#/components/schemas/enrollPayload'
enrolled:
name: enrolled
payload:
$ref: '#/components/schemas/enrolledPayload'
error:
name: error
payload:
$ref: '#/components/schemas/errorPayload'
execute_batch_update:
name: execute_batch_update
payload:
$ref: '#/components/schemas/execute_batch_updatePayload'
execute_update:
name: execute_update
payload:
$ref: '#/components/schemas/execute_updatePayload'
host_connectivity_updated:
name: host_connectivity_updated
payload:
$ref: '#/components/schemas/host_connectivity_updatedPayload'
ping:
name: ping
payload:
$ref: '#/components/schemas/pingPayload'
pong:
name: pong
payload:
$ref: '#/components/schemas/pongPayload'
register:
name: register
payload:
$ref: '#/components/schemas/registerPayload'
rejected:
name: rejected
payload:
$ref: '#/components/schemas/rejectedPayload'
renew_certificate:
name: renew_certificate
payload:
$ref: '#/components/schemas/renew_certificatePayload'
report_hosts:
name: report_hosts
payload:
$ref: '#/components/schemas/report_hostsPayload'
report_plugin_config:
name: report_plugin_config
payload:
$ref: '#/components/schemas/report_plugin_configPayload'
report_plugin_config_response:
name: report_plugin_config_response
payload:
$ref: '#/components/schemas/report_plugin_config_responsePayload'
request_ca_rotation:
name: request_ca_rotation
payload:
$ref: '#/components/schemas/request_ca_rotationPayload'
request_cert_renewal:
name: request_cert_renewal
payload:
$ref: '#/components/schemas/request_cert_renewalPayload'
request_certificate:
name: request_certificate
payload:
$ref: '#/components/schemas/request_certificatePayload'
request_crl_renewal:
name: request_crl_renewal
payload:
$ref: '#/components/schemas/request_crl_renewalPayload'
reset_data:
name: reset_data
payload:
$ref: '#/components/schemas/reset_dataPayload'
server_restarting:
name: server_restarting
payload:
$ref: '#/components/schemas/server_restartingPayload'
service_config_ack:
name: service_config_ack
payload:
$ref: '#/components/schemas/service_config_ackPayload'
service_config_delivery:
name: service_config_delivery
payload:
$ref: '#/components/schemas/service_config_deliveryPayload'
service_config_updated:
name: service_config_updated
payload:
$ref: '#/components/schemas/service_config_updatedPayload'
service_credentials:
name: service_credentials
payload:
$ref: '#/components/schemas/service_credentialsPayload'
service_settings:
name: service_settings
payload:
$ref: '#/components/schemas/service_settingsPayload'
service_trigger_host_batch_update:
name: service_trigger_host_batch_update
payload:
$ref: '#/components/schemas/service_trigger_host_batch_updatePayload'
service_trigger_update:
name: service_trigger_update
payload:
$ref: '#/components/schemas/service_trigger_updatePayload'
set_update_freeze:
name: set_update_freeze
payload:
$ref: '#/components/schemas/set_update_freezePayload'
software_states:
name: software_states
payload:
$ref: '#/components/schemas/software_statesPayload'
software_states_changed:
name: software_states_changed
payload:
$ref: '#/components/schemas/software_states_changedPayload'
stdin_attention:
name: stdin_attention
payload:
$ref: '#/components/schemas/stdin_attentionPayload'
store_service_config:
name: store_service_config
payload:
$ref: '#/components/schemas/store_service_configPayload'
surface_action_cancel:
name: surface_action_cancel
payload:
$ref: '#/components/schemas/surface_action_cancelPayload'
surface_action_request:
name: surface_action_request
payload:
$ref: '#/components/schemas/surface_action_requestPayload'
surface_action_response:
name: surface_action_response
payload:
$ref: '#/components/schemas/surface_action_responsePayload'
surface_registration:
name: surface_registration
payload:
$ref: '#/components/schemas/surface_registrationPayload'
test_plugin_config:
name: test_plugin_config
payload:
$ref: '#/components/schemas/test_plugin_configPayload'
test_plugin_config_result:
name: test_plugin_config_result
payload:
$ref: '#/components/schemas/test_plugin_config_resultPayload'
token_revoked:
name: token_revoked
payload:
$ref: '#/components/schemas/token_revokedPayload'
update_output:
name: update_output
payload:
$ref: '#/components/schemas/update_outputPayload'
update_result:
name: update_result
payload:
$ref: '#/components/schemas/update_resultPayload'
update_started:
name: update_started
payload:
$ref: '#/components/schemas/update_startedPayload'
update_stdin_data:
name: update_stdin_data
payload:
$ref: '#/components/schemas/update_stdin_dataPayload'
version_check_results:
name: version_check_results
payload:
$ref: '#/components/schemas/version_check_resultsPayload'
workload_claim:
name: workload_claim
payload:
$ref: '#/components/schemas/workload_claimPayload'
workload_claim_announcement:
name: workload_claim_announcement
payload:
$ref: '#/components/schemas/workload_claim_announcementPayload'
workload_claim_result:
name: workload_claim_result
payload:
$ref: '#/components/schemas/workload_claim_resultPayload'
workload_claim_sync_request:
name: workload_claim_sync_request
payload:
$ref: '#/components/schemas/workload_claim_sync_requestPayload'
workload_claim_sync_response:
name: workload_claim_sync_response
payload:
$ref: '#/components/schemas/workload_claim_sync_responsePayload'
workload_release:
name: workload_release
payload:
$ref: '#/components/schemas/workload_releasePayload'