Rename Vexer to Excititor

This commit is contained in:
2025-10-18 20:00:46 +03:00
parent fbd1826ef3
commit 7e1b10d3b2
263 changed files with 848 additions and 848 deletions

View File

@@ -0,0 +1,25 @@
# AGENTS
## Role
ASP.NET Minimal API surface for Excititor ingest, provider administration, reconciliation, export, and verification flows.
## Scope
- Program bootstrap, DI wiring for connectors/normalizers/export/attestation/policy/storage.
- HTTP endpoints `/excititor/*` with authentication, authorization scopes, request validation, and deterministic responses.
- Job orchestration bridges for Worker hand-off (when co-hosted) and offline-friendly configuration.
- Observability (structured logs, metrics, tracing) aligned with StellaOps conventions.
## Participants
- StellaOps.Cli sends `excititor` verbs to this service via token-authenticated HTTPS.
- Worker receives scheduled jobs and uses shared infrastructure via common DI extensions.
- Authority service provides tokens; WebService enforces scopes before executing operations.
## Interfaces & contracts
- DTOs for ingest/export requests, run metadata, provider management.
- Background job interfaces for ingest/resume/reconcile triggering.
- Health/status endpoints exposing pull/export history and current policy revision.
## In/Out of scope
In: HTTP hosting, request orchestration, DI composition, auth/authorization, logging.
Out: long-running ingestion loops (Worker), export rendering (Export module), connector implementations.
## Observability & security expectations
- Enforce bearer token scopes, enforce audit logging (request/response correlation IDs, provider IDs).
- Emit structured events for ingest runs, export invocations, attestation references.
- Provide built-in counters/histograms for latency and throughput.
## Tests
- Minimal API contract/unit tests and integration harness will live in `../StellaOps.Excititor.WebService.Tests`.

View File

@@ -0,0 +1,91 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Options;
using StellaOps.Excititor.Attestation.Extensions;
using StellaOps.Excititor.Attestation;
using StellaOps.Excititor.Attestation.Transparency;
using StellaOps.Excititor.ArtifactStores.S3.Extensions;
using StellaOps.Excititor.Export;
using StellaOps.Excititor.Storage.Mongo;
using StellaOps.Excititor.Connectors.RedHat.CSAF.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;
var services = builder.Services;
services.AddOptions<VexMongoStorageOptions>()
.Bind(configuration.GetSection("Excititor:Storage:Mongo"))
.ValidateOnStart();
services.AddExcititorMongoStorage();
services.AddVexExportEngine();
services.AddVexExportCacheServices();
services.AddVexAttestation();
services.Configure<VexAttestationClientOptions>(configuration.GetSection("Excititor:Attestation:Client"));
services.AddRedHatCsafConnector();
var rekorSection = configuration.GetSection("Excititor:Attestation:Rekor");
if (rekorSection.Exists())
{
services.AddVexRekorClient(opts => rekorSection.Bind(opts));
}
var fileSystemSection = configuration.GetSection("Excititor:Artifacts:FileSystem");
if (fileSystemSection.Exists())
{
services.AddVexFileSystemArtifactStore(opts => fileSystemSection.Bind(opts));
}
else
{
services.AddVexFileSystemArtifactStore(_ => { });
}
var s3Section = configuration.GetSection("Excititor:Artifacts:S3");
if (s3Section.Exists())
{
services.AddVexS3ArtifactClient(opts => s3Section.GetSection("Client").Bind(opts));
services.AddSingleton<IVexArtifactStore, S3ArtifactStore>(provider =>
{
var options = new S3ArtifactStoreOptions();
s3Section.GetSection("Store").Bind(options);
return new S3ArtifactStore(
provider.GetRequiredService<IS3ArtifactClient>(),
Microsoft.Extensions.Options.Options.Create(options),
provider.GetRequiredService<Microsoft.Extensions.Logging.ILogger<S3ArtifactStore>>());
});
}
var offlineSection = configuration.GetSection("Excititor:Artifacts:OfflineBundle");
if (offlineSection.Exists())
{
services.AddVexOfflineBundleArtifactStore(opts => offlineSection.Bind(opts));
}
services.AddEndpointsApiExplorer();
services.AddHealthChecks();
services.AddSingleton(TimeProvider.System);
var app = builder.Build();
app.MapGet("/excititor/status", async (HttpContext context,
IEnumerable<IVexArtifactStore> artifactStores,
IOptions<VexMongoStorageOptions> mongoOptions,
TimeProvider timeProvider) =>
{
var payload = new StatusResponse(
timeProvider.GetUtcNow(),
mongoOptions.Value.RawBucketName,
mongoOptions.Value.GridFsInlineThresholdBytes,
artifactStores.Select(store => store.GetType().Name).ToArray());
context.Response.ContentType = "application/json";
await System.Text.Json.JsonSerializer.SerializeAsync(context.Response.Body, payload);
});
app.MapHealthChecks("/excititor/health");
app.Run();
public partial class Program;
internal sealed record StatusResponse(DateTimeOffset UtcNow, string MongoBucket, int InlineThreshold, string[] ArtifactStores);

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\StellaOps.Excititor.Core\StellaOps.Excititor.Core.csproj" />
<ProjectReference Include="..\StellaOps.Excititor.Storage.Mongo\StellaOps.Excititor.Storage.Mongo.csproj" />
<ProjectReference Include="..\StellaOps.Excititor.Export\StellaOps.Excititor.Export.csproj" />
<ProjectReference Include="..\StellaOps.Excititor.Attestation\StellaOps.Excititor.Attestation.csproj" />
<ProjectReference Include="..\StellaOps.Excititor.ArtifactStores.S3\StellaOps.Excititor.ArtifactStores.S3.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,8 @@
If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md).
# TASKS
| Task | Owner(s) | Depends on | Notes |
|---|---|---|---|
|EXCITITOR-WEB-01-001 Minimal API bootstrap & DI|Team Excititor WebService|EXCITITOR-CORE-01-003, EXCITITOR-STORAGE-01-003|**DONE (2025-10-17)** Minimal API host composes storage/export/attestation/artifact stores, binds Mongo/attestation options, and exposes `/excititor/status` + health endpoints with regression coverage in `StatusEndpointTests`.|
|EXCITITOR-WEB-01-002 Ingest & reconcile endpoints|Team Excititor WebService|EXCITITOR-WEB-01-001|TODO Implement `/excititor/init`, `/excititor/ingest/run`, `/excititor/ingest/resume`, `/excititor/reconcile` with token scope enforcement and structured run telemetry.|
|EXCITITOR-WEB-01-003 Export & verify endpoints|Team Excititor WebService|EXCITITOR-WEB-01-001, EXCITITOR-EXPORT-01-001, EXCITITOR-ATTEST-01-001|TODO Add `/excititor/export`, `/excititor/export/{id}`, `/excititor/export/{id}/download`, `/excititor/verify`, returning artifact + attestation metadata with cache awareness.|
|EXCITITOR-WEB-01-004 Resolve API & signed responses|Team Excititor WebService|EXCITITOR-WEB-01-001, EXCITITOR-ATTEST-01-002|TODO Deliver `/excititor/resolve` (subject/context), return consensus + score envelopes, attach cosign/Rekor metadata, and document auth + rate guardrails.|