diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9bce2f8a..10088af1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -247,7 +247,7 @@ jobs:
- name: Fail if the generated files drifted
run: |
- if ! git diff --quiet -- src/Web/autopilot-monitor-web/utils/shared-manifests.generated.ts src/Web/autopilot-monitor-web/utils/wire-types.generated.ts src/McpServer/autopilot-monitor-mcp/src/generated/wire-types.generated.ts src/McpServer/autopilot-monitor-mcp/src/generated/wire-vocabularies.generated.ts; then
+ if ! git diff --quiet -- src/Web/autopilot-monitor-web/lib/generated/shared-manifests.generated.ts src/Web/autopilot-monitor-web/lib/generated/wire-types.generated.ts src/McpServer/autopilot-monitor-mcp/src/generated/wire-types.generated.ts src/McpServer/autopilot-monitor-mcp/src/generated/wire-vocabularies.generated.ts; then
echo "::error::Generated wire types are out of date. Run 'npm run generate:manifests' in src/Web/autopilot-monitor-web and commit the result."
git diff --stat
exit 1
diff --git a/.github/workflows/combine-rules.yml b/.github/workflows/combine-rules.yml
index dfdb28ff..75533ebc 100644
--- a/.github/workflows/combine-rules.yml
+++ b/.github/workflows/combine-rules.yml
@@ -60,7 +60,7 @@ jobs:
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -- rules/dist/ \
- src/Web/autopilot-monitor-web/utils/guardrails.generated.ts \
+ src/Web/autopilot-monitor-web/lib/generated/guardrails.generated.ts \
src/McpServer/autopilot-monitor-mcp/src/rule-authoring.generated.ts
if git diff --cached --quiet; then
echo "Generated outputs unchanged - nothing to commit"
diff --git a/rules/scripts/combine.js b/rules/scripts/combine.js
index e8771e77..c1a6827e 100644
--- a/rules/scripts/combine.js
+++ b/rules/scripts/combine.js
@@ -86,12 +86,12 @@ for (const config of configs) {
// ── Guardrails generation ───────────────────────────────────────────────────
const guardrailsPath = path.join(rulesRoot, 'guardrails.json');
-// NOTE: consumers import from "@/utils/guardrails.generated" (see guardValidation.ts
+// NOTE: consumers import from "@/lib/generated/guardrails.generated" (see guardValidation.ts
// and SectionGatherRules.tsx). The web re-org (commit a3e8e044) moved this file to
// utils/ but left this output path pointing at the now-orphaned lib/ copy, which
// silently froze the live allowlist. Keep this in sync with the import path.
const guardrailsOutput = path.resolve(
- rulesRoot, '..', 'src', 'Web', 'autopilot-monitor-web', 'utils', 'guardrails.generated.ts'
+ rulesRoot, '..', 'src', 'Web', 'autopilot-monitor-web', 'lib', 'generated', 'guardrails.generated.ts'
);
if (fs.existsSync(guardrailsPath)) {
diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/SessionFreeTextSearchTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/SessionFreeTextSearchTests.cs
index b8cf51a7..dbd8ccfb 100644
--- a/src/Backend/AutopilotMonitor.Functions.Tests/SessionFreeTextSearchTests.cs
+++ b/src/Backend/AutopilotMonitor.Functions.Tests/SessionFreeTextSearchTests.cs
@@ -15,12 +15,12 @@ namespace AutopilotMonitor.Functions.Tests;
/// Server-side free-text search (q=) for the dashboard search box. The predicate is the
/// search grammar of over the web dashboard's client-side
/// searchable field set (minus derived-only tokens). Parity with the web parser is pinned by
-/// the shared case file src/Web/autopilot-monitor-web/utils/session-search-syntax.cases.json,
-/// which vitest runs against app/dashboard/utils/sessionSearchQuery.ts.
+/// the shared case file src/Web/autopilot-monitor-web/app/dashboard/lib/session-search-syntax.cases.json,
+/// which vitest runs against app/dashboard/lib/sessionSearchQuery.ts.
///
public class SessionFreeTextSearchTests
{
- private const string CasesRepoPath = "src/Web/autopilot-monitor-web/utils/session-search-syntax.cases.json";
+ private const string CasesRepoPath = "src/Web/autopilot-monitor-web/app/dashboard/lib/session-search-syntax.cases.json";
private static SessionSummary Sample() => new()
{
diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/SharedManifestParityTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/SharedManifestParityTests.cs
index 936ca204..e3e5e55c 100644
--- a/src/Backend/AutopilotMonitor.Functions.Tests/SharedManifestParityTests.cs
+++ b/src/Backend/AutopilotMonitor.Functions.Tests/SharedManifestParityTests.cs
@@ -12,7 +12,7 @@ namespace AutopilotMonitor.Functions.Tests;
///
/// Cross-language parity anchor: reflects the wire-relevant catalogs out of
/// AutopilotMonitor.Shared (models, enums, string vocabularies) into a canonical JSON
-/// manifest committed at src/Web/autopilot-monitor-web/utils/shared-manifests.json.
+/// manifest committed at src/Web/autopilot-monitor-web/lib/generated/shared-manifests.json.
/// The web's vitest suite and compile-time checks compare their hand-written TS mirrors
/// against that manifest — so a C# change that would silently drift a TS mirror first
/// fails HERE, and the TS side fails until its mirror follows.
@@ -23,7 +23,7 @@ namespace AutopilotMonitor.Functions.Tests;
///
public sealed class SharedManifestParityTests
{
- private const string ManifestRepoPath = "src/Web/autopilot-monitor-web/utils/shared-manifests.json";
+ private const string ManifestRepoPath = "src/Web/autopilot-monitor-web/lib/generated/shared-manifests.json";
private const string WriteEnvVar = "AM_WRITE_SHARED_MANIFESTS";
[Fact]
@@ -155,7 +155,7 @@ public sealed class SharedManifestParityTests
// the portal's counters and upload budget read the same numbers the backend enforces.
["submissionLimits"] = ConstInts(typeof(Constants.SubmissionLimits)),
// Every IApiResponse + IApiRequest implementer + [WireContract] type, transitively closed —
- // the source of utils/wire-types.generated.ts. See WireTypeManifestBuilder.
+ // the source of lib/generated/wire-types.generated.ts. See WireTypeManifestBuilder.
["types"] = WireTypeManifestBuilder.BuildTypesSection(),
};
diff --git a/src/Backend/AutopilotMonitor.Functions/Helpers/SessionSearchQuery.cs b/src/Backend/AutopilotMonitor.Functions/Helpers/SessionSearchQuery.cs
index 40231868..f560605c 100644
--- a/src/Backend/AutopilotMonitor.Functions/Helpers/SessionSearchQuery.cs
+++ b/src/Backend/AutopilotMonitor.Functions/Helpers/SessionSearchQuery.cs
@@ -9,8 +9,8 @@ namespace AutopilotMonitor.Functions.Helpers;
///
/// The dashboard search-box grammar, parsed once per request for the server-side sweep
/// (q= on /api/search/sessions and the global twin). Mirrors the web's
-/// app/dashboard/utils/sessionSearchQuery.ts exactly — both run
-/// utils/session-search-syntax.cases.json, because a term that matches on one side
+/// app/dashboard/lib/sessionSearchQuery.ts exactly — both run
+/// app/dashboard/lib/session-search-syntax.cases.json, because a term that matches on one side
/// and not the other is a ghost result (found by the server, filtered out by the client, or
/// never fetched at all).
///
diff --git a/src/McpServer/autopilot-monitor-mcp/src/__tests__/wire-types-freshness.test.ts b/src/McpServer/autopilot-monitor-mcp/src/__tests__/wire-types-freshness.test.ts
index a0c0bced..9a66e159 100644
--- a/src/McpServer/autopilot-monitor-mcp/src/__tests__/wire-types-freshness.test.ts
+++ b/src/McpServer/autopilot-monitor-mcp/src/__tests__/wire-types-freshness.test.ts
@@ -38,7 +38,7 @@ describe('generated wire types freshness (MCP copy)', () => {
const { buildMcpWireTypesSource } = require(
join(webRoot!, 'scripts', 'generate-shared-manifest-types.js'),
);
- const json = readFileSync(join(webRoot!, 'utils', 'shared-manifests.json'), 'utf8');
+ const json = readFileSync(join(webRoot!, 'lib', 'generated', 'shared-manifests.json'), 'utf8');
const committed = readFileSync(
join(dirname(fileURLToPath(import.meta.url)), '..', 'generated', 'wire-types.generated.ts'),
'utf8',
@@ -59,7 +59,7 @@ describe('generated wire vocabularies freshness (MCP copy)', () => {
const { buildMcpVocabulariesSource } = require(
join(webRoot!, 'scripts', 'generate-shared-manifest-types.js'),
);
- const json = readFileSync(join(webRoot!, 'utils', 'shared-manifests.json'), 'utf8');
+ const json = readFileSync(join(webRoot!, 'lib', 'generated', 'shared-manifests.json'), 'utf8');
const committed = readFileSync(
join(dirname(fileURLToPath(import.meta.url)), '..', 'generated', 'wire-vocabularies.generated.ts'),
'utf8',
diff --git a/src/McpServer/autopilot-monitor-mcp/src/generated/wire-types.generated.ts b/src/McpServer/autopilot-monitor-mcp/src/generated/wire-types.generated.ts
index f5240ef8..91869a2e 100644
--- a/src/McpServer/autopilot-monitor-mcp/src/generated/wire-types.generated.ts
+++ b/src/McpServer/autopilot-monitor-mcp/src/generated/wire-types.generated.ts
@@ -1,5 +1,5 @@
// GENERATED — do not edit by hand. Second copy for the MCP server.
-// Source: src/Web/autopilot-monitor-web/utils/shared-manifests.json.
+// Source: src/Web/autopilot-monitor-web/lib/generated/shared-manifests.json.
// Regenerate: npm run generate:manifests in src/Web/autopilot-monitor-web.
//
// Wire types reflected from AutopilotMonitor.Shared (every IApiResponse and IApiRequest
diff --git a/src/McpServer/autopilot-monitor-mcp/src/generated/wire-vocabularies.generated.ts b/src/McpServer/autopilot-monitor-mcp/src/generated/wire-vocabularies.generated.ts
index 25a8fd49..ee7ba4ba 100644
--- a/src/McpServer/autopilot-monitor-mcp/src/generated/wire-vocabularies.generated.ts
+++ b/src/McpServer/autopilot-monitor-mcp/src/generated/wire-vocabularies.generated.ts
@@ -1,5 +1,5 @@
// GENERATED — do not edit by hand. Second copy for the MCP server.
-// Source: src/Web/autopilot-monitor-web/utils/shared-manifests.json.
+// Source: src/Web/autopilot-monitor-web/lib/generated/shared-manifests.json.
// Regenerate: npm run generate:manifests in src/Web/autopilot-monitor-web.
//
// Vocabularies reflected from AutopilotMonitor.Shared. These are VALUES (not just types)
diff --git a/src/Shared/AutopilotMonitor.Shared/Services/ErrorCodeCatalog.cs b/src/Shared/AutopilotMonitor.Shared/Services/ErrorCodeCatalog.cs
index 0e8bf0c6..63a8959d 100644
--- a/src/Shared/AutopilotMonitor.Shared/Services/ErrorCodeCatalog.cs
+++ b/src/Shared/AutopilotMonitor.Shared/Services/ErrorCodeCatalog.cs
@@ -17,7 +17,7 @@ namespace AutopilotMonitor.Shared.Services
/// keyed by normalised code string (lowercase hex, e.g. 0x80070005, or decimal MSI
/// exit code, e.g. 1603), by symbol and by enforcement state.
///
- /// Mirror of src/Web/autopilot-monitor-web/utils/errorCodeMap.ts and the MCP
+ /// Mirror of src/Web/autopilot-monitor-web/lib/errorCodeMap.ts and the MCP
/// server's error-code-catalog.ts; the JSON file is the authoritative copy.
///
///
diff --git a/src/Web/autopilot-monitor-web/app/about/layout.tsx b/src/Web/autopilot-monitor-web/app/about/layout.tsx
index f386bbe8..c5462c95 100644
--- a/src/Web/autopilot-monitor-web/app/about/layout.tsx
+++ b/src/Web/autopilot-monitor-web/app/about/layout.tsx
@@ -1,5 +1,5 @@
import type { Metadata } from "next";
-import { SITE_URL } from "@/utils/config";
+import { SITE_URL } from "@/lib/config";
import { OPEN_GRAPH_BASE, TWITTER_BASE } from "@/lib/siteMetadata";
export const metadata: Metadata = {
diff --git a/src/Web/autopilot-monitor-web/app/about/page.tsx b/src/Web/autopilot-monitor-web/app/about/page.tsx
index 2dc5027e..d345e17a 100644
--- a/src/Web/autopilot-monitor-web/app/about/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/about/page.tsx
@@ -1,7 +1,7 @@
import Link from "next/link";
import { LandingNavbar } from "../../components/landing/LandingNavbar";
import { SiteFooter } from "../../components/SiteFooter";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
import { ABOUT_FAQ } from "./faq";
// FAQPage structured data mirrors the visible "Common Questions" section
diff --git a/src/Web/autopilot-monitor-web/app/activation/page.tsx b/src/Web/autopilot-monitor-web/app/activation/page.tsx
index 65314260..f1c4ee9c 100644
--- a/src/Web/autopilot-monitor-web/app/activation/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/activation/page.tsx
@@ -7,9 +7,9 @@ import { api } from "@/lib/api";
import { apiErrorText, fetchOk, jsonBody } from "@/lib/apiClient";
import { landingTarget } from "@/lib/landingTarget";
import { consumePostLoginReturnUrl } from "@/lib/postLoginReturn";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
import { BrandMark } from "../../components/BrandMark";
-import type { SaveNotificationEmailRequest } from "@/utils/wire-types.generated";
+import type { SaveNotificationEmailRequest } from "@/lib/generated/wire-types.generated";
// The URL query string is fixed for the lifetime of a page load — nothing to subscribe to.
const subscribeNever = () => () => {};
diff --git a/src/Web/autopilot-monitor-web/app/admin/AdminConfigContext.tsx b/src/Web/autopilot-monitor-web/app/admin/AdminConfigContext.tsx
index c9488a58..f8082f0d 100644
--- a/src/Web/autopilot-monitor-web/app/admin/AdminConfigContext.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/AdminConfigContext.tsx
@@ -13,7 +13,7 @@ import type {
GetPreviewWhitelistResponse,
TestNotificationChannelRequest,
TestWebhookNotificationResponse,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
import type { NotificationChannel } from "@/app/settings/types";
// Re-export so existing `import { AdminConfiguration } from "../AdminConfigContext"` consumers keep working
diff --git a/src/Web/autopilot-monitor-web/app/admin/backups/components/RestoreRowDiffModal.tsx b/src/Web/autopilot-monitor-web/app/admin/backups/components/RestoreRowDiffModal.tsx
index 3b768476..84a37455 100644
--- a/src/Web/autopilot-monitor-web/app/admin/backups/components/RestoreRowDiffModal.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/backups/components/RestoreRowDiffModal.tsx
@@ -8,7 +8,7 @@ import type {
RestoreRowPreviewResponse,
RestoreRowPropertyDiff,
RestoreRowPropertySnapshot,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
import { apiErrorText, fetchJson, jsonBody } from "@/lib/apiClient";
import { ModalPortal } from "@/components/ModalPortal";
diff --git a/src/Web/autopilot-monitor-web/app/admin/backups/detail/page.tsx b/src/Web/autopilot-monitor-web/app/admin/backups/detail/page.tsx
index 86de5f08..4c326ce2 100644
--- a/src/Web/autopilot-monitor-web/app/admin/backups/detail/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/backups/detail/page.tsx
@@ -8,7 +8,7 @@ import {
type BackupManifest,
type BackupTableEntry,
} from "@/lib/api";
-import type { RestoreRowCommitResponse, RestoreRowPreviewResponse, RestoreRowRequest } from "@/utils/wire-types.generated";
+import type { RestoreRowCommitResponse, RestoreRowPreviewResponse, RestoreRowRequest } from "@/lib/generated/wire-types.generated";
import { apiErrorText, fetchJson, jsonBody } from "@/lib/apiClient";
import { useAdminConfig } from "../../AdminConfigContext";
import { AdminNotifications } from "../../AdminNotifications";
diff --git a/src/Web/autopilot-monitor-web/app/admin/backups/page.tsx b/src/Web/autopilot-monitor-web/app/admin/backups/page.tsx
index 76548c75..509d172e 100644
--- a/src/Web/autopilot-monitor-web/app/admin/backups/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/backups/page.tsx
@@ -4,7 +4,7 @@ import { backupUrl } from "@/lib/routes";
import { useCallback, useEffect, useState } from "react";
import Link from "next/link";
import { api } from "@/lib/api";
-import type { BackupJobStatus, BackupTriggerResponse, ListBackupsResponse } from "@/utils/wire-types.generated";
+import type { BackupJobStatus, BackupTriggerResponse, ListBackupsResponse } from "@/lib/generated/wire-types.generated";
import { apiErrorText, fetchJson } from "@/lib/apiClient";
import { useAdminConfig } from "../AdminConfigContext";
import { AdminNotifications } from "../AdminNotifications";
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/ConfigReseedSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/ConfigReseedSection.tsx
index 9502b9f0..f478d76d 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/ConfigReseedSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/ConfigReseedSection.tsx
@@ -4,7 +4,7 @@ import { useState } from "react";
import { api } from "@/lib/api";
import { apiErrorText, fetchJson } from "@/lib/apiClient";
import { SectionCardHeader } from "@/components/SectionCardHeader";
-import type { ReseedFromGitHubResponse } from "@/utils/wire-types.generated";
+import type { ReseedFromGitHubResponse } from "@/lib/generated/wire-types.generated";
interface ConfigReseedSectionProps {
getAccessToken: () => Promise;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/DeviceBlockSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/DeviceBlockSection.tsx
index 13756e9b..1116ccfa 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/DeviceBlockSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/DeviceBlockSection.tsx
@@ -12,7 +12,7 @@ import { TenantSearchSelect } from "./TenantSearchSelect";
import { useCanMutatePlatform } from "@/hooks/useCanMutatePlatform";
import { firstBlockedSessionId, blockedSessionCount } from "./blockedDeviceHelpers";
import { SectionCardHeader } from "@/components/SectionCardHeader";
-import type { BlockDeviceRequest, BlockedDeviceEntry, BlockedDeviceListResponse, GetSessionResponse } from "@/utils/wire-types.generated";
+import type { BlockDeviceRequest, BlockedDeviceEntry, BlockedDeviceListResponse, GetSessionResponse } from "@/lib/generated/wire-types.generated";
interface ResolvedDevice {
sessionId: string;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/DiagnosticsLogPathsSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/DiagnosticsLogPathsSection.tsx
index 8055a467..c50e242e 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/DiagnosticsLogPathsSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/DiagnosticsLogPathsSection.tsx
@@ -1,7 +1,7 @@
"use client";
import { useState, useMemo } from "react";
-import { validateDiagnosticsPath } from "@/utils/guardValidation";
+import { validateDiagnosticsPath } from "@/lib/guardValidation";
import { ValidationIndicator } from "@/components/ValidationIndicator";
import { BuiltInSectionsList } from "@/components/diagnostics/BuiltInSectionsList";
import { DiagnosticsPathRow } from "@/components/diagnostics/DiagnosticsPathRow";
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/DistressReportsSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/DistressReportsSection.tsx
index 8c44fae4..73002650 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/DistressReportsSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/DistressReportsSection.tsx
@@ -4,7 +4,7 @@ import { useState, useEffect } from "react";
import { api } from "@/lib/api";
import { apiErrorText, fetchJson, nullOn404 } from "@/lib/apiClient";
import { TableSkeleton } from "@/components/skeletons/TableSkeleton";
-import type { DistressReportEntry, DistressReportListResponse } from "@/utils/wire-types.generated";
+import type { DistressReportEntry, DistressReportListResponse } from "@/lib/generated/wire-types.generated";
import { ModalPortal } from "@/components/ModalPortal";
/** One stored distress report — the wire shape (optional where the agent sent nothing). */
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/FeedbackSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/FeedbackSection.tsx
index 5634bc20..12985fec 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/FeedbackSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/FeedbackSection.tsx
@@ -3,7 +3,7 @@
import { useCallback, useEffect, useState } from "react";
import { api } from "@/lib/api";
import { apiErrorText, fetchJson } from "@/lib/apiClient";
-import type { FeedbackEntryWire, FeedbackListResponse } from "@/utils/wire-types.generated";
+import type { FeedbackEntryWire, FeedbackListResponse } from "@/lib/generated/wire-types.generated";
import { avgRating, paginate, partitionFeedback, type FeedbackTab } from "@/lib/feedbackPartition";
/** One stored feedback entry — the wire shape (fields absent on dismissals). */
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/IdentityBindingsSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/IdentityBindingsSection.tsx
index 200677ae..07dcfa09 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/IdentityBindingsSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/IdentityBindingsSection.tsx
@@ -5,7 +5,7 @@ import { api } from "@/lib/api";
import { apiErrorText, fetchJson, fetchOk, jsonBody } from "@/lib/apiClient";
import { useCanMutatePlatform } from "@/hooks/useCanMutatePlatform";
import { isGuid, type IdentityBinding } from "@/lib/identityBinding";
-import type { IdentityBindingListResponse, IdentityBindingRequest } from "@/utils/wire-types.generated";
+import type { IdentityBindingListResponse, IdentityBindingRequest } from "@/lib/generated/wire-types.generated";
interface IdentityBindingsSectionProps {
tenantId: string;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/IgnoredSoftwareTab.tsx b/src/Web/autopilot-monitor-web/app/admin/components/IgnoredSoftwareTab.tsx
index e2d64c24..8c2e8ba1 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/IgnoredSoftwareTab.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/IgnoredSoftwareTab.tsx
@@ -7,7 +7,7 @@ import TruncatedLabel from "@/components/TruncatedLabel";
import { trackEvent } from "@/lib/appInsights";
import { TableSkeleton } from "@/components/skeletons/TableSkeleton";
import type { AutoResolveResult, IgnoredSoftwareEntry } from "./SoftwareMappingTypes";
-import type { AutoResolveCpeMappingRequest, GetIgnoredSoftwareResponse, IgnoreSoftwareDeleteRequest } from "@/utils/wire-types.generated";
+import type { AutoResolveCpeMappingRequest, GetIgnoredSoftwareResponse, IgnoreSoftwareDeleteRequest } from "@/lib/generated/wire-types.generated";
interface IgnoredSoftwareTabProps {
getAccessToken: () => Promise;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/MaintenanceTriggerSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/MaintenanceTriggerSection.tsx
index e47a5e68..6d97482a 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/MaintenanceTriggerSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/MaintenanceTriggerSection.tsx
@@ -6,7 +6,7 @@ import { ApiError, apiErrorText, fetchJson, fetchOk } from "@/lib/apiClient";
import { CONFIG_PATH_PREFIX, invalidateCachedAuthFetch } from "@/lib/cachedAuthFetch";
import { parseOpsDetails, useOpsRunStatus, type OpsRunLifecycle } from "@/hooks/useOpsRunStatus";
import { SectionCardHeader } from "@/components/SectionCardHeader";
-import type { GetLatestVersionsResponse } from "@/utils/wire-types.generated";
+import type { GetLatestVersionsResponse } from "@/lib/generated/wire-types.generated";
const LIFECYCLE: OpsRunLifecycle = {
category: "Maintenance",
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/MappedSoftwareTab.tsx b/src/Web/autopilot-monitor-web/app/admin/components/MappedSoftwareTab.tsx
index 9cb400b1..beb1179d 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/MappedSoftwareTab.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/MappedSoftwareTab.tsx
@@ -6,7 +6,7 @@ import { apiErrorText, fetchJson, fetchOk, jsonBody } from "@/lib/apiClient";
import { trackEvent } from "@/lib/appInsights";
import { CpeMappingEntry } from "./SoftwareMappingTypes";
import { TableSkeleton } from "@/components/skeletons/TableSkeleton";
-import type { DeleteCustomCpeMappingRequest, GetCpeMappingsResponse, SaveCustomCpeMappingRequest } from "@/utils/wire-types.generated";
+import type { DeleteCustomCpeMappingRequest, GetCpeMappingsResponse, SaveCustomCpeMappingRequest } from "@/lib/generated/wire-types.generated";
interface MappedSoftwareTabProps {
getAccessToken: () => Promise;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/OpsEventsSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/OpsEventsSection.tsx
index 32c1e2d5..8d376a51 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/OpsEventsSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/OpsEventsSection.tsx
@@ -10,7 +10,7 @@ import type { CursorPage } from "@/lib/cursorPager";
import { useCursorPager } from "@/hooks/useCursorPager";
import { extractSessionId, buildAutoReason } from "./opsEventSessionHelpers";
import { SectionCardHeader } from "@/components/SectionCardHeader";
-import type { OpsEventEntry, OpsEventListResponse } from "@/utils/wire-types.generated";
+import type { OpsEventEntry, OpsEventListResponse } from "@/lib/generated/wire-types.generated";
import { ModalPortal } from "@/components/ModalPortal";
/** One ops event row (wire shape). */
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/RuleSubmissionsSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/RuleSubmissionsSection.tsx
index 50add470..33872405 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/RuleSubmissionsSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/RuleSubmissionsSection.tsx
@@ -7,7 +7,7 @@ import { apiErrorText, fetchJson, fetchOk, jsonBody, nullOn404 } from "@/lib/api
import TruncatedLabel from "@/components/TruncatedLabel";
import type { CursorPage } from "@/lib/cursorPager";
import { useCursorPager } from "@/hooks/useCursorPager";
-import { isGuid } from "@/utils/inputValidation";
+import { isGuid } from "@/lib/inputValidation";
import { trackEvent } from "@/lib/appInsights";
import { useCanMutatePlatform } from "@/hooks/useCanMutatePlatform";
import { TableSkeleton } from "@/components/skeletons/TableSkeleton";
@@ -22,7 +22,7 @@ import type {
RuleSubmissionFireStats,
RuleSubmissionItem,
RuleSubmissionListResponse,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
const PAGE_SIZE = 20;
const STATUS_FILTERS = ["pending", "approved", "declined", "withdrawn"] as const;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/SessionExportSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/SessionExportSection.tsx
index fbc55890..c669da6c 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/SessionExportSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/SessionExportSection.tsx
@@ -5,10 +5,10 @@ import { api } from "@/lib/api";
import { apiErrorText, fetchJson } from "@/lib/apiClient";
import { TenantConfiguration } from "./TenantManagementSection";
import { TenantSearchSelect } from "./TenantSearchSelect";
-import { SessionExportEvent, generateCsvExport, generateUiExport } from "@/utils/sessionExportUtils";
+import { SessionExportEvent, generateCsvExport, generateUiExport } from "@/lib/sessionExportUtils";
import { trackEvent } from "@/lib/appInsights";
import { SectionCardHeader } from "@/components/SectionCardHeader";
-import type { GetSessionEventsResponse } from "@/utils/wire-types.generated";
+import type { GetSessionEventsResponse } from "@/lib/generated/wire-types.generated";
function downloadFile(content: string, filename: string, mimeType: string) {
const blob = new Blob([content], { type: mimeType });
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/SessionReportsSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/SessionReportsSection.tsx
index 15fe409d..f15b82d7 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/SessionReportsSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/SessionReportsSection.tsx
@@ -7,12 +7,12 @@ import { apiErrorText, fetchJson, fetchOk, jsonBody, nullOn404 } from "@/lib/api
import TruncatedLabel from "@/components/TruncatedLabel";
import type { CursorPage } from "@/lib/cursorPager";
import { useCursorPager } from "@/hooks/useCursorPager";
-import { isGuid } from "@/utils/inputValidation";
+import { isGuid } from "@/lib/inputValidation";
import { trackEvent } from "@/lib/appInsights";
import { useCanMutatePlatform } from "@/hooks/useCanMutatePlatform";
import { TableSkeleton } from "@/components/skeletons/TableSkeleton";
import { SectionCardHeader } from "@/components/SectionCardHeader";
-import type { SessionReportDownloadUrlResponse, SessionReportListResponse, SessionReportMetadata, UpdateSessionReportNoteRequest } from "@/utils/wire-types.generated";
+import type { SessionReportDownloadUrlResponse, SessionReportListResponse, SessionReportMetadata, UpdateSessionReportNoteRequest } from "@/lib/generated/wire-types.generated";
import { ModalPortal } from "@/components/ModalPortal";
const PAGE_SIZE = 20;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/SoftwareMappingTypes.ts b/src/Web/autopilot-monitor-web/app/admin/components/SoftwareMappingTypes.ts
index 84e45811..86018a5f 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/SoftwareMappingTypes.ts
+++ b/src/Web/autopilot-monitor-web/app/admin/components/SoftwareMappingTypes.ts
@@ -1,4 +1,4 @@
-import type { UnmatchedSoftwareItem } from "@/utils/wire-types.generated";
+import type { UnmatchedSoftwareItem } from "@/lib/generated/wire-types.generated";
/** One row of GET vulnerability/unmatched-software — the wire shape. */
export type UnmatchedSoftwareEntry = UnmatchedSoftwareItem;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/TenantAdminSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/TenantAdminSection.tsx
index 1c44060c..ae98cfbb 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/TenantAdminSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/TenantAdminSection.tsx
@@ -6,8 +6,8 @@ import { apiErrorText, fetchJson, fetchOk, jsonBody } from "@/lib/apiClient";
import { useCanMutatePlatform } from "@/hooks/useCanMutatePlatform";
import { AddMemberForm } from "@/components/members/AddMemberForm";
import { MemberList } from "@/components/members/MemberList";
-import type { AddTenantAdminRequest, TenantAdminRow, UpdateMemberPermissionsRequest } from "@/utils/wire-types.generated";
-import { looksLikeGuid, type MemberKind } from "@/utils/principalKeys";
+import type { AddTenantAdminRequest, TenantAdminRow, UpdateMemberPermissionsRequest } from "@/lib/generated/wire-types.generated";
+import { looksLikeGuid, type MemberKind } from "@/lib/principalKeys";
// Wire type is generated from the backend DTO ("role" is absent for legacy pre-role rows).
type TenantAdmin = TenantAdminRow;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx
index ddc535ad..dfdc1c6a 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx
@@ -16,7 +16,7 @@ import type {
TenantConfiguration as WireTenantConfiguration,
TenantOffboardingStatusResponse,
UpdateTenantAppHomingResponse,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
import { useSearchParams } from "next/navigation";
import { api } from "@/lib/api";
import { ApiError, apiErrorText, fetchJson, fetchOk, jsonBody } from "@/lib/apiClient";
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/UnmappedSoftwareTab.tsx b/src/Web/autopilot-monitor-web/app/admin/components/UnmappedSoftwareTab.tsx
index 597a527f..809d6724 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/UnmappedSoftwareTab.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/UnmappedSoftwareTab.tsx
@@ -8,7 +8,7 @@ import TruncatedLabel from "@/components/TruncatedLabel";
import { TableSkeleton } from "@/components/skeletons/TableSkeleton";
import { trackEvent } from "@/lib/appInsights";
import type { UnmatchedSoftwareEntry, AutoResolveResult } from "./SoftwareMappingTypes";
-import type { AutoResolveCpeMappingRequest, GetUnmatchedSoftwareResponse, IgnoreSoftwareRequest, SaveCustomCpeMappingRequest } from "@/utils/wire-types.generated";
+import type { AutoResolveCpeMappingRequest, GetUnmatchedSoftwareResponse, IgnoreSoftwareRequest, SaveCustomCpeMappingRequest } from "@/lib/generated/wire-types.generated";
interface UnmappedSoftwareTabProps {
getAccessToken: () => Promise;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/VersionBlockSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/VersionBlockSection.tsx
index 9f98c532..cb3648c2 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/VersionBlockSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/VersionBlockSection.tsx
@@ -5,7 +5,7 @@ import { api } from "@/lib/api";
import { apiErrorText, fetchJson, fetchOk, jsonBody } from "@/lib/apiClient";
import { useCanMutatePlatform } from "@/hooks/useCanMutatePlatform";
import { SectionCardHeader } from "@/components/SectionCardHeader";
-import type { BlockedVersionListResponse, BlockVersionRequest } from "@/utils/wire-types.generated";
+import type { BlockedVersionListResponse, BlockVersionRequest } from "@/lib/generated/wire-types.generated";
interface BlockedVersion {
versionPattern: string;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/VulnerabilityDataSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/VulnerabilityDataSection.tsx
index 9ea2e871..5533ca86 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/VulnerabilityDataSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/VulnerabilityDataSection.tsx
@@ -18,7 +18,7 @@ import type {
TriggerMsrcSyncResponse,
TriggerNvdCacheRefreshResponse,
TriggerVulnerabilityDataSyncResponse,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
interface VulnerabilityDataSectionProps {
adminConfig: AdminConfiguration | null;
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/__tests__/tenantEditorFields.test.ts b/src/Web/autopilot-monitor-web/app/admin/components/__tests__/tenantEditorFields.test.ts
index c0daadfb..16e91e71 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/__tests__/tenantEditorFields.test.ts
+++ b/src/Web/autopilot-monitor-web/app/admin/components/__tests__/tenantEditorFields.test.ts
@@ -4,8 +4,8 @@
* list would 400 the save — and against the manifest.
*/
import { describe, expect, it } from "vitest";
-import { SHARED_MANIFEST } from "@/utils/shared-manifests.generated";
-import type { TenantConfiguration } from "@/utils/wire-types.generated";
+import { SHARED_MANIFEST } from "@/lib/generated/shared-manifests.generated";
+import type { TenantConfiguration } from "@/lib/generated/wire-types.generated";
import { TENANT_EDITOR_FIELDS, tenantEditorPatch } from "../tenantEditorFields";
/** BaseDeniedFields in TenantConfigPatchService, camelCased — independent copy. */
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/tenantEditorFields.ts b/src/Web/autopilot-monitor-web/app/admin/components/tenantEditorFields.ts
index 6da47b4b..2409f488 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/tenantEditorFields.ts
+++ b/src/Web/autopilot-monitor-web/app/admin/components/tenantEditorFields.ts
@@ -1,5 +1,5 @@
import { changedTenantConfigFields, type TenantConfigFieldName } from "@/lib/tenantConfigSave";
-import type { TenantConfiguration } from "@/utils/wire-types.generated";
+import type { TenantConfiguration } from "@/lib/generated/wire-types.generated";
/**
* The fields the Global Admin tenant editor saves with its generic Save. Plan, trial, delegated
diff --git a/src/Web/autopilot-monitor-web/app/admin/customs-archive/detail/page.tsx b/src/Web/autopilot-monitor-web/app/admin/customs-archive/detail/page.tsx
index a864d475..7fb95679 100644
--- a/src/Web/autopilot-monitor-web/app/admin/customs-archive/detail/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/customs-archive/detail/page.tsx
@@ -8,7 +8,7 @@ import { apiErrorText, fetchJson, fetchOk } from "@/lib/apiClient";
import { useAdminConfig } from "../../AdminConfigContext";
import { AdminNotifications } from "../../AdminNotifications";
import { DeleteConfirmModal } from "../components/DeleteConfirmModal";
-import type { CustomsArchiveEntryListResponse, CustomsArchiveEntryResponse, CustomsArchiveEntrySummary, TenantOffboardingCustomsArchiveEntry } from "@/utils/wire-types.generated";
+import type { CustomsArchiveEntryListResponse, CustomsArchiveEntryResponse, CustomsArchiveEntrySummary, TenantOffboardingCustomsArchiveEntry } from "@/lib/generated/wire-types.generated";
export default function CustomsArchiveDetailPage() {
// useSearchParams() in CustomsArchiveDetailContent requires a Suspense boundary
diff --git a/src/Web/autopilot-monitor-web/app/admin/customs-archive/page.tsx b/src/Web/autopilot-monitor-web/app/admin/customs-archive/page.tsx
index 5ae5584c..e5d6c0d7 100644
--- a/src/Web/autopilot-monitor-web/app/admin/customs-archive/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/customs-archive/page.tsx
@@ -8,7 +8,7 @@ import { apiErrorText, fetchJson } from "@/lib/apiClient";
import { useAdminConfig } from "../AdminConfigContext";
import { AdminNotifications } from "../AdminNotifications";
import { DeleteConfirmModal } from "./components/DeleteConfirmModal";
-import type { CustomsArchiveDeleteRunResponse, CustomsArchiveRunListResponse, CustomsArchiveRunSummary } from "@/utils/wire-types.generated";
+import type { CustomsArchiveDeleteRunResponse, CustomsArchiveRunListResponse, CustomsArchiveRunSummary } from "@/lib/generated/wire-types.generated";
export default function CustomsArchivePage() {
const { getAccessToken, setError, setSuccessMessage } = useAdminConfig();
diff --git a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionMcpUsage.tsx b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionMcpUsage.tsx
index 18ce6b39..cbda8830 100644
--- a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionMcpUsage.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionMcpUsage.tsx
@@ -6,8 +6,8 @@ import { useCallback, useEffect, useState } from "react";
import { useAuth } from "../../../../contexts/AuthContext";
import { apiErrorText, fetchJson } from "@/lib/apiClient";
import { api } from "@/lib/api";
-import { isApplicationKey, principalLabel } from "@/utils/principalKeys";
-import type { GetGlobalMcpUsageDailyResponse, GetGlobalMcpUsageResponse, UserUsageDailySummary } from "@/utils/wire-types.generated";
+import { isApplicationKey, principalLabel } from "@/lib/principalKeys";
+import type { GetGlobalMcpUsageDailyResponse, GetGlobalMcpUsageResponse, UserUsageDailySummary } from "@/lib/generated/wire-types.generated";
interface UsageRecord {
userId: string;
diff --git a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionPlatformUsage.tsx b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionPlatformUsage.tsx
index 1dc8582b..d795aa7f 100644
--- a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionPlatformUsage.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionPlatformUsage.tsx
@@ -7,7 +7,7 @@ import { useAuth } from '../../../../contexts/AuthContext';
import { apiErrorText, fetchJson } from "@/lib/apiClient";
import { useFetchProgress } from "@/hooks/useFetchProgress";
import { CalculatingCard } from "@/components/CalculatingCard";
-import type { PlatformUsageMetrics } from "@/utils/wire-types.generated";
+import type { PlatformUsageMetrics } from "@/lib/generated/wire-types.generated";
// A fresh cross-tenant compute takes tens of seconds server-side; the default 30s fetch timeout
// aborted it client-side (HTTP 499 on the backend) while the server kept computing. Give this one
diff --git a/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreConfirmDialog.tsx b/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreConfirmDialog.tsx
index bfe8c53e..9c80dd31 100644
--- a/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreConfirmDialog.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreConfirmDialog.tsx
@@ -3,7 +3,7 @@
import { useState } from "react";
import { api } from "@/lib/api";
import { apiErrorText, fetchJson, jsonBody } from "@/lib/apiClient";
-import type { RestoreSessionRequest, SessionRestoreResponse } from "@/utils/wire-types.generated";
+import type { RestoreSessionRequest, SessionRestoreResponse } from "@/lib/generated/wire-types.generated";
import { ModalPortal } from "@/components/ModalPortal";
interface RestoreConfirmDialogProps {
diff --git a/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionDelegatedAdmins.tsx b/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionDelegatedAdmins.tsx
index 2487ebdd..b5ef2d0c 100644
--- a/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionDelegatedAdmins.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionDelegatedAdmins.tsx
@@ -9,7 +9,7 @@ import { HOME_TENANT_UNRESOLVED } from "@/lib/identityBinding";
import { parseSlotLimitError, type SlotLimitError } from "@/lib/delegatedSlots";
import { DelegatedSlotPrompt, raiseDelegatedSlotLimit } from "@/components/DelegatedSlotPrompt";
import { SectionCardHeader } from "@/components/SectionCardHeader";
-import type { DelegatedAdminListResponse, GrantDelegatedAdminRequest } from "@/utils/wire-types.generated";
+import type { DelegatedAdminListResponse, GrantDelegatedAdminRequest } from "@/lib/generated/wire-types.generated";
/** One delegated-admin assignment as returned by /api/global/delegated-admins (camelCase JSON). */
interface DelegatedAssignment {
diff --git a/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionEmailTemplates.tsx b/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionEmailTemplates.tsx
index 87f3b251..ab656444 100644
--- a/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionEmailTemplates.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionEmailTemplates.tsx
@@ -5,7 +5,7 @@ import { api } from "@/lib/api";
import { fetchJson, fetchOk, jsonBody } from "@/lib/apiClient";
import { useAdminConfig } from "../../AdminConfigContext";
import { AdminNotifications } from "../../AdminNotifications";
-import type { EmailTemplateRequest, EmailTemplateTestSendResponse } from "@/utils/wire-types.generated";
+import type { EmailTemplateRequest, EmailTemplateTestSendResponse } from "@/lib/generated/wire-types.generated";
import { ModalPortal } from "@/components/ModalPortal";
type TemplateKind = "welcome" | "farewell";
diff --git a/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionTenantGroups.tsx b/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionTenantGroups.tsx
index 5fe7b7de..d88d91d3 100644
--- a/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionTenantGroups.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionTenantGroups.tsx
@@ -14,7 +14,7 @@ import type {
TenantGroup,
TenantGroupListResponse,
UpdateTenantGroupRequest,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
import { parseSlotLimitError, type SlotLimitError } from "@/lib/delegatedSlots";
import { DelegatedSlotPrompt, raiseDelegatedSlotLimit } from "@/components/DelegatedSlotPrompt";
diff --git a/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionUsagePlans.tsx b/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionUsagePlans.tsx
index 78b99643..ddb78c03 100644
--- a/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionUsagePlans.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/settings/sections/SectionUsagePlans.tsx
@@ -10,7 +10,7 @@ import type {
PlanTierDefinitionsResponse,
SetPlanTierDefinitionsRequest,
UsagePlanCatalogDefaults,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
interface PlanTierDefinition {
name: string;
diff --git a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx
index e7b43547..b6b20d7f 100644
--- a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx
@@ -9,7 +9,7 @@ import type {
McpClientRegistrationListResponse,
TenantConfiguration,
TenantFeatureFlagsResponse,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
import {
isNonDefault,
RUNTIME_REPORT_SECTIONS,
diff --git a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/__tests__/tenantConfigReportCatalog.test.ts b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/__tests__/tenantConfigReportCatalog.test.ts
index 5e6126e1..58b4cbcb 100644
--- a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/__tests__/tenantConfigReportCatalog.test.ts
+++ b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/__tests__/tenantConfigReportCatalog.test.ts
@@ -9,8 +9,8 @@
* (AgentConfigResolverTests) — nothing is re-computed here.
*/
import { describe, expect, it } from "vitest";
-import { SHARED_MANIFEST } from "@/utils/shared-manifests.generated";
-import type { AgentConfigResponse } from "@/utils/wire-types.generated";
+import { SHARED_MANIFEST } from "@/lib/generated/shared-manifests.generated";
+import type { AgentConfigResponse } from "@/lib/generated/wire-types.generated";
import {
ANALYZER_FIELDS,
COLLECTOR_FIELDS,
diff --git a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/tenantConfigReportCatalog.ts b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/tenantConfigReportCatalog.ts
index b13b9f3f..f0b30384 100644
--- a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/tenantConfigReportCatalog.ts
+++ b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/tenantConfigReportCatalog.ts
@@ -14,13 +14,13 @@
* which the shared manifest carries as `defaults` (generated by the same test) — no
* hand-copied default anywhere in this file.
*/
-import { SHARED_MANIFEST } from "@/utils/shared-manifests.generated";
+import { SHARED_MANIFEST } from "@/lib/generated/shared-manifests.generated";
import type {
AgentConfigResponse,
AnalyzerConfiguration,
CollectorConfiguration,
TenantConfiguration,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
// ── Defaults from the manifest (compile-time complete over the wire types) ────
diff --git a/src/Web/autopilot-monitor-web/app/ai/layout.tsx b/src/Web/autopilot-monitor-web/app/ai/layout.tsx
index 6a5a8ddb..c18a6ae8 100644
--- a/src/Web/autopilot-monitor-web/app/ai/layout.tsx
+++ b/src/Web/autopilot-monitor-web/app/ai/layout.tsx
@@ -1,5 +1,5 @@
import type { Metadata } from "next";
-import { SITE_URL } from "@/utils/config";
+import { SITE_URL } from "@/lib/config";
import { OPEN_GRAPH_BASE, TWITTER_BASE } from "@/lib/siteMetadata";
const SHARE_TITLE = "AI Analysis for Windows Autopilot – Bring Your Own AI";
diff --git a/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleFormFields.tsx b/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleFormFields.tsx
index 80880c0b..3eb44358 100644
--- a/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleFormFields.tsx
+++ b/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleFormFields.tsx
@@ -7,7 +7,7 @@ import {
validateOnEventTypes,
} from "../types";
import { isReservedBuiltInRuleId, RESERVED_RULE_ID_MESSAGE } from "@/lib/ruleIdPolicy";
-import { BLOCKED_INTERIM_TRIGGER_EVENT_TYPES } from "@/utils/guardrails.generated";
+import { BLOCKED_INTERIM_TRIGGER_EVENT_TYPES } from "@/lib/generated/guardrails.generated";
interface AnalyzeRuleFormFieldsProps {
form: RuleForm;
diff --git a/src/Web/autopilot-monitor-web/app/analyze-rules/page.tsx b/src/Web/autopilot-monitor-web/app/analyze-rules/page.tsx
index 2211c156..c1610de2 100644
--- a/src/Web/autopilot-monitor-web/app/analyze-rules/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/analyze-rules/page.tsx
@@ -19,7 +19,7 @@ import { groupRulesByCategory, categoryLabel } from "@/lib/ruleGroups";
import { RuleCategoryGroups } from "@/components/rules/RuleCategoryGroups";
import { useCollapsedGroups } from "@/hooks/useCollapsedGroups";
import { AnalyzeRule, RuleForm, PastedAnalyzeJson, EMPTY_FORM, EMPTY_CONDITION, ruleToForm, jsonToForm, formToEvaluateOn, validateOnEventTypes, getCategoryColor } from "./types";
-import { BLOCKED_INTERIM_TRIGGER_EVENT_TYPES } from "@/utils/guardrails.generated";
+import { BLOCKED_INTERIM_TRIGGER_EVENT_TYPES } from "@/lib/generated/guardrails.generated";
/** Pre-flight for the evaluation-trigger form fields; returns an error message or null. */
function validateEvaluateOnForm(form: RuleForm): string | null {
@@ -36,7 +36,7 @@ import TemplateConfigModal from "./components/TemplateConfigModal";
import { SectionCardHeader } from "@/components/SectionCardHeader";
import { DOCS_PATHS } from "@/lib/docsPaths";
import { DocsLink } from "@/components/DocsLink";
-import type { CreateAnalyzeRuleFromTemplateRequest, RuleStatsResponse, TenantConfiguration } from "@/utils/wire-types.generated";
+import type { CreateAnalyzeRuleFromTemplateRequest, RuleStatsResponse, TenantConfiguration } from "@/lib/generated/wire-types.generated";
import { fetchJson, jsonBody } from "@/lib/apiClient";
import { useWindowDays } from "@/hooks/useWindowDays";
import { utcDateDaysAgo } from "@/lib/timeWindow";
diff --git a/src/Web/autopilot-monitor-web/app/apps/components/VulnerabilitiesTab.tsx b/src/Web/autopilot-monitor-web/app/apps/components/VulnerabilitiesTab.tsx
index 33662dac..9824e1bf 100644
--- a/src/Web/autopilot-monitor-web/app/apps/components/VulnerabilitiesTab.tsx
+++ b/src/Web/autopilot-monitor-web/app/apps/components/VulnerabilitiesTab.tsx
@@ -5,7 +5,7 @@ import { useAuth } from "../../../contexts/AuthContext";
import { useNotifications } from "../../../contexts/NotificationContext";
import { scopedApi } from "@/lib/scopedApi";
import VulnerabilityExposurePanel from "@/components/VulnerabilityExposurePanel";
-import type { CveExposureSummary } from "@/utils/wire-types.generated";
+import type { CveExposureSummary } from "@/lib/generated/wire-types.generated";
import type { SoftwareTabScope } from "./types";
import { windowProgressKey } from "@/lib/timeWindow";
import { ApiError, fetchJson } from "@/lib/apiClient";
diff --git a/src/Web/autopilot-monitor-web/app/apps/detail/page.tsx b/src/Web/autopilot-monitor-web/app/apps/detail/page.tsx
index 9b9e8b32..e8adbcc7 100644
--- a/src/Web/autopilot-monitor-web/app/apps/detail/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/apps/detail/page.tsx
@@ -9,11 +9,11 @@ import { useTenant } from "../../../contexts/TenantContext";
import { useAuth } from "../../../contexts/AuthContext";
import { useNotifications } from "../../../contexts/NotificationContext";
import { scopedApi } from "@/lib/scopedApi";
-import { getErrorCodeEntry, formatErrorCode, formatErrorCodeSource } from "@/utils/errorCodeMap";
+import { getErrorCodeEntry, formatErrorCode, formatErrorCodeSource } from "@/lib/errorCodeMap";
import { trackEvent } from "@/lib/appInsights";
// Static import is safe: appReportData is pure data prep with no jsPDF dependency —
// jsPDF itself only loads with the dynamic import inside handleExportPdf.
-import { scopeLabel } from "@/utils/pdf/appReportData";
+import { scopeLabel } from "@/lib/pdf/appReportData";
import { useAggregatedAdminScope } from "@/hooks";
import { GlobalAdminBanner, globalAdminSubtitle } from "@/components/GlobalAdminBanner";
import { TenantScopeSelector } from "@/components/TenantScopeSelector";
@@ -374,7 +374,7 @@ function AppDetailContent() {
try {
// Lazy import keeps jsPDF out of the route bundle; a failed chunk load
// (deploy skew, offline) lands in the catch below and is tracked too.
- const { generateAppReportPdf } = await import("@/utils/pdf/appReportPdf");
+ const { generateAppReportPdf } = await import("@/lib/pdf/appReportPdf");
const result = generateAppReportPdf({
analytics,
appName,
diff --git a/src/Web/autopilot-monitor-web/app/audit/page.tsx b/src/Web/autopilot-monitor-web/app/audit/page.tsx
index 1440b9cf..5b3a0f96 100644
--- a/src/Web/autopilot-monitor-web/app/audit/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/audit/page.tsx
@@ -13,7 +13,7 @@ import { TenantScopeSelector } from "@/components/TenantScopeSelector";
import { GlobalAdminBanner, globalAdminSubtitle } from "@/components/GlobalAdminBanner";
import { DocsLink } from "@/components/DocsLink";
import { DOCS_PATHS } from "@/lib/docsPaths";
-import type { AuditLogListResponse } from "@/utils/wire-types.generated";
+import type { AuditLogListResponse } from "@/lib/generated/wire-types.generated";
import { fetchJson } from "@/lib/apiClient";
import { notifyApiError } from "@/contexts/NotificationContext";
diff --git a/src/Web/autopilot-monitor-web/app/buy/layout.tsx b/src/Web/autopilot-monitor-web/app/buy/layout.tsx
index 07a94ae0..1c79bf5c 100644
--- a/src/Web/autopilot-monitor-web/app/buy/layout.tsx
+++ b/src/Web/autopilot-monitor-web/app/buy/layout.tsx
@@ -1,5 +1,5 @@
import type { Metadata } from "next";
-import { SITE_URL } from "@/utils/config";
+import { SITE_URL } from "@/lib/config";
import { OPEN_GRAPH_BASE, TWITTER_BASE } from "@/lib/siteMetadata";
export const metadata: Metadata = {
diff --git a/src/Web/autopilot-monitor-web/app/buy/page.tsx b/src/Web/autopilot-monitor-web/app/buy/page.tsx
index 0d07d674..366e0dbf 100644
--- a/src/Web/autopilot-monitor-web/app/buy/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/buy/page.tsx
@@ -1,7 +1,7 @@
import Link from "next/link";
import { LandingNavbar } from "../../components/landing/LandingNavbar";
import { SiteFooter } from "../../components/SiteFooter";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
/**
* Purchase page for Pro: hands the buyer off to one of the two purchase channels. Linked from
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/components/ActivelyDevelopedBanner.tsx b/src/Web/autopilot-monitor-web/app/dashboard/components/ActivelyDevelopedBanner.tsx
index ec934125..d2bff9ac 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/components/ActivelyDevelopedBanner.tsx
+++ b/src/Web/autopilot-monitor-web/app/dashboard/components/ActivelyDevelopedBanner.tsx
@@ -1,7 +1,7 @@
"use client";
import { useSyncExternalStore } from "react";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
import { trackEvent } from "@/lib/appInsights";
import { useWhatsNew } from "@/hooks/useWhatsNew";
import { openFeedbackDialog } from "@/lib/feedbackDialogStore";
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/components/AppHomingBanner.tsx b/src/Web/autopilot-monitor-web/app/dashboard/components/AppHomingBanner.tsx
index 158038ee..e5250be1 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/components/AppHomingBanner.tsx
+++ b/src/Web/autopilot-monitor-web/app/dashboard/components/AppHomingBanner.tsx
@@ -2,7 +2,7 @@
import { useEffect, useSyncExternalStore } from "react";
import Link from "next/link";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
import { DOCS_PATHS } from "@/lib/docsPaths";
import { trackEvent } from "@/lib/appInsights";
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/components/SessionTable.tsx b/src/Web/autopilot-monitor-web/app/dashboard/components/SessionTable.tsx
index 6477b7c7..6e348c6c 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/components/SessionTable.tsx
+++ b/src/Web/autopilot-monitor-web/app/dashboard/components/SessionTable.tsx
@@ -7,14 +7,14 @@ import type { Route } from "next";
import { useState, useEffect, useRef, useMemo, useDeferredValue } from "react";
import { Session } from "../types";
import { trackEvent } from "@/lib/appInsights";
-import { fuzzyContains } from "@/utils/fuzzy";
+import { fuzzyContains } from "@/lib/fuzzy";
import { buildUniqueValuesByField } from "./uniqueValuesByField";
import {
SESSION_SEARCH_FIELDS,
buildSessionSearchMatcher,
matchedSearchField,
parseSessionSearchQuery,
-} from "../utils/sessionSearchQuery";
+} from "../lib/sessionSearchQuery";
import { SessionStatusBadge } from "@/components/SessionStatusBadge";
import { TenantFilterBar } from "./TenantFilterBar";
import type { DeleteTarget } from "../hooks/useDeleteSession";
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/components/WelcomeMessage.tsx b/src/Web/autopilot-monitor-web/app/dashboard/components/WelcomeMessage.tsx
index be883206..05589272 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/components/WelcomeMessage.tsx
+++ b/src/Web/autopilot-monitor-web/app/dashboard/components/WelcomeMessage.tsx
@@ -1,6 +1,6 @@
"use client";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
export function WelcomeMessage() {
return (
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/components/__tests__/AppHomingBanner.test.ts b/src/Web/autopilot-monitor-web/app/dashboard/components/__tests__/AppHomingBanner.test.ts
index 63c7d242..5cf773bb 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/components/__tests__/AppHomingBanner.test.ts
+++ b/src/Web/autopilot-monitor-web/app/dashboard/components/__tests__/AppHomingBanner.test.ts
@@ -2,7 +2,7 @@ import { describe, it, expect } from "vitest";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { AppHomingBanner } from "../AppHomingBanner";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
describe("AppHomingBanner", () => {
it("renders the nudge with the settings CTA, the docs link and a per-tab dismiss control", () => {
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/hooks/useBlockDevice.ts b/src/Web/autopilot-monitor-web/app/dashboard/hooks/useBlockDevice.ts
index 7fee46bc..248bb2cd 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/hooks/useBlockDevice.ts
+++ b/src/Web/autopilot-monitor-web/app/dashboard/hooks/useBlockDevice.ts
@@ -5,7 +5,7 @@ import { TokenExpiredError } from "@/lib/authenticatedFetch";
import { NotificationType } from "@/contexts/NotificationContext";
import { BULK_CONCURRENCY, runWithConcurrency, summarizeBlockOutcomes, type BlockOutcome } from "./bulkActions";
import { ApiError, fetchOk, jsonBody } from "@/lib/apiClient";
-import type { BlockDeviceRequest } from "@/utils/wire-types.generated";
+import type { BlockDeviceRequest } from "@/lib/generated/wire-types.generated";
export interface BlockTarget {
serialNumber: string;
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardFilters.ts b/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardFilters.ts
index 4e78d9ea..eac4cc8a 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardFilters.ts
+++ b/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardFilters.ts
@@ -3,7 +3,7 @@
import { useDeferredValue, useEffect, useMemo, useState } from "react";
import { trackEvent } from "@/lib/appInsights";
import type { Session } from "../types";
-import { buildSessionSearchMatcher, parseSessionSearchQuery } from "../utils/sessionSearchQuery";
+import { buildSessionSearchMatcher, parseSessionSearchQuery } from "../lib/sessionSearchQuery";
const SESSIONS_PER_PAGE_KEY = "sessionsPerPage";
const DEFAULT_SESSIONS_PER_PAGE = 10;
@@ -119,7 +119,7 @@ export function useDashboardFilters({
const deferredSearchQuery = useDeferredValue(searchQuery);
// Search grammar (terms AND-ed, `-` excludes, quotes, `field=value`) — see
- // utils/sessionSearchQuery. Null while the query carries no filter.
+ // lib/sessionSearchQuery. Null while the query carries no filter.
const searchMatcher = useMemo(() => buildSessionSearchMatcher(deferredSearchQuery), [deferredSearchQuery]);
// The client-derived `extra` text is read by free terms only (a qualified term reads its one
// field), so it is built only while the query has one.
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardSessions.ts b/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardSessions.ts
index 28ccd1da..96155be5 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardSessions.ts
+++ b/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardSessions.ts
@@ -4,16 +4,16 @@ import { useCallback, useEffect, useRef, useState } from "react";
import { api } from "@/lib/api";
import { useLatest } from "@/hooks/useLatest";
import { extractContinuation } from "@/lib/paginationLink";
-import { asGuidOrUndefined } from "@/utils/inputValidation";
-import { boundTenantToDelegatedScope } from "@/utils/delegatedScope";
+import { asGuidOrUndefined } from "@/lib/inputValidation";
+import { boundTenantToDelegatedScope } from "@/lib/delegatedScope";
import { mergeSessionsById } from "@/lib/sessionSearchMerge";
-import { isHomeTenantTarget } from "@/utils/homeTenantScope";
+import { isHomeTenantTarget } from "@/lib/homeTenantScope";
import { hasTenantReadScope } from "@/lib/tenantScope";
import { useSignalRResync } from "@/contexts/SignalRContext";
import { type NotificationType, notifyApiError } from "@/contexts/NotificationContext";
import type { Session } from "../types";
import type { SignalRMessageName } from "@/lib/signalrMessages";
-import type { BlockedDeviceListResponse, SearchSessionsResponse, SessionListResponse } from "@/utils/wire-types.generated";
+import type { BlockedDeviceListResponse, SearchSessionsResponse, SessionListResponse } from "@/lib/generated/wire-types.generated";
import { ApiError, fetchJson, nullOnApiError } from "@/lib/apiClient";
import { getSessionsFetchPageSize } from "./sessionsPageSize";
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardStats.ts b/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardStats.ts
index 5f8af8be..1674f24f 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardStats.ts
+++ b/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardStats.ts
@@ -4,11 +4,11 @@ import { useCallback, useEffect, useRef, useState } from "react";
import { api } from "@/lib/api";
import { useLatest } from "@/hooks/useLatest";
import { useSignalRResync } from "@/contexts/SignalRContext";
-import { asGuidOrUndefined } from "@/utils/inputValidation";
-import { boundTenantToDelegatedScope } from "@/utils/delegatedScope";
-import { isHomeTenantTarget } from "@/utils/homeTenantScope";
+import { asGuidOrUndefined } from "@/lib/inputValidation";
+import { boundTenantToDelegatedScope } from "@/lib/delegatedScope";
+import { isHomeTenantTarget } from "@/lib/homeTenantScope";
import type { SignalRMessageName } from "@/lib/signalrMessages";
-import type { SessionStatsResponse } from "@/utils/wire-types.generated";
+import type { SessionStatsResponse } from "@/lib/generated/wire-types.generated";
import { ApiError, fetchJson } from "@/lib/apiClient";
import { DASHBOARD_STATS_DEFAULT_DAYS } from "./sessionsPageSize";
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/utils/__tests__/sessionSearchQuery.test.ts b/src/Web/autopilot-monitor-web/app/dashboard/lib/__tests__/sessionSearchQuery.test.ts
similarity index 98%
rename from src/Web/autopilot-monitor-web/app/dashboard/utils/__tests__/sessionSearchQuery.test.ts
rename to src/Web/autopilot-monitor-web/app/dashboard/lib/__tests__/sessionSearchQuery.test.ts
index 0b8df691..28dc44b8 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/utils/__tests__/sessionSearchQuery.test.ts
+++ b/src/Web/autopilot-monitor-web/app/dashboard/lib/__tests__/sessionSearchQuery.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
-import cases from "@/utils/session-search-syntax.cases.json";
+import cases from "@/app/dashboard/lib/session-search-syntax.cases.json";
import {
SESSION_SEARCH_FIELDS,
buildSessionSearchMatcher,
diff --git a/src/Web/autopilot-monitor-web/utils/session-search-syntax.cases.json b/src/Web/autopilot-monitor-web/app/dashboard/lib/session-search-syntax.cases.json
similarity index 91%
rename from src/Web/autopilot-monitor-web/utils/session-search-syntax.cases.json
rename to src/Web/autopilot-monitor-web/app/dashboard/lib/session-search-syntax.cases.json
index 0be423b2..8bd99741 100644
--- a/src/Web/autopilot-monitor-web/utils/session-search-syntax.cases.json
+++ b/src/Web/autopilot-monitor-web/app/dashboard/lib/session-search-syntax.cases.json
@@ -1,5 +1,5 @@
{
- "$comment": "Parity cases for the session search grammar. Run by the web (app/dashboard/utils/__tests__/sessionSearchQuery.test.ts) and the backend (SessionFreeTextSearchTests) against the SAME sample session: a query that matches on one side must match on the other, or the server sweep returns ghost results the client filters back out. Cases with `extra` are client-only (client-derived tokens the server never sees). All values are synthetic.",
+ "$comment": "Parity cases for the session search grammar. Run by the web (app/dashboard/lib/__tests__/sessionSearchQuery.test.ts) and the backend (SessionFreeTextSearchTests) against the SAME sample session: a query that matches on one side must match on the other, or the server sweep returns ghost results the client filters back out. Cases with `extra` are client-only (client-derived tokens the server never sees). All values are synthetic.",
"session": {
"deviceName": "DESKTOP-A1B2C3",
"serialNumber": "5CG1234XYZ",
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/utils/sessionSearchQuery.ts b/src/Web/autopilot-monitor-web/app/dashboard/lib/sessionSearchQuery.ts
similarity index 98%
rename from src/Web/autopilot-monitor-web/app/dashboard/utils/sessionSearchQuery.ts
rename to src/Web/autopilot-monitor-web/app/dashboard/lib/sessionSearchQuery.ts
index a329b653..a3ca3c9f 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/utils/sessionSearchQuery.ts
+++ b/src/Web/autopilot-monitor-web/app/dashboard/lib/sessionSearchQuery.ts
@@ -16,7 +16,7 @@
// `foo=bar`). Qualified terms are substring matches like every other term — exact
// matching is the column filter's job. The backend parses the SAME grammar for the
// server-side sweep (`q=` on /api/search/sessions, SessionSearchQuery.cs); both sides
-// run utils/session-search-syntax.cases.json, so a term that matches here matches there.
+// run app/dashboard/lib/session-search-syntax.cases.json, so a term that matches here matches there.
import type { Session } from "../types";
import { literalText, tokenizeSearchQuery } from "@/lib/searchQueryTokens";
diff --git a/src/Web/autopilot-monitor-web/app/dashboard/page.tsx b/src/Web/autopilot-monitor-web/app/dashboard/page.tsx
index 29ed9de2..e8207a12 100644
--- a/src/Web/autopilot-monitor-web/app/dashboard/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/dashboard/page.tsx
@@ -23,9 +23,9 @@ import { useDeleteSession } from "./hooks/useDeleteSession";
import { useBlockDevice } from "./hooks/useBlockDevice";
import { useTenantSecurityConfig } from "./hooks/useTenantSecurityConfig";
import { useTenantList } from "./hooks/useTenantList";
-import { delegatedScopedTenantList, upnDomain } from "@/utils/homeTenantScope";
-import { resolveTenantFilterInput } from "@/utils/tenantFilterResolve";
-import { isGuid } from "@/utils/inputValidation";
+import { delegatedScopedTenantList, upnDomain } from "@/lib/homeTenantScope";
+import { resolveTenantFilterInput } from "@/lib/tenantFilterResolve";
+import { isGuid } from "@/lib/inputValidation";
import { useDashboardFilters } from "./hooks/useDashboardFilters";
import { useDashboardSessions } from "./hooks/useDashboardSessions";
import { useDashboardStats } from "./hooks/useDashboardStats";
@@ -33,7 +33,7 @@ import { api } from "@/lib/api";
import { formatDuration } from "@/lib/formatting";
import { hasTenantReadScope } from "@/lib/tenantScope";
import { TableSkeleton } from "@/components/skeletons/TableSkeleton";
-import type { GetRuleHitSessionsResponse } from "@/utils/wire-types.generated";
+import type { GetRuleHitSessionsResponse } from "@/lib/generated/wire-types.generated";
import { fetchJson } from "@/lib/apiClient";
export default function Home() {
@@ -158,7 +158,7 @@ function HomeContent() {
const rawTenantList = useTenantList(crossTenant, getAccessToken);
// Delegated: bound the tenant filter's autocomplete to the managed subset (defense in depth on top of the
// backend-bounded config/all), plus the caller's own HOME tenant when they hold a member role there —
- // home-tenant reads route via the member path (see utils/homeTenantScope.ts). GA/Reader: the full list.
+ // home-tenant reads route via the member path (see lib/homeTenantScope.ts). GA/Reader: the full list.
const tenantList = useMemo(() => {
if (!isDelegated || hasGlobalScope) return rawTenantList;
return delegatedScopedTenantList(
diff --git a/src/Web/autopilot-monitor-web/app/delegations/accept/page.tsx b/src/Web/autopilot-monitor-web/app/delegations/accept/page.tsx
index 9acfcd50..1292f4cb 100644
--- a/src/Web/autopilot-monitor-web/app/delegations/accept/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/delegations/accept/page.tsx
@@ -6,7 +6,7 @@ import { useSearchParams } from "next/navigation";
import { useAuth } from "@/contexts/AuthContext";
import { api } from "@/lib/api";
import { describeDelegationError, invitationStatusLabel } from "@/lib/delegations";
-import type { AcceptDelegationInvitationRequest, AcceptDelegationInvitationResponse, DelegationAcceptPreviewResponse } from "@/utils/wire-types.generated";
+import type { AcceptDelegationInvitationRequest, AcceptDelegationInvitationResponse, DelegationAcceptPreviewResponse } from "@/lib/generated/wire-types.generated";
import { ApiError, apiErrorText, fetchJson, jsonBody } from "@/lib/apiClient";
import { CONFIG_PATH_PREFIX, invalidateCachedAuthFetch } from "@/lib/cachedAuthFetch";
diff --git a/src/Web/autopilot-monitor-web/app/diagnosis/page.tsx b/src/Web/autopilot-monitor-web/app/diagnosis/page.tsx
index 3b6f0daf..11d58811 100644
--- a/src/Web/autopilot-monitor-web/app/diagnosis/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/diagnosis/page.tsx
@@ -14,11 +14,11 @@ import { interpolateRuleTemplate } from "@/lib/interpolateRuleTemplate";
import { ConfidenceBadge, SeverityBadge } from "./components/DiagnosisBadges";
import { Session, EnrollmentEvent, RuleResult } from "@/types";
import { useAdminMode } from "@/hooks/useAdminMode";
-import { isGuid } from "@/utils/inputValidation";
+import { isGuid } from "@/lib/inputValidation";
import { safeHttpUrl } from "@/lib/safeDocUrl";
import { DocsLink } from "@/components/DocsLink";
import { DOCS_PATHS } from "@/lib/docsPaths";
-import type { GetRuleResultsResponse, GetSessionEventsResponse, GetSessionResponse } from "@/utils/wire-types.generated";
+import type { GetRuleResultsResponse, GetSessionEventsResponse, GetSessionResponse } from "@/lib/generated/wire-types.generated";
import { fetchJson } from "@/lib/apiClient";
import { notifyApiError } from "@/contexts/NotificationContext";
diff --git a/src/Web/autopilot-monitor-web/app/error.tsx b/src/Web/autopilot-monitor-web/app/error.tsx
index 74595389..58b460ae 100644
--- a/src/Web/autopilot-monitor-web/app/error.tsx
+++ b/src/Web/autopilot-monitor-web/app/error.tsx
@@ -2,7 +2,7 @@
import { useEffect } from "react";
import { useRouter } from "next/navigation";
-import { isChunkLoadError, tryRecoverFromChunkError } from "@/utils/chunkReloadRecovery";
+import { isChunkLoadError, tryRecoverFromChunkError } from "@/lib/chunkReloadRecovery";
import { trackEvent } from "@/lib/appInsights";
/**
@@ -21,7 +21,7 @@ export default function Error({
const router = useRouter();
// Stale-bundle chunk failure after a deploy: reload once instead of showing the
- // error card (utils/chunkReloadRecovery.ts — the guard prevents reload loops; a
+ // error card (lib/chunkReloadRecovery.ts — the guard prevents reload loops; a
// repeat inside the guard window falls through to the card below).
useEffect(() => {
if (isChunkLoadError(error)) {
diff --git a/src/Web/autopilot-monitor-web/app/events/[slug]/page.tsx b/src/Web/autopilot-monitor-web/app/events/[slug]/page.tsx
index 15eaf8ef..0f150991 100644
--- a/src/Web/autopilot-monitor-web/app/events/[slug]/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/events/[slug]/page.tsx
@@ -6,7 +6,7 @@ import { BrandMark } from "@/components/BrandMark";
import { GitHubStarLink } from "@/components/GitHubStarLink";
import { SiteFooter } from "@/components/SiteFooter";
import { CUSTOMER_QUOTE } from "@/components/landing/customerQuote";
-import { DOCS_URL, sitePageUrl } from "@/utils/config";
+import { DOCS_URL, sitePageUrl } from "@/lib/config";
import {
COMMUNITY_COMPANIONS,
EVENT_PAGE_ROBOTS,
diff --git a/src/Web/autopilot-monitor-web/app/events/__tests__/events.guard.test.ts b/src/Web/autopilot-monitor-web/app/events/__tests__/events.guard.test.ts
index 83da0879..23cfb411 100644
--- a/src/Web/autopilot-monitor-web/app/events/__tests__/events.guard.test.ts
+++ b/src/Web/autopilot-monitor-web/app/events/__tests__/events.guard.test.ts
@@ -7,7 +7,7 @@ import sitemap from "../../sitemap";
import EventFollowupPage, { generateMetadata, generateStaticParams } from "../[slug]/page";
import { COMMUNITY_COMPANIONS, FOLLOWUP_EVENTS, WALKTHROUGH_EMAIL, walkthroughMailto } from "../events";
import { trackIdOf } from "../eventClicks";
-import { sitePageUrl } from "@/utils/config";
+import { sitePageUrl } from "@/lib/config";
/**
* Event follow-up pages are reached only through the follow-up email: never indexed, never
diff --git a/src/Web/autopilot-monitor-web/app/fleet-health/hooks/useFleetHealth.ts b/src/Web/autopilot-monitor-web/app/fleet-health/hooks/useFleetHealth.ts
index 07c5d38c..296df8a3 100644
--- a/src/Web/autopilot-monitor-web/app/fleet-health/hooks/useFleetHealth.ts
+++ b/src/Web/autopilot-monitor-web/app/fleet-health/hooks/useFleetHealth.ts
@@ -10,7 +10,7 @@ import { ApiError, fetchJson } from "@/lib/apiClient";
// Wire shape of the server-aggregated Fleet Health payload: the generated mirror of the
// backend FleetHealthMetrics DTO. Presentation-only derivations (bar maxima, axis
// labels) stay in the page.
-import type { FleetHealthMetrics } from "@/utils/wire-types.generated";
+import type { FleetHealthMetrics } from "@/lib/generated/wire-types.generated";
export type FleetHealthData = FleetHealthMetrics;
diff --git a/src/Web/autopilot-monitor-web/app/fleet-health/page.tsx b/src/Web/autopilot-monitor-web/app/fleet-health/page.tsx
index 087770f9..eb775989 100644
--- a/src/Web/autopilot-monitor-web/app/fleet-health/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/fleet-health/page.tsx
@@ -4,8 +4,8 @@ import { Suspense, useEffect, useState, useRef, useMemo } from "react";
import Link from "next/link";
import type { Route } from "next";
import { dashboardUrl } from "@/lib/routes";
-import { buildSessionSearchQuery } from "../dashboard/utils/sessionSearchQuery";
-import type { FleetModelHealth } from "@/utils/wire-types.generated";
+import { buildSessionSearchQuery } from "../dashboard/lib/sessionSearchQuery";
+import type { FleetModelHealth } from "@/lib/generated/wire-types.generated";
import { ProtectedRoute } from "../../components/ProtectedRoute";
import { useSignalR } from "../../contexts/SignalRContext";
import { useTenant } from "../../contexts/TenantContext";
diff --git a/src/Web/autopilot-monitor-web/app/fleet/hooks/useFleetSummaries.ts b/src/Web/autopilot-monitor-web/app/fleet/hooks/useFleetSummaries.ts
index 7a5997af..6b3f63ff 100644
--- a/src/Web/autopilot-monitor-web/app/fleet/hooks/useFleetSummaries.ts
+++ b/src/Web/autopilot-monitor-web/app/fleet/hooks/useFleetSummaries.ts
@@ -3,9 +3,9 @@
import { useEffect, useState } from "react";
import { useAuth } from "@/contexts/AuthContext";
import { api } from "@/lib/api";
-import { isHomeTenantTarget } from "@/utils/homeTenantScope";
+import { isHomeTenantTarget } from "@/lib/homeTenantScope";
import type { FleetSummary } from "../lib/fleetRollup";
-import type { SessionStatsResponse } from "@/utils/wire-types.generated";
+import type { SessionStatsResponse } from "@/lib/generated/wire-types.generated";
import { fetchJson, nullOnApiError } from "@/lib/apiClient";
export interface FleetSummariesState {
@@ -27,7 +27,7 @@ const CONCURRENCY = 6;
* @param days lookback window passed to each per-tenant stats call.
* @param homeTenantId the caller's OWN home tenant, if it is part of tenantIds: its summary is fetched via
* the JWT-bound member stats endpoint — home access is member-based, and the /global/ single-tenant path
- * is bounded to the managed set (would return empty for it). See utils/homeTenantScope.ts.
+ * is bounded to the managed set (would return empty for it). See lib/homeTenantScope.ts.
*/
export function useFleetSummaries(tenantIds: string[], days: number, homeTenantId?: string): FleetSummariesState {
const { getAccessToken } = useAuth();
diff --git a/src/Web/autopilot-monitor-web/app/fleet/page.tsx b/src/Web/autopilot-monitor-web/app/fleet/page.tsx
index 42649e77..a031c932 100644
--- a/src/Web/autopilot-monitor-web/app/fleet/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/fleet/page.tsx
@@ -5,7 +5,7 @@ import Link from "next/link";
import { dashboardUrl } from "@/lib/routes";
import { useAuth } from "@/contexts/AuthContext";
import { useTenantList, type TenantInfo } from "@/hooks/useTenantList";
-import { delegatedScopedTenantList, upnDomain } from "@/utils/homeTenantScope";
+import { delegatedScopedTenantList, upnDomain } from "@/lib/homeTenantScope";
import { useFleetSummaries } from "./hooks/useFleetSummaries";
import { computeFleetRollup, type FleetSummary } from "./lib/fleetRollup";
@@ -26,7 +26,7 @@ export default function FleetPage() {
const tenants = useTenantList(isDelegated);
// Managed subset plus the caller's own HOME tenant when they hold a member role there — the home
- // tenant is member-path access, not a delegated grant (see utils/homeTenantScope.ts), so its
+ // tenant is member-path access, not a delegated grant (see lib/homeTenantScope.ts), so its
// summary is fetched via the JWT-bound member stats endpoint below.
const myTenants = useMemo(
() => delegatedScopedTenantList(tenants, user?.delegatedTenantIds, user?.tenantId, upnDomain(user?.upn), !!user?.role),
diff --git a/src/Web/autopilot-monitor-web/app/gather-rules/components/GatherRuleCard.tsx b/src/Web/autopilot-monitor-web/app/gather-rules/components/GatherRuleCard.tsx
index 923519b7..751c640c 100644
--- a/src/Web/autopilot-monitor-web/app/gather-rules/components/GatherRuleCard.tsx
+++ b/src/Web/autopilot-monitor-web/app/gather-rules/components/GatherRuleCard.tsx
@@ -4,7 +4,7 @@ import { useMemo, useState } from "react";
import { GatherRule, NewRuleForm, PastedGatherJson, getCategoryColor, COLLECTOR_TYPE_LABELS, formatTrigger, formatGatherPhase, gatherRuleToForm } from "../types";
import { GatherRuleFormFields } from "./GatherRuleFormFields";
import { FormJsonToggle, JsonModeToggleButtons, ReadOnlyJsonView } from "@/components/rules/FormJsonToggle";
-import { validateGatherRuleTarget } from "@/utils/guardValidation";
+import { validateGatherRuleTarget } from "@/lib/guardValidation";
import { ValidationIndicator } from "@/components/ValidationIndicator";
import { stripInternalFields } from "@/lib/rulePageHelpers";
diff --git a/src/Web/autopilot-monitor-web/app/gather-rules/components/GatherRuleFormFields.tsx b/src/Web/autopilot-monitor-web/app/gather-rules/components/GatherRuleFormFields.tsx
index e9d8c898..24aef76d 100644
--- a/src/Web/autopilot-monitor-web/app/gather-rules/components/GatherRuleFormFields.tsx
+++ b/src/Web/autopilot-monitor-web/app/gather-rules/components/GatherRuleFormFields.tsx
@@ -20,7 +20,7 @@ import {
supportsEmitMode,
} from "../types";
import { KNOWN_EVENT_TYPES, findEventType } from "../eventTypes";
-import { validateGatherRuleTarget } from "@/utils/guardValidation";
+import { validateGatherRuleTarget } from "@/lib/guardValidation";
import { ValidationIndicator } from "@/components/ValidationIndicator";
import { isReservedBuiltInRuleId, RESERVED_RULE_ID_MESSAGE } from "@/lib/ruleIdPolicy";
diff --git a/src/Web/autopilot-monitor-web/app/gather-rules/page.tsx b/src/Web/autopilot-monitor-web/app/gather-rules/page.tsx
index 179f0d32..ef2d19ad 100644
--- a/src/Web/autopilot-monitor-web/app/gather-rules/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/gather-rules/page.tsx
@@ -22,7 +22,7 @@ import { GatherRuleCard } from "./components/GatherRuleCard";
import { SectionCardHeader } from "@/components/SectionCardHeader";
import { DOCS_PATHS } from "@/lib/docsPaths";
import { DocsLink } from "@/components/DocsLink";
-import type { TenantFeatureFlagsResponse } from "@/utils/wire-types.generated";
+import type { TenantFeatureFlagsResponse } from "@/lib/generated/wire-types.generated";
import { fetchJson } from "@/lib/apiClient";
import { CommunityContributionBox } from "@/components/rules/CommunityContributionBox";
import { MySubmissionsList } from "@/components/rules/MySubmissionsList";
diff --git a/src/Web/autopilot-monitor-web/app/gather-rules/types.ts b/src/Web/autopilot-monitor-web/app/gather-rules/types.ts
index 33953ac9..fe097443 100644
--- a/src/Web/autopilot-monitor-web/app/gather-rules/types.ts
+++ b/src/Web/autopilot-monitor-web/app/gather-rules/types.ts
@@ -1,4 +1,4 @@
-import { validateGatherRuleTarget } from "@/utils/guardValidation";
+import { validateGatherRuleTarget } from "@/lib/guardValidation";
export interface GatherRule {
ruleId: string;
diff --git a/src/Web/autopilot-monitor-web/app/geographic-performance/GeoMap.tsx b/src/Web/autopilot-monitor-web/app/geographic-performance/GeoMap.tsx
index a3efbd5e..0b3cc814 100644
--- a/src/Web/autopilot-monitor-web/app/geographic-performance/GeoMap.tsx
+++ b/src/Web/autopilot-monitor-web/app/geographic-performance/GeoMap.tsx
@@ -4,7 +4,7 @@ import { useEffect, useMemo } from "react";
import { MapContainer, TileLayer, CircleMarker, Tooltip, useMap } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import { formatThroughput } from "@/lib/formatting";
-import type { GlobalAverages, LocationMetrics } from "@/utils/wire-types.generated";
+import type { GlobalAverages, LocationMetrics } from "@/lib/generated/wire-types.generated";
import { bucketFilterAllows, type BucketFilter, type MapColorMode } from "./mapColorModes";
interface GeoMapProps {
diff --git a/src/Web/autopilot-monitor-web/app/geographic-performance/__tests__/LocationTableNote.test.ts b/src/Web/autopilot-monitor-web/app/geographic-performance/__tests__/LocationTableNote.test.ts
index 13478b7d..961a5095 100644
--- a/src/Web/autopilot-monitor-web/app/geographic-performance/__tests__/LocationTableNote.test.ts
+++ b/src/Web/autopilot-monitor-web/app/geographic-performance/__tests__/LocationTableNote.test.ts
@@ -3,7 +3,7 @@ import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { LocationTableNote, LOCATION_TABLE_NOTE } from "../LocationTableNote";
import { DOCS_PATHS } from "@/lib/docsPaths";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
describe("LocationTableNote", () => {
const html = renderToStaticMarkup(createElement(LocationTableNote));
diff --git a/src/Web/autopilot-monitor-web/app/geographic-performance/__tests__/mapColorModes.test.ts b/src/Web/autopilot-monitor-web/app/geographic-performance/__tests__/mapColorModes.test.ts
index 658fb9e9..ca232d22 100644
--- a/src/Web/autopilot-monitor-web/app/geographic-performance/__tests__/mapColorModes.test.ts
+++ b/src/Web/autopilot-monitor-web/app/geographic-performance/__tests__/mapColorModes.test.ts
@@ -1,5 +1,5 @@
import { describe, it, expect } from "vitest";
-import type { GlobalAverages, LocationMetrics } from "@/utils/wire-types.generated";
+import type { GlobalAverages, LocationMetrics } from "@/lib/generated/wire-types.generated";
import {
DEFAULT_MAP_COLOR_MODE,
MAP_COLOR_MODES,
diff --git a/src/Web/autopilot-monitor-web/app/geographic-performance/mapColorModes.ts b/src/Web/autopilot-monitor-web/app/geographic-performance/mapColorModes.ts
index 2bc39789..f6fe0f68 100644
--- a/src/Web/autopilot-monitor-web/app/geographic-performance/mapColorModes.ts
+++ b/src/Web/autopilot-monitor-web/app/geographic-performance/mapColorModes.ts
@@ -1,4 +1,4 @@
-import type { GlobalAverages, LocationMetrics } from "@/utils/wire-types.generated";
+import type { GlobalAverages, LocationMetrics } from "@/lib/generated/wire-types.generated";
/**
* Single source of truth for how a location is colour-coded on the Geographic Performance page.
diff --git a/src/Web/autopilot-monitor-web/app/geographic-performance/page.tsx b/src/Web/autopilot-monitor-web/app/geographic-performance/page.tsx
index 8860b0f9..e57631af 100644
--- a/src/Web/autopilot-monitor-web/app/geographic-performance/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/geographic-performance/page.tsx
@@ -19,7 +19,7 @@ import { CalculatingCard } from "@/components/CalculatingCard";
import { DocsLink } from "@/components/DocsLink";
import { DOCS_PATHS } from "@/lib/docsPaths";
import { formatThroughput } from "@/lib/formatting";
-import type { GeographicMetricsResponse } from "@/utils/wire-types.generated";
+import type { GeographicMetricsResponse } from "@/lib/generated/wire-types.generated";
import {
DEFAULT_MAP_COLOR_MODE,
MAP_COLOR_MODES,
diff --git a/src/Web/autopilot-monitor-web/app/geographic-performance/sessions/page.tsx b/src/Web/autopilot-monitor-web/app/geographic-performance/sessions/page.tsx
index 6342c9bb..0250f4ed 100644
--- a/src/Web/autopilot-monitor-web/app/geographic-performance/sessions/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/geographic-performance/sessions/page.tsx
@@ -10,14 +10,14 @@ import { api } from "@/lib/api";
import { useAdminMode } from "@/hooks/useAdminMode";
import { SessionStatusBadge } from "@/components/SessionStatusBadge";
import { GlobalAdminBanner } from "@/components/GlobalAdminBanner";
-import { boundTenantToDelegatedScope } from "@/utils/delegatedScope";
-import { isHomeTenantTarget } from "@/utils/homeTenantScope";
+import { boundTenantToDelegatedScope } from "@/lib/delegatedScope";
+import { isHomeTenantTarget } from "@/lib/homeTenantScope";
import { useFetchProgress } from "@/hooks/useFetchProgress";
import { useWindowDays } from "@/hooks/useWindowDays";
import { windowProgressKey } from "@/lib/timeWindow";
import { GEO_DEFAULT_WINDOW_DAYS } from "../geoWindow";
import { CalculatingCard } from "@/components/CalculatingCard";
-import type { GeographicLocationSessionsResponse, LocationSessionRow } from "@/utils/wire-types.generated";
+import type { GeographicLocationSessionsResponse, LocationSessionRow } from "@/lib/generated/wire-types.generated";
import { fetchJson } from "@/lib/apiClient";
// A cross-tenant drilldown can take tens of seconds server-side; the default 30s fetch
diff --git a/src/Web/autopilot-monitor-web/app/get-started/page.tsx b/src/Web/autopilot-monitor-web/app/get-started/page.tsx
index 7fe7dbe5..ece81b08 100644
--- a/src/Web/autopilot-monitor-web/app/get-started/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/get-started/page.tsx
@@ -3,7 +3,7 @@ import { LandingNavbar } from "../../components/landing/LandingNavbar";
import { SignupConsentCta } from "../../components/landing/SignupConsentCta";
import { SiteFooter } from "../../components/SiteFooter";
import { MarketingTracker } from "../../components/MarketingTracker";
-import { DOCS_URL, SITE_URL } from "@/utils/config";
+import { DOCS_URL, SITE_URL } from "@/lib/config";
export const metadata: Metadata = {
title: "Get started",
diff --git a/src/Web/autopilot-monitor-web/app/health-check/page.tsx b/src/Web/autopilot-monitor-web/app/health-check/page.tsx
index 40c0e829..aa0ea063 100644
--- a/src/Web/autopilot-monitor-web/app/health-check/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/health-check/page.tsx
@@ -17,7 +17,7 @@ import {
MCP_PROBE_TIMEOUT_MS,
} from '@/lib/healthCheckView';
import { useLatest } from '@/hooks/useLatest';
-import type { DetailedHealthCheckResponse, HealthCheck, McpHealthCheckResponse } from '@/utils/wire-types.generated';
+import type { DetailedHealthCheckResponse, HealthCheck, McpHealthCheckResponse } from '@/lib/generated/wire-types.generated';
import { DocsLink } from "@/components/DocsLink";
import { DOCS_PATHS } from "@/lib/docsPaths";
import { ApiError, fetchJson } from "@/lib/apiClient";
diff --git a/src/Web/autopilot-monitor-web/app/help/layout.tsx b/src/Web/autopilot-monitor-web/app/help/layout.tsx
index e5cdf9e6..a04a0c2c 100644
--- a/src/Web/autopilot-monitor-web/app/help/layout.tsx
+++ b/src/Web/autopilot-monitor-web/app/help/layout.tsx
@@ -1,5 +1,5 @@
import type { Metadata } from "next";
-import { SITE_URL } from "@/utils/config";
+import { SITE_URL } from "@/lib/config";
import { OPEN_GRAPH_BASE, TWITTER_BASE } from "@/lib/siteMetadata";
export const metadata: Metadata = {
diff --git a/src/Web/autopilot-monitor-web/app/help/page.tsx b/src/Web/autopilot-monitor-web/app/help/page.tsx
index 25242ff8..2a1a784a 100644
--- a/src/Web/autopilot-monitor-web/app/help/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/help/page.tsx
@@ -1,7 +1,7 @@
import { LandingNavbar } from "../../components/landing/LandingNavbar";
import { WhatsNewTile } from "../../components/landing/WhatsNewTile";
import { SiteFooter } from "../../components/SiteFooter";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
const GITHUB_ISSUES = "https://github.com/okieselbach/AutopilotMonitor/issues";
const LINKEDIN_PROFILE = "https://www.linkedin.com/in/oliver-kieselbach/";
diff --git a/src/Web/autopilot-monitor-web/app/layout.tsx b/src/Web/autopilot-monitor-web/app/layout.tsx
index 7045370d..ad656cc1 100644
--- a/src/Web/autopilot-monitor-web/app/layout.tsx
+++ b/src/Web/autopilot-monitor-web/app/layout.tsx
@@ -19,7 +19,7 @@ import AppInsightsInit from "../components/AppInsightsInit";
import ChunkReloadRecovery from "../components/ChunkReloadRecovery";
import { HostRoutingGuard } from "../components/HostRoutingGuard";
import { LegacyPathRedirect } from "../components/LegacyPathRedirect";
-import { API_BASE_URL, DOCS_URL, SITE_URL, sitePageUrl } from "@/utils/config";
+import { API_BASE_URL, DOCS_URL, SITE_URL, sitePageUrl } from "@/lib/config";
import { AUTH_HINT_INLINE_SCRIPT } from "@/lib/authHint";
const inter = Inter({ subsets: ["latin"] });
diff --git a/src/Web/autopilot-monitor-web/app/plans/layout.tsx b/src/Web/autopilot-monitor-web/app/plans/layout.tsx
index ffb1f9d3..a1674caf 100644
--- a/src/Web/autopilot-monitor-web/app/plans/layout.tsx
+++ b/src/Web/autopilot-monitor-web/app/plans/layout.tsx
@@ -1,5 +1,5 @@
import type { Metadata } from "next";
-import { SITE_URL } from "@/utils/config";
+import { SITE_URL } from "@/lib/config";
import { OPEN_GRAPH_BASE, TWITTER_BASE } from "@/lib/siteMetadata";
export const metadata: Metadata = {
diff --git a/src/Web/autopilot-monitor-web/app/plans/page.tsx b/src/Web/autopilot-monitor-web/app/plans/page.tsx
index 96525c64..37145f8a 100644
--- a/src/Web/autopilot-monitor-web/app/plans/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/plans/page.tsx
@@ -2,7 +2,7 @@ import Link from "next/link";
import { LandingNavbar } from "../../components/landing/LandingNavbar";
import { SiteFooter } from "../../components/SiteFooter";
import { PlanCards } from "../../components/plans/PlanCards";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
/**
* Public plans page. Deliberately named "Plans" (not "Pricing"): the message is
diff --git a/src/Web/autopilot-monitor-web/app/privacy/layout.tsx b/src/Web/autopilot-monitor-web/app/privacy/layout.tsx
index e8aa21cc..6f1c6cbf 100644
--- a/src/Web/autopilot-monitor-web/app/privacy/layout.tsx
+++ b/src/Web/autopilot-monitor-web/app/privacy/layout.tsx
@@ -1,5 +1,5 @@
import type { Metadata } from "next";
-import { SITE_URL } from "@/utils/config";
+import { SITE_URL } from "@/lib/config";
import { OPEN_GRAPH_BASE } from "@/lib/siteMetadata";
export const metadata: Metadata = {
diff --git a/src/Web/autopilot-monitor-web/app/privacy/page.tsx b/src/Web/autopilot-monitor-web/app/privacy/page.tsx
index 251e5929..48df2d81 100644
--- a/src/Web/autopilot-monitor-web/app/privacy/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/privacy/page.tsx
@@ -1,6 +1,6 @@
import { LandingNavbar } from "../../components/landing/LandingNavbar";
import { SiteFooter } from "../../components/SiteFooter";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
const LAST_UPDATED = "1 October 2026";
const DOCS_SECURITY_FAQ = `${DOCS_URL}/trust/security-faq`;
diff --git a/src/Web/autopilot-monitor-web/app/progress/components/ProgressAccessHint.tsx b/src/Web/autopilot-monitor-web/app/progress/components/ProgressAccessHint.tsx
index cf5e0638..ae298b29 100644
--- a/src/Web/autopilot-monitor-web/app/progress/components/ProgressAccessHint.tsx
+++ b/src/Web/autopilot-monitor-web/app/progress/components/ProgressAccessHint.tsx
@@ -1,6 +1,6 @@
import { DOCS_PATHS } from "@/lib/docsPaths";
import { SUPPORT_EMAIL } from "@/lib/supportContact";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
import type { ProgressAccessHint as Hint } from "../hooks/progressAccessHint";
export const ACCESS_HINT_DOCS_URL = `${DOCS_URL}${DOCS_PATHS.progressPortalOnly}`;
diff --git a/src/Web/autopilot-monitor-web/app/progress/components/__tests__/ProgressAccessHint.test.ts b/src/Web/autopilot-monitor-web/app/progress/components/__tests__/ProgressAccessHint.test.ts
index 5afd1ac3..b9b8c1e5 100644
--- a/src/Web/autopilot-monitor-web/app/progress/components/__tests__/ProgressAccessHint.test.ts
+++ b/src/Web/autopilot-monitor-web/app/progress/components/__tests__/ProgressAccessHint.test.ts
@@ -3,7 +3,7 @@ import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { ACCESS_HINT_DOCS_URL, ProgressAccessHint } from "../ProgressAccessHint";
import { SUPPORT_EMAIL } from "@/lib/supportContact";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
const render = (hint: Parameters[0]["hint"]) =>
renderToStaticMarkup(createElement(ProgressAccessHint, { hint }));
diff --git a/src/Web/autopilot-monitor-web/app/progress/hooks/progressAccessHint.ts b/src/Web/autopilot-monitor-web/app/progress/hooks/progressAccessHint.ts
index 892dadcf..74c62816 100644
--- a/src/Web/autopilot-monitor-web/app/progress/hooks/progressAccessHint.ts
+++ b/src/Web/autopilot-monitor-web/app/progress/hooks/progressAccessHint.ts
@@ -1,4 +1,4 @@
-import type { ProgressTenantStatusResponse } from "@/utils/wire-types.generated";
+import type { ProgressTenantStatusResponse } from "@/lib/generated/wire-types.generated";
/** The note below the Progress Portal search for a member without a role. */
export type ProgressAccessHint =
diff --git a/src/Web/autopilot-monitor-web/app/progress/hooks/progressLayout.ts b/src/Web/autopilot-monitor-web/app/progress/hooks/progressLayout.ts
index 1258e937..b941494c 100644
--- a/src/Web/autopilot-monitor-web/app/progress/hooks/progressLayout.ts
+++ b/src/Web/autopilot-monitor-web/app/progress/hooks/progressLayout.ts
@@ -1,5 +1,5 @@
import { EnrollmentEvent, Session } from "@/types";
-import { resolvePhaseLayout } from "@/app/sessions/utils/phaseConstants";
+import { resolvePhaseLayout } from "@/app/sessions/lib/phaseConstants";
import { isParkedAfterTechnicianPart } from "@/lib/preProvisioning";
import { deriveOsUpdateLive, deviceNowMs, osUpdateLiveState } from "@/lib/osUpdateLive";
diff --git a/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressDerivedData.ts b/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressDerivedData.ts
index f72fe327..69b21206 100644
--- a/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressDerivedData.ts
+++ b/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressDerivedData.ts
@@ -3,8 +3,8 @@
import { useEffect, useMemo, useState } from "react";
import { EnrollmentEvent, Session } from "@/types";
import { computeDeviceStatus, DeviceStatus } from "./deviceStatus";
-import { detectSkipUserStatusPage } from "@/app/sessions/utils/espConfig";
-import { isTerminalStatus } from "@/utils/sessionStatus";
+import { detectSkipUserStatusPage } from "@/app/sessions/lib/espConfig";
+import { isTerminalStatus } from "@/lib/sessionStatus";
import {
buildProgressSteps,
computeOverallProgress,
diff --git a/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressEvents.ts b/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressEvents.ts
index a74aa445..8190cab8 100644
--- a/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressEvents.ts
+++ b/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressEvents.ts
@@ -5,7 +5,7 @@ import { api } from "@/lib/api";
import { createBurstScheduler, type BurstScheduler } from "@/lib/burstScheduler";
import { EnrollmentEvent, Session } from "@/types";
import { type NotificationType, notifyApiError } from "@/contexts/NotificationContext";
-import type { ProgressGetSessionEventsResponse, ProgressLookupSessionResponse } from "@/utils/wire-types.generated";
+import type { ProgressGetSessionEventsResponse, ProgressLookupSessionResponse } from "@/lib/generated/wire-types.generated";
import { fetchJson, nullOnApiError } from "@/lib/apiClient";
// Live refetch coalescing on SignalR signals (see lib/burstScheduler). Each refresh is two
diff --git a/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressSearch.ts b/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressSearch.ts
index 7df2a88f..42811d4a 100644
--- a/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressSearch.ts
+++ b/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressSearch.ts
@@ -5,7 +5,7 @@ import { api } from "@/lib/api";
import { trackEvent } from "@/lib/appInsights";
import { Session } from "@/types";
import { type NotificationType, notifyApiError } from "@/contexts/NotificationContext";
-import type { ProgressLookupSessionResponse } from "@/utils/wire-types.generated";
+import type { ProgressLookupSessionResponse } from "@/lib/generated/wire-types.generated";
import { ApiError, fetchJson } from "@/lib/apiClient";
import { readSerialParam, withSerialParam } from "./serialDeepLink";
diff --git a/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressTenantStatus.ts b/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressTenantStatus.ts
index 62ec1ae5..2daef623 100644
--- a/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressTenantStatus.ts
+++ b/src/Web/autopilot-monitor-web/app/progress/hooks/useProgressTenantStatus.ts
@@ -3,7 +3,7 @@
import { useEffect, useState } from "react";
import { api } from "@/lib/api";
import { fetchJson, type GetAccessToken } from "@/lib/apiClient";
-import type { ProgressTenantStatusResponse } from "@/utils/wire-types.generated";
+import type { ProgressTenantStatusResponse } from "@/lib/generated/wire-types.generated";
/**
* One read of the caller's tenant status for the access hint, only for members without a role
diff --git a/src/Web/autopilot-monitor-web/app/robots.ts b/src/Web/autopilot-monitor-web/app/robots.ts
index 877b3395..41b43020 100644
--- a/src/Web/autopilot-monitor-web/app/robots.ts
+++ b/src/Web/autopilot-monitor-web/app/robots.ts
@@ -2,7 +2,7 @@
export const dynamic = "force-static";
import type { MetadataRoute } from "next";
-import { SITE_URL } from "@/utils/config";
+import { SITE_URL } from "@/lib/config";
// Public marketing / legal pages.
const PUBLIC_PATHS = ["/", "/about", "/ai", "/buy", "/get-started", "/help", "/plans", "/privacy", "/terms"];
diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/AnalysisResultsSection.tsx b/src/Web/autopilot-monitor-web/app/sessions/components/AnalysisResultsSection.tsx
index d61b9c11..9c0ab24a 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/components/AnalysisResultsSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/components/AnalysisResultsSection.tsx
@@ -12,7 +12,7 @@ import { recentWindowStartIso, sumRecentFires } from "@/lib/ruleRecentFires";
import { useAuth } from "@/contexts/AuthContext";
import { useTenant } from "@/contexts/TenantContext";
import { safeHttpUrl } from "@/lib/safeDocUrl";
-import type { RuleStatsResponse } from "@/utils/wire-types.generated";
+import type { RuleStatsResponse } from "@/lib/generated/wire-types.generated";
import { fetchJson } from "@/lib/apiClient";
interface AnalysisResultsSectionProps {
diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/CollectLogsButton.tsx b/src/Web/autopilot-monitor-web/app/sessions/components/CollectLogsButton.tsx
index 8d1b2ed9..ca73ee2c 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/components/CollectLogsButton.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/components/CollectLogsButton.tsx
@@ -7,7 +7,7 @@ import { ApiError, apiErrorText, fetchJson, fetchOk, jsonBody } from "@/lib/apiC
import { CONFIG_PATH_PREFIX, invalidateCachedAuthFetch } from "@/lib/cachedAuthFetch";
import { changedTenantConfigFields, patchTenantConfigFields } from "@/lib/tenantConfigSave";
import { NotificationType } from "@/contexts/NotificationContext";
-import type { QueueSessionActionRequest, TenantConfiguration } from "@/utils/wire-types.generated";
+import type { QueueSessionActionRequest, TenantConfiguration } from "@/lib/generated/wire-types.generated";
import {
CollectPhase,
COLLECT_TIMEOUT_MS,
diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/DeviceDetailsCard.tsx b/src/Web/autopilot-monitor-web/app/sessions/components/DeviceDetailsCard.tsx
index 25fcc519..e4c2cb1f 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/components/DeviceDetailsCard.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/components/DeviceDetailsCard.tsx
@@ -5,7 +5,7 @@ import Link from "next/link";
import { networkTimelineUrl } from "@/lib/routes";
import { EnrollmentEvent, Session } from "@/types";
import OobeConfigModal from "./OobeConfigModal";
-import { compareVersions, stripGitHashSuffix } from "@/utils/bootstrapVersion";
+import { compareVersions, stripGitHashSuffix } from "@/lib/bootstrapVersion";
// Minimal structural shapes for the event payloads this card reads. Values arrive as
// deserialized JSON; only the fields the JSX uses in a typed position (string props,
diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx b/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx
index 550e656c..e3907a29 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx
@@ -2,9 +2,9 @@
import { createContext, useContext, useState, useMemo, useDeferredValue } from "react";
import { EnrollmentEvent, Session } from "@/types";
-import { normalizeEventDataForDisplay, shortenBuildHashInMessage } from "../utils/eventHelpers";
-import { buildEventSearchMatcher, formatEventSearchTerm, parseEventSearchQuery } from "../utils/eventSearchQuery";
-import { getEnrichedOrLookup, formatErrorCode, errorCodeTooltip, type ErrorCodeInfo } from "@/utils/errorCodeMap";
+import { normalizeEventDataForDisplay, shortenBuildHashInMessage } from "../lib/eventHelpers";
+import { buildEventSearchMatcher, formatEventSearchTerm, parseEventSearchQuery } from "../lib/eventSearchQuery";
+import { getEnrichedOrLookup, formatErrorCode, errorCodeTooltip, type ErrorCodeInfo } from "@/lib/errorCodeMap";
import { readTimeProvenance, classifyTimeJump, readClockChangeDeltaMs } from "@/lib/timeProvenance";
import { isRebootOrRetryClass } from "@/lib/installProgress";
import { formatDuration, formatUtcOffset } from "@/lib/formatting";
@@ -76,7 +76,7 @@ export default function EventTimeline({
// visible rows) follows the deferred one, so a keystroke never waits for the per-phase filter pass.
const deferredSearchQuery = useDeferredValue(searchQuery);
- // Terms are AND-ed, a leading minus excludes, key=value restricts — see utils/eventSearchQuery.ts.
+ // Terms are AND-ed, a leading minus excludes, key=value restricts — see lib/eventSearchQuery.ts.
const matchesSearch = useMemo(() => buildEventSearchMatcher(deferredSearchQuery), [deferredSearchQuery]);
const excludedTerms = useMemo(
() => parseEventSearchQuery(deferredSearchQuery).exclude.map(formatEventSearchTerm),
diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/PhaseTimeline.tsx b/src/Web/autopilot-monitor-web/app/sessions/components/PhaseTimeline.tsx
index 4b81e9e5..be5fc0a2 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/components/PhaseTimeline.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/components/PhaseTimeline.tsx
@@ -2,7 +2,7 @@
import React, { useMemo } from "react";
import { EnrollmentEvent } from "@/types";
-import { resolvePhaseLayout } from "../utils/phaseConstants";
+import { resolvePhaseLayout } from "../lib/phaseConstants";
import { summarizeEventsByPhase } from "./phaseEventSummary";
interface PhaseTimelineProps {
diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/ReportSessionModal.tsx b/src/Web/autopilot-monitor-web/app/sessions/components/ReportSessionModal.tsx
index 9c76c3bb..c3593ca9 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/components/ReportSessionModal.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/components/ReportSessionModal.tsx
@@ -7,7 +7,7 @@ import { AttachmentBudgetLine, AttachmentField } from "@/components/ReportAttach
import { useAttachmentPack } from "@/hooks/useAttachmentPack";
import { formatBytes } from "@/lib/formatting";
import { ATTACHMENT_BUDGET_BYTES, packedSize, type PackedAttachment } from "@/lib/reportAttachments";
-import { SHARED_MANIFEST } from "@/utils/shared-manifests.generated";
+import { SHARED_MANIFEST } from "@/lib/generated/shared-manifests.generated";
const MAX_COMMENT_CHARS = SHARED_MANIFEST.submissionLimits.reportCommentMaxChars;
const MAX_EMAIL_CHARS = SHARED_MANIFEST.submissionLimits.contactEmailMaxChars;
diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/SessionAnnotationsCard.tsx b/src/Web/autopilot-monitor-web/app/sessions/components/SessionAnnotationsCard.tsx
index 21e9606a..a16092bf 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/components/SessionAnnotationsCard.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/components/SessionAnnotationsCard.tsx
@@ -21,7 +21,7 @@ import {
type AnnotationVerdict,
type SessionAnnotationDto,
} from "./sessionAnnotationLogic";
-import type { UpsertSessionAnnotationRequest } from "@/utils/wire-types.generated";
+import type { UpsertSessionAnnotationRequest } from "@/lib/generated/wire-types.generated";
/**
* Session annotations: per-lane human verdict + note about this enrollment's analysis
diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/TimeAttributionLane.tsx b/src/Web/autopilot-monitor-web/app/sessions/components/TimeAttributionLane.tsx
index 1a606f44..a64a8276 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/components/TimeAttributionLane.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/components/TimeAttributionLane.tsx
@@ -1,7 +1,7 @@
"use client";
import React from "react";
-import type { SessionTimeBreakdown } from "@/utils/wire-types.generated";
+import type { SessionTimeBreakdown } from "@/lib/generated/wire-types.generated";
import { osUpdateDetail } from "./timeAttributionLogic";
/**
diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/__tests__/timeAttributionLogic.test.ts b/src/Web/autopilot-monitor-web/app/sessions/components/__tests__/timeAttributionLogic.test.ts
index 92409d21..598d7d54 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/components/__tests__/timeAttributionLogic.test.ts
+++ b/src/Web/autopilot-monitor-web/app/sessions/components/__tests__/timeAttributionLogic.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
-import { SHARED_MANIFEST } from "@/utils/shared-manifests.generated";
+import { SHARED_MANIFEST } from "@/lib/generated/shared-manifests.generated";
import { osUpdateDetail } from "../timeAttributionLogic";
describe("osUpdateDetail", () => {
diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/timeAttributionLogic.ts b/src/Web/autopilot-monitor-web/app/sessions/components/timeAttributionLogic.ts
index af10b8ae..dbe7d665 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/components/timeAttributionLogic.ts
+++ b/src/Web/autopilot-monitor-web/app/sessions/components/timeAttributionLogic.ts
@@ -1,4 +1,4 @@
-import type { OsUpdateSpan } from "@/utils/wire-types.generated";
+import type { OsUpdateSpan } from "@/lib/generated/wire-types.generated";
import type { OsUpdateOutcome } from "@/lib/osUpdateLive";
/** The words the Windows Update slice names an outcome with; "unknown" names nothing. */
diff --git a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionAnalysis.ts b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionAnalysis.ts
index aa2e9607..2f9edfc5 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionAnalysis.ts
+++ b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionAnalysis.ts
@@ -2,8 +2,8 @@
import { useState, useCallback, useEffect } from "react";
import { api } from "@/lib/api";
import { RuleResult } from "@/types";
-import { isGuid } from "@/utils/inputValidation";
-import type { GetRuleResultsResponse, GetVulnerabilityReportResponse } from "@/utils/wire-types.generated";
+import { isGuid } from "@/lib/inputValidation";
+import type { GetRuleResultsResponse, GetVulnerabilityReportResponse } from "@/lib/generated/wire-types.generated";
import { fetchJson } from "@/lib/apiClient";
export function useSessionAnalysis(
diff --git a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionDerivedData.ts b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionDerivedData.ts
index 3ddffbee..9b381813 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionDerivedData.ts
+++ b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionDerivedData.ts
@@ -2,10 +2,10 @@
import { useMemo } from "react";
import { EnrollmentEvent, Session } from "@/types";
-import { V1_PHASE_NAMES, V2_PHASE_NAMES, V1_PHASE_ORDER, V2_PHASE_ORDER } from "../utils/phaseConstants";
-import { detectSkipUserStatusPage } from "../utils/espConfig";
-import { computeWhiteGloveDurations, computeWhiteGloveSplitSequence, groupEventsByPhase } from "../utils/eventHelpers";
-import type { WhiteGloveDurations } from "../utils/eventHelpers";
+import { V1_PHASE_NAMES, V2_PHASE_NAMES, V1_PHASE_ORDER, V2_PHASE_ORDER } from "../lib/phaseConstants";
+import { detectSkipUserStatusPage } from "../lib/espConfig";
+import { computeWhiteGloveDurations, computeWhiteGloveSplitSequence, groupEventsByPhase } from "../lib/eventHelpers";
+import type { WhiteGloveDurations } from "../lib/eventHelpers";
import { enrollmentWindowOf, sumStandbySeconds } from "@/lib/standby";
import { deriveOsUpdateLive, type OsUpdateLiveFacts } from "@/lib/osUpdateLive";
diff --git a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionDetail.ts b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionDetail.ts
index 817dbc3b..264a7cee 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionDetail.ts
+++ b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionDetail.ts
@@ -3,10 +3,10 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { api } from "@/lib/api";
import { TokenExpiredError } from "@/lib/authenticatedFetch";
-import { isGuid } from "@/utils/inputValidation";
+import { isGuid } from "@/lib/inputValidation";
import { Session } from "@/types";
import { type NotificationType, notifyApiError } from "@/contexts/NotificationContext";
-import type { GetSessionResponse } from "@/utils/wire-types.generated";
+import type { GetSessionResponse } from "@/lib/generated/wire-types.generated";
import { ApiError, fetchJson } from "@/lib/apiClient";
type AddNotification = (
diff --git a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionEvents.ts b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionEvents.ts
index ccb805e4..f060ae65 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionEvents.ts
+++ b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionEvents.ts
@@ -4,11 +4,11 @@ import { useCallback, useEffect, useRef, useState } from "react";
import { api } from "@/lib/api";
import { createBurstScheduler, type BurstScheduler } from "@/lib/burstScheduler";
import { extractContinuation, MAX_EAGER_PAGES } from "@/lib/paginationLink";
-import { isGuid } from "@/utils/inputValidation";
-import { isTerminalStatus } from "@/utils/sessionStatus";
+import { isGuid } from "@/lib/inputValidation";
+import { isTerminalStatus } from "@/lib/sessionStatus";
import { EnrollmentEvent, Session } from "@/types";
import { type NotificationType, notifyApiError } from "@/contexts/NotificationContext";
-import type { GetSessionEventsResponse } from "@/utils/wire-types.generated";
+import type { GetSessionEventsResponse } from "@/lib/generated/wire-types.generated";
import { ApiError, fetchJson } from "@/lib/apiClient";
const TIMELINE_PAGE_SIZE = 200;
diff --git a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionSignalR.ts b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionSignalR.ts
index 19e4918a..fa285fc7 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionSignalR.ts
+++ b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionSignalR.ts
@@ -2,7 +2,7 @@
import { useEffect } from "react";
import { Session, RuleResult } from "@/types";
-import { isTerminalStatus } from "@/utils/sessionStatus";
+import { isTerminalStatus } from "@/lib/sessionStatus";
import type { SignalRMessageName } from "@/lib/signalrMessages";
import { useSignalRResync } from "@/contexts/SignalRContext";
import type { FetchEventsReason } from "./useSessionEvents";
diff --git a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionTenantConfig.ts b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionTenantConfig.ts
index 899938ac..c9c4583f 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionTenantConfig.ts
+++ b/src/Web/autopilot-monitor-web/app/sessions/hooks/useSessionTenantConfig.ts
@@ -3,7 +3,7 @@
import { useCallback, useEffect, useState } from "react";
import { api } from "@/lib/api";
import { cachedAuthFetchJson, FEATURE_FLAGS_TTL_MS } from "@/lib/cachedAuthFetch";
-import type { TenantFeatureFlagsResponse } from "@/utils/wire-types.generated";
+import type { TenantFeatureFlagsResponse } from "@/lib/generated/wire-types.generated";
interface UseSessionTenantConfigReturn {
showScriptOutput: boolean;
diff --git a/src/Web/autopilot-monitor-web/app/sessions/utils/__tests__/eventSearchQuery.test.ts b/src/Web/autopilot-monitor-web/app/sessions/lib/__tests__/eventSearchQuery.test.ts
similarity index 100%
rename from src/Web/autopilot-monitor-web/app/sessions/utils/__tests__/eventSearchQuery.test.ts
rename to src/Web/autopilot-monitor-web/app/sessions/lib/__tests__/eventSearchQuery.test.ts
diff --git a/src/Web/autopilot-monitor-web/app/sessions/utils/espConfig.ts b/src/Web/autopilot-monitor-web/app/sessions/lib/espConfig.ts
similarity index 100%
rename from src/Web/autopilot-monitor-web/app/sessions/utils/espConfig.ts
rename to src/Web/autopilot-monitor-web/app/sessions/lib/espConfig.ts
diff --git a/src/Web/autopilot-monitor-web/app/sessions/utils/eventHelpers.ts b/src/Web/autopilot-monitor-web/app/sessions/lib/eventHelpers.ts
similarity index 100%
rename from src/Web/autopilot-monitor-web/app/sessions/utils/eventHelpers.ts
rename to src/Web/autopilot-monitor-web/app/sessions/lib/eventHelpers.ts
diff --git a/src/Web/autopilot-monitor-web/app/sessions/utils/eventSearchQuery.ts b/src/Web/autopilot-monitor-web/app/sessions/lib/eventSearchQuery.ts
similarity index 100%
rename from src/Web/autopilot-monitor-web/app/sessions/utils/eventSearchQuery.ts
rename to src/Web/autopilot-monitor-web/app/sessions/lib/eventSearchQuery.ts
diff --git a/src/Web/autopilot-monitor-web/app/sessions/utils/phaseConstants.ts b/src/Web/autopilot-monitor-web/app/sessions/lib/phaseConstants.ts
similarity index 100%
rename from src/Web/autopilot-monitor-web/app/sessions/utils/phaseConstants.ts
rename to src/Web/autopilot-monitor-web/app/sessions/lib/phaseConstants.ts
diff --git a/src/Web/autopilot-monitor-web/app/sessions/network-timeline/networkTimelineModel.ts b/src/Web/autopilot-monitor-web/app/sessions/network-timeline/networkTimelineModel.ts
index 1b97b1f3..27b99bc4 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/network-timeline/networkTimelineModel.ts
+++ b/src/Web/autopilot-monitor-web/app/sessions/network-timeline/networkTimelineModel.ts
@@ -16,7 +16,7 @@
// attributing the quiet period to the active network.
// ─────────────────────────────────────────────────────────────────────────────
-import { V1_PHASE_NAMES, V2_PHASE_NAMES } from '@/app/sessions/utils/phaseConstants';
+import { V1_PHASE_NAMES, V2_PHASE_NAMES } from '@/app/sessions/lib/phaseConstants';
import type { EnrollmentEvent, Session } from '@/types';
// ── Types ────────────────────────────────────────────────────────────────────
diff --git a/src/Web/autopilot-monitor-web/app/sessions/network-timeline/page.tsx b/src/Web/autopilot-monitor-web/app/sessions/network-timeline/page.tsx
index 574f7967..d66c48f2 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/network-timeline/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/network-timeline/page.tsx
@@ -16,7 +16,7 @@ import { useSearchParams } from 'next/navigation';
import Link from 'next/link';
import { ProtectedRoute } from '@/components/ProtectedRoute';
import { useAuth } from '@/contexts/AuthContext';
-import { isGuid } from '@/utils/inputValidation';
+import { isGuid } from '@/lib/inputValidation';
import { api } from '@/lib/api';
import { extractContinuation, MAX_EAGER_PAGES } from '@/lib/paginationLink';
import { sessionUrl } from '@/lib/routes';
@@ -24,9 +24,9 @@ import NetworkBand from './NetworkBand';
import { buildNetworkModel, fmtDuration, NetworkModel } from './networkTimelineModel';
import { enrollmentWindowOf, sumStandbySeconds } from '@/lib/standby';
import type { EnrollmentEvent, Session } from '@/types';
-import type { GetSessionEventsResponse } from "@/utils/wire-types.generated";
+import type { GetSessionEventsResponse } from "@/lib/generated/wire-types.generated";
import { apiErrorText, fetchJson } from "@/lib/apiClient";
-import type { GetSessionResponse } from "@/utils/wire-types.generated";
+import type { GetSessionResponse } from "@/lib/generated/wire-types.generated";
// ── Data loading ─────────────────────────────────────────────────────────────
diff --git a/src/Web/autopilot-monitor-web/app/sessions/page.tsx b/src/Web/autopilot-monitor-web/app/sessions/page.tsx
index 556422c5..aca6b999 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/page.tsx
@@ -17,8 +17,8 @@ import { findUserPhaseBoundary } from '@/lib/userPhaseBoundary';
import { useLatestVersions } from '@/lib/useLatestVersions';
import { useScriptDisplayNames } from '@/lib/scriptDisplayNames';
import { api } from "@/lib/api";
-import { isGuid } from "@/utils/inputValidation";
-import { isTerminalStatus } from "@/utils/sessionStatus";
+import { isGuid } from "@/lib/inputValidation";
+import { isTerminalStatus } from "@/lib/sessionStatus";
import { hasTenantReadScope } from "@/lib/tenantScope";
import { ApiError, fetchBlob, fetchJson, fetchOk, jsonBody } from "@/lib/apiClient";
@@ -48,14 +48,14 @@ import { usePageSections } from "../../hooks/usePageSections";
import { PageSectionItem } from "../../contexts/SidebarContext";
import { InformationCircleIcon, ComputerDesktopIcon, PlayCircleIcon, SparklesIcon, ChartBarIcon, CodeBracketIcon, ArrowDownTrayIcon, ListBulletIcon, ClockIcon, ShieldCheckIcon, PencilSquareIcon } from "../../lib/sidebarIcons";
import DeviceDetailsCard from "./components/DeviceDetailsCard";
-import { generateUiExport, generateCsvExport, generateSessionCsvExport, generateRuleResultsCsvExport, SessionExportEvent } from "@/utils/sessionExportUtils";
+import { generateUiExport, generateCsvExport, generateSessionCsvExport, generateRuleResultsCsvExport, SessionExportEvent } from "@/lib/sessionExportUtils";
import { trackEvent } from "@/lib/appInsights";
import { bytesToBase64 } from "@/lib/base64";
import { fitsReportRequest } from "@/lib/reportAttachments";
import { useAdminMode } from "@/hooks/useAdminMode";
import { DocsLink } from "@/components/DocsLink";
import { DOCS_PATHS } from "@/lib/docsPaths";
-import type { GetSessionTimeAttributionResponse, SubmitSessionReportRequest } from "@/utils/wire-types.generated";
+import type { GetSessionTimeAttributionResponse, SubmitSessionReportRequest } from "@/lib/generated/wire-types.generated";
export default function SessionDetailPage() {
// useSearchParams() in SessionDetailContent requires a Suspense boundary for static prerender.
diff --git a/src/Web/autopilot-monitor-web/app/settings/TenantConfigContext.tsx b/src/Web/autopilot-monitor-web/app/settings/TenantConfigContext.tsx
index aff8adde..14508740 100644
--- a/src/Web/autopilot-monitor-web/app/settings/TenantConfigContext.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/TenantConfigContext.tsx
@@ -30,7 +30,7 @@ import { TenantConfiguration, TenantAdmin, DiagnosticsLogPath, NotificationChann
import { SECTION_FIELD_MAP, type SectionFieldSpec, type SettingsSectionName } from "./sectionFieldMap";
import { HELLO_WAIT_TIMEOUT_DEFAULT_SECONDS } from "./lib/helloWaitTimeout";
import { changedTenantConfigFields, patchTenantConfigFields } from "@/lib/tenantConfigSave";
-import { looksLikeGuid, type MemberKind } from "@/utils/principalKeys";
+import { looksLikeGuid, type MemberKind } from "@/lib/principalKeys";
import { type BootstrapSessionItem } from "./components/BootstrapSessionsSection";
import type {
AddTenantAdminRequest,
@@ -44,7 +44,7 @@ import type {
TestNotificationChannelRequest,
TestWebhookNotificationResponse,
UpdateMemberPermissionsRequest,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
/**
* Channels for display/editing from a loaded config: prefers notificationChannelsJson; while
@@ -300,7 +300,7 @@ interface TenantConfigContextValue {
setNewAdminEmail: (v: string) => void;
newMemberRole: string;
setNewMemberRole: (v: string) => void;
- /** Person (UPN) or service principal (application id) — see utils/principalKeys. */
+ /** Person (UPN) or service principal (application id) — see lib/principalKeys. */
newMemberKind: MemberKind;
setNewMemberKind: (v: MemberKind) => void;
addingAdmin: boolean;
diff --git a/src/Web/autopilot-monitor-web/app/settings/__tests__/sectionFieldMap.test.ts b/src/Web/autopilot-monitor-web/app/settings/__tests__/sectionFieldMap.test.ts
index a9e24e78..b8b4ce7f 100644
--- a/src/Web/autopilot-monitor-web/app/settings/__tests__/sectionFieldMap.test.ts
+++ b/src/Web/autopilot-monitor-web/app/settings/__tests__/sectionFieldMap.test.ts
@@ -6,7 +6,7 @@
* (never derived from the map itself — see tasks/lessons.md on circular parity fixtures).
*/
import { describe, expect, it } from "vitest";
-import { SHARED_MANIFEST } from "@/utils/shared-manifests.generated";
+import { SHARED_MANIFEST } from "@/lib/generated/shared-manifests.generated";
import { SECTION_FIELD_MAP } from "../sectionFieldMap";
const sections = Object.entries(SECTION_FIELD_MAP) as Array<
diff --git a/src/Web/autopilot-monitor-web/app/settings/components/AdminManagementSection.tsx b/src/Web/autopilot-monitor-web/app/settings/components/AdminManagementSection.tsx
index db1914b4..40e9f971 100644
--- a/src/Web/autopilot-monitor-web/app/settings/components/AdminManagementSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/components/AdminManagementSection.tsx
@@ -6,7 +6,7 @@ import { SectionCardHeader } from "@/components/SectionCardHeader";
import { AddMemberForm } from "@/components/members/AddMemberForm";
import { MemberList } from "@/components/members/MemberList";
import { DOCS_PATHS } from "@/lib/docsPaths";
-import type { MemberKind } from "@/utils/principalKeys";
+import type { MemberKind } from "@/lib/principalKeys";
interface AdminManagementSectionProps {
admins: TenantAdmin[];
diff --git a/src/Web/autopilot-monitor-web/app/settings/components/AppHomingAddOnStep.tsx b/src/Web/autopilot-monitor-web/app/settings/components/AppHomingAddOnStep.tsx
index 2d6d7f79..26f796af 100644
--- a/src/Web/autopilot-monitor-web/app/settings/components/AppHomingAddOnStep.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/components/AppHomingAddOnStep.tsx
@@ -3,7 +3,7 @@
import { useCallback, useState } from "react";
import { trackEvent } from "@/lib/appInsights";
import { DOCS_PATHS } from "@/lib/docsPaths";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
interface AppHomingAddOnStepProps {
/** Optional Graph add-on roles the previous app holds but the new app still lacks. */
diff --git a/src/Web/autopilot-monitor-web/app/settings/components/BootstrapSessionsSection.tsx b/src/Web/autopilot-monitor-web/app/settings/components/BootstrapSessionsSection.tsx
index c6d420cf..05720499 100644
--- a/src/Web/autopilot-monitor-web/app/settings/components/BootstrapSessionsSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/components/BootstrapSessionsSection.tsx
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
-import { BOOTSTRAP_GO_URL } from "@/utils/config";
+import { BOOTSTRAP_GO_URL } from "@/lib/config";
import { SectionCardHeader } from "@/components/SectionCardHeader";
import { DOCS_PATHS } from "@/lib/docsPaths";
diff --git a/src/Web/autopilot-monitor-web/app/settings/components/DiagnosticsSection.tsx b/src/Web/autopilot-monitor-web/app/settings/components/DiagnosticsSection.tsx
index 102e94a9..94ae840e 100644
--- a/src/Web/autopilot-monitor-web/app/settings/components/DiagnosticsSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/components/DiagnosticsSection.tsx
@@ -3,7 +3,7 @@
import { useMemo, useState } from "react";
import { DiagnosticsLogPath } from "../types";
import type { DiagnosticsBuiltInSection } from "@/types/diagnostics";
-import { validateDiagnosticsPath } from "@/utils/guardValidation";
+import { validateDiagnosticsPath } from "@/lib/guardValidation";
import { ValidationIndicator } from "@/components/ValidationIndicator";
import { BuiltInSectionsList } from "@/components/diagnostics/BuiltInSectionsList";
import { ContextPill, DiagnosticsPathRow } from "@/components/diagnostics/DiagnosticsPathRow";
diff --git a/src/Web/autopilot-monitor-web/app/settings/components/HardwareRejectionInsights.tsx b/src/Web/autopilot-monitor-web/app/settings/components/HardwareRejectionInsights.tsx
index e6fedecb..a3dac516 100644
--- a/src/Web/autopilot-monitor-web/app/settings/components/HardwareRejectionInsights.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/components/HardwareRejectionInsights.tsx
@@ -3,7 +3,7 @@
import { useState, useEffect, useCallback } from "react";
import { api } from "@/lib/api";
import { apiErrorText, fetchJson } from "@/lib/apiClient";
-import type { HardwareRejectedResponse } from "@/utils/wire-types.generated";
+import type { HardwareRejectedResponse } from "@/lib/generated/wire-types.generated";
diff --git a/src/Web/autopilot-monitor-web/app/settings/components/McpUsersSection.tsx b/src/Web/autopilot-monitor-web/app/settings/components/McpUsersSection.tsx
index 11e63041..de44616f 100644
--- a/src/Web/autopilot-monitor-web/app/settings/components/McpUsersSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/components/McpUsersSection.tsx
@@ -7,7 +7,7 @@ import { api } from "@/lib/api";
import { patchAdminConfigFields } from "@/lib/adminConfigSave";
import { useTenantList } from "@/hooks/useTenantList";
import { HOME_TENANT_UNRESOLVED } from "@/lib/identityBinding";
-import { isApplicationKey, looksLikeGuid, principalLabel } from "@/utils/principalKeys";
+import { isApplicationKey, looksLikeGuid, principalLabel } from "@/lib/principalKeys";
import { SectionCardHeader } from "@/components/SectionCardHeader";
import { DOCS_PATHS } from "@/lib/docsPaths";
import type {
@@ -17,7 +17,7 @@ import type {
PlanTierDefinition as PlanTierDefinitionWire,
PlanTierDefinitionsResponse,
SetUsagePlanRequest,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
/** One MCP user row and one plan tier — the wire shapes. */
type McpUser = McpUserEntry;
diff --git a/src/Web/autopilot-monitor-web/app/settings/components/NotRegisteredDevicesInsights.tsx b/src/Web/autopilot-monitor-web/app/settings/components/NotRegisteredDevicesInsights.tsx
index 3f6c0a50..a27d9553 100644
--- a/src/Web/autopilot-monitor-web/app/settings/components/NotRegisteredDevicesInsights.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/components/NotRegisteredDevicesInsights.tsx
@@ -3,7 +3,7 @@
import { useState, useEffect, useCallback } from "react";
import { api } from "@/lib/api";
import { apiErrorText, fetchJson } from "@/lib/apiClient";
-import type { DeviceNotRegisteredResponse } from "@/utils/wire-types.generated";
+import type { DeviceNotRegisteredResponse } from "@/lib/generated/wire-types.generated";
diff --git a/src/Web/autopilot-monitor-web/app/settings/components/__tests__/AppHomingAddOnStep.test.ts b/src/Web/autopilot-monitor-web/app/settings/components/__tests__/AppHomingAddOnStep.test.ts
index 81c06b95..ee0b3a78 100644
--- a/src/Web/autopilot-monitor-web/app/settings/components/__tests__/AppHomingAddOnStep.test.ts
+++ b/src/Web/autopilot-monitor-web/app/settings/components/__tests__/AppHomingAddOnStep.test.ts
@@ -2,7 +2,7 @@ import { describe, it, expect } from "vitest";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { AppHomingAddOnStep } from "../AppHomingAddOnStep";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
describe("AppHomingAddOnStep", () => {
const roles = ["CloudPC.Read.All", "DeviceManagementScripts.Read.All"];
diff --git a/src/Web/autopilot-monitor-web/app/settings/lib/__tests__/helloWaitTimeout.test.ts b/src/Web/autopilot-monitor-web/app/settings/lib/__tests__/helloWaitTimeout.test.ts
index 36fcbbcb..36884c78 100644
--- a/src/Web/autopilot-monitor-web/app/settings/lib/__tests__/helloWaitTimeout.test.ts
+++ b/src/Web/autopilot-monitor-web/app/settings/lib/__tests__/helloWaitTimeout.test.ts
@@ -1,7 +1,7 @@
import { describe, expect, it } from "vitest";
import fs from "node:fs";
import path from "node:path";
-import { SHARED_MANIFEST } from "@/utils/shared-manifests.generated";
+import { SHARED_MANIFEST } from "@/lib/generated/shared-manifests.generated";
import {
clampHelloWaitTimeoutSeconds,
HELLO_WAIT_TIMEOUT_DEFAULT_SECONDS,
diff --git a/src/Web/autopilot-monitor-web/app/settings/reporting/sections/SectionMcpUsage.tsx b/src/Web/autopilot-monitor-web/app/settings/reporting/sections/SectionMcpUsage.tsx
index 63bef7f5..8dcedcd9 100644
--- a/src/Web/autopilot-monitor-web/app/settings/reporting/sections/SectionMcpUsage.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/reporting/sections/SectionMcpUsage.tsx
@@ -16,8 +16,8 @@ import type {
GetMyMcpUsageResponse,
McpOrganizationQuotaNode,
McpUsageQuotaNode,
-} from "@/utils/wire-types.generated";
-import { isApplicationKey, principalLabel } from "@/utils/principalKeys";
+} from "@/lib/generated/wire-types.generated";
+import { isApplicationKey, principalLabel } from "@/lib/principalKeys";
interface UsageRecord {
userId: string;
diff --git a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionAiIntegration.tsx b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionAiIntegration.tsx
index 3cc927ac..21521de9 100644
--- a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionAiIntegration.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionAiIntegration.tsx
@@ -9,12 +9,12 @@ import { api } from "@/lib/api";
import { SectionCardHeader } from "@/components/SectionCardHeader";
import { DOCS_PATHS } from "@/lib/docsPaths";
import { useCopy } from "@/hooks/useCopy";
-import { MCP_SERVER_URL } from "@/utils/config";
+import { MCP_SERVER_URL } from "@/lib/config";
import type {
CreateMcpClientRegistrationRequest,
CreateMcpClientRegistrationResponse,
McpClientRegistrationListResponse,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
function formatDay(iso: string | undefined | null): string {
if (!iso) return "—";
diff --git a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionAutopilotValidation.tsx b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionAutopilotValidation.tsx
index b6269cfb..7b4c029e 100644
--- a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionAutopilotValidation.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionAutopilotValidation.tsx
@@ -8,13 +8,13 @@ import { api } from "@/lib/api";
import { buildAddOnGrantCommand } from "@/lib/appHoming";
import { legacyConfigured, primaryClientId, switchAuthApp } from "@/lib/authApp";
import { DOCS_PATHS } from "@/lib/docsPaths";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
import { useTenantConfig } from "../../TenantConfigContext";
import { TenantNotifications } from "../../TenantNotifications";
import { AppHomingAddOnStep } from "../../components/AppHomingAddOnStep";
import AutopilotValidationSection from "../../components/AutopilotValidationSection";
import NotRegisteredDevicesInsights from "../../components/NotRegisteredDevicesInsights";
-import type { GetGraphPermissionsStatusResponse } from "@/utils/wire-types.generated";
+import type { GetGraphPermissionsStatusResponse } from "@/lib/generated/wire-types.generated";
import { addOnGranted, INTUNE_ENROLLMENT_FEATURE } from "@/lib/deviceValidation";
export function SectionAutopilotValidation() {
diff --git a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionDelegatedAccess.tsx b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionDelegatedAccess.tsx
index 0d136613..45dc1966 100644
--- a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionDelegatedAccess.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionDelegatedAccess.tsx
@@ -11,7 +11,7 @@ import { SectionCardHeader } from "@/components/SectionCardHeader";
import { DOCS_PATHS } from "@/lib/docsPaths";
import { isProViaMsp } from "@/lib/edition";
import { buildInviteLink, describeDelegationError, holdRemainingLabel, invitationStatusLabel } from "@/lib/delegations";
-import { principalLabel } from "@/utils/principalKeys";
+import { principalLabel } from "@/lib/principalKeys";
import type {
CreateDelegationInvitationResponse,
DelegationAssigneeListResponse,
@@ -21,7 +21,7 @@ import type {
RemoveManagedTenantRequest,
RevokeTenantManagerRequest,
TenantManagerListResponse,
-} from "@/utils/wire-types.generated";
+} from "@/lib/generated/wire-types.generated";
type Confirm =
| { kind: "revoke"; homeTenantId: string; label: string }
diff --git a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionOptionalGraphCapabilities.tsx b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionOptionalGraphCapabilities.tsx
index 11efc4a6..9d800c0e 100644
--- a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionOptionalGraphCapabilities.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionOptionalGraphCapabilities.tsx
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useState } from "react";
import { useAuth } from "../../../../contexts/AuthContext";
import { useTenant } from "../../../../contexts/TenantContext";
import { api } from "@/lib/api";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
import { apiErrorText, fetchJson, fetchOk } from "@/lib/apiClient";
import { ADD_ON_GRANT_SCRIPT_URL, addOnFeaturesSelector, buildAddOnGrantCommand } from "@/lib/appHoming";
import { trackEvent } from "@/lib/appInsights";
diff --git a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionPlan.tsx b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionPlan.tsx
index fab08575..a4e91d1c 100644
--- a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionPlan.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionPlan.tsx
@@ -5,7 +5,7 @@ import Link from "next/link";
import { useTenantConfig } from "../../TenantConfigContext";
import { isProViaMsp, missingContactProfileParts, trialDaysLeft } from "@/lib/edition";
import { PlanCards } from "@/components/plans/PlanCards";
-import { sitePageUrl } from "@/utils/config";
+import { sitePageUrl } from "@/lib/config";
import { SectionCardHeader } from "@/components/SectionCardHeader";
import { DOCS_PATHS } from "@/lib/docsPaths";
diff --git a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionSubmitLogs.tsx b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionSubmitLogs.tsx
index 06ede890..0d67319c 100644
--- a/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionSubmitLogs.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/tenant/sections/SectionSubmitLogs.tsx
@@ -10,8 +10,8 @@ import { openFeedbackDialog } from "@/lib/feedbackDialogStore";
import { ATTACHMENT_BUDGET_BYTES, fitsReportRequest, packedSize } from "@/lib/reportAttachments";
import { useAttachmentPack } from "@/hooks/useAttachmentPack";
import { AttachmentBudgetLine, AttachmentField } from "@/components/ReportAttachments";
-import { SHARED_MANIFEST } from "@/utils/shared-manifests.generated";
-import type { SubmitDiagFilesReportRequest } from "@/utils/wire-types.generated";
+import { SHARED_MANIFEST } from "@/lib/generated/shared-manifests.generated";
+import type { SubmitDiagFilesReportRequest } from "@/lib/generated/wire-types.generated";
const LOG_ACCEPT = ".log,.txt,.zip,.json,.jsonl,.ndjson";
const MAX_COMMENT_CHARS = SHARED_MANIFEST.submissionLimits.reportCommentMaxChars;
diff --git a/src/Web/autopilot-monitor-web/app/settings/types.ts b/src/Web/autopilot-monitor-web/app/settings/types.ts
index b9d79007..376cd977 100644
--- a/src/Web/autopilot-monitor-web/app/settings/types.ts
+++ b/src/Web/autopilot-monitor-web/app/settings/types.ts
@@ -150,4 +150,4 @@ export interface TenantConfiguration {
}
// Wire type is generated from the backend DTO ("role" is absent for legacy pre-role rows).
-export type { TenantAdminRow as TenantAdmin } from "@/utils/wire-types.generated";
+export type { TenantAdminRow as TenantAdmin } from "@/lib/generated/wire-types.generated";
diff --git a/src/Web/autopilot-monitor-web/app/sitemap.ts b/src/Web/autopilot-monitor-web/app/sitemap.ts
index 9319c878..853038ea 100644
--- a/src/Web/autopilot-monitor-web/app/sitemap.ts
+++ b/src/Web/autopilot-monitor-web/app/sitemap.ts
@@ -2,8 +2,8 @@
export const dynamic = "force-static";
import type { MetadataRoute } from "next";
-import { PAGE_LASTMOD } from "@/utils/page-lastmod.generated";
-import { sitePageUrl } from "@/utils/config";
+import { PAGE_LASTMOD } from "@/lib/generated/page-lastmod.generated";
+import { sitePageUrl } from "@/lib/config";
// Build-time only (static export): a URL missing from PAGE_LASTMOD means
// scripts/generate-lastmod.js drifted from this list -- fail the build rather
diff --git a/src/Web/autopilot-monitor-web/app/sla/page.tsx b/src/Web/autopilot-monitor-web/app/sla/page.tsx
index abd39112..bcdfb100 100644
--- a/src/Web/autopilot-monitor-web/app/sla/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/sla/page.tsx
@@ -36,7 +36,7 @@ import { CardSkeleton } from "@/components/skeletons/PageSkeleton";
// Wire type of the SLA endpoint — note status is a NUMBER there (the C# SessionStatus
// enum serialized as int; rendered via statusLabels below), unlike the string status
// on SessionSummary.
-import type { SlaMetricsResponse } from "@/utils/wire-types.generated";
+import type { SlaMetricsResponse } from "@/lib/generated/wire-types.generated";
import { DocsLink } from "@/components/DocsLink";
import { DOCS_PATHS } from "@/lib/docsPaths";
import { fetchJson } from "@/lib/apiClient";
diff --git a/src/Web/autopilot-monitor-web/app/terms/layout.tsx b/src/Web/autopilot-monitor-web/app/terms/layout.tsx
index 40d50a94..742b0b17 100644
--- a/src/Web/autopilot-monitor-web/app/terms/layout.tsx
+++ b/src/Web/autopilot-monitor-web/app/terms/layout.tsx
@@ -1,5 +1,5 @@
import type { Metadata } from "next";
-import { SITE_URL } from "@/utils/config";
+import { SITE_URL } from "@/lib/config";
import { OPEN_GRAPH_BASE } from "@/lib/siteMetadata";
export const metadata: Metadata = {
diff --git a/src/Web/autopilot-monitor-web/app/terms/page.tsx b/src/Web/autopilot-monitor-web/app/terms/page.tsx
index a8917dc8..e5e4155d 100644
--- a/src/Web/autopilot-monitor-web/app/terms/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/terms/page.tsx
@@ -1,6 +1,6 @@
import { LandingNavbar } from "../../components/landing/LandingNavbar";
import { SiteFooter } from "../../components/SiteFooter";
-import { DOCS_URL } from "@/utils/config";
+import { DOCS_URL } from "@/lib/config";
const LAST_UPDATED = "11 September 2026";
const DOCS_SECURITY_FAQ = `${DOCS_URL}/trust/security-faq`;
diff --git a/src/Web/autopilot-monitor-web/app/usage-metrics/page.tsx b/src/Web/autopilot-monitor-web/app/usage-metrics/page.tsx
index b6709005..f6b17b15 100644
--- a/src/Web/autopilot-monitor-web/app/usage-metrics/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/usage-metrics/page.tsx
@@ -11,7 +11,7 @@ import { TenantScopeSelector } from "@/components/TenantScopeSelector";
import { CardSkeleton } from "@/components/skeletons/PageSkeleton";
import { DocsLink } from "@/components/DocsLink";
import { DOCS_PATHS } from "@/lib/docsPaths";
-import type { PlatformUsageMetrics } from "@/utils/wire-types.generated";
+import type { PlatformUsageMetrics } from "@/lib/generated/wire-types.generated";
import { fetchJson } from "@/lib/apiClient";
import { useWindowDays } from "@/hooks/useWindowDays";
import { notifyApiError } from "@/contexts/NotificationContext";
diff --git a/src/Web/autopilot-monitor-web/components/ChunkReloadRecovery.tsx b/src/Web/autopilot-monitor-web/components/ChunkReloadRecovery.tsx
index 73512c9c..b7f8ca85 100644
--- a/src/Web/autopilot-monitor-web/components/ChunkReloadRecovery.tsx
+++ b/src/Web/autopilot-monitor-web/components/ChunkReloadRecovery.tsx
@@ -1,10 +1,10 @@
"use client";
import { useEffect } from "react";
-import { isChunkLoadError, tryRecoverFromChunkError } from "@/utils/chunkReloadRecovery";
+import { isChunkLoadError, tryRecoverFromChunkError } from "@/lib/chunkReloadRecovery";
/**
- * Global listener pair for stale-bundle chunk failures (see utils/chunkReloadRecovery.ts).
+ * Global listener pair for stale-bundle chunk failures (see lib/chunkReloadRecovery.ts).
* Two paths surface them outside any React error boundary:
* - a rejected dynamic import that nothing awaits → unhandledrejection
* - the chunk