From 186a2c6ea22589ca28f655eba01526ceb74ec2d9 Mon Sep 17 00:00:00 2001
From: Zacgoose <107489668+Zacgoose@users.noreply.github.com>
Date: Fri, 15 May 2026 02:29:31 -0500
Subject: [PATCH 1/5] audit log template tweak
---
src/data/AuditLogTemplates.json | 2 +-
src/layouts/config.js | 7 +
src/pages/cipp/advanced/worker-health.js | 442 +++++++++++++++++++++++
3 files changed, 450 insertions(+), 1 deletion(-)
create mode 100644 src/pages/cipp/advanced/worker-health.js
diff --git a/src/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json
index 1762fb2eb7bb..63df852bd318 100644
--- a/src/data/AuditLogTemplates.json
+++ b/src/data/AuditLogTemplates.json
@@ -450,7 +450,7 @@
{
"Property": { "value": "String", "label": "SecuredAccessPassData" },
"Operator": { "value": "like", "label": "Like" },
- "Input": { "value": "*" }
+ "Input": { "value": "[*]" }
}
]
}
diff --git a/src/layouts/config.js b/src/layouts/config.js
index a9df0957241d..987ab9d8f984 100644
--- a/src/layouts/config.js
+++ b/src/layouts/config.js
@@ -1116,6 +1116,13 @@ export const nativeMenuItems = [
permissions: ['CIPP.SuperAdmin.*'],
scope: 'global',
},
+ {
+ title: 'Worker Health',
+ path: '/cipp/advanced/worker-health',
+ roles: ['superadmin'],
+ permissions: ['CIPP.SuperAdmin.*'],
+ scope: 'global',
+ },
],
},
],
diff --git a/src/pages/cipp/advanced/worker-health.js b/src/pages/cipp/advanced/worker-health.js
new file mode 100644
index 000000000000..fd23de33c031
--- /dev/null
+++ b/src/pages/cipp/advanced/worker-health.js
@@ -0,0 +1,442 @@
+import { useMemo } from "react";
+import Head from "next/head";
+import {
+ Box,
+ Button,
+ Card,
+ CardContent,
+ CardHeader,
+ Chip,
+ CircularProgress,
+ Container,
+ LinearProgress,
+ Stack,
+ Table,
+ TableBody,
+ TableCell,
+ TableContainer,
+ TableHead,
+ TableRow,
+ Typography,
+} from "@mui/material";
+import {
+ Memory,
+ Speed,
+ PlayArrow,
+ HourglassEmpty,
+ CheckCircle,
+ Warning,
+ Cancel,
+ Delete,
+ LowPriority,
+ DeleteSweep,
+} from "@mui/icons-material";
+import { Grid } from "@mui/system";
+import { Layout as DashboardLayout } from "../../../layouts/index.js";
+import { CippInfoBar } from "../../../components/CippCards/CippInfoBar";
+import { CippPropertyListCard } from "../../../components/CippCards/CippPropertyListCard";
+import { CippDataTable } from "../../../components/CippTable/CippDataTable";
+import { ApiGetCall, ApiPostCall } from "../../../api/ApiCall";
+
+const formatDuration = (ms) => {
+ if (ms === 0 || ms == null) return "—";
+ if (ms < 1000) return `${ms}ms`;
+ if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
+ return `${(ms / 60000).toFixed(1)}m`;
+};
+
+const formatUptime = (seconds) => {
+ if (!seconds) return "—";
+ const h = Math.floor(seconds / 3600);
+ const m = Math.floor((seconds % 3600) / 60);
+ if (h > 0) return `${h}h ${m}m`;
+ return `${m}m`;
+};
+
+const WorkerStatusChip = ({ isBusy, currentFunction }) => {
+ if (isBusy) {
+ return (
+ }
+ sx={{ maxWidth: 200 }}
+ />
+ );
+ }
+ return } />;
+};
+
+const UtilizationBar = ({ value }) => (
+
+
+ 80 ? "error" : value > 50 ? "warning" : "primary"}
+ sx={{ height: 8, borderRadius: 4 }}
+ />
+
+
+ {value}%
+
+
+);
+
+const WorkerTable = ({ workers, title }) => {
+ if (!workers || workers.length === 0) return null;
+
+ return (
+
+
+
+
+
+
+
+ Worker
+ Status
+ Invocations
+ Utilization
+ Avg
+ Min
+ Max
+ Last
+ Faults
+
+
+
+ {workers.map((w) => (
+
+
+
+ W{w.WorkerId}
+
+
+
+
+
+ {w.TotalInvocations?.toLocaleString() ?? 0}
+
+
+
+ {formatDuration(w.AvgDurationMs)}
+ {formatDuration(w.MinDurationMs)}
+ {formatDuration(w.MaxDurationMs)}
+ {formatDuration(w.LastDurationMs)}
+
+ {w.TotalFaults > 0 ? (
+
+ ) : (
+ "0"
+ )}
+
+
+ ))}
+
+
+
+
+
+ );
+};
+
+const Page = () => {
+ const healthQuery = ApiGetCall({
+ url: "/api/ListWorkerHealth",
+ data: { Action: "Snapshot" },
+ queryKey: "WorkerHealth",
+ refetchInterval: 5000,
+ });
+
+ const jobAction = ApiPostCall({
+ relatedQueryKeys: ["WorkerHealthJobs", "WorkerHealth"],
+ });
+
+ const snapshot = healthQuery.data?.Results;
+
+ const infoBarData = useMemo(() => {
+ if (!snapshot) return [];
+ const http = snapshot.HttpPool || {};
+ const bg = snapshot.BgPool || {};
+ const jobs = snapshot.Jobs || {};
+ const limiter = snapshot.Limiter || {};
+
+ return [
+ {
+ icon: ,
+ name: "HTTP Workers",
+ data: `${http.BusyCount ?? 0} / ${http.PoolSize ?? 0} busy`,
+ color: http.BusyCount >= http.PoolSize ? "error" : "primary",
+ },
+ {
+ icon: ,
+ name: "BG Workers",
+ data: `${bg.BusyCount ?? 0} / ${bg.PoolSize ?? 0} busy`,
+ color: bg.BusyCount >= bg.PoolSize ? "error" : "primary",
+ },
+ {
+ icon: jobs.Running > 0 ? : ,
+ name: "Job Queue",
+ data: `${jobs.Running ?? 0} running, ${jobs.Queued ?? 0} queued`,
+ color: jobs.Queued > 10 ? "warning" : "primary",
+ },
+ {
+ icon: limiter.IsHttpThrottled ? : ,
+ name: "BG Limiter",
+ data: limiter.IsHttpThrottled
+ ? "HTTP Throttled"
+ : `${limiter.Active ?? 0} / ${limiter.CurrentMax ?? 0} active`,
+ color: limiter.IsHttpThrottled ? "error" : "primary",
+ },
+ ];
+ }, [snapshot]);
+
+ const httpPoolItems = useMemo(() => {
+ if (!snapshot?.HttpPool) return [];
+ const p = snapshot.HttpPool;
+ return [
+ { label: "Pool Size", value: p.PoolSize },
+ { label: "Available", value: p.Available },
+ { label: "Busy", value: p.BusyCount },
+ { label: "Total Invocations", value: p.TotalInvocations?.toLocaleString() ?? 0 },
+ { label: "Total Busy Time", value: formatDuration(p.TotalBusyMs) },
+ { label: "Avg Utilization", value: `${p.AvgUtilizationPct ?? 0}%` },
+ { label: "Avg Duration", value: formatDuration(p.AvgDurationMs) },
+ { label: "Total Faults", value: p.TotalFaults ?? 0 },
+ ];
+ }, [snapshot]);
+
+ const bgPoolItems = useMemo(() => {
+ if (!snapshot?.BgPool) return [];
+ const p = snapshot.BgPool;
+ return [
+ { label: "Pool Size", value: p.PoolSize },
+ { label: "Available", value: p.Available },
+ { label: "Busy", value: p.BusyCount },
+ { label: "Total Invocations", value: p.TotalInvocations?.toLocaleString() ?? 0 },
+ { label: "Total Busy Time", value: formatDuration(p.TotalBusyMs) },
+ { label: "Avg Utilization", value: `${p.AvgUtilizationPct ?? 0}%` },
+ { label: "Avg Duration", value: formatDuration(p.AvgDurationMs) },
+ { label: "Total Faults", value: p.TotalFaults ?? 0 },
+ ];
+ }, [snapshot]);
+
+ const limiterItems = useMemo(() => {
+ if (!snapshot?.Limiter) return [];
+ const l = snapshot.Limiter;
+ return [
+ { label: "Base Concurrency", value: l.BaseConcurrency },
+ { label: "Ceiling Concurrency", value: l.CeilingConcurrency },
+ { label: "Current Max", value: l.CurrentMax },
+ { label: "Active", value: l.Active },
+ { label: "Waiting", value: l.Waiting },
+ {
+ label: "HTTP Throttled",
+ value: l.IsHttpThrottled ? "Yes" : "No",
+ },
+ ];
+ }, [snapshot]);
+
+ const jobItems = useMemo(() => {
+ if (!snapshot?.Jobs) return [];
+ const j = snapshot.Jobs;
+ return [
+ { label: "Running", value: j.Running },
+ { label: "Queued", value: j.Queued },
+ { label: "Completed", value: j.Completed?.toLocaleString() ?? 0 },
+ { label: "Failed", value: j.Failed },
+ { label: "Total Processed", value: j.TotalProcessed?.toLocaleString() ?? 0 },
+ { label: "Max Concurrency", value: j.MaxConcurrency },
+ { label: "Active Concurrency", value: j.ActiveConcurrency },
+ ];
+ }, [snapshot]);
+
+ const jobSimpleColumns = ["Name", "RunName", "Priority", "Status", "WaitSeconds", "DurationSeconds"];
+
+ const jobActions = useMemo(
+ () => [
+ {
+ label: "Cancel Job",
+ icon: ,
+ color: "error.main",
+ noConfirm: true,
+ customFunction: (row) => {
+ jobAction.mutate({
+ url: "/api/ListWorkerHealth",
+ data: { Action: "CancelJob", JobId: row.Id },
+ });
+ },
+ condition: (row) => row.Status === "Queued",
+ },
+ {
+ label: "Change Priority",
+ icon: ,
+ fields: [
+ {
+ type: "textField",
+ name: "Priority",
+ label: "New Priority (0 = highest)",
+ },
+ ],
+ url: "/api/ListWorkerHealth",
+ data: { Action: "ChangePriority" },
+ dataFunction: (row, formData) => ({
+ Action: "ChangePriority",
+ JobId: row.Id,
+ Priority: parseInt(formData.Priority, 10),
+ }),
+ confirmText: "Change",
+ condition: (row) => row.Status === "Queued",
+ relatedQueryKeys: ["WorkerHealthJobs", "WorkerHealth"],
+ },
+ {
+ label: "Cancel Run",
+ icon: ,
+ color: "error.main",
+ noConfirm: true,
+ customFunction: (row) => {
+ if (row.RunName) {
+ jobAction.mutate({
+ url: "/api/ListWorkerHealth",
+ data: { Action: "CancelRun", RunName: row.RunName },
+ });
+ }
+ },
+ condition: (row) => row.Status === "Queued" && row.RunName,
+ },
+ {
+ label: "Delete",
+ icon: ,
+ noConfirm: true,
+ customFunction: (row) => {
+ jobAction.mutate({
+ url: "/api/ListWorkerHealth",
+ data: { Action: "DeleteJob", JobId: row.Id },
+ });
+ },
+ condition: (row) => row.Status !== "Queued" && row.Status !== "Running",
+ },
+ ],
+ [jobAction]
+ );
+
+ const jobFilters = useMemo(
+ () => [
+ {
+ filterName: "Queued",
+ value: [{ id: "Status", value: "Queued" }],
+ },
+ {
+ filterName: "Running",
+ value: [{ id: "Status", value: "Running" }],
+ },
+ {
+ filterName: "Failed",
+ value: [{ id: "Status", value: "Failed" }],
+ },
+ ],
+ []
+ );
+
+ return (
+ <>
+
+ Worker Health | CIPP
+
+
+
+
+
+ Worker Health
+
+ {healthQuery.isFetching && }
+ {snapshot && (
+
+ Uptime: {formatUptime(snapshot.UptimeSeconds)} | Auto-refreshing every 5s
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ color="warning"
+ onClick={() =>
+ jobAction.mutate({
+ url: "/api/ListWorkerHealth",
+ data: { Action: "PurgeCompleted" },
+ })
+ }
+ >
+ Purge Completed
+
+ }
+ />
+
+
+
+ >
+ );
+};
+
+Page.getLayout = (page) => {page};
+
+export default Page;
From 9d5ce40275098a4a442d247fe42541958d08ba88 Mon Sep 17 00:00:00 2001
From: Zacgoose <107489668+Zacgoose@users.noreply.github.com>
Date: Mon, 18 May 2026 07:27:51 -0400
Subject: [PATCH 2/5] Org auto expanding archive property usage
---
src/components/CippCards/CippExchangeInfoCard.jsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/components/CippCards/CippExchangeInfoCard.jsx b/src/components/CippCards/CippExchangeInfoCard.jsx
index 6a00f53c0248..8bb2737f76c3 100644
--- a/src/components/CippCards/CippExchangeInfoCard.jsx
+++ b/src/components/CippCards/CippExchangeInfoCard.jsx
@@ -247,7 +247,9 @@ export const CippExchangeInfoCard = (props) => {
<>
- Auto Expanding Archive:
+ {exchangeData?.AutoExpandingArchiveScope === 'Organization'
+ ? 'Auto Expanding Archive: (org)'
+ : 'Auto Expanding Archive:'}
{getCippFormatting(
From 6db7e7760fc02807df809897fcda40b48a8b365b Mon Sep 17 00:00:00 2001
From: Zacgoose <107489668+Zacgoose@users.noreply.github.com>
Date: Mon, 18 May 2026 14:37:01 -0400
Subject: [PATCH 3/5] Delete .claude directory
Signed-off-by: Zacgoose <107489668+Zacgoose@users.noreply.github.com>
---
.claude/worktrees/blissful-golick-d405ab | 1 -
1 file changed, 1 deletion(-)
delete mode 160000 .claude/worktrees/blissful-golick-d405ab
diff --git a/.claude/worktrees/blissful-golick-d405ab b/.claude/worktrees/blissful-golick-d405ab
deleted file mode 160000
index 0710355e2ada..000000000000
--- a/.claude/worktrees/blissful-golick-d405ab
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 0710355e2adac37fffe4c7eef48d6f2c3a04993d
From 1e7aef11995feb42e9872ec4aefac39fc7ba67c5 Mon Sep 17 00:00:00 2001
From: Zacgoose <107489668+Zacgoose@users.noreply.github.com>
Date: Tue, 19 May 2026 08:19:29 -0400
Subject: [PATCH 4/5] Update alerts.json
---
src/data/alerts.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/data/alerts.json b/src/data/alerts.json
index 9bce965852ab..ac8a28fa6cc0 100644
--- a/src/data/alerts.json
+++ b/src/data/alerts.json
@@ -125,7 +125,7 @@
"inputType": "textField",
"inputLabel": "Enter quota percentage",
"inputName": "QuotaUsedQuota",
- "recommendedRunInterval": "4h"
+ "recommendedRunInterval": "1d"
},
{
"name": "SharePointQuota",
@@ -134,7 +134,7 @@
"inputType": "textField",
"inputLabel": "Enter quota percentage",
"inputName": "SharePointQuota",
- "recommendedRunInterval": "4h"
+ "recommendedRunInterval": "1d"
},
{
"name": "OneDriveQuota",
@@ -143,7 +143,7 @@
"inputType": "textField",
"inputLabel": "Enter quota percentage (default: 90)",
"inputName": "OneDriveQuota",
- "recommendedRunInterval": "4h"
+ "recommendedRunInterval": "1d"
},
{
"name": "ExpiringLicenses",
From fc246a54ee6c1720f9d442f4cf22568b53add85d Mon Sep 17 00:00:00 2001
From: Zacgoose <107489668+Zacgoose@users.noreply.github.com>
Date: Tue, 19 May 2026 10:02:02 -0400
Subject: [PATCH 5/5] update default value for standard
---
src/data/standards.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/data/standards.json b/src/data/standards.json
index 4c61c04cf250..16a6406db1fa 100644
--- a/src/data/standards.json
+++ b/src/data/standards.json
@@ -4100,7 +4100,7 @@
"type": "number",
"name": "standards.IntuneComplianceSettings.deviceComplianceCheckinThresholdDays",
"label": "Compliance status validity period (days)",
- "defaultValue": 130,
+ "defaultValue": 120,
"validators": {
"min": { "value": 1, "message": "Minimum value is 1" },
"max": { "value": 120, "message": "Maximum value is 120" }