From 621aa356bf8d27d273291f4e4449e83f9d53600b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 25 Sep 2026 03:33:29 +0000 Subject: [PATCH] Add the update.install_now board command Boards now hold release channel updates until their nightly install window. update.install_now asks a board to check the channels and install a new app or agent at once. It is DISRUPTIVE: the board shows its update screen, and an agent update restarts the agent. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VUxfdFFUkL7SmAEUvUzspy --- .../com/ibrasoft/lensbridge/model/auth/Permission.java | 2 +- .../lensbridge/model/board/commands/CommandKind.java | 2 ++ .../model/board/commands/CommandPayload.java | 3 ++- .../model/board/commands/UpdateInstallNowPayload.java | 10 ++++++++++ .../model/board/commands/CommandKindTest.java | 3 ++- 5 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/ibrasoft/lensbridge/model/board/commands/UpdateInstallNowPayload.java diff --git a/src/main/java/com/ibrasoft/lensbridge/model/auth/Permission.java b/src/main/java/com/ibrasoft/lensbridge/model/auth/Permission.java index 7bb326a..3b25dce 100644 --- a/src/main/java/com/ibrasoft/lensbridge/model/auth/Permission.java +++ b/src/main/java/com/ibrasoft/lensbridge/model/auth/Permission.java @@ -57,7 +57,7 @@ public enum Permission implements GrantedAuthority { /** Recoverable, no data egress: chrome.reload, config.refresh. */ BOARD_COMMAND_BENIGN(Authority.BOARD_COMMAND_BENIGN), - /** Takes a physical display down: kiosk.restart, system.reboot. */ + /** Takes a physical display down: kiosk.restart, system.reboot, update.install_now. */ BOARD_COMMAND_DISRUPTIVE(Authority.BOARD_COMMAND_DISRUPTIVE), /** Data egress: chrome.screenshot returns an image of a screen in a prayer space; logs.tail leaks internals. */ BOARD_COMMAND_INSPECT(Authority.BOARD_COMMAND_INSPECT), diff --git a/src/main/java/com/ibrasoft/lensbridge/model/board/commands/CommandKind.java b/src/main/java/com/ibrasoft/lensbridge/model/board/commands/CommandKind.java index 94cd69f..582c507 100644 --- a/src/main/java/com/ibrasoft/lensbridge/model/board/commands/CommandKind.java +++ b/src/main/java/com/ibrasoft/lensbridge/model/board/commands/CommandKind.java @@ -26,6 +26,8 @@ public enum CommandKind { KIOSK_RESTART("kiosk.restart", CommandRisk.DISRUPTIVE), SYSTEM_REBOOT("system.reboot", CommandRisk.DISRUPTIVE), + /** Takes the board off its content for the update screen, and may restart the agent. */ + UPDATE_INSTALL_NOW("update.install_now", CommandRisk.DISRUPTIVE), CHROME_SCREENSHOT("chrome.screenshot", CommandRisk.INSPECT), LOGS_TAIL("logs.tail", CommandRisk.INSPECT); diff --git a/src/main/java/com/ibrasoft/lensbridge/model/board/commands/CommandPayload.java b/src/main/java/com/ibrasoft/lensbridge/model/board/commands/CommandPayload.java index 13ddfd3..edd0490 100644 --- a/src/main/java/com/ibrasoft/lensbridge/model/board/commands/CommandPayload.java +++ b/src/main/java/com/ibrasoft/lensbridge/model/board/commands/CommandPayload.java @@ -22,10 +22,11 @@ @JsonSubTypes.Type(value = SystemRebootPayload.class, name = "system.reboot"), @JsonSubTypes.Type(value = ConfigRefreshPayload.class, name = "config.refresh"), @JsonSubTypes.Type(value = LogsTailPayload.class, name = "logs.tail"), + @JsonSubTypes.Type(value = UpdateInstallNowPayload.class, name = "update.install_now"), }) public sealed interface CommandPayload permits ChromeReloadPayload, ChromeScreenshotPayload, KioskRestartPayload, - SystemRebootPayload, ConfigRefreshPayload, LogsTailPayload { + SystemRebootPayload, ConfigRefreshPayload, LogsTailPayload, UpdateInstallNowPayload { String kind(); } diff --git a/src/main/java/com/ibrasoft/lensbridge/model/board/commands/UpdateInstallNowPayload.java b/src/main/java/com/ibrasoft/lensbridge/model/board/commands/UpdateInstallNowPayload.java new file mode 100644 index 0000000..f4d1251 --- /dev/null +++ b/src/main/java/com/ibrasoft/lensbridge/model/board/commands/UpdateInstallNowPayload.java @@ -0,0 +1,10 @@ +package com.ibrasoft.lensbridge.model.board.commands; + +/** + * Check the release channels and install a new board app or agent now, instead of in the + * board's nightly install window. The board shows its update screen while it installs, and + * an agent update restarts the agent. + */ +public record UpdateInstallNowPayload() implements CommandPayload { + @Override public String kind() { return "update.install_now"; } +} diff --git a/src/test/java/com/ibrasoft/lensbridge/model/board/commands/CommandKindTest.java b/src/test/java/com/ibrasoft/lensbridge/model/board/commands/CommandKindTest.java index 4283b56..7268a93 100644 --- a/src/test/java/com/ibrasoft/lensbridge/model/board/commands/CommandKindTest.java +++ b/src/test/java/com/ibrasoft/lensbridge/model/board/commands/CommandKindTest.java @@ -60,9 +60,10 @@ void reloadAndConfigRefreshAreBenign() { } @Test - void restartAndRebootAreDisruptive() { + void restartRebootAndUpdateNowAreDisruptive() { assertThat(CommandKind.KIOSK_RESTART.getRisk()).isEqualTo(CommandRisk.DISRUPTIVE); assertThat(CommandKind.SYSTEM_REBOOT.getRisk()).isEqualTo(CommandRisk.DISRUPTIVE); + assertThat(CommandKind.UPDATE_INSTALL_NOW.getRisk()).isEqualTo(CommandRisk.DISRUPTIVE); } /** Both return device-side data to the caller. Neither may ride along with a reboot grant. */