Oliver Kieselbach dc56c8a73a fix(backend): PR3 codex-review follow-ups (F2 lock-clobber, F3 SchemaHash, F4 resume, F5 preview shape)
Round-2 codex review on PR3 surfaced four real issues. Finding 1 (the
guard not being wired at the 9 writer sites) was the deferred-by-design
decision and stays scheduled for PR5.

== F2 (HIGH): StoreSessionAsync silently clobbered the cascade lock ==
Re-registration reads the existing Sessions row but built a fresh
TableEntity for the UpsertEntity (Replace) without carrying over
DeletionState + PendingDeletionManifestId. An agent restart during
Preparing/Queued/Running would have cleared the lock and let the
agent's subsequent writes race the in-flight cascade. Fix: extract
both columns alongside the other preserved fields and re-stamp on
the new entity before the Upsert. Comment marks the silent-clobber
risk so a future refactor can't quietly remove the preservation.

== F3 (HIGH): Producer invalidated the manifest SchemaHash ==
Builder generated a ManifestId, hashed the manifest content, then the
producer overwrote manifest.ManifestId. SchemaHash was now stale
(computed against the old ID); a future hash-verification path on the
worker would treat legitimate manifests as tampered/corrupt. Fix:
DeletionManifestBuilder.BuildAsync accepts an optional
preAllocatedManifestId so the producer's CAS-stamped ID lands on the
manifest BEFORE the hash computation. Producer no longer overwrites.
Preview path passes null (transient ID).

== F4 (MEDIUM): No resume path for stranded Queued state ==
If CAS Preparing→Queued succeeded but SendMessageAsync failed
(network blip, queue throttling), the Sessions row sat in Queued state
with no live queue message. A retry just returned AlreadyInFlight and
left the cascade stranded. Fix: producer's WrongState=Queued branch
re-sends the queue envelope with the EXISTING manifestId (stamped
with reason ":resume" for audit traceability), returns Enqueued.
Idempotent — duplicate envelopes are tolerated by PR4's worker via
the manifest-bound progress blob. Preparing + Running unchanged
(let GC handle Preparing; trust the worker for Running).

== F5 (MEDIUM): mode=full preview wrapped manifest in an envelope ==
Plan §5 PR3 promises mode=full returns "the entire manifest JSON
snapshot inline ... identical structure to what would be uploaded
to deletion-manifests blob container" — but the response wrapped the
manifest in { success, mode, manifest } so byte-comparison against
a real cascade's snapshot was impossible. Fix: mode=full now returns
the RAW manifest JSON as the body. Side-channel data (in-flight hint,
builder duration, schema hash, manifest id) moves to response headers
(X-Deletion-Preview-*). Only mode=summary still uses the envelope
shape (it's a summary, not a snapshot).

== Tests ==
- SessionDeletionPr3CodexFixesTests (5 new): pin F3 hash consistency
  with + without preAllocatedManifestId, F4 resume re-sends queue
  message with existing ManifestId, F4 Running + Preparing do NOT
  re-send.
- Updated 1 existing producer test: AlreadyInFlight assertion now
  uses Running state (Queued is the resume path post-F4).
- Backend suite: 1345/1345 green.

== Finding 1 (guard wiring) ==
Confirmed deferred to PR5 per the original PR3 scope decision. PR5
wires the producer call into DeleteSessionFunction AND the 9 guard
sites in the same PR. Cascade can't fire until then, so the guard
being dormant in PR3 has zero runtime impact.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:18:40 +02:00
2026-03-17 18:24:01 +01:00
2026-03-26 07:02:33 +01:00
2026-05-07 08:51:22 +02:00

Autopilot Monitor

Status License Website

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.

S
Description
Windows Autopilot & Intune enrollment monitoring: live session timelines, fleet health, diagnostics, and an MCP server for AI-assisted troubleshooting.
Readme AGPL-3.0 60 MiB
Languages
C# 72.7%
TypeScript 25.7%
PowerShell 1%
JavaScript 0.5%