Compare commits

...

5 Commits

Author SHA1 Message Date
Oliver Kieselbach 0ed1e6f542 Merge branch 'main' of https://github.com/okieselbach/Autopilot-Monitor 2026-08-18 03:21:54 +02:00
dependabot[bot] 522911c5a7 chore(deps-dev): bump tsx (#130)
Bumps the mcp group in /src/McpServer/autopilot-monitor-mcp with 1 update: [tsx](https://github.com/privatenumber/tsx).


Updates `tsx` from 4.23.11 to 4.23.12
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.23.11...v4.23.12)

---
updated-dependencies:
- dependency-name: tsx
  dependency-version: 4.23.12
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: mcp
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-18 03:20:26 +02:00
dependabot[bot] 0bfe1e327b chore(deps): bump the web group (#131)
Bumps the web group in /src/Web/autopilot-monitor-web with 4 updates: [@xyflow/react](https://github.com/xyflow/xyflow/tree/HEAD/packages/react), [next](https://github.com/vercel/next.js), [@next/bundle-analyzer](https://github.com/vercel/next.js/tree/HEAD/packages/next-bundle-analyzer) and [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next).


Updates `@xyflow/react` from 12.11.2 to 12.11.3
- [Release notes](https://github.com/xyflow/xyflow/releases)
- [Changelog](https://github.com/xyflow/xyflow/blob/main/packages/react/CHANGELOG.md)
- [Commits](https://github.com/xyflow/xyflow/commits/@xyflow/react@12.11.3/packages/react)

Updates `next` from 16.3.0 to 16.3.1
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/compare/v16.3.0...v16.3.1)

Updates `@next/bundle-analyzer` from 16.3.0 to 16.3.1
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/commits/v16.3.1/packages/next-bundle-analyzer)

Updates `eslint-config-next` from 16.3.0 to 16.3.1
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/commits/v16.3.1/packages/eslint-config-next)

---
updated-dependencies:
- dependency-name: "@xyflow/react"
  dependency-version: 12.11.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: web
- dependency-name: next
  dependency-version: 16.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: web
- dependency-name: "@next/bundle-analyzer"
  dependency-version: 16.3.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: web
- dependency-name: eslint-config-next
  dependency-version: 16.3.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: web
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-18 03:20:10 +02:00
Oliver Kieselbach 2cf7216be5 Token-failure grace window + registry_app_baseline summary
Live findings from the first two 2.0.1402 sessions (Oliver, 2026-08-18):

1. "Failed to get AAD token" is logged routinely during the device phase
   (no user token exists yet) - both test sessions raised the Warning
   although nothing was wrong. The failure is now held pending: any
   IME-TOKEN-SUCCESS match clears it (staleness-gated so a replayed
   success from a previous enrollment cannot mask a current outage), and
   ime_token_failure fires only when no success follows for the 30-min
   grace window, then deduped per errorCode. Genuine auth outages run
   long enough to hit the window; routine device-phase failures never do.

2. New one-shot registry_app_baseline event (Info, only when non-empty):
   summary of the Win32Apps state that predates the agent run - counts
   by enforcement class + capped 50-app typed payload incl.
   LastUpdatedTimeUtc. On WDP the DPP-policy apps install in Batch 1
   before the bootstrap-script agent exists; their outcomes live only in
   this baseline, closing the pre-agent app gap without log backfill.
   The diff rail stays silent on baseline state (anti-replay unchanged).

Event type dual-registered (Constants + MCP catalog + manifests regen).
Tests: grace-window cycle (resolved / unresolved / re-arm dedup),
baseline summary (counts, one-shot, empty). All suites green
(Agent 2274, Functions 4262, MCP 561, web 762), 0 warnings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 03:16:58 +02:00
Oliver Kieselbach 587adc5ddf ci(msi): build from project dir - wix resolves File/@Source against cwd
WIX0103 on the first run: Invoke-BootstrapDownload.ps1 not found because
wix build resolves File/@Source relative to the working directory, not
the wxs location. Matches the local build documented in Package.wxs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 03:11:12 +02:00
17 changed files with 271 additions and 88 deletions
+6 -1
View File
@@ -68,7 +68,12 @@ jobs:
- name: Build MSI
shell: pwsh
run: |
wix build "$env:MSI_PROJECT_DIR/Package.wxs" -arch x64 -o $env:STABLE_MSI
# wix resolves File/@Source relative to the working directory, not the wxs —
# build from inside the project dir (same as the local build documented in the wxs).
$out = Join-Path (Get-Location) $env:STABLE_MSI
Push-Location $env:MSI_PROJECT_DIR
wix build Package.wxs -arch x64 -o $out
Pop-Location
if (-not (Test-Path $env:STABLE_MSI)) { Write-Error "wix build produced no MSI"; exit 1 }
$sha256 = (Get-FileHash $env:STABLE_MSI -Algorithm SHA256).Hash.ToLowerInvariant()
Write-Host "Built $env:STABLE_MSI ($([math]::Round((Get-Item $env:STABLE_MSI).Length / 1KB)) KB)"
+1 -1
View File
@@ -629,7 +629,7 @@
"category": "always",
"pattern": "Failed to get AAD token\\..*?errorCode = (?<errorCode>.*?)$",
"action": "imeTokenFailure",
"description": "IME token acquisition failure ('Failed to get AAD token. len = N using client id ... and resource id ..., errorCode = N', IntuneTokenManager, IntuneManagementExtension.log). Complements IME-TOKEN-SUCCESS: an auth outage (WAM broken, conditional access, network) previously left every check-in silently doing nothing with no timeline evidence. errorCode can be empty when IME logged none; the agent dedups to one Warning per distinct code. Verified against IME 1.97 and 1.104 decompiled sources.",
"description": "IME token acquisition failure ('Failed to get AAD token. len = N using client id ... and resource id ..., errorCode = N', IntuneTokenManager, IntuneManagementExtension.log). This line appears ROUTINELY during the device phase (no user token exists yet), so the agent holds the failure pending: any IME-TOKEN-SUCCESS match clears it, and the ime_token_failure Warning fires only when no success follows for the whole 30-min grace window (then deduped to one Warning per distinct errorCode). A genuine auth outage (WAM broken, conditional access, network) runs long enough to hit the window. Verified against IME 1.97 and 1.104 decompiled sources.",
"enabled": true
},
{
@@ -4,6 +4,6 @@
"category": "always",
"pattern": "Failed to get AAD token\\..*?errorCode = (?<errorCode>.*?)$",
"action": "imeTokenFailure",
"description": "IME token acquisition failure ('Failed to get AAD token. len = N using client id ... and resource id ..., errorCode = N', IntuneTokenManager, IntuneManagementExtension.log). Complements IME-TOKEN-SUCCESS: an auth outage (WAM broken, conditional access, network) previously left every check-in silently doing nothing with no timeline evidence. errorCode can be empty when IME logged none; the agent dedups to one Warning per distinct code. Verified against IME 1.97 and 1.104 decompiled sources.",
"description": "IME token acquisition failure ('Failed to get AAD token. len = N using client id ... and resource id ..., errorCode = N', IntuneTokenManager, IntuneManagementExtension.log). This line appears ROUTINELY during the device phase (no user token exists yet), so the agent holds the failure pending: any IME-TOKEN-SUCCESS match clears it, and the ime_token_failure Warning fires only when no success follows for the whole 30-min grace window (then deduped to one Warning per distinct errorCode). A genuine auth outage (WAM broken, conditional access, network) runs long enough to hit the window. Verified against IME 1.97 and 1.104 decompiled sources.",
"enabled": true
}
@@ -119,6 +119,40 @@ namespace AutopilotMonitor.Agent.V2.Core.Tests.Monitoring.SystemSignals
Assert.Equal("success", evt.Payload["enforcementClass"]);
}
[Fact]
public void NonEmpty_baseline_emits_one_summary_with_counts()
{
var (sink, clock, observer) = CreateObserver(trackerApps: null);
var current = Snapshot((App1, 1000, 0), (App2, 5003, 101));
using (new ImeRegistryAppStateObserver.ScopedSnapshotOverride(() => current))
{
observer.Tick("baseline");
observer.Tick("periodic"); // summary is one-shot, not per tick
}
var summary = Assert.Single(Events(sink, SharedEventTypes.RegistryAppBaseline));
Assert.Equal("2", summary.Payload!["totalApps"]);
Assert.Equal("1", summary.Payload["successCount"]);
Assert.Equal("1", summary.Payload["errorCount"]);
// The baseline stays silent on the diff rail.
Assert.Empty(Events(sink, SharedEventTypes.RegistryAppState));
}
[Fact]
public void Empty_baseline_emits_no_summary()
{
var (sink, clock, observer) = CreateObserver(trackerApps: null);
var current = new ImeRegistrySnapshot();
using (new ImeRegistryAppStateObserver.ScopedSnapshotOverride(() => current))
{
observer.Tick("baseline");
}
Assert.Empty(Events(sink, SharedEventTypes.RegistryAppBaseline));
}
[Fact]
public void Unchanged_snapshot_emits_nothing()
{
@@ -479,16 +479,32 @@ namespace AutopilotMonitor.Agent.V2.Core.Tests.SignalAdapters
}
[Fact]
public void ImeTokenFailure_tracker_dedups_per_error_code()
public void ImeTokenFailure_grace_window_emits_only_without_token_success()
{
// "Failed to get AAD token" appears routinely during the device phase (no user
// token yet) — the Warning must fire only when NO success follows for the whole
// grace window.
using var f = new ImeLogTrackerAdapterFixture();
using var adapter = new ImeLogTrackerAdapter(f.Tracker, f.Ingress, f.Clock);
var t0 = DateTime.UtcNow;
// Failure resolved by a token success: never emitted, not even after the window.
f.Tracker.HandleImeTokenFailureForTest("100", "line a");
f.Tracker.HandleImeTokenFailureForTest("100", "line b"); // same code — suppressed
f.Tracker.HandleImeTokenFailureForTest("200", "line c"); // new code — emitted
f.Tracker.NoteTokenSuccessForTest();
f.Tracker.CheckPendingTokenFailure(t0 + ImeLogTracker.TokenFailureGraceWindow + TimeSpan.FromMinutes(1));
Assert.Empty(f.InfoEvents(SharedEventTypes.ImeTokenFailure));
Assert.Equal(2, f.InfoEvents(SharedEventTypes.ImeTokenFailure).Count);
// Unresolved failure: silent before the window, one Warning after it.
f.Tracker.HandleImeTokenFailureForTest("100", "line b");
f.Tracker.CheckPendingTokenFailure(t0 + TimeSpan.FromMinutes(5));
Assert.Empty(f.InfoEvents(SharedEventTypes.ImeTokenFailure));
f.Tracker.CheckPendingTokenFailure(t0 + ImeLogTracker.TokenFailureGraceWindow + TimeSpan.FromHours(1));
Assert.Single(f.InfoEvents(SharedEventTypes.ImeTokenFailure));
// Same code again: re-armed window expires but the per-code dedup suppresses.
f.Tracker.HandleImeTokenFailureForTest("100", "line c");
f.Tracker.CheckPendingTokenFailure(t0 + TimeSpan.FromHours(3));
Assert.Single(f.InfoEvents(SharedEventTypes.ImeTokenFailure));
}
[Fact]
@@ -25,25 +25,70 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Enrollment.Ime
private DateTime _impersonationLastRollupUtc = DateTime.MinValue;
private static readonly TimeSpan ImpersonationRollupInterval = TimeSpan.FromSeconds(60);
// IME retries token acquisition on every check-in — dedup per distinct error
// code so an outage yields one Warning, not a timeline flood.
// "Failed to get AAD token" is logged ROUTINELY during the device phase (no user
// token exists yet — field-confirmed: the line appears en masse in every enrollment,
// Oliver 2026-08-18). A failure is therefore only meaningful when NO token success
// follows: the failure is held pending, any IME-TOKEN-SUCCESS match clears it, and
// the Warning fires only after the grace window elapses without a success. Genuine
// auth outages (WAM broken, conditional access, network) run long enough to hit it.
// Not persisted across restarts — failures keep arriving, the window re-arms.
internal static readonly TimeSpan TokenFailureGraceWindow = TimeSpan.FromMinutes(30);
private sealed class PendingTokenFailure
{
public string Code = "unknown";
public string Excerpt = string.Empty;
public DateTime FirstFailureUtc;
}
private PendingTokenFailure _pendingTokenFailure;
// Dedup per distinct error code so a persistent outage yields one Warning total.
private readonly HashSet<string> _reportedTokenFailureCodes = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private void HandleImeTokenFailure(string errorCode, string message)
{
var code = string.IsNullOrEmpty(errorCode) ? "unknown" : errorCode.Trim();
if (!_reportedTokenFailureCodes.Add(code)) return;
if (_pendingTokenFailure != null) return; // earliest unresolved failure wins
var code = string.IsNullOrEmpty(errorCode) ? "unknown" : errorCode.Trim();
var excerpt = message ?? string.Empty;
if (excerpt.Length > 300) excerpt = excerpt.Substring(0, 300);
_logger.Warning($"ImeLogTracker: IME token acquisition failure (errorCode={code})");
OnImeTokenFailure?.Invoke(code, excerpt);
_pendingTokenFailure = new PendingTokenFailure
{
Code = code,
Excerpt = excerpt,
// Source-line time so a late-starting agent replaying an ongoing outage
// ages the window correctly; a success later in the same log still clears
// before the expiry check runs (lines are drained first, expiry after).
FirstFailureUtc = LastMatchedLogTimestamp ?? DateTime.UtcNow,
};
}
// Test seam: drives HandleImeTokenFailure without the regex pipeline.
private void ClearPendingTokenFailure()
{
if (_pendingTokenFailure == null) return;
_logger.Debug($"ImeLogTracker: token success observed — pending token failure (errorCode={_pendingTokenFailure.Code}) cleared");
_pendingTokenFailure = null;
}
/// <summary>Called once per poll cycle after the log drain (and testable directly).</summary>
internal void CheckPendingTokenFailure(DateTime nowUtc)
{
var pending = _pendingTokenFailure;
if (pending == null) return;
if (nowUtc - pending.FirstFailureUtc < TokenFailureGraceWindow) return;
_pendingTokenFailure = null; // next failure line re-arms a fresh window
if (!_reportedTokenFailureCodes.Add(pending.Code)) return;
_logger.Warning($"ImeLogTracker: IME token acquisition failing for >= {TokenFailureGraceWindow.TotalMinutes:0} min without a success (errorCode={pending.Code})");
OnImeTokenFailure?.Invoke(pending.Code, pending.Excerpt);
}
// Test seams: drive the pending/clear/expiry cycle without the regex pipeline.
internal void HandleImeTokenFailureForTest(string errorCode, string message)
=> HandleImeTokenFailure(errorCode, message);
internal void NoteTokenSuccessForTest() => ClearPendingTokenFailure();
private void HandleImeImpersonation(string user)
{
@@ -244,6 +244,14 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Enrollment.Ime
return;
}
// A token success resolves any pending token failure (grace-window model, see
// HandleImeTokenFailure). Matched on our own stable pattern ID — the line also
// drives espPhaseDetected, whose handler must stay unaware of token semantics.
// Placed after the staleness gate so a success replayed from a previous
// enrollment's log cannot clear a genuine current outage.
if (!isStaleReplayLine && string.Equals(pattern.PatternId, "IME-TOKEN-SUCCESS", StringComparison.OrdinalIgnoreCase))
ClearPendingTokenFailure();
try
{
var id = match.Groups["id"]?.Value;
@@ -607,6 +607,11 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Enrollment.Ime
// line never arrived within the grace period. Runs on this same loop
// thread (no locking) so it observes the buffer right after parsing.
FlushStalePlatformScriptResults(DateTime.UtcNow);
// Token-failure grace window: fires only when the failure stayed
// unresolved (no IME-TOKEN-SUCCESS) for the whole window. Runs after
// the drain so a success later in the same batch clears first.
CheckPendingTokenFailure(DateTime.UtcNow);
}
catch (OperationCanceledException) { break; }
catch (Exception ex)
@@ -119,9 +119,15 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Enrollment.SystemSignals
if (_last == null)
{
// Silent baseline — see class doc.
// Silent baseline for the DIFF stream — see class doc. But the baseline
// itself is valuable evidence: on WDP the DPP-policy apps install in
// Batch 1 BEFORE the agent (bootstrap = Batch 2), so their terminal
// states exist ONLY here. One capped summary event closes that
// pre-agent gap without any log backfill (Oliver, 2026-08-18).
_last = snapshot;
_logger?.Info($"RegistryAppState: baseline captured ({snapshot.Entries.Count} app entries, trigger={reason})");
if (snapshot.Entries.Count > 0)
EmitBaselineSummary(snapshot, nowUtc);
return;
}
@@ -181,6 +187,7 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Enrollment.SystemSignals
var entry = snapshot.GetOrAdd(userName, appId);
entry.ExitCode = TryReadInt(appKey.GetValue("ExitCode"));
entry.Intent = TryReadInt(appKey.GetValue("Intent"));
entry.LastUpdatedUtc = appKey.GetValue("LastUpdatedTimeUtc") as string;
using var esm = appKey.OpenSubKey("EnforcementStateMessage");
var json = esm?.GetValue("EnforcementStateMessage") as string;
@@ -452,6 +459,64 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Enrollment.SystemSignals
occurredAtUtc: nowUtc);
}
// Baseline entries in the summary's typed payload are capped — a long-lived device
// with many historical Win32Apps entries must not produce an oversized event.
internal const int MaxBaselineSummaryApps = 50;
private void EmitBaselineSummary(ImeRegistrySnapshot snapshot, DateTime nowUtc)
{
int success = 0, error = 0, inProgress = 0, other = 0;
var apps = new List<Dictionary<string, string>>();
foreach (var entry in snapshot.Entries.Values)
{
var cls = entry.EnforcementState is int es ? ClassifyEnforcementState(es) : null;
switch (cls)
{
case "success": success++; break;
case "error": error++; break;
case "inProgress": inProgress++; break;
default: other++; break;
}
if (apps.Count >= MaxBaselineSummaryApps) continue;
var app = new Dictionary<string, string>(StringComparer.Ordinal)
{
["appId"] = entry.AppId,
["userContext"] = entry.UserContext,
};
if (entry.EnforcementState is int state)
{
app["enforcementState"] = state.ToString(CultureInfo.InvariantCulture);
app["enforcementClass"] = ClassifyEnforcementState(state);
}
if (entry.ErrorCode is long ec) app["errorCode"] = ec.ToString(CultureInfo.InvariantCulture);
if (entry.ExitCode is int xc) app["exitCode"] = xc.ToString(CultureInfo.InvariantCulture);
if (!string.IsNullOrEmpty(entry.LastUpdatedUtc)) app["lastUpdatedUtc"] = entry.LastUpdatedUtc!;
if (entry.EspTracked) app["espTracked"] = "true";
apps.Add(app);
}
var data = new Dictionary<string, string>(StringComparer.Ordinal)
{
["totalApps"] = snapshot.Entries.Count.ToString(CultureInfo.InvariantCulture),
["successCount"] = success.ToString(CultureInfo.InvariantCulture),
["errorCount"] = error.ToString(CultureInfo.InvariantCulture),
["inProgressCount"] = inProgress.ToString(CultureInfo.InvariantCulture),
["otherCount"] = other.ToString(CultureInfo.InvariantCulture),
};
if (snapshot.Entries.Count > MaxBaselineSummaryApps)
data["appListTruncated"] = "true";
_post.Emit(
eventType: SharedEventTypes.RegistryAppBaseline,
source: SourceLabel,
message: $"Registry app baseline at agent start: {snapshot.Entries.Count} apps ({success} success, {error} error, {inProgress} in progress) — state that predates this agent run",
severity: EventSeverity.Info,
data: data,
occurredAtUtc: nowUtc,
typedPayload: new { apps });
}
private void TrackTerminalTransitions(ImeRegistrySnapshot snapshot, DateTime nowUtc)
{
foreach (var kv in snapshot.Entries)
@@ -552,6 +617,7 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Enrollment.SystemSignals
public string Key { get; }
public string UserContext { get; }
public string AppId { get; }
public string? LastUpdatedUtc { get; set; }
public int? EnforcementState { get; set; }
public long? ErrorCode { get; set; }
public int? ExitCode { get; set; }
+4 -4
View File
@@ -24,7 +24,7 @@
"@types/compression": "^1.8.1",
"@types/express": "^5.0.6",
"@types/node": "^22.20.1",
"tsx": "^4.23.11",
"tsx": "^4.23.12",
"typescript": "^5.0.0",
"vitest": "^4.1.10"
},
@@ -3823,9 +3823,9 @@
"optional": true
},
"node_modules/tsx": {
"version": "4.23.11",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.11.tgz",
"integrity": "sha512-Ry2oTEUnhBdeEdWIztY8kf3/nBGnPnjMLVGL0YfdRXMORuPER5NlKmayqxtxRxwB1xBN+RivRaJfe7PM1rtiyw==",
"version": "4.23.12",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.12.tgz",
"integrity": "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -32,7 +32,7 @@
"@types/compression": "^1.8.1",
"@types/express": "^5.0.6",
"@types/node": "^22.20.1",
"tsx": "^4.23.11",
"tsx": "^4.23.12",
"typescript": "^5.0.0",
"vitest": "^4.1.10"
},
@@ -148,6 +148,7 @@ export const EVENT_TYPES_CATALOG = {
'ime_agent_version',
'ime_token_failure',
'registry_app_state',
'registry_app_baseline',
'app_state_reconciliation',
'ime_user_session_completed',
'ime_session_change',
@@ -421,6 +421,7 @@ namespace AutopilotMonitor.Shared
// per-app state read straight from HKLM\...\IntuneManagementExtension. Observability only —
// never consumed by the DecisionEngine.
public const string RegistryAppState = "registry_app_state"; // Info, state-change-only (snapshot-diff vs silent startup baseline; capped 200/session, cap announced once as Warning): per-app EnforcementState/ErrorCode/ExitCode/StatusService status/ESP-tracking from the registry.
public const string RegistryAppBaseline = "registry_app_baseline"; // Info, one-shot at agent start (only when non-empty): summary of the Win32Apps state that PREDATES this agent run. Closes the WDP pre-agent gap — DPP-policy apps install in Batch 1 before the bootstrap-script agent exists, so their outcomes live only in this baseline (typed payload capped at 50 apps).
public const string AppStateReconciliation = "app_state_reconciliation"; // Warning, once per app, immediate upload: registry terminal outcome (settled >= 90 s) diverges from the IME-log-derived app state — the built-in log-pattern drift alarm (registry = truth, logs = narrative).
public const string ImeUserSessionCompleted = "ime_user_session_completed";
public const string DoTelemetry = "do_telemetry";
+64 -64
View File
@@ -13,25 +13,25 @@
"@microsoft/applicationinsights-web": "^3.4.3",
"@microsoft/signalr": "^10.0.11",
"@types/leaflet": "^1.9.22",
"@xyflow/react": "^12.11.2",
"@xyflow/react": "^12.11.3",
"dagre": "^0.8.5",
"fflate": "^0.8.3",
"leaflet": "^1.9.4",
"next": "^16.3.0",
"next": "^16.3.1",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-leaflet": "^5.0.0",
"recharts": "^2.15.4"
},
"devDependencies": {
"@next/bundle-analyzer": "^16.3.0",
"@next/bundle-analyzer": "^16.3.1",
"@types/dagre": "^0.7.54",
"@types/node": "^22.20.1",
"@types/react": "^19",
"@types/react-dom": "^19",
"autoprefixer": "^10.5.4",
"eslint": "^9.39.5",
"eslint-config-next": "^16.3.0",
"eslint-config-next": "^16.3.1",
"postcss": "^8.5.12",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.3",
@@ -1358,9 +1358,9 @@
"license": "MIT"
},
"node_modules/@next/bundle-analyzer": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-16.3.0.tgz",
"integrity": "sha512-o8OiXKIATcSC6kHm5BIEmaDEDTFUDhpy9POQIbzAQTlb8NWwFhEQheTLFSbyQXxH2ywhjZ/e8EUlbOjj2k22Yg==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-16.3.1.tgz",
"integrity": "sha512-/6XQeYPHM6jF1gTeJ82Mu6yXOHQIFVxzAn3DkPtHDp5v6SDXoCicBMTHloN+2h4WKFCQujSLCgLZHItJ3jN1uw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1368,15 +1368,15 @@
}
},
"node_modules/@next/env": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.0.tgz",
"integrity": "sha512-o9r1S0BNiNreHP9Vs+Qnqd9kviDkJh8xIACY7UFZSmiGbbQRzPBBosvHzAU4TULHOIuOj/18RSsyz2qrREmIFw==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.1.tgz",
"integrity": "sha512-35G3xwkQUb2oETSDjFXGrVugknoayLFBh7vSE+yAcl9IP2zT9wyGwq7297AYHR11kJld807t5f8AJBs6WBzXsQ==",
"license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.3.0.tgz",
"integrity": "sha512-OqgJ8PN0d04KcPhDX/PTY5tJUJZxlbrt7O7FBsm4XE0XW2JDrKnDXsc9uo9WUimJGPoo2j+JRGhyXApC//mvbw==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.3.1.tgz",
"integrity": "sha512-B4SznlXwVpaLDa7Tbi6zLuueria2d/PmFDhXyDymPGrk2r1n/RMJmcn5FZq1L64k+Jsyte1lKvOr7lP9Xo80mQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1385,9 +1385,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.0.tgz",
"integrity": "sha512-55hpqq18bEVAlxedlTt3tFqZmKg2nUXT1kn1G/BGEy0R13h3LwtwHPVzzjG6P4LLeOHE32PFDQUVaJEWvBEZBw==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.1.tgz",
"integrity": "sha512-ABMIu2zQ7cnNIHm5ivKGwZwUrm0pAai3yiJ/gK/rF1c1VP9UOnj7XECbMKFdVKp9I9eMYq9NoDs1WXOoowxzJw==",
"cpu": [
"arm64"
],
@@ -1401,9 +1401,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.0.tgz",
"integrity": "sha512-SOi96kSaF5T+0wW4koiM1bWzSPwjzTesC1p3df+FjdOi5LIQkBK/blxh7HdoKnNuI4PURF1OO7TZqtfnbWDSgw==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.1.tgz",
"integrity": "sha512-gNG21e/UnrroeScbY/QndUEdl0mF1FRibW7BBeYUz/5ABCepjqDdEdgr592vpzMtCn/m7FTjYq3TN4TpyDnutw==",
"cpu": [
"x64"
],
@@ -1417,9 +1417,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.0.tgz",
"integrity": "sha512-P0gZAoPMF4dyTRzhmkV4PrqVzSOB6t4mC1oI3c4dqijJ+OVEVx5clIXAKR4/uQpsqw2KKM/0D5tVumcR2r5blg==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.1.tgz",
"integrity": "sha512-6B6Lw016iwNUQuaJoraMMTLh6TwHzFUtxipSScD1F3YyymcrRWkobodRS2ftIOkF5vrs4zNlyUrTC5YZQ9Lz5w==",
"cpu": [
"arm64"
],
@@ -1436,9 +1436,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.0.tgz",
"integrity": "sha512-tXXGKJw0m37O0eKJARVTX/TheKPhz0QFVtVVZXmOig+9YKLQOSP6hvf2pxv5DO7CLEJyTHx3Pg043CDQkv1G4Q==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.1.tgz",
"integrity": "sha512-JUiPXZKK9wOhjf4MgDiH29GZLxfqOesbLtHq2pDxwH/WwscTRV2ToymnOTh1egzaZf0ueUf8T2+CeYTGHjW0Iw==",
"cpu": [
"arm64"
],
@@ -1455,9 +1455,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.0.tgz",
"integrity": "sha512-pjGxK5EY7yWml78ALejFkWmgHsU7wbFQrISiugpH6FbUJhgEvw3xFZ/EBAtLl7QtL0WdQKiG9eWJ3mOKGTukHw==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.1.tgz",
"integrity": "sha512-Uog9jsrmIRIL/lfvIp9htmskSNC7JcQsMVucXL2V2YY1y/D9IUN3LPEafqy0zRJ2cIU1SQ0V6F6TlffQ+pLAGg==",
"cpu": [
"x64"
],
@@ -1474,9 +1474,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.0.tgz",
"integrity": "sha512-sjo++Xx+lomlPs3HRsHWhVDyGG6ms1kGW5EtHLERdII8AyG1i+f6aq68xHREO6AEMlhjTNEWBSmfJfqm9orf7g==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.1.tgz",
"integrity": "sha512-6yy3FT13KgUFOj5H8bl8w/6nKiJwHIvbtwh1V+1acsu+7y4tJjnemSa6mhsh53BeoVrlozE+fMgZhXH46WmjMA==",
"cpu": [
"x64"
],
@@ -1493,9 +1493,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.0.tgz",
"integrity": "sha512-C5JSgiO54wURdaxdEUIXqkz04uMqC9UmPX1gtDrV/5Tf1UowdWYI8uA5hfFbPolTlp0q4KZ60xlHePNibf0VIw==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.1.tgz",
"integrity": "sha512-iOoN1QecUoGNZik536U/vtK43YwgyrCsGIkth52yIkl612n+0C9MjSnJbQAikISpb+WYRooBVhaDlUW7iZoKog==",
"cpu": [
"arm64"
],
@@ -1890,9 +1890,9 @@
"license": "MIT"
},
"node_modules/@swc/helpers": {
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
"integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
"version": "0.5.23",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz",
"integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.8.0"
@@ -2762,12 +2762,12 @@
}
},
"node_modules/@xyflow/react": {
"version": "12.11.2",
"resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.11.2.tgz",
"integrity": "sha512-eLAlDWJfWnQEhJwGMjlWdAXO9eYllKpliUmPQlAmOLxz6mExXuzMVDUKLMquixgkrtmMFFtug3jGKmYYld12cA==",
"version": "12.11.3",
"resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.11.3.tgz",
"integrity": "sha512-G3jogHz2GWUtIOkhavUGno2YzY9u6fILIJBttfsBendb0/HWB90JG+sOTAvlIMEwyvq9zgy9V9ZQSwyQjR5QzQ==",
"license": "MIT",
"dependencies": {
"@xyflow/system": "0.0.79",
"@xyflow/system": "0.0.80",
"classcat": "^5.0.3",
"zustand": "^4.4.0"
},
@@ -2787,9 +2787,9 @@
}
},
"node_modules/@xyflow/system": {
"version": "0.0.79",
"resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.79.tgz",
"integrity": "sha512-czLyOh91NF0hIzbNzwi8I6GlqG23BHh2435OddfI6uiaLH3xdrdygO93gqgH1Bv9mhy8XPFQJOBn1FTq4LvEWA==",
"version": "0.0.80",
"resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.80.tgz",
"integrity": "sha512-ywc3ZqG91brzWrH1WlwMdIX4goOfrpBy6AbLdVSaof/Xx9l138ijIKRExM6EkMro2F+OImGmSiA/WKcXvKVcfA==",
"license": "MIT",
"dependencies": {
"@types/d3-drag": "^3.0.7",
@@ -4216,13 +4216,13 @@
}
},
"node_modules/eslint-config-next": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.3.0.tgz",
"integrity": "sha512-lPrf1kHsMJEZqO0uXkNB400c5MGrhrTk3BNX7P0ol4gt61+iUlQfjy9TyIOEA9eOXrf+5+mYbT/JsY8+zqUByQ==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.3.1.tgz",
"integrity": "sha512-0vtrpwFVHFEkycUgV/DyrG29OS+HSRdah5Yu8YuZoiBMtlAT6NIiWzaLwDkJZxr2kGfx+9LIvfQ7KHAlEs0VsA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@next/eslint-plugin-next": "16.3.0",
"@next/eslint-plugin-next": "16.3.1",
"eslint-import-resolver-node": "^0.3.6",
"eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-import": "^2.32.0",
@@ -6308,13 +6308,13 @@
"license": "MIT"
},
"node_modules/next": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/next/-/next-16.3.0.tgz",
"integrity": "sha512-NEdGOzH+08eTXMUp9UYkA99Nhi5N6Thrhc1jgFOQgfgnGK/dA2hRwBpXep+exdFQrnwlRf/3Wixyp8lLBUpE2A==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/next/-/next-16.3.1.tgz",
"integrity": "sha512-hsAp0i7Rh+/dhe7DGIeN2YlpLM1DP4MNxti9EtDMtqcO612X81MvvEj388/oTce9U1EcEIOWDlGq0zRwrBKvuA==",
"license": "MIT",
"dependencies": {
"@next/env": "16.3.0",
"@swc/helpers": "0.5.15",
"@next/env": "16.3.1",
"@swc/helpers": "0.5.23",
"baseline-browser-mapping": "^2.9.19",
"caniuse-lite": "^1.0.30001579",
"postcss": "8.5.23",
@@ -6327,14 +6327,14 @@
"node": ">=20.9.0"
},
"optionalDependencies": {
"@next/swc-darwin-arm64": "16.3.0",
"@next/swc-darwin-x64": "16.3.0",
"@next/swc-linux-arm64-gnu": "16.3.0",
"@next/swc-linux-arm64-musl": "16.3.0",
"@next/swc-linux-x64-gnu": "16.3.0",
"@next/swc-linux-x64-musl": "16.3.0",
"@next/swc-win32-arm64-msvc": "16.3.0",
"@next/swc-win32-x64-msvc": "16.3.0",
"@next/swc-darwin-arm64": "16.3.1",
"@next/swc-darwin-x64": "16.3.1",
"@next/swc-linux-arm64-gnu": "16.3.1",
"@next/swc-linux-arm64-musl": "16.3.1",
"@next/swc-linux-x64-gnu": "16.3.1",
"@next/swc-linux-x64-musl": "16.3.1",
"@next/swc-win32-arm64-msvc": "16.3.1",
"@next/swc-win32-x64-msvc": "16.3.1",
"sharp": "^0.35.3"
},
"peerDependencies": {
@@ -6361,9 +6361,9 @@
}
},
"node_modules/next/node_modules/@next/swc-win32-x64-msvc": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.0.tgz",
"integrity": "sha512-fDOggsweNb5SSw0ZKVk6U+gxSyGFFlIBY/LBc1r8GUj4u/6t6oArL+Pmkg0MBnsgR+KkdsURilVH4F3GXUGepA==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.1.tgz",
"integrity": "sha512-d/k+PpAriUPaeMJJOG7HUSdqfEX46FEPWU1p3/nm2ACmXhj9hFEWdFODUBIpkuijXYkfL90qZzTqVPRp4BW/hw==",
"cpu": [
"x64"
],
+4 -4
View File
@@ -20,25 +20,25 @@
"@microsoft/applicationinsights-web": "^3.4.3",
"@microsoft/signalr": "^10.0.11",
"@types/leaflet": "^1.9.22",
"@xyflow/react": "^12.11.2",
"@xyflow/react": "^12.11.3",
"dagre": "^0.8.5",
"fflate": "^0.8.3",
"leaflet": "^1.9.4",
"next": "^16.3.0",
"next": "^16.3.1",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-leaflet": "^5.0.0",
"recharts": "^2.15.4"
},
"devDependencies": {
"@next/bundle-analyzer": "^16.3.0",
"@next/bundle-analyzer": "^16.3.1",
"@types/dagre": "^0.7.54",
"@types/node": "^22.20.1",
"@types/react": "^19",
"@types/react-dom": "^19",
"autoprefixer": "^10.5.4",
"eslint": "^9.39.5",
"eslint-config-next": "^16.3.0",
"eslint-config-next": "^16.3.1",
"postcss": "^8.5.12",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.3",
@@ -604,6 +604,7 @@ export const SHARED_MANIFEST = {
"realmjoin_resolved",
"realmjoin_timeout",
"reboot_triggered",
"registry_app_baseline",
"registry_app_state",
"remote_config_fetch_failed",
"script_completed",
@@ -600,6 +600,7 @@
"realmjoin_resolved",
"realmjoin_timeout",
"reboot_triggered",
"registry_app_baseline",
"registry_app_state",
"remote_config_fetch_failed",
"script_completed",