feat(device-detail): rename, delete, move devices (VAPP-9) #15

Merged
David merged 2 commits from feat/device-management-actions into main 2026-06-06 23:52:26 +02:00
Owner

Implements VAPP-9: device management (rename, delete, move to mesh) from the web UI.

What

The device detail header gains an overflow (...) menu with Rename, Move to mesh, and Delete. Each opens a modal dialog and writes over the existing /control.ashx control channel, surfacing the server's ack result inline.

  • Server fns (src/server_fns/mod.rs): rename_device, remove_device, move_device, each one control-channel action plus ack. A shared device_write_ack helper maps every non-ok ack result (not-authorized, not-found, bad-name, mtype-mismatch, ...) to a human message. Verbs and ack for fields were verified against vervain-server's user_session.rs handlers (note editdevice acks as changedevice, and delete uses removedevices).
  • Rename: inline text prompt; refreshes the header via the existing use_server_future restart.
  • Move to mesh: select fed by list_meshes (the device's current mesh is excluded); refreshes the header on success.
  • Delete: typed-confirmation dialog. The Delete button stays disabled until the typed text matches the device name exactly; on success it navigates back to /devices.
  • control.rs: REQUEST_TIMEOUT made pub so the write helper reuses the standard round-trip ceiling.
  • models: Mesh derives PartialEq/Eq (component prop). main.css adds vc-btn-danger and a disabled-button style.

Tags and notes are intentionally out of scope per the issue.

Acceptance criteria

  • Rename updates the device name and survives reload (header restarts its server future; name is read back via get_device)
  • Move to mesh updates the mesh column on /devices and the detail header
  • Delete requires typing the device name, removes the node, and returns to /devices
  • All three surface ack errors (no rights) inline (not-authorized ack -> inline error)
  • Non-admin user without device rights sees errors, not silent no-ops

Checks

cargo check --features server, cargo check --target wasm32-unknown-unknown, cargo clippy --all-targets --features server -- -D warnings, cargo fmt --check, and cargo test --features server --bin vervain-app all pass.

🤖 Generated with Claude Code

Implements VAPP-9: device management (rename, delete, move to mesh) from the web UI. ## What The device detail header gains an overflow (...) menu with **Rename**, **Move to mesh**, and **Delete**. Each opens a modal dialog and writes over the existing `/control.ashx` control channel, surfacing the server's ack result inline. - **Server fns** (`src/server_fns/mod.rs`): `rename_device`, `remove_device`, `move_device`, each one control-channel action plus ack. A shared `device_write_ack` helper maps every non-`ok` ack `result` (`not-authorized`, `not-found`, `bad-name`, `mtype-mismatch`, ...) to a human message. Verbs and ack `for` fields were verified against vervain-server's `user_session.rs` handlers (note `editdevice` acks as `changedevice`, and delete uses `removedevices`). - **Rename**: inline text prompt; refreshes the header via the existing `use_server_future` restart. - **Move to mesh**: select fed by `list_meshes` (the device's current mesh is excluded); refreshes the header on success. - **Delete**: typed-confirmation dialog. The Delete button stays disabled until the typed text matches the device name exactly; on success it navigates back to `/devices`. - `control.rs`: `REQUEST_TIMEOUT` made `pub` so the write helper reuses the standard round-trip ceiling. - `models`: `Mesh` derives `PartialEq`/`Eq` (component prop). `main.css` adds `vc-btn-danger` and a disabled-button style. Tags and notes are intentionally out of scope per the issue. ## Acceptance criteria - [x] Rename updates the device name and survives reload (header restarts its server future; name is read back via `get_device`) - [x] Move to mesh updates the mesh column on /devices and the detail header - [x] Delete requires typing the device name, removes the node, and returns to /devices - [x] All three surface ack errors (no rights) inline (`not-authorized` ack -> inline error) - [x] Non-admin user without device rights sees errors, not silent no-ops ## Checks `cargo check --features server`, `cargo check --target wasm32-unknown-unknown`, `cargo clippy --all-targets --features server -- -D warnings`, `cargo fmt --check`, and `cargo test --features server --bin vervain-app` all pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(device-detail): rename, delete, and move devices from the UI
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 48s
f77d6610aa
Add the write path for device management. The detail header gains an overflow (...) menu with Rename, Move to mesh, and Delete, each opening a modal that surfaces the control-channel ack result inline so a user without mesh rights sees the "not-authorized" error instead of a silent no-op.

- Three new server fns in server_fns/mod.rs: rename_device (changedevice verb), remove_device (single-node removedevices), move_device (changeDeviceMesh). A shared device_write_ack helper sends the action, awaits the {action:"ack",for:<verb>,result:...} envelope, and maps every non-"ok" result (not-authorized, not-found, bad-name, mtype-mismatch, ...) to a human message. Verbs and ack "for" fields verified against vervain-server's user_session.rs handlers (editdevice acks as changedevice).
- control.rs: REQUEST_TIMEOUT is now pub so the write helper can reuse the standard round-trip ceiling.
- Rename uses an inline text prompt; Move is a select fed by list_meshes (the device's current mesh is excluded); Delete is a typed-confirmation dialog (the Delete button stays disabled until the typed text matches the device name exactly). Rename and Move restart the header's use_server_future so the new name/mesh show without a manual reload; Delete navigates back to /devices.
- models: Mesh derives PartialEq/Eq so it can ride as a component prop. main.css gains vc-btn-danger and a disabled-button style.
- Tags and notes stay out of scope per the issue; they ride different doc fields and can follow once the basic write path is proven.

#VAPP-9

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Owner

Resolved the merge conflict with main: PR #17's PowerActions component and this PR's management overflow menu both rewrote the device-detail header action cluster. Resolution keeps PowerActions (Wake, Power dropdown, Remote desktop) and appends the overflow menu beside it; the management dialogs block is unchanged. Verified post-merge against a live vervain-server with an enrolled agent: header renders both feature sets, and rename / move-to-mesh / delete all round-tripped (name change and mesh move confirmed via meshctrl, delete left 0 nodes). just check clean.

Resolved the merge conflict with main: PR #17's PowerActions component and this PR's management overflow menu both rewrote the device-detail header action cluster. Resolution keeps PowerActions (Wake, Power dropdown, Remote desktop) and appends the overflow menu beside it; the management dialogs block is unchanged. Verified post-merge against a live vervain-server with an enrolled agent: header renders both feature sets, and rename / move-to-mesh / delete all round-tripped (name change and mesh move confirmed via meshctrl, delete left 0 nodes). just check clean.
Merge branch 'main' into feat/device-management-actions
All checks were successful
Create release / Create release from merged PR (pull_request) Has been skipped
Check / fmt + clippy + build + tests (pull_request) Successful in 51s
e431a848ba
David merged commit a4de0e75ae into main 2026-06-06 23:52:26 +02:00
David deleted branch feat/device-management-actions 2026-06-06 23:52:26 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-apps!15
No description provided.