Wake-on-LAN — complete the mobile.ts stub (relay-aware, audit-traced, /24 fallback) #694
Replies: 4 comments
-
|
Green light — PR welcome. The half-wired A couple of nudges before you open the PR:
One open question before you start: would you like the |
Beta Was this translation helpful? Give feedback.
-
|
Thanks for the green light. Two of the three nudges land cleanly — One clarification before I open the PR: I read your So the nudge could mean any of:
Which one matches your intent? I'd rather ask than guess given the table's traffic profile. |
Beta Was this translation helpful? Give feedback.
-
|
Good catch — you're right, I was sloppy. Retracting nudge #1.
The reason I half-typed that nudge was a stale mental model — I was thinking about the hot agent-write tables that do denormalize Carry on with the PR as designed. The other two nudges still stand (server-generated |
Beta Was this translation helpful? Give feedback.
-
|
Shipped — relay-aware Wake-on-LAN with audit trail, /24 fallback, and the agent magic-packet handler landed on The half-wired |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Why
apps/api/src/routes/mobile.ts:880-891accepts awakeaction and inserts adevice_commandsrow addressed to the offline target itself.apps/docs/src/content/docs/features/mobile.mdx:74describes the action as available for all devices.apps/api/src/routes/devices/schemas.ts:44doesn't list'wake'increateCommandSchema.type, so the mobile UI'sPOST /devices/:id/commandscall atapps/mobile/src/services/api.ts:466hits a validator error before reaching that stub.Net effect: the existing
wakescaffolding is incomplete — the schema, route, and docs each have partial entries but they don't connect to an executing agent handler. This proposal finishes wiring those pieces.What this proposes
A relay-aware Wake-on-LAN implementation that fits Breeze's existing command pipeline:
apps/api/src/services/wakeOnLan.ts) —dispatchWake(targetDeviceId, userId, options)returns a discriminated union:WakeSuccessor one of sevenWakeFailureCodes (TARGET_NOT_FOUND,NO_MACS,NO_SUBNET,IPV6_ONLY,NO_RELAY,RELAY_OVERRIDE_INVALID,WS_SEND_FAILED).site_idas target, online status, target's most-recent active IPv4 subnet matches an online peer's most-recent active IPv4 subnet. Most-recentlastSeenwins. Verifies WS connection before claiming.device_network(live inventory), fall back todevice_ip_historyfor legacy data. Includes every NIC's MAC, not just primary.device_ip_history.subnet_mask. Falls back to/24when the column is null (pre-existing upstream gap; fix proposed below).device_commands.deviceId= the relay's deviceId so the result handler atapps/api/src/routes/agentWs.ts:1248matches. Payload carries{ targetDeviceId, macs, broadcast, ports: [7, 9], wakeAttemptId }.auditLogsrow addressed to the target (action =device.wake_on_lan). Details include relay info, broadcast, mask,maskSource: 'agent' | 'fallback_24', MAC list.POST /devices/:id/commandswithtype: 'wake'callsdispatchWake. Returns202with{commandId, wakeAttemptId, relay, network, broadcast, macs}or412with{code, error}. Mobile-actions endpoint (/mobile/devices/:id/actions) wired in parallel for the legacy stub call site.agent/internal/remote/tools/wake_on_lan.go) — pure-stdlibMagicPacket(mac)builder +WakeOnLan(payload)that fires 3 rounds × N MACs × M ports (default 7+9), 500 ms between rounds. Bind UDP to the broadcast address; rely on the kernel's interface selection. SO_BROADCAST is skipped because directed-broadcast (e.g.,192.168.1.255) works on Linux/macOS/Windows without it for this case; could be added behind a build-split helper if field testing shows otherwise.agent/internal/collectors/inventory.go'sNetworkAdapterInfohad noSubnetMaskfield, soip_tracking.go:366-372never populated it. Result:device_ip_history.subnet_maskis null on 100% of rows in production. Adds the field + populates from*net.IPNet.Maskreturned bynet.ParseCIDR. After this lands and agents heartbeat, the API-side/24fallback becomes dead code for new data.DeviceActions(compact + full bars), visible only whendevice.status === 'offline'. Renders the 7 failure codes as friendly toast text.apps/docs/src/content/docs/features/mobile.mdx:74rewritten with accurate semantics + a new pre-flight reference table.No schema migration. All required columns already exist on
devices,device_network,device_ip_history,sites,device_commands,audit_logs.Live test result
Overnight on our prod fork: an offline workstation (
10.10.144.172last-known) → web Wake click → API auto-picked an online peer (10.10.144.126/24) → agent fired 18 packets (3 MACs × 2 ports × 3 rounds) to10.10.144.255in 1037 ms → target reported online 3 seconds later. End-to-end works.Tests
apps/api/src/services/wakeOnLan.test.ts— 10 helper unit tests (ipv4ToInt,intToIpv4,computeBroadcastacross /8 /16 /23 /24 /32 + malformed input). All pass.agent/internal/remote/tools/wake_on_lan_test.go— 11 tests including magic-packet byte equality, MAC format parsing (colon/hyphen/cisco-dot/whitespace), IPv4-only enforcement, port range validation, and a full loopback dispatch test that opens a real UDP listener on127.0.0.1and verifies the 102-byte packet arrives.Open questions for upstream
relayDeviceIdOverride; only auto-pick is wired through the UI. For troubleshooting multi-VLAN sites it'd help to expose a dropdown when 2+ candidates exist. Preference?bulkCommandSchema.typeunchanged — bulk wake isn't sensible until relay capacity is reasoned about. Worth allowing?DEVICES_EXECUTE(matching the/devices/:id/commandsroute's existing gate). Want to tighten to a newDEVICES_WAKEpermission?Test plan
NO_MACS,NO_SUBNET,IPV6_ONLY,NO_RELAYsurfaced as 412 with code in bodywake_on_lancommand, fires packets, returnscompletedwithpacketsSent/packetsTotalsubnet_maskis null (covered by service unit test)[object Object]PR is ready to open whenever you give the nod.
Beta Was this translation helpful? Give feedback.
All reactions