Commit Graph

15 Commits

Author SHA1 Message Date
Oliver Kieselbach 425502c419 feat(ppkg): array-aware analyze rules + allow-list + size-chunked scan event
Reworks PPKG detection to one aggregate event the rules parse as an array,
adds a default + customizable allow-list, and makes the event storage-safe.

Rule engine:
- New condition source event_data_array + ItemField: iterates an array field
  (any-element match), with dot-path dataField support. (RuleEngine.ConditionEvaluators)

Agent:
- Drop per-package provisioning_package_detected events (noise: a clean Win11 VM
  ships ~22 OS-inbox .ppkg). One provisioning_package_scan carries an artifacts[]
  array; anyPpkgFound derived from it (consistent, incl. recovery residue).
- Size-based chunking: split artifacts across multiple scan events so each event's
  Newtonsoft DataJson stays < 24k (well under the 30k Table-Storage truncation that
  would blind the rule); never drops a tail artifact. Per-artifact string fields
  (identity/dir/rank/installTime) hard-capped at 256; scanErrors capped.

Rules:
- ANALYZE-SEC-005 (default on) + SEC-006 (template) fire on artifacts.identity
  not matching an anchored allow-list (^(?:...)\b) that covers OS-inbox families.
- ANALYZE-SEC-007 alarms when a per-source collection cap was hit (scanTruncated).

Web/MCP/docs: event_data_array in the rule form (types + fields), analyze-rules
docs section + example, event-type catalogs.

Tests: rule-engine array/anchor/dot-path/SEC-007; agent artifacts/chunking/field-cap
/worst-case-size. Build green; V2.Core 1236; backend rule + web tsc green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 15:14:51 +02:00
Oliver Kieselbach 76284cfcb2 fix(agent/v2,rules): two-stage health-script emission to close short-session timing gap
The post-PR-HS1 single-source design (HS-NEW-RESULT JSON only) had a real timing gap:
IME emits the [HS] new result = JSON line only AFTER its batch send to the Microsoft
service, ~30-90 s after the actual script ran (verified in session c1e714e6: 34-74 s
gap per policy). Short Autopilot enrollments often end inside that window, so health-
script rows were entirely missing from completed sessions even though IME had executed
the scripts.

Two-stage approach (matches original V1 timing for the early signal, while keeping
HS-NEW-RESULT as the canonical truth):

- Re-add HS-COMPLIANCE pattern matching BOTH `pre-remdiation` AND `post-remdiation`
  detection compliance lines → HandleHealthScriptDetectionResult emits a script_completed
  event immediately. Single regex (`(?<part>pre|post)-remdiation`) covers both phases.

- Re-add HS-RUN-CONTEXT / HS-EXITCODE / HS-STDOUT / HS-STDERR patterns feeding a
  single-slot `_pendingHealthScript` accumulator (IME runs health scripts sequentially
  within a session — verified). HS-COMPLIANCE merges the slot data onto the early-signal
  event so exit / stdout / stderr / runContext are populated from the start, not just
  the inferred compliance verdict.

- HS-NEW-RESULT continues to fire later with the full JSON (RemediationStatus,
  TargetType, ErrorCode, plus the actual remediation phase's data). UI reducer's
  dataCompleteness() scoring keeps the more complete entry — early-signal row gets
  enriched in place, no duplicate cards.

Remediation phase itself has no early-signal source in IME logs (only the late JSON
exposes Info.RemediationExitCode and RemediationScriptOutputDetails). A follow-up
based on the agentexecutor invocation line's _RemediationScript.output suffix is
possible once we have a real non-compliant cycle log to validate against.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 00:58:21 +02:00
Oliver Kieselbach 527e36b957 fix(rules/schema): allow healthScriptResult action in ime-log-pattern enum
CI ajv validation rejected HS-NEW-RESULT.json because the new healthScriptResult
action wasn't in the schema's enum allowlist. Add it next to the other script*
actions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:41:19 +02:00
Oliver Kieselbach 5abdcb6eee feat(rules): preconditions gate — skip rules silently on non-matching device facts
Adds an optional `preconditions` array to analyze rules. Preconditions
evaluate BEFORE conditions and are AND-combined; any failing precondition
silently skips the rule (no RuleResult, no UI card, no tenant-visible
"rule fired"). Distinct from `conditions`, which decide whether the rule
fires given that it applies.

Use case: rules that should only run on certain hardware/OS profiles
(e.g. "skip ANALYZE-SEC-001 on virtual machines because UEFI CA 2023
deployment is host-controlled").

Backend
- New `RulePrecondition` model + `Preconditions` list on `AnalyzeRule`.
- JSON schema gains optional top-level `preconditions` referencing a new
  `rulePrecondition` definition (no signal/required/correlation noise —
  pure boolean gate).
- `RuleEngine.EvaluateRule` runs preconditions first; on failure returns
  null. `EvaluatePrecondition` reuses MatchesEventType / GetDataFieldValue
  / MatchesOperator. Operator semantics:
    * not_exists → passes when event type absent OR field empty (handy
      for "old agent without the new field" path).
    * exists / others → fail closed when event type or field missing.
- `TableStorageService` rule round-trip extended with `PreconditionsJson`
  on Store + Map (column-mapped, not blob — same pattern as Conditions).

Web (analyze-rules editor)
- `AnalyzeRule` / `RuleForm` types gain `preconditions` array; form
  payload round-trips on POST + PUT; ruleToForm + EMPTY_FORM updated.
- `AnalyzeRuleFormFields`: new amber Preconditions panel above Conditions
  with eventType/dataField/operator/value/description rows.
- `AnalyzeRuleCard`: read-only chip section above Conditions with
  "skipped silently if any fails" hint.

Tests
- `RuleEnginePreconditionTests` (7 cases): empty preconditions = legacy
  behavior, single pass/fail, AND-semantics with two preconditions,
  not_exists passes when event missing, equals fails closed when event
  missing, baseline.
- 781/781 backend, 507/507 V1 agent, 782/782 V2 agent, 208/208 web vitest.

No agent change yet — useful preconditions can already target existing
event fields (os_info.edition, hardware_spec.cpuName, tpm_status.specVersion,
…). Adding `hardware_spec.isVirtualMachine` is a follow-up PR (agent collector).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 23:18:40 +02:00
Oliver Kieselbach 45edbab0e1 feat: enhanced analyze rule engine (in not_in support) MarkSessionAsFailed support, new ESP rule for cert errors 2026-04-14 21:46:20 +02:00
Oliver Kieselbach 625809423f Better app failure detection and reporting 2026-04-10 18:12:30 +02:00
Oliver Kieselbach 3e7f66e8ea added app dashboard 2026-04-07 15:57:45 +02:00
Oliver Kieselbach 6a8a916d3c extended schema with new values 2026-04-06 17:56:11 +02:00
Oliver Kieselbach ed0e19fa36 added template vars to analyze rules for better user journey 2026-04-03 19:52:58 +02:00
Oliver Kieselbach dc3a3a5923 added security category to rule schema 2026-03-20 14:49:47 +01:00
Oliver Kieselbach 4dc61b4728 fix IsDeviceOnlyDeployment completion event, added community rules 2026-03-17 22:31:49 +01:00
Oliver Kieselbach 0b960d7d6f added PowerShell Script Execution Tracking 2026-03-05 10:12:57 +01:00
Oliver Kieselbach eae2898ce2 add Galactic Admin audit logs, audit pagination, and platform metrics backend cache
- Galactic Admin Mode for Audit Logs: banner + cross-tenant endpoint (galactic/audit/logs)
- Audit page pagination (12 entries per page) with Previous/Next controls
- Platform Metrics: moved computation to backend PlatformMetricsService with 5-min cache
- New endpoint GET /api/galactic/metrics/platform replaces N+1 client-side fetches
- IME log tracker enhancements, DO telemetry pattern, and download progress improvements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:40:37 +01:00
Oliver Kieselbach 7cb5cf040c fix: add count_per_group_gte operator to analyze rule schema
Adds the missing operator to the enum so ANALYZE-APP-006.json passes
schema validation in the combine-rules workflow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 13:19:35 +01:00
Oliver Kieselbach 1f796bf6e3 feat: externalize rules to GitHub + API consolidation + preview mode
## Rules as GitHub single source of truth
- Add 75 individual JSON rule files (2 gather, 18 analyze, 55 IME patterns)
  under rules/gather/, rules/analyze/, rules/ime-log-patterns/
- Add JSON Schemas for all three rule types with VS Code IntelliSense support
- Add CI combine script (rules/scripts/combine.js) + GitHub Action that
  validates schemas with ajv-cli and generates rules/dist/ combined files
- Convert BuiltIn*.cs from hardcoded C# objects to embedded JSON resource loaders
- Add GitHubRuleRepository service to fetch dist/ files from raw.githubusercontent.com
- Add ReseedFromGitHubFunction: POST /api/rules/reseed-from-github?type=all|gather|analyze|ime

## IME Log Patterns
- Extend ImeLogPattern model with Description and IsBuiltIn properties
- Add ImeLogPatterns table + API constants
- Add TableStorageService CRUD methods for IME log patterns
- Add ImeLogPatternService (CRUD, merge, auto-seed from embedded JSON)
- Add ImeLogPatternsFunction: GET/PUT /api/rules/ime-log-patterns (Phase 1: read-only
  for tenants, Galactic Admin can enable/disable/edit globally)
- Add IME Log Patterns management page (/ime-log-patterns)
- Wire GetAgentConfigFunction to use ImeLogPatternService instead of static class

## API route consolidation
- All rule endpoints now under /api/rules/* for single certificate exclusion path:
  /api/rules/gather, /api/rules/analyze, /api/rules/ime-log-patterns,
  /api/rules/reseed-from-github

## Export buttons
- Add per-rule and export-all JSON download buttons to gather-rules,
  analyze-rules, and ime-log-patterns pages

## Admin configuration
- Replace old individual reseed buttons with unified "Fetch & Reseed from GitHub"
  (calls new GitHub endpoint) plus compact individual-type reseed buttons
- Add CDN cache hint: GitHub raw.githubusercontent.com caches up to 5 minutes

## Preview mode
- ?preview=1 URL param seeds localStorage.previewMode (persists across navigation)
- ?preview=0 clears it; toggle in Navbar settings dropdown (indigo, eye icon)
- IME Log Patterns nav link gated behind galacticAdminMode OR previewMode
- Preview badge shown on nav link when active for normal users

## Tests
- Add xUnit test project (net8.0) with 5 tests for embedded resource loading,
  known IME actions validation, and valid categories check

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 13:12:09 +01:00