HydraIssues

Add per-node BodyConfig overrides (enable_debug, kiosk_mode_enabled, virtual_display_enabled)
open feature Project: hydracluster Reporter: 22 Apr 2026 17:56

Description

## Context

Three BodyConfig fields are hardcoded globally in `hydracluster/pkg/api/handlers_body.go:256`:

```go
resp.KioskModeEnabled = true
resp.EnableDebug = false // flipped from true to false in v2.0.25 on 2026-04-22
resp.VirtualDisplayEnabled = true
```

Every body fleet-wide gets the same value. There is no per-node override mechanism. This came up concretely in two scenarios during the 2026-04-21/22 session:

1. **Kiosk mode off for physical-exposure bodies**: wobbly needed kiosk disabled so testers could see desktop shortcuts. Original plan was to add a per-node `kiosk_mode` field on Node (mirroring the existing `release_channel` pattern in `pkg/store/store.go`). Plan was abandoned when the direction shifted to StreamDeck, but the underlying gap remains.

2. **Enable debug per-node**: we flipped `EnableDebug` globally to `false` because the debug cogwheel overlay was broken (LWA_COLORKEY). If a dev later needs the debug cogwheel enabled on one body to inspect audio telemetry, the only option today is re-release hydracluster with the hardcode flipped fleet-wide — overkill and cross-fleet impact.

## Proposal

Mirror the `release_channel` pattern (already implemented at `pkg/store/store.go:63` + `SetReleaseChannel` + `/admin/nodes/{id}/release-channel`).

Add three optional `Node` fields:
```go
EnableDebug *bool `yaml:"enable_debug,omitempty"`
KioskModeEnabled *bool `yaml:"kiosk_mode_enabled,omitempty"`
VirtualDisplayEnabled *bool `yaml:"virtual_display_enabled,omitempty"`
```
(Pointer-to-bool distinguishes "unset" from "explicit false".)

In `handleBodyConfig`, fall back to the global default when the node field is nil:
```go
resp.EnableDebug = valueOr(node.EnableDebug, false)
resp.KioskModeEnabled = valueOr(node.KioskModeEnabled, true)
resp.VirtualDisplayEnabled = valueOr(node.VirtualDisplayEnabled, true)
```

Expose admin routes and JSON API endpoints to flip each, same shape as `release_channel`. Admin detail page gets three rows with dropdowns (default / enabled / disabled).

## Blocked by / related

- #103 (periodic body-config refresh) — without that, any per-node change only takes effect after a body cache-clear + restart.

## Why this matters

Structural. Every new body-level feature flag we introduce hits this same wall if we don't generalize. Also: the "temporarily enable debug on one body" workflow is a real need we keep hitting operationally.

## References

- Abandoned earlier plan (per-node kiosk override): `/home/claude-user/.claude/plans/glowing-beaming-kitten.md`
- hydracluster v2.0.25 (2026-04-22) — global EnableDebug flip that motivated this