Oliver Kieselbach 522f0ae048 fix(backend): PR3 codex round-2 follow-ups (F2 ETag-CAS, F4 Preparing-resume)
Round 2 of codex feedback flagged that the first follow-up wasn't tight
enough:

== F2 round 2 (HIGH): TOCTOU race still possible on Sessions row ==
The first fix only preserved DeletionState if it was non-empty on the
INITIAL read. The race remained: T1 StoreSessionAsync reads row →
DeletionState=None; T2 producer CAS-es None → Preparing; T3
StoreSessionAsync writes Replace → silently clobbers the lock. Codex
specifically asked for ETag/Retry oder Merge.

Fix: replace the unconditional UpsertEntityAsync with an ETag-bound CAS
write loop (bounded retry = 5 attempts). Each iteration re-reads the
CURRENT row to capture (a) the fresh ETag and (b) the live cascade-lock
columns, stamps the cascade-lock columns from that FRESH read onto our
entity (so the producer's intervening write isn't clobbered), then tries
UpdateEntity(etag, Replace). On 412/409 conflict: retry. Falls back to
AddEntity when the row was deleted between reads (tombstone race). The
preserved-fields extract from the initial read still runs as a
best-effort hint; the per-iteration fresh read is what actually wins
the race.

Replace mode is kept (not Merge) so registration can still clear stale
fields like FailureReason on a successful re-register. Only the
cascade-lock columns get the cross-iteration preservation treatment.

== F4 round 2 (MEDIUM): stranded Preparing with progress blob ==
If the prior producer call CAS'd None → Preparing AND uploaded snapshot
+ progress blobs AND audited deletion_started, then crashed before the
CAS Preparing → Queued step — the row stays in Preparing forever. Plan
§10 GC only clears Preparing-WITHOUT-progress-blob (intentional, to
avoid racing in-flight producers); the resume path I added before only
covered the Queued case. So this would sit until manual intervention.

Fix: in the WrongState=Preparing branch with non-empty
PendingDeletionManifestId, probe the snapshot blob via the new
BlobStorageService.DeletionSnapshotExistsAsync helper. If it exists,
the prior crash happened POST-upload — safe to finish the CAS
Preparing → Queued + send the queue message (resume from step 6). If
absent, the prior crash was PRE-upload — bail out as AlreadyInFlight
and let the §10 GC clean up after 1h.

Probe failure (e.g. transient blob storage outage) also falls back to
AlreadyInFlight rather than risk a half-completed recovery. Extracted
the queue-message-resume call into a shared helper
(ResumeBySendingQueueMessageAsync) so both Queued-resume and
Preparing-resume go through one audit-marker code path
(Reason="resume").

== Tests ==
- SessionDeletionPr3CodexFixesRound2Tests (4 new):
  - Stranded Preparing-with-blob → resumes (CAS Preparing→Queued runs,
    queue message sent, returns Enqueued + Reason=resume)
  - Preparing without blob → AlreadyInFlight, no CAS attempt
  - Snapshot existence probe throws → AlreadyInFlight, no CAS attempt
  - Resume CAS loses to concurrent writer → AlreadyInFlight, no queue
    message
- Backend suite: 1349/1349 green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:34:42 +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%