- Command intake (reboot/shutdown) on infoscreen/{uuid}/commands with ack lifecycle
- MQTT_USER/MQTT_PASSWORD_BROKER split from identity vars; configure_mqtt_security() updated
- infoscreen-simclient.service: Type=notify, WatchdogSec=60, Restart=on-failure
- infoscreen-notify-failure@.service + script: retained MQTT alert when systemd gives up (Gap 3)
- _sd_notify() watchdog keepalive in simclient main loop (Gap 1)
- broker_connection block in health payload: reconnect_count, last_disconnect_at (Gap 2)
- COMMAND_MOCK_REBOOT_IMMEDIATE_COMPLETE canary flag with safety guard
- SERVER_TEAM_ACTIONS.md: server-side integration action items
- Docs: README, CHANGELOG, src/README, copilot-instructions updated
- 43 tests passing
150 lines
3.4 KiB
JSON
150 lines
3.4 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://infoscreen.local/schemas/reboot-command-payload-schemas.json",
|
|
"title": "Infoscreen Reboot Command Payload Schemas",
|
|
"description": "Frozen v1 schemas for per-client command and command acknowledgement payloads.",
|
|
"$defs": {
|
|
"commandPayloadV1": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"schema_version",
|
|
"command_id",
|
|
"client_uuid",
|
|
"action",
|
|
"issued_at",
|
|
"expires_at",
|
|
"requested_by",
|
|
"reason"
|
|
],
|
|
"properties": {
|
|
"schema_version": {
|
|
"type": "string",
|
|
"const": "1.0"
|
|
},
|
|
"command_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"client_uuid": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"action": {
|
|
"type": "string",
|
|
"enum": [
|
|
"reboot_host",
|
|
"shutdown_host"
|
|
]
|
|
},
|
|
"issued_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"expires_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"requested_by": {
|
|
"type": [
|
|
"integer",
|
|
"null"
|
|
],
|
|
"minimum": 1
|
|
},
|
|
"reason": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"maxLength": 2000
|
|
}
|
|
}
|
|
},
|
|
"commandAckPayloadV1": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"command_id",
|
|
"status",
|
|
"error_code",
|
|
"error_message"
|
|
],
|
|
"properties": {
|
|
"command_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"status": {
|
|
"type": "string",
|
|
"enum": [
|
|
"accepted",
|
|
"execution_started",
|
|
"completed",
|
|
"failed"
|
|
]
|
|
},
|
|
"error_code": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"maxLength": 128
|
|
},
|
|
"error_message": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"maxLength": 4000
|
|
}
|
|
},
|
|
"allOf": [
|
|
{
|
|
"if": {
|
|
"properties": {
|
|
"status": {
|
|
"const": "failed"
|
|
}
|
|
}
|
|
},
|
|
"then": {
|
|
"properties": {
|
|
"error_code": {
|
|
"type": "string",
|
|
"minLength": 1
|
|
},
|
|
"error_message": {
|
|
"type": "string",
|
|
"minLength": 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"examples": [
|
|
{
|
|
"commandPayloadV1": {
|
|
"schema_version": "1.0",
|
|
"command_id": "5d1f8b4b-7e85-44fb-8f38-3f5d5da5e2e4",
|
|
"client_uuid": "9b8d1856-ff34-4864-a726-12de072d0f77",
|
|
"action": "reboot_host",
|
|
"issued_at": "2026-04-03T12:48:10Z",
|
|
"expires_at": "2026-04-03T12:52:10Z",
|
|
"requested_by": 1,
|
|
"reason": "operator_request"
|
|
}
|
|
},
|
|
{
|
|
"commandAckPayloadV1": {
|
|
"command_id": "5d1f8b4b-7e85-44fb-8f38-3f5d5da5e2e4",
|
|
"status": "execution_started",
|
|
"error_code": null,
|
|
"error_message": null
|
|
}
|
|
}
|
|
]
|
|
}
|