* feat(backend): typed API response infrastructure — IApiResponse marker, wire-settings single source, widened anonymous-body ratchet (batch 0 of typed-api-contract) IApiResponse (Shared, with SuccessMessageResponse/SuccessOnlyResponse and the ProjectedItems/WireContract attributes for the upcoming manifest export) plus generic OkAsync/CreatedAsync/JsonAsync<T> overloads constrained on it, so anonymous success bodies stop compiling once the legacy object overloads go; ApiJsonOptions is now the single source of the production wire settings (camelCase, WhenWritingNull, string enums) used by Program.cs AND the three endpoint-test harnesses (two serialized PascalCase-with-nulls, one JsonSerializerDefaults.Web — all could pass while the deployed wire differed); TypedResponseGuardTests replaces OkAsyncBaselineGuardTests with the same ratchet mechanics over two frozen baselines (44 anonymous helper sites unchanged, plus 134 anonymous success WriteAsJsonAsync sites across 76 files — error-shaped bodies stay anonymous by design) and a flatness/location reflection guard (IApiResponse implementers derive from object and live in Shared, protecting JSON key order); ApiResponseWireParityTests carries the ordinal old-vs-new serialization proof each converted site must add Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(backend): Sessions/Annotations/Reports/Raw/Progress success responses are typed wire DTOs (batch 1 of typed-api-contract) 34 anonymous success bodies across 24 functions replaced with flat IApiResponse DTOs in Shared (SessionApiModels/ReportApiModels + new Annotation/Raw/ProgressApiModels) — minimal in-place transformation, call structure/status codes untouched, declaration order == wire order, nullable exactly where a site can emit null (WhenWritingNull); fields= projections stay IReadOnlyList<object> marked [ProjectedItems(SessionSummary/ EnrollmentEvent)], raw table rows stay PascalCase-verbatim dictionaries (no DictionaryKeyPolicy — pinned by test), AnnotationWire and the distress-report aggregations now build named item types instead of anonymous ones, and shared shapes collapse to one DTO (SessionListResponse x4, SessionAnnotationListResponse x2, SessionReportListResponse/GetSessionEventsResponse paged+unpaged via absent-null nextLink); 54 new wire-parity facts serialize each OLD anonymous literal (independent fixture copied from the pre-migration site) against the new DTO ordinally, with a null case per vanishing key; ratchet baselines shrink 44->14 helper sites and 134->122 write sites; the three distress-report test files read the now-typed aggregation items directly instead of via reflection-ToDynamic Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(backend): every anonymous API success body is a typed wire DTO — ratchet baselines empty, legacy object overloads deleted (batches 2-5 of typed-api-contract) the remaining 141 anonymous success sites (Admin 36, Rules 24, Config 15, Graph 5, Metrics 16, Vulnerability 17, Infrastructure/Global/Notifications/Bootstrap/ Diagnostics 20 incl. the 429 quota body in McpQuotaEnforcementMiddleware, plus the 14 helper-call sites) now return flat IApiResponse DTOs from Shared (new Admin/ Rules/Config/Graph/Metrics/Vulnerability/Infrastructure/Notifications/Diagnostics ApiModels; GeographicApiModels extended) — same minimal in-place transformation as batch 1: declaration order == wire order, nullable exactly where a site can emit null, dual success/failure sites keep their status-code logic and reuse SuccessMessageResponse, MCP-critical key names (records/summaries/inventory) pinned; wire item shapes that were function-local (CustomsArchive Run/EntrySummary, CpeMappingDto, UnmatchedSoftwareAgg, AutoResolve items, LogPatternTestResult, CveExposureSummary/SeverityBreakdown/TopCve — records rewritten as flat classes, netstandard2.0 has no IsExternalInit) moved to Shared so the manifest export sees them; payload types that must stay in the Functions assembly (RuleDryRun, PreviewWhitelistEntity, GlobalAdminEntity, HealthCheck, GlobalNotificationDto, Backfill/Reclassification/MaintenanceResult, TenantAdminEntity, TenantConfigFieldSchema) ride as object slots — wire-identical via runtime-type serialization, proven by the parity facts; 126 new wire-parity facts total (Admin 26, Rules 12, Config 17, Graph 7, Metrics 16, Vulnerability 19, Infrastructure 21 + Dictionary-key-verbatim and null-value pins); both TypedResponseGuard baselines are now EMPTY regression guards and the untyped OkAsync/CreatedAsync(object) overloads are gone, so a new anonymous success body no longer compiles through the helper and fails the guard through raw WriteAsJsonAsync; deliberately untouched: error bodies (one anonymous shape by design), auth/me (AuthDecisionResult.Body slot shared with error bodies, tests reflect over it), CheckMcpAccess (conditional dictionary keys), raw-byte streamers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(contract): C#→TS wire codegen — shared-manifests v2 exports the full response-type graph as generated TypeScript (batch 6 of typed-api-contract) SharedManifestParityTests now writes schemaVersion 2: the v1 catalog sections stay byte-compatible (sectionFieldMap/signalrMessages/sharedManifestChecks untouched), the consumer-less sessionSummary section is gone, and a new types section carries every wire type — roots are all IApiResponse implementers plus [WireContract]-marked types (SlaViolatorSession, ImeVersionHistoryEntry), transitively closed by the new WireTypeManifestBuilder over refs, collections, dictionaries, enums and [ProjectedItems] item types (208 types). Fields honour [JsonPropertyName]/ [JsonIgnore], get-only members export readonly, a nullable slot exports optional (WhenWritingNull omits the KEY — explicit null survives only inside collections and dictionary values, so the nullable flag lives on nested descriptors only), field order follows STJ's derived-before-base serialization for the one legacy inherited wire type (LocationSessionRow : SessionSummary), and unmappable shapes (non-string dictionary keys, foreign BCL classes) fail the build instead of degrading to unknown. C# <summary> texts travel as JSDoc: Shared builds XML docs now (doc-quality warnings CS1591/1573/1574/1584/0419 suppressed — crefs to foreign assemblies cannot resolve from Shared; CS1570 malformed-XML stays an error, which surfaced a raw 0x01 control char and an unescaped ampersand in existing comments). generate-shared-manifest-types.js emits utils/wire-types.generated.ts (interfaces + string-union enums, 2.7k lines) next to the lean literal module, npm run generate:manifests wraps it, the vitest freshness test pins BOTH outputs, and a new shared-manifests-in-sync CI job (guardrails-in-sync pattern) fails on drift Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(web): hand-written response types re-export the generated wire interfaces (batch 7+8 of typed-api-contract) types/session.ts, types/enrollment.ts and types/adminConfig.ts are re-exports over utils/wire-types.generated.ts (Session = SessionSummary alias for the 25+ barrel importers; adminConfig keeps only the excessiveEventAutoActionMode literal-union narrowing and the client-side OpsAlertRule view) — the generated types are never weakened, consumers adapt: durationSeconds is now optional as on the wire (int? — consumers guard with ?? 0, which also retires the latent NaN-minutes display on in-progress sessions), status is the SessionStatus union (fixtures on canonical values; the generic string-sort test keeps its own fixture type), required bools break hand-built fixtures once → new test/factories.ts makeSession/makeEvent (Object.assign, not spread — Partial spread re-widens and tests must force data: undefined); the string|null lifecycle branches were already truthiness-based. Duplicate local types deleted: geographic-performance now uses the real LocationSessionRow wire type (incl. DO fields), GlobalSearch the generated QuickSearchResult, sla/page.tsx the generated SlaViolatorSession (status stays a number — C# int, rendered via statusLabels); sessionExportUtils aliases SessionExportEvent = EnrollmentEvent and derives RuleResultCsvData via Pick, CSV output unchanged; the three structural ReplayInputEvent clones (InstallEvent, ScriptInputEvent, DownloadEvent) are aliases now. docs: drift-guards.md replaces the shrink-only-OkAsync section with the typed-wire-DTO contract, index.md/log.md updated. tsc 0, vitest 957, eslint 0 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(tests): SlaMetricsServiceTests anchor sessions inside the current ISO week — the 'now - 1h' fixture crossed into LAST week during the first hour of every Monday (UTC), emptying CurrentWeek and failing the three snapshot asserts (CI on Mon 2026-08-31 00:20Z; pre-existing Monday-morning time bomb, unrelated to the DTO migration); the anchor is now clamped to the week's Monday 00:00, proven green inside the same failure window Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
AutopilotMonitor
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.
Availability
Autopilot Monitor is publicly available — the Community plan is free. Sign in with your work account at autopilotmonitor.com; new organizations complete a short activation step after first sign-in.
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 admin documentation is available at docs.autopilotmonitor.com
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.



