Files
PatchProbe-Server/CLAUDE.md
2026-05-25 10:29:38 +08:00

616 lines
10 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build
```bash
# Debug build
dotnet build PatchProbe.Cli/PatchProbe.Cli.csproj
# Self-contained single-file win-x64 release
dotnet publish PatchProbe.Cli/PatchProbe.Cli.csproj -c Release
# Output: PatchProbe.Cli/bin/Release/net10.0-windows/win-x64/publish/PatchProbe.exe
```
## Run
```bash
# Collect evidence, write JSON to output/ directory
PatchProbe.exe scan
# Write payload to a specific path
PatchProbe.exe scan --output C:\temp\scan.json
# Collect but print JSON to stdout instead of uploading
PatchProbe.exe scan --no-upload
```
Note: must be run as administrator for full data access (WUA, event logs, WMI).
---
# Project Overview
I am building a Windows patch-management evidence collection and orchestration platform similar in concept to the patch-management component of major RMM tools.
The goal is NOT to replace Windows Update Agent (WUA), CBS, DISM, or the Windows driver-selection stack.
Instead, the platform should act as a centralized control plane that:
* collects patch-related evidence from endpoints
* evaluates compliance
* manages policy/rings/approvals
* eventually orchestrates installations
* reports status and failures
Windows itself remains authoritative for:
* update applicability
* prerequisites
* supersedence
* CBS/component servicing logic
* driver matching/ranking
* installation success/failure
The collector should be:
* portable
* standalone
* self-contained
* executable as administrator
* non-persistent
* non-installed
* safe/read-only initially
The first milestone is NOT patch installation.
The first milestone is proving that a one-shot executable can collect equivalent patch-management evidence to what an RMM platform sees.
---
# Current State
I have already:
* created a new C# Console App
* selected .NET 9
* chosen a self-contained single-file EXE architecture
The collector executable should eventually be called:
```text
PatchProbe.exe
```
---
# Architecture Requirements
The application should use:
* C#
* .NET 9
* Generic Host
* Dependency Injection
* HttpClientFactory
* Structured logging
* Clean collector/service architecture
The project should remain a console application.
Do NOT use:
* WinForms
* WPF
* ASP.NET
* Worker Service
* MAUI
The collector flow is:
```text
PatchProbe.exe
→ collect evidence
→ serialize to JSON
→ upload to backend
→ exit
```
The collector should not:
* install updates
* download updates
* modify policy
* create scheduled tasks
* register services
* persist locally beyond optional logs/cache
---
# Desired Solution Structure
The solution should be scaffolded approximately like this:
```text
PatchProbe.sln
├── PatchProbe.Cli/
│ ├── Program.cs
│ ├── Collectors/
│ ├── Models/
│ ├── Services/
│ └── Utils/
├── PatchProbe.Shared/
│ ├── Models/
│ ├── Contracts/
│ └── Serialization/
└── PatchProbe.Engine.Contracts/
├── ApiModels/
└── Versioning/
```
Even if some projects begin mostly empty.
---
# NuGet Packages To Use
Immediately add:
```bash
dotnet add package System.Management
dotnet add package Serilog
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File
dotnet add package System.CommandLine
dotnet add package Microsoft.Extensions.Hosting
dotnet add package Microsoft.Extensions.DependencyInjection
dotnet add package Microsoft.Extensions.Http
```
---
# Program.cs Architecture
Use Generic Host architecture.
Example direction:
```csharp
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
var builder = Host.CreateApplicationBuilder(args);
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("logs/patchprobe.log")
.CreateLogger();
builder.Services.AddSingleton<DeviceCollector>();
builder.Services.AddSingleton<WindowsUpdateCollector>();
builder.Services.AddSingleton<PayloadUploader>();
var host = builder.Build();
var deviceCollector = host.Services.GetRequiredService<DeviceCollector>();
var wuCollector = host.Services.GetRequiredService<WindowsUpdateCollector>();
var device = await deviceCollector.CollectAsync();
var updates = await wuCollector.CollectAsync();
Console.WriteLine("Collection complete.");
```
Maintain proper layering and separation of concerns.
---
# Core Philosophy
Treat collected data as immutable evidence.
Meaning:
```text
PatchProbe scan = factual snapshot
```
NOT:
* interpreted state
* compliance judgment
* install decisions
Those belong in the backend engine later.
The backend evaluates:
* policy
* compliance
* approval
* orchestration
* ring logic
The collector only gathers evidence.
---
# Windows Patch-Management Philosophy
The engine does NOT replace:
* Windows Update Agent
* CBS
* TrustedInstaller
* DISM
* Windows driver ranking
Instead:
```text
The platform provides:
- policy
- scheduling
- approvals
- maintenance windows
- telemetry
- compliance reporting
- failure classification
- orchestration
Windows provides:
- applicability
- prerequisites
- supersedence
- servicing logic
- driver selection
- install success/failure
```
---
# Required Initial Collectors
Implement collectors in this approximate order.
## 1. DeviceCollector
Collect:
* hostname
* manufacturer
* model
* serial number
* BIOS version
* BIOS date
* TPM presence/version
* RAM
* domain/workgroup
* system type
Use:
* WMI/CIM
* registry
* environment info
---
## 2. OsCollector
Collect:
* ProductName
* EditionID
* DisplayVersion
* ReleaseId
* Build number
* UBR
* architecture
* install date
* last boot
Registry path:
```text
HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion
```
---
## 3. WindowsUpdateCollector
This is the core component.
Use WUA COM APIs.
Use:
* Microsoft.Update.Session
* CreateUpdateSearcher()
Collect:
* applicable updates
* update titles
* KB IDs
* categories
* severity
* reboot requirements
* WUA result codes
* update history
* WU source/policy state
Search criteria:
```text
IsInstalled=0 and IsHidden=0
```
Use COM interop or dynamic COM access.
Example direction:
```csharp
Type sessionType = Type.GetTypeFromProgID("Microsoft.Update.Session");
dynamic session = Activator.CreateInstance(sessionType);
dynamic searcher = session.CreateUpdateSearcher();
dynamic result = searcher.Search("IsInstalled=0 and IsHidden=0");
```
The collector should ask Windows what is applicable rather than attempting to independently determine applicability.
---
# Important Patch-Management Concepts
Windows decides:
* whether an update is applicable
* whether prerequisites are met
* supersedence
* CBS/component servicing logic
* driver ranking/matching
* installation success
The platform should observe and orchestrate, not replace these systems.
---
# 4. PendingRebootCollector
Collect pending reboot indicators from:
* CBS
* Windows Update
* Session Manager
* Computer rename state
Registry locations include:
```text
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired
HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager
```
---
# 5. DriverCollector
Collect:
* device name
* driver version
* manufacturer
* INF name
* hardware IDs
* device class
* driver date
Use:
* Win32_PnPSignedDriver
* pnputil where useful
Important:
Do NOT attempt to replace Windows driver ranking logic.
---
# 6. CBS / DISM Collector
Collect:
* package state
* servicing state
* DISM package output
Use:
```text
dism /online /get-packages /format:table
```
Treat CBS as the servicing authority.
---
# 7. Windows Update Policy Collector
Collect policy/configuration from:
* WSUS
* WUfB
* AU settings
* deferrals
Registry paths include:
```text
HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate
HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU
HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings
```
---
# 8. Event Collector
Collect recent relevant events from:
* System
* Microsoft-Windows-WindowsUpdateClient/Operational
* Microsoft-Windows-UpdateOrchestrator/Operational
Focus on:
* failures
* installs
* servicing issues
* reboot events
---
# Payload Design
The collector should produce a JSON payload approximately shaped like:
```json
{
"schemaVersion": "0.1",
"collector": {},
"device": {},
"os": {},
"pendingReboot": {},
"windowsUpdate": {
"applicableUpdates": [],
"history": [],
"policy": {}
},
"installedHotfixes": [],
"cbsPackages": [],
"drivers": [],
"recentUpdateEvents": []
}
```
This payload should be treated as immutable evidence.
---
# CLI Shape
The executable should eventually support:
```text
PatchProbe.exe scan
PatchProbe.exe upload
PatchProbe.exe export
PatchProbe.exe debug
PatchProbe.exe validate
```
Initially only implement:
```text
PatchProbe.exe scan
```
---
# Publishing Requirements
The application should be published as:
* self-contained
* single-file
* win-x64 executable
Example publish command:
```bash
dotnet publish ^
-c Release ^
-r win-x64 ^
--self-contained true ^
-p:PublishSingleFile=true ^
-p:EnableCompressionInSingleFile=true
```
Result:
* one EXE
* no installed runtime dependency
---
# Important Design Constraints
Do NOT:
* tightly couple collection and analysis
* tightly couple collection and orchestration
* make compliance decisions in the collector
Maintain:
```text
Collector
→ evidence payload
Backend
→ analysis/policy/compliance
Frontend
→ visualization/reporting
```
---
# Future Evolution Path
The architecture should naturally evolve into:
```text
Phase 1:
One-shot evidence collector
Phase 2:
Scheduled execution
Phase 3:
Patch orchestration
Phase 4:
Remediation engine
Phase 5:
Approval rings/policies
Phase 6:
Full RMM-style patch-management platform
```
---
# Current Request
Based on all of the above:
* scaffold the initial project architecture
* implement the first collectors
* implement payload models
* implement logging
* implement WUA scanning
* implement JSON serialization
* implement upload abstraction
* implement clean DI architecture
* implement a production-quality starting structure suitable for future expansion