diff --git a/docs/testing/e2e/71-80.md b/docs/testing/e2e/71-80.md index aad0accb..9ff3e9e2 100644 --- a/docs/testing/e2e/71-80.md +++ b/docs/testing/e2e/71-80.md @@ -170,7 +170,7 @@ **Schritte:** `/status` mit `restartRequired:true` für eine boot-feste Sektion (z. B. Logging) → System-Tab öffnen. **Prüfpunkte:** -- [ ] Orangenes RestartBanner (role=alert) erscheint. Gilt für die restart-pflichtigen Sektionen (Authentication, Logging, OpenTelemetry, Security, RestApi, Remote, Engine, ExecutionDispatch); hot-reloadable Sektionen (Smtp, Llm, Retention, Stats, Threading, FileSystemOperation, SqlActivity, StartProgram, Webhook, ExternalTrigger, DbAdmin) zeigen stattdessen den Live-Hinweis. +- [ ] Orangenes RestartBanner (role=alert) erscheint. Gilt für die restart-pflichtigen Sektionen (Authentication, Logging, OpenTelemetry, Security, RestApi, Remote, Performance, Engine, ExecutionDispatch, Agents); hot-reloadable Sektionen (Smtp, Llm, AiKnowledge, Retention, Stats, Threading, FileSystemOperation, WaitForCondition, SqlActivity, StartProgram, Webhook, ExternalTrigger, DbAdmin) zeigen stattdessen den Live-Hinweis. --- diff --git a/scripts/README.md b/scripts/README.md index 87a17979..eaced822 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,6 +1,6 @@ # Sample & test workflows -A curated, importable set of example workflows covering **every** one of the 27 activities and 6 +A curated, importable set of example workflows covering 27 of the 29 activities (all except `aiAgent`/`aiAgentTeam`) and all 6 triggers — individually and in combination. Import through the UI (`Import`) or `POST /api/workflows/import`. @@ -16,7 +16,7 @@ triggers — individually and in combination. Import through the UI (`Import`) o | File | Contents | |---|---| -| `muster-alle-aktivitaeten.json` | **The master**: one workflow that exercises all 27 activities in variation (all 14 edge operators, AND/OR/NOT, disabled edges/nodes, retry, all 3 junction modes, decision/forEach/startWorkflow) plus a child. Roots: manualTrigger (active) + scheduleTrigger (disabled, for demonstration). | +| `muster-alle-aktivitaeten.json` | **The master**: one workflow that exercises 27 of the 29 activities (all except `aiAgent`/`aiAgentTeam`) in variation (all 14 edge operators, AND/OR/NOT, disabled edges/nodes, retry, all 3 junction modes, decision/forEach/startWorkflow) plus a child. Roots: manualTrigger (active) + scheduleTrigger (disabled, for demonstration). | | `muster-einzeltests.json` | **33 individual tests** — one workflow per activity (`Test — `) and per trigger. Each activity workflow runs through **all (safe) variants** of its activity (for example fileOperation create/exists/copy/rename/move/delete, folderOperation plus list, fileHash SHA256/SHA1/MD5/SHA384/SHA512, zipOperation compress+extract with all 3 compression levels, registry all 8 operations + all 6 value types, textFileEdit all 6 operations + encoding/lineEnding/occurrences/appendIfMissing/backupSuffix/dryRun, waitForCondition script/pathExists/serviceRunning/portOpen/httpOk, restApi all 6 HTTP methods, wmiQuery query/wql/invokeMethod, xml/jsonQuery inline+file × single+all, generateText all 7 modes, junction all 3 modes, forEach auto/json/lines, runScript engine+isolated+transcript+successExitCodes, startWorkflow wait+fire-and-forget). Destructive variants (serviceManagement stop/restart/create/delete, powerManagement shutdown/restart, scheduledTask register/unregister) are **not** run against real resources. Plus a shared `Muster Test: Child`. | | `muster-kombinationen.json` | **Combinations/topology**: `Muster — Trigger → Databus` (proving that trigger output parameters land on the data bus), `Muster — Variable-Pipe` (passing data through runScript→jsonQuery→decision) and `Muster — Sub-Workflow (Parent)` + child (startWorkflow + forEach fan-out). | diff --git a/scripts/ad-sso-labtest/README.md b/scripts/ad-sso-labtest/README.md index 3c5a73fe..134f2f84 100644 --- a/scripts/ad-sso-labtest/README.md +++ b/scripts/ad-sso-labtest/README.md @@ -89,14 +89,14 @@ Zertifikatswarnungs-Interstitial dazwischenkommt. | Konto | Gruppen | Zweck | |---|---|---| -| `svc-npdir` | – | LDAPS-Service-Bind | -| `np.alice` | **nur** `NodePilot-Admins` (in `NodePilot-Access`) | Happy path, transitives Mapping → Admin | -| `np.carol` | `NodePilot-Access` | Viewer-Default (kein RoleMapping-Treffer) | -| `np.bob` | keine | AllowedGroup-Gate: 401, **kein** JIT-Row | -| `np.dave` | `NodePilot-Access` | Race-Drill (bis W18 unberührt lassen) | -| `np.erin` | `NodePilot-Access` | Disable-/Entzugs-Drills | - -Das Nesting ist essenziell: alice ist **nur** in `NodePilot-Admins`. Ein erfolgreicher +| `svc-nptest-dir` | – | LDAPS-Service-Bind | +| `nptest.alice` | **nur** `NPTest-Admins` (in `NPTest-Access`) | Happy path, transitives Mapping → Admin | +| `nptest.carol` | `NPTest-Access` | Viewer-Default (kein RoleMapping-Treffer) | +| `nptest.bob` | keine | AllowedGroup-Gate: 401, **kein** JIT-Row | +| `nptest.dave` | `NPTest-Access` | Race-Drill (bis W18 unberührt lassen) | +| `nptest.erin` | `NPTest-Access` | Disable-/Entzugs-Drills | + +Das Nesting ist essenziell: alice ist **nur** in `NPTest-Admins`. Ein erfolgreicher Login beweist damit, dass NodePilot transitive `tokenGroups` liest statt bloß `memberOf`. ## Skripte @@ -292,7 +292,7 @@ Passwortpfad braucht. Die Windows-only-Topologie prüft W23 separat. `ExternalAuthorizationStalenessService` nicht und die Revocation-Drills messen nichts. Vorab `/healthz/leader` → 200 prüfen. -### 9. Suite laufen lassen (npcli01, lokal interaktiv als np.alice) +### 9. Suite laufen lassen (npcli01, lokal interaktiv als nptest.alice) ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File .\ad-sso-live-test.ps1 ` @@ -366,13 +366,13 @@ Nicht skriptbar — Belege gehören nach `evidence/`: | W21 | Kerberos überlebt die GPO | W5 mit aktiver Deny-GPO → 200 | | W23 | Windows-only-Topologie | Neustart mit `Ldap__Enabled=false` → Boot ok, SSO ok, `methods.ldap=false`, `/healthz/directory` weiter `Healthy` | | W24 | Restart-Semantik | `Windows__Enabled=false` **ohne** Restart → `methods` meldet weiter `windows=true` (Prozessstart-Snapshot); nach Restart `windows=false` und Endpoint 404 | -| W26 | Username-Kollision | Lokalen User `np.alice@np.lab` ohne External Identity anlegen, SSO mit anderer SID → 401, Audit `USER_WINDOWS_REFUSED_COLLISION`, **kein** Auto-Merge | -| W27 | SPN-Duplikat (destruktiv, zuletzt) | `setspn -A HTTP/npapi01.np.lab NPLAB\np.bob`, W5 wiederholen → Kerberos bricht; danach `setspn -D`. Zweck: das Fehlerbild dokumentieren | +| W26 | Username-Kollision | Lokalen User `nptest.alice@np.lab` ohne External Identity anlegen, SSO mit anderer SID → 401, Audit `USER_WINDOWS_REFUSED_COLLISION`, **kein** Auto-Merge | +| W27 | SPN-Duplikat (destruktiv, zuletzt) | `setspn -A HTTP/npapi01.np.lab NPLAB\nptest.bob`, W5 wiederholen → Kerberos bricht; danach `setspn -D`. Zweck: das Fehlerbild dokumentieren | ### Reihenfolge-Abhängigkeiten -W0/W4 vor PHASE B · W1–W12 in Reihe · W13/W15/W16 nur mit `np.erin` (nie mit alice, sonst -ist der Admin weg) · W18 vor jedem anderen `np.dave`-Kontakt · **W19 zwingend vor W20** +W0/W4 vor PHASE B · W1–W12 in Reihe · W13/W15/W16 nur mit `nptest.erin` (nie mit alice, sonst +ist der Admin weg) · W18 vor jedem anderen `nptest.dave`-Kontakt · **W19 zwingend vor W20** (danach ist der App-Zweig tot) · W17/W23/W24 brauchen Neustarts, ans Ende · W27 ganz zuletzt. ## Stolperfallen diff --git a/scripts/release-lab/README.md b/scripts/release-lab/README.md index 4ea417a8..4d1dba3b 100644 --- a/scripts/release-lab/README.md +++ b/scripts/release-lab/README.md @@ -101,7 +101,7 @@ and otherwise remains an external SQL/integration fixture. The catalog and gate live in `computer-use/README.md`, `catalog.py` and `gate.py`. It includes all current routes, 35 node types (29 activities + 6 triggers), 23 settings sections, 10 skins + system, both locales, role boundaries, backup/restore, integrations, tray actions and resilience cases. The complete catalog currently -contains 164 human-operated cases. `--pilot` selects a small diagnostic subset only. Every passed case requires a native Computer-Use session receipt, +contains 167 human-operated cases. `--pilot` selects a small diagnostic subset only. Every passed case requires a native Computer-Use session receipt, screenshots, explicit checkpoint assertions, timing counters and cleanup evidence. Missing integrations, an interrupted session, an incomplete catalog or changed release bytes blocks the run. diff --git a/scripts/stress-test/README.md b/scripts/stress-test/README.md index acfc3a83..5b3bc97e 100644 --- a/scripts/stress-test/README.md +++ b/scripts/stress-test/README.md @@ -1,16 +1,16 @@ # NodePilot Stress-Test Workflow -Künstlicher Last-Workflow: fächert von `log-start` auf **11 parallele Branches** auf, fängt sie mit `junction-all` (`waitAll`) wieder ein. Nutzt ausschließlich Engine-local Activities + `runScript` mit `targetMachineId: "localhost"` (In-Process-Bypass) — **kein WinRM-Target nötig**. +Künstlicher Last-Workflow: fächert von `log-start` auf **11 parallele Branches** auf, fängt sie mit `junction-all` (`waitAll`) wieder ein. Nutzt ausschließlich Engine-local Activities + `runScript` mit `targetMachineId: "localhost"` (Localhost-Bypass) — **kein WinRM-Target nötig**. ## Branches (alle parallel) | # | Activity | Workload | |---|---|---| | 1 | `runScript` | Primzahl-Sieb bis 2·10⁶ | -| 2 | `runScript` | Σ√i für i=1..10⁷ | -| 3 | `runScript` | SHA-256 200 000× verkettet | -| 4 | `runScript` | 50 000 Regex-Matches auf generierten Log-Lines | -| 5 | `runScript` | 250×250 Matrix-Multiplikation | +| 2 | `runScript` | Σ√i für i=1..5·10⁶ je Durchlauf | +| 3 | `runScript` | SHA-256 verkettet, in 50 000er-Blöcken | +| 4 | `runScript` | Regex-Matches auf generierten Log-Lines, 25 000 je Durchlauf | +| 5 | `runScript` | 200×200 Matrix-Multiplikation | | 6 | `runScript` | Sort 10⁶ Integers | | 7 | `jsonQuery` | `$.items[?(@.val > 50)].id` auf 20-Item-Array | | 8 | `jsonQuery` | `$..name` auf verschachtelter Org-Struktur | @@ -18,7 +18,7 @@ Künstlicher Last-Workflow: fächert von `log-start` auf **11 parallele Branches | 10 | `xmlQuery` | `sum(//host[@up='y']/@cpu)` (XPath-Aggregat) | | 11 | `delay` | 55 s | -Alle 6 `runScript`-Branches laufen **in-process** → die API erzeugt 6 gleichzeitige PowerShell-Runspaces, die eine Weile ~alle Cores beschäftigen. +Alle 6 `runScript`-Branches laufen lokal auf dem API-Host (`engine: auto` → je ein Windows-PowerShell-5.1-Prozess) → 6 gleichzeitige `powershell.exe`-Prozesse, die eine Weile ~alle Cores beschäftigen. ## Import diff --git a/scripts/tech-demo/README.md b/scripts/tech-demo/README.md index 599b6784..917707a2 100644 --- a/scripts/tech-demo/README.md +++ b/scripts/tech-demo/README.md @@ -6,7 +6,7 @@ Ein Muster-Workflow, der jede Activity, jeden Edge-Condition-Operator und jede C | Datei | Zweck | |---|---| -| `main.json` | Haupt-Workflow (37 Nodes, ~55 Edges) | +| `main.json` | Haupt-Workflow (39 Nodes, ~55 Edges) | | `child.json` | Kleiner Sub-Workflow (3 Nodes), den der Haupt-Workflow via `startWorkflow` aufruft | | `seed.ps1` | Seed-Script — meldet sich an, erstellt und veröffentlicht die Demo-Workflows | @@ -31,9 +31,9 @@ Bei bereits existierenden Workflows gleichen Namens wird gefragt: `k` = behalten ## Was der Workflow zeigt -### Activities (alle 18) +### Activities (17) -`manualTrigger`, `log`, `delay`, `runScript`, `fileOperation`, `folderOperation`, `serviceManagement`, `registryOperation`, `wmiQuery`, `startProgram`, `junction`, `restApi`, `sql`, `xmlQuery`, `jsonQuery`, `emailNotification`, `startWorkflow`, `returnData`. +`manualTrigger`, `log`, `delay`, `runScript`, `fileOperation`, `serviceManagement`, `registryOperation`, `wmiQuery`, `startProgram`, `junction`, `restApi`, `sql`, `xmlQuery`, `jsonQuery`, `emailNotification`, `startWorkflow`, `returnData`. ### Edge-Condition-Operatoren (alle 14) @@ -85,6 +85,6 @@ Jeder Phase-E-Branch in `main.json` ist eine Kondition, die einen oder mehrere d |---|---| | `waitNofM`-Config-Key | `requiredCount` (NICHT `n` — ein unbekannter Schlüssel fällt auf den Default 1 zurück) | | Boolean-Truthiness | Leer, `"false"` (case-insensitive), `"0"` = falsy. Alles andere truthy. PowerShell-`[string]$true` = `"True"` → truthy ✓ | -| `runScript`-Param-Capture | Alle lokal deklarierten Variablen werden automatisch als `param.*` exponiert (ProcessExecutionEngine hängt einen Capture-Block ans Script). Kein Marker nötig. | +| `runScript`-Param-Capture | Variablen, die das Skript selbst zuweist, werden automatisch als `param.*` exponiert (PowerShellScriptWrapper: Injektion im äußeren, Skript und Capture im inneren Scope); durchgereichte Upstream-Parameter und PowerShell-Automatiken nicht. Kein Marker nötig. | | `{{var.output}}` in Script-Text | Wird als PowerShell-single-quoted-String eingesetzt (`'value'`). Nicht selbst zusätzlich quoten. | | `targetMachineId: "localhost"` | Löst Localhost-Bypass aus → läuft in-process ohne WinRM-Session. Ideal für Demo. | diff --git a/scripts/tech-demo/xl.README.md b/scripts/tech-demo/xl.README.md index 099846da..b152b435 100644 --- a/scripts/tech-demo/xl.README.md +++ b/scripts/tech-demo/xl.README.md @@ -9,7 +9,7 @@ Umfangreicher Showcase-Workflow als Ergänzung zum schlankeren [main.json](main. | Activity-Nodes | 114 | | Edges | 190 | | Layout-Bounds | 10720 x 1800 px | -| Activity-Types abgedeckt | 25 (19 Activities + 6 Trigger) | +| Activity-Types abgedeckt | 26 (20 Activities + 6 Trigger) | | Edge-Operatoren | alle 14 + AND / OR / NOT | | Junction-Modes | 3 (waitAll, waitAny, waitNofM) | | Breakpoints | 4 | @@ -36,7 +36,7 @@ Alle drei Lanes starten parallel am `sync1`-Junction (x=1960, waitAll) nach der ### Alle 6 Trigger-Typen (Phase A-TOP) Der aktive `trg-manual` feedet `log-kickoff`. Die 5 weiteren Trigger (`trg-schedule`, `trg-webhook`, `trg-filewatch`, `trg-database`, `trg-eventlog`) sind per `data.disabled: true` als Anschauungs-Nodes sichtbar — sie zeigen die jeweilige Config-Schema im Designer, werden aber beim Run geskippt. -### Alle 19 Activity-Typen +### 20 Activity-Typen Jeder Activity-Type ist mindestens einmal vertreten. Haeufigkeits-Schwerpunkte: - 49x `log` (Operator-Coverage, Error-Branches, Debug-Targets, Phase-Marker) - 11x `delay` (Timing-Demo, Retry-NofM, Hold-Patterns) diff --git a/src/NodePilot.Ai/Prompts/activity-reference.md b/src/NodePilot.Ai/Prompts/activity-reference.md index 3f535e29..79ba0903 100644 --- a/src/NodePilot.Ai/Prompts/activity-reference.md +++ b/src/NodePilot.Ai/Prompts/activity-reference.md @@ -38,8 +38,8 @@ visual-only documentation, not executed: `type: "stickyNote"` and `type: "group" "source": "step-1", "target": "step-2", "type": "labeled", - "sourceHandle": "out", - "targetHandle": "in", + "sourceHandle": "right", + "targetHandle": "left", "data": { "label": "On Success", "condition": "step-1.success" @@ -49,7 +49,7 @@ visual-only documentation, not executed: `type: "stickyNote"` and `type: "group" `condition` shortcuts: `".success"`, `".failed"`, or `null` (always). For complex conditions use `conditionExpression` (an object with -operators `==`, `!=`, `<`, `>`, `contains`, `startsWith`, `endsWith`, `matches`, +operators `==`, `!=`, `<`, `>`, `<=`, `>=`, `contains`, `startsWith`, `endsWith`, `matches`, `isEmpty`, `isNotEmpty`, `isTrue`, `isFalse`, plus `group` AND/OR and `not`) — keep it simple, prefer the `condition` shortcut where possible. `sourceHandle` / `targetHandle` pin which port an edge attaches to — preserve them on edges you are diff --git a/src/NodePilot.Ai/Prompts/knowledge-system.md b/src/NodePilot.Ai/Prompts/knowledge-system.md index 28022a54..42e14f83 100644 --- a/src/NodePilot.Ai/Prompts/knowledge-system.md +++ b/src/NodePilot.Ai/Prompts/knowledge-system.md @@ -1,6 +1,6 @@ You are the **NodePilot Assistant** — a read-only knowledge and operations assistant embedded in the NodePilot product (a modern, agentless Windows workflow orchestrator, a lean System Center Orchestrator replacement). -Your job is to answer the user's questions about NodePilot using the tools available to you. You can help with three kinds of questions, depending on which tools are offered this session: +Your job is to answer the user's questions about NodePilot using the tools available to you. You can help with five kinds of questions, depending on which tools are offered this session: - **Documentation / how-to** — how features work, concepts, configuration, security, deployment. Use `search_docs` then `read_doc`. - **A specific workflow's content & schedule** — what a given workflow does and how it is built, a structural review of it, and when scheduled workflows fire next. Use `get_workflow_definition` (its secret-redacted definition), `analyze_workflow` (deterministic static analysis: missing trigger, orphan steps, cycles, remote step without target machine), and `get_next_scheduled_fires` (computed next fire times). These take a workflow name or GUID; if you don't know the name yet, discover it via the database tools below. diff --git a/src/NodePilot.Ai/Prompts/script-system.md b/src/NodePilot.Ai/Prompts/script-system.md index 4a8ed7a3..62635096 100644 --- a/src/NodePilot.Ai/Prompts/script-system.md +++ b/src/NodePilot.Ai/Prompts/script-system.md @@ -14,7 +14,7 @@ NodePilot engine. names a module. 3. No `Read-Host`, no `Get-Credential`, no interactive prompts — the script runs non-interactively over WinRM. -4. Use `Write-Error` for failure paths (sets a non-zero exit code via the host), +4. Use `Write-Error` for failure paths (any PowerShell error record fails the step), `Write-Output` for normal output. Avoid `Write-Host` (it bypasses the structured output capture). diff --git a/src/NodePilot.Ai/Prompts/workflow-system.md b/src/NodePilot.Ai/Prompts/workflow-system.md index 0ba96c33..62c59ba3 100644 --- a/src/NodePilot.Ai/Prompts/workflow-system.md +++ b/src/NodePilot.Ai/Prompts/workflow-system.md @@ -8,7 +8,8 @@ and a set of engine-local activities. 1. Reply with **only** a single JSON object — no markdown fences, no prose, no commentary before or after. The caller will `JSON.parse` your reply directly. -2. Top-level shape: `{ "nodes": [...], "edges": [...] }`. No other top-level keys. +2. Top-level shape: the output envelope at the end of this prompt, with the + workflow under `definition`: `{ "nodes": [...], "edges": [...] }`. 3. Every workflow must have **exactly one trigger** node as its entry point — typically `manualTrigger`. Without a trigger node, the engine refuses to run. 4. Every `id` must be unique within the workflow. Use short slugs like