Closes the last peripheral-parity gap flagged by the user: Legacy's admin
kill-switch / device-block / admin-mark-failed signals flow through the
batch-upload response and drive the same termination / pause paths. Without
this the V2 agent had no way to be remotely stopped or quarantined — it
could only be self-destructed by its own decision engine.
UploadResult extended
- New optional fields on success: DeviceBlocked, UnblockAt, DeviceKillSignal,
AdminAction, Actions. Factory OkWithSignals(...) for success-with-control.
- Legacy-parity: same semantic as IngestEventsResponse's quarantine / kill /
admin surface, just riding on the new /api/telemetry/batch response body.
BackendTelemetryUploader.TryReadControlSignalsAsync
- Parses the 2xx response body as JSON (defensive — empty body or malformed
JSON degrades cleanly to plain Ok). Accepts both camelCase and PascalCase
field names so an M5 backend can choose either without breaking V2
agents in the wild.
- Recognises deviceBlocked (bool) + unblockAt (ISO-8601 UTC) + deviceKillSignal
(bool) + adminAction (string) + actions (ServerAction[]).
TelemetryUploadOrchestrator
- New public event ServerResponseReceived fires on successful uploads that
carry any control signal. Handlers run after the cursor has moved, so a
handler exception does not abort or re-run the batch.
- New public IsPaused property — DeviceBlocked sets an internal
_pausedUntilUtc; subsequent DrainAllAsync calls short-circuit with a
"device blocked" LastErrorReason until UnblockAt elapses (or indefinitely
when UnblockAt is null). UnblockAt=null maps to DateTime.MaxValue so the
comparison stays deterministic without a null branch per tick.
EnrollmentOrchestrator.Transport property
- Exposes the live TelemetryUploadOrchestrator so Program.cs can subscribe
to ServerResponseReceived without leaking transport internals through
public orchestrator API.
Program.cs WireTelemetryServerResponse
- Routes ServerResponseReceived through the existing ServerActionDispatcher:
• DeviceKillSignal → synthesises terminate_session with forceSelfDestruct=
true + gracePeriodSeconds=0 (kill overrides local SelfDestructOnComplete
config — Legacy parity, the operator's decision wins)
• AdminAction → synthesises soft terminate_session respecting local config
• Actions[] → dispatched directly
• DeviceBlocked → logged (the transport already paused itself)
- onTerminateRequested extended: reads params["forceSelfDestruct"] and
flips agentConfig.SelfDestructOnComplete at runtime when set, so the
cleanup service actually runs.
Tests (+15 in V2.Core.Tests → 384)
- BackendTelemetryUploaderControlSignalsTests: empty body, malformed JSON,
DeviceBlocked + UnblockAt, PascalCase accepted, DeviceKillSignal,
AdminAction, Actions array round-trip, non-2xx does not parse signals,
body with only unknown fields.
- TelemetryUploadOrchestratorServerResponseTests: plain Ok is silent,
kill-signal raises event once, admin-action forwards field, actions
forward list, DeviceBlocked pauses → unblock lifts pause → next drain
uploads the queued item, handler exceptions do not break cursor.
All 4 suites green: 88 DecisionCore + 384 V2.Core + 507 Agent.Core + 557 Functions
= 1536 tests green.
With this commit M4.6 closes all known Legacy-vs-V2 peripheral-parity gaps:
agent_kill (DeviceKillSignal → synthesized terminate_session), agent_blocked
(DeviceBlocked → paused drain), portal Mark-Failed/Mark-Succeeded (AdminAction
→ synthesized terminate_session), plus the generic server-queued Actions[].
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Autopilot Monitor
Advanced monitoring and troubleshooting solution for Windows Autopilot deployments. Gain full visibility into every enrollment session with a detailed event timeline, fleet health dashboards, and session reporting. Define custom analysis rules to automatically detect issues and gather rules to collect targeted evidence. Retrieve diagnostics packages on demand, configure agent settings like auto-reboot behavior and automatic timezone adjustment — all managed centrally from the web dashboard.
Private Preview
Autopilot Monitor is currently running as a Private Preview. Visit autopilotmonitor.com to request access and learn more.
Overview
Autopilot Monitor provides real-time tracking, intelligent diagnostics, and automated troubleshooting for Windows Autopilot enrollment processes. It consists of:
- Bootstrap Script — PowerShell script deployed via Intune that starts monitoring early in the enrollment process
- Monitoring Agent — Lightweight .NET application that collects telemetry and evidence during enrollment
- Backend API — Azure Functions-based ingestion and processing pipeline
- Web Dashboard — Next.js application for real-time monitoring and fleet analytics
Architecture
For detailed information about the system architecture, components, and data flow, see Architecture Documentation.
Documentation
Full documentation is available at autopilotmonitor.com/docs
License
This project uses a split licensing model:
- MIT License — Agent (
src/Agent/) and Shared library (src/Shared/) — unrestricted use on end-user devices - AGPL-3.0 — Backend (
src/Backend/), Web Dashboard (src/Web/), and MCP Server (src/McpServer/) — server-side components remain open source
See LICENSE for full details.



