audit, advisories and doctors/setup work
This commit is contained in:
48
src/Doctor/AGENTS.md
Normal file
48
src/Doctor/AGENTS.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# AGENTS - StellaOps Doctor
|
||||
|
||||
## Roles
|
||||
- Backend engineer: Doctor engine, pack loader, checks, and evidence output.
|
||||
- QA engineer: unit/integration tests for Doctor engine and web service.
|
||||
- Docs/PM: keep sprint status in `docs/implplan/SPRINT_*` aligned and update Doctor docs.
|
||||
|
||||
## Working directory
|
||||
- Primary: `src/Doctor/**` (web service, plugins, tests).
|
||||
- Allowed shared libraries:
|
||||
- `src/__Libraries/StellaOps.Doctor/**`
|
||||
- `src/__Libraries/StellaOps.Doctor.Plugins.*/**`
|
||||
- `src/__Libraries/__Tests/StellaOps.Doctor.*.Tests/**`
|
||||
- Do not edit other modules unless the sprint explicitly allows cross-module edits.
|
||||
|
||||
## Required reading (treat as read before DOING)
|
||||
- `docs/README.md`
|
||||
- `docs/technical/architecture/07_HIGH_LEVEL_ARCHITECTURE.md`
|
||||
- `docs/modules/platform/architecture-overview.md`
|
||||
- `docs/doctor/doctor-capabilities.md`
|
||||
- `docs/doctor/cli-reference.md`
|
||||
- `docs/doctor/README.md`
|
||||
- Sprint file under `docs/implplan/`
|
||||
|
||||
## Coding standards
|
||||
- Target .NET 10 with preview features as configured.
|
||||
- Determinism: stable ordering, UTC timestamps, invariant culture, fixed JSON options.
|
||||
- Never call `DateTime.UtcNow`, `Guid.NewGuid()`, or `Random.Shared` directly; use injected providers.
|
||||
- DSSE PAE and JSON canonicalization must use shared helpers; do not reimplement.
|
||||
- Remediation commands must be non-destructive; destructive steps are manual guidance only.
|
||||
|
||||
## Evidence and remediation
|
||||
- Every check emits evidence and `how_to_fix` alias for agent/CLI/UI consumption.
|
||||
- Evidence logs are JSONL with deterministic ordering and include `doctor_command`.
|
||||
- DSSE summaries assume operator execution and include the same command note.
|
||||
|
||||
## Testing
|
||||
- Doctor engine tests: `src/__Libraries/__Tests/StellaOps.Doctor.Tests`
|
||||
- Plugin tests: `src/__Libraries/__Tests/StellaOps.Doctor.Plugins.*.Tests`
|
||||
- Web service tests: `src/Doctor/__Tests/StellaOps.Doctor.WebService.Tests`
|
||||
- Tests must be offline-safe and deterministic (no network access, fixed inputs).
|
||||
|
||||
## Sprint/status discipline
|
||||
- Mirror task state in the relevant `SPRINT_*` doc (TODO -> DOING -> DONE/BLOCKED).
|
||||
- If a decision is needed, mark the task BLOCKED in the sprint and continue with other tasks.
|
||||
|
||||
## Contacts/ownership
|
||||
- Module owner: Doctor Guild
|
||||
@@ -45,6 +45,7 @@ public sealed class DoctorRunService
|
||||
public Task<string> StartRunAsync(RunDoctorRequest request, CancellationToken ct)
|
||||
{
|
||||
var runMode = Enum.Parse<DoctorRunMode>(request.Mode, ignoreCase: true);
|
||||
var runId = GenerateRunId();
|
||||
var options = new DoctorRunOptions
|
||||
{
|
||||
Mode = runMode,
|
||||
@@ -54,10 +55,11 @@ public sealed class DoctorRunService
|
||||
Timeout = TimeSpan.FromMilliseconds(request.TimeoutMs),
|
||||
Parallelism = request.Parallelism,
|
||||
IncludeRemediation = request.IncludeRemediation,
|
||||
TenantId = request.TenantId
|
||||
TenantId = request.TenantId,
|
||||
RunId = runId,
|
||||
DoctorCommand = "POST /api/v1/doctor/run"
|
||||
};
|
||||
|
||||
var runId = GenerateRunId();
|
||||
var state = new DoctorRunState
|
||||
{
|
||||
RunId = runId,
|
||||
|
||||
@@ -84,7 +84,7 @@ public sealed class LogRotationCheck : IDoctorCheck
|
||||
CommandType.Shell)
|
||||
.AddStep(2, "Adjust rotation threshold",
|
||||
"Edit Logging:RollingPolicy in configuration",
|
||||
CommandType.Config))
|
||||
CommandType.FileEdit))
|
||||
.Build());
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ public sealed class LogRotationCheck : IDoctorCheck
|
||||
.WithRemediation(rb => rb
|
||||
.AddStep(1, "Enable application-level log rotation",
|
||||
"Set Logging:RollingPolicy to 'Size' or 'Date' in appsettings.json",
|
||||
CommandType.Config)
|
||||
CommandType.FileEdit)
|
||||
.AddStep(2, "Or configure system-level rotation",
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||
? "Use Windows Event Log or configure log cleanup task"
|
||||
@@ -179,3 +179,4 @@ public sealed class LogRotationCheck : IDoctorCheck
|
||||
return "/var/log/stellaops";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ public sealed class PrometheusScrapeCheck : IDoctorCheck
|
||||
.WithRemediation(rb => rb
|
||||
.AddStep(1, "Enable metrics endpoint",
|
||||
"Set Metrics:Enabled=true in appsettings.json",
|
||||
CommandType.Config)
|
||||
CommandType.FileEdit)
|
||||
.AddStep(2, "Verify metrics configuration",
|
||||
"stella config get Metrics",
|
||||
CommandType.Shell))
|
||||
@@ -133,3 +133,4 @@ public sealed class PrometheusScrapeCheck : IDoctorCheck
|
||||
.Count(line => !line.StartsWith('#') && line.Contains(' '));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,18 +10,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="xunit" />
|
||||
<PackageReference Include="xunit.runner.visualstudio">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="FluentAssertions" />
|
||||
<PackageReference Include="coverlet.collector">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using StellaOps.Doctor.Engine;
|
||||
using StellaOps.Doctor.Models;
|
||||
using StellaOps.Doctor.Output;
|
||||
using StellaOps.Doctor.Packs;
|
||||
using StellaOps.Doctor.Plugins;
|
||||
using StellaOps.Doctor.WebService.Contracts;
|
||||
using StellaOps.Doctor.WebService.Options;
|
||||
@@ -36,18 +39,34 @@ public sealed class DoctorRunServiceTests
|
||||
|
||||
private static DoctorEngine CreateMockEngine()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Doctor:Evidence:Enabled"] = "false"
|
||||
})
|
||||
.Build();
|
||||
|
||||
var packLoader = new DoctorPackLoader(
|
||||
new Mock<IDoctorPackCommandRunner>().Object,
|
||||
NullLogger<DoctorPackLoader>.Instance);
|
||||
|
||||
var registry = new CheckRegistry(
|
||||
Enumerable.Empty<IDoctorPlugin>(),
|
||||
packLoader,
|
||||
NullLogger<CheckRegistry>.Instance);
|
||||
|
||||
var executor = new CheckExecutor(NullLogger<CheckExecutor>.Instance, TimeProvider.System);
|
||||
var evidenceWriter = new DoctorEvidenceLogWriter(
|
||||
configuration,
|
||||
NullLogger<DoctorEvidenceLogWriter>.Instance);
|
||||
|
||||
return new DoctorEngine(
|
||||
registry,
|
||||
executor,
|
||||
new Mock<IServiceProvider>().Object,
|
||||
new Mock<Microsoft.Extensions.Configuration.IConfiguration>().Object,
|
||||
configuration,
|
||||
TimeProvider.System,
|
||||
evidenceWriter,
|
||||
NullLogger<DoctorEngine>.Instance);
|
||||
}
|
||||
|
||||
@@ -105,8 +124,7 @@ public sealed class DoctorRunServiceTests
|
||||
var result = await service.GetRunResultAsync(runId, CancellationToken.None);
|
||||
|
||||
result.Should().NotBeNull();
|
||||
// Note: RunId may differ between running/completed states due to engine having its own runId
|
||||
result!.RunId.Should().StartWith("dr_");
|
||||
result!.RunId.Should().Be(runId);
|
||||
result.Status.Should().BeOneOf("running", "completed");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user