This commit is contained in:
2026-06-25 20:57:09 -05:00
parent 552b86c323
commit e47d09d7d6
35 changed files with 4507 additions and 101 deletions

View File

@@ -32,6 +32,8 @@ The current UI is a Vue/Vite view layer over the Express API. All create/update/
- Host Library with searchable/sortable/paginated table, modal add/edit flow, VMware vCenter VM import wizard, standalone ESXi connection records, and manual/dynamic Host Groups for RunPlan and script-test targeting.
- Credential Vault as its own menu item with encrypted-at-rest secrets and modal add/edit flow.
- RunPlan Library with searchable/sortable/paginated table, modal composer, and execute action.
- Scheduling workspace for automated RunPlan execution with one-time, interval, daily, weekly, monthly, and yearly cadences plus calendar, Gantt-style timeline, and datatable views.
- Job Output workspace for RunPlans and Script Test / Run jobs, grouping generated STDOUT PDF, datatable JSON, and terminal transcript artifacts by job.
- Admin System Jobs console for background worker run-now actions, stuck execution cancellation, and audited job-management history.
- Aggregate job log viewer with search/filter/pagination.
- System log tab for Winston request/application logs.
@@ -90,6 +92,8 @@ Dashboard widgets are intentionally split:
Script authoring helpers are split under `client/src/components/scripts`. `VariableEditorModal.vue` owns the PSADT/POSHManager variable catalog browser and custom variable editor so future PSADT snippets, Intune deployment helpers, and variable packs can be added without bloating `App.vue`.
Scheduling is implemented as its own view in `client/src/views/SchedulingView.vue` and API domain modules under `server/routes/runPlanScheduleRoutes.js`, `server/controllers/runPlanScheduleController.js`, `server/models/runPlanScheduleModel.js`, and `server/services/runPlanScheduleWorker.js`. The Vue view renders calendar, timeline, and datatable projections; recurrence calculation, dispatch, and history remain backend-owned.
## Quick Start
```bash
@@ -157,7 +161,7 @@ Important environment variables:
| `DEFAULT_ADMIN_EMAIL` | First-run admin email. |
| `DEFAULT_ADMIN_PASSWORD` | First-run admin password. |
| `DEFAULT_ADMIN_NAME` | First-run admin display name. |
| `POWERSHELL_BIN` | PowerShell executable. Defaults to `pwsh`. |
| `POWERSHELL_BIN` | Initial/default PowerShell executable. Defaults to `pwsh`; admins can override the live runtime value with Config -> Application Config -> Execution -> PowerShell Binary. |
| `ALLOW_SCRIPT_EXECUTION` | Set `false` to disable actual RunPlan execution. |
| `VCENTER_ENABLED` | Enables VMware vCenter VM discovery and Host import workflows. |
| `VCENTER_BASE_URL` | vCenter REST API root, for example `https://vcenter.contoso.local`. |
@@ -167,6 +171,7 @@ Important environment variables:
| `VCENTER_REQUEST_TIMEOUT_MS` | Per-request vCenter HTTP timeout. Defaults to `20000`. |
| `VCENTER_ALLOW_UNTRUSTED_TLS` | Set `true` to allow self-signed/private CA vCenter certificates. |
| `HOST_GROUP_SYNC_INTERVAL_MINUTES` | Minutes between dynamic Host Group rule syncs. Defaults to `60`; set `0` to disable the worker. |
| `RUNPLAN_SCHEDULE_INTERVAL_MINUTES` | Minutes between automated RunPlan schedule dispatch scans. Defaults to `1`; set `0` to disable the scheduler. |
| `CATALOG_CHECK_INTERVAL_MINUTES` | Minutes between catalog upstream-version checks. `0` disables. |
| `AUTO_PROMOTE_INTERVAL_MINUTES` | Minutes between auto-promote soak checks. `0` disables. |
| `TOOLS_DIR` | Directory for bundled tools. Defaults to `./tools`. |
@@ -1170,10 +1175,23 @@ with per-host log rows.
| `PUT` | `/api/runplans/:id` | User | Update RunPlan. |
| `DELETE` | `/api/runplans/:id` | User | Delete RunPlan. |
| `POST` | `/api/runplans/:id/execute` | User | Queue/execute a RunPlan. |
| `GET` | `/api/schedules` | User | List visible RunPlan schedules plus recent schedule dispatch history. |
| `POST` | `/api/schedules` | User | Create an automated RunPlan schedule. |
| `POST` | `/api/schedules/preview` | User | Preview upcoming occurrences for a schedule payload. |
| `PUT` | `/api/schedules/:id` | User | Update a saved schedule. |
| `DELETE` | `/api/schedules/:id` | User | Delete a saved schedule. |
| `POST` | `/api/schedules/:id/toggle` | User | Enable or pause a saved schedule. |
| `POST` | `/api/schedules/:id/run-now` | User | Queue the schedule's RunPlan immediately and record schedule history. |
| `GET` | `/api/jobs` | User | List jobs. |
| `GET` | `/api/jobs/:id` | User | Read job with logs. |
| `GET` | `/api/job-output` | User | List generated job output artifacts visible to the operator. |
| `GET` | `/api/job-output/jobs/:jobId` | User | List generated artifacts for one visible job. |
| `POST` | `/api/job-output/jobs/:jobId/generate` | User | Regenerate FileLocker artifacts for a completed/failed/canceled job. |
| `GET` | `/api/job-output/:id/content` | User | Read table JSON or terminal text through a JSON wrapper for UI/API clients. |
| `GET` | `/api/job-output/:id/view` | User | Inline-view the stored artifact file. |
| `GET` | `/api/job-output/:id/download` | User | Download the stored artifact file. |
| `GET` | `/api/system-jobs` | Admin | List running/queued execution jobs, controllable background workers, and recent job-management audit actions. |
| `POST` | `/api/system-jobs/:jobId/run` | Admin | Run a supported background worker now, such as dynamic Host Group sync, catalog auto-check, or Intune auto-promotion. |
| `POST` | `/api/system-jobs/:jobId/run` | Admin | Run a supported background worker now, such as dynamic Host Group sync, RunPlan schedule dispatch, catalog auto-check, or Intune auto-promotion. |
| `POST` | `/api/system-jobs/:jobId/cancel` | Admin | Cancel a queued/running script execution job, signal active PowerShell child processes, and audit the action. |
RunPlan payload:
@@ -1206,6 +1224,42 @@ curl -X POST http://localhost:3000/api/runplans/rp_123/execute \
-d '{}'
```
Scheduling:
```bash
curl http://localhost:3000/api/schedules \
-H "Authorization: Bearer $TOKEN"
curl -X POST http://localhost:3000/api/schedules \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name":"Engineering patch validation",
"runplanId":"run_123",
"scheduleType":"weekly",
"startAt":"2026-06-29T14:00:00.000Z",
"timeOfDay":"09:00",
"daysOfWeek":[1,3],
"enabled":true,
"visibility":"shared"
}'
curl -X POST http://localhost:3000/api/schedules/sched_123/run-now \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{}'
```
Schedules support `once`, `interval`, `daily`, `weekly`, `monthly`, and
`yearly` recurrence. Interval schedules use `intervalValue` plus
`intervalUnit` (`minutes`, `hours`, `days`, `months`, or `years`). Weekly
schedules use `daysOfWeek` with `0` = Sunday through `6` = Saturday. Monthly
and yearly schedules can pin `dayOfMonth`; yearly schedules can also set
`monthOfYear`. The backend stores `nextRunAt`, updates it after each dispatch,
and records rows in `runplan_schedule_runs`. The API worker scans every
`runplan_schedule_interval_minutes` minutes and can be triggered manually from
System Jobs with `worker:runplan-schedule-dispatch`.
Linux compatibility preflight:
```bash
@@ -1226,6 +1280,34 @@ Windows-specific environment variables, and alias-heavy script style. RunPlan
execution and Script Test / Run also write the same warning summary into
per-host job logs for Linux targets.
Job Output artifacts:
```bash
curl http://localhost:3000/api/job-output \
-H "Authorization: Bearer $TOKEN"
curl -X POST http://localhost:3000/api/job-output/jobs/job_123/generate \
-H "Authorization: Bearer $TOKEN"
curl http://localhost:3000/api/job-output/jout_123/content \
-H "Authorization: Bearer $TOKEN"
```
When a RunPlan, scheduled RunPlan, or Script Test / Run reaches a terminal state, the API writes
generated output artifacts to `FileLocker/job-output/<jobId>/` and records them
in SQLite. The generated set includes a combined PDF containing only `STDOUT`
grouped by host, a parsed datatable JSON file, and a terminal transcript text
file with all streams. The datatable parser treats hosts as the row axis. It
prefers structured output in this order: JSON/JSON-lines, CSV/TSV/pipe-delimited
text, PowerShell table output, and PowerShell `Name : Value` object output.
When STDOUT is plain text instead of a table/object/array, the datatable keeps
one row per host and uses only that host's last non-empty STDOUT line. Job
Output artifacts use the
same visibility rules as jobs and logs. The Job Output UI groups the three
artifact types into one row per job; operators choose PDF, datatable, or
terminal transcript from the row-level artifact selector before opening a
preview in a separate browser window or downloading.
Admin System Jobs console:
```bash
@@ -1235,6 +1317,9 @@ curl http://localhost:3000/api/system-jobs \
curl -X POST http://localhost:3000/api/system-jobs/worker%3Ahost-group-sync/run \
-H "Authorization: Bearer $TOKEN"
curl -X POST http://localhost:3000/api/system-jobs/worker%3Arunplan-schedule-dispatch/run \
-H "Authorization: Bearer $TOKEN"
curl -X POST http://localhost:3000/api/system-jobs/job_123/cancel \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
@@ -1268,11 +1353,13 @@ Settings update:
## Execution Notes
The runner writes a temporary PowerShell wrapper and launches `pwsh` with environment variables instead of shell interpolation.
The runner writes a temporary PowerShell wrapper and launches the configured PowerShell binary with environment variables instead of shell interpolation.
- `local` hosts run the script directly in the API container.
- `winrm` hosts use `Invoke-Command -ComputerName`.
- `ssh` hosts use `Invoke-Command -HostName`.
- From a Linux API host/container, `winrm` targets require Linux WSMan client support for PowerShell remoting. If PowerShell reports `no supported WSMan client library`, install/configure the WSMan dependencies in the API image or use SSH transport for PowerShell 7 targets.
- Wrapper failures use `$ErrorActionPreference = "Stop"` and remote `Invoke-Command -ErrorAction Stop`, so remoting errors mark the host failed instead of completing with exit code 0.
- Host credential resolution happens inside backend execution flows.
- POSHManager runtime variables are injected as PowerShell variables and `POSHM_*` environment variables.
- `POSHM_HOST_OS_FAMILY` is injected with `windows`, `linux`, or `other` so scripts can branch on the target OS type.