Frontend gaps fill work. Testing fixes work. Auditing in progress.
This commit is contained in:
137
src/VexLens/StellaOps.VexLens.WebService/Program.cs
Normal file
137
src/VexLens/StellaOps.VexLens.WebService/Program.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
using Serilog;
|
||||
using StellaOps.VexLens.Api;
|
||||
using StellaOps.VexLens.Consensus;
|
||||
using StellaOps.VexLens.Persistence;
|
||||
using StellaOps.VexLens.Storage;
|
||||
using StellaOps.VexLens.Trust;
|
||||
using StellaOps.VexLens.WebService.Extensions;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Configure Serilog
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.ReadFrom.Configuration(builder.Configuration)
|
||||
.Enrich.FromLogContext()
|
||||
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
|
||||
.CreateLogger();
|
||||
|
||||
builder.Host.UseSerilog();
|
||||
|
||||
// Configure OpenAPI
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddOpenApi();
|
||||
|
||||
// Configure OpenTelemetry
|
||||
builder.Services.AddOpenTelemetry()
|
||||
.ConfigureResource(resource => resource.AddService("StellaOps.VexLens"))
|
||||
.WithTracing(tracing =>
|
||||
{
|
||||
tracing
|
||||
.AddAspNetCoreInstrumentation()
|
||||
.AddHttpClientInstrumentation();
|
||||
|
||||
if (builder.Environment.IsDevelopment())
|
||||
{
|
||||
tracing.AddConsoleExporter();
|
||||
}
|
||||
});
|
||||
|
||||
// Configure VexLens services
|
||||
builder.Services.AddSingleton<IVexConsensusEngine, DefaultVexConsensusEngine>();
|
||||
builder.Services.AddSingleton<ITrustWeightEngine, DefaultTrustWeightEngine>();
|
||||
builder.Services.AddSingleton<IConsensusProjectionStore, InMemoryConsensusProjectionStore>();
|
||||
builder.Services.AddSingleton<IIssuerDirectory, InMemoryIssuerDirectory>();
|
||||
builder.Services.AddSingleton<IVexStatementProvider, NullVexStatementProvider>();
|
||||
builder.Services.AddScoped<IVexLensApiService, VexLensApiService>();
|
||||
|
||||
// Configure PostgreSQL persistence if configured
|
||||
var connectionString = builder.Configuration.GetConnectionString("VexLens");
|
||||
if (!string.IsNullOrEmpty(connectionString))
|
||||
{
|
||||
builder.Services.AddSingleton<IConsensusProjectionStore>(sp =>
|
||||
new PostgresConsensusProjectionStore(connectionString, "vexlens"));
|
||||
builder.Services.AddSingleton<IIssuerDirectory>(sp =>
|
||||
new PostgresIssuerDirectory(connectionString, "vexlens"));
|
||||
}
|
||||
|
||||
// Configure health checks
|
||||
builder.Services.AddHealthChecks();
|
||||
|
||||
// Configure rate limiting
|
||||
builder.Services.AddRateLimiter(options =>
|
||||
{
|
||||
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
||||
options.AddFixedWindowLimiter("vexlens", limiterOptions =>
|
||||
{
|
||||
limiterOptions.PermitLimit = 100;
|
||||
limiterOptions.Window = TimeSpan.FromMinutes(1);
|
||||
});
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure request pipeline
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.MapOpenApi();
|
||||
}
|
||||
|
||||
app.UseRateLimiter();
|
||||
app.UseSerilogRequestLogging();
|
||||
|
||||
// Map health check endpoint
|
||||
app.MapHealthChecks("/health", new HealthCheckOptions
|
||||
{
|
||||
ResponseWriter = async (context, report) =>
|
||||
{
|
||||
context.Response.ContentType = "application/json";
|
||||
var result = new
|
||||
{
|
||||
status = report.Status.ToString(),
|
||||
checks = report.Entries.Select(e => new
|
||||
{
|
||||
name = e.Key,
|
||||
status = e.Value.Status.ToString(),
|
||||
description = e.Value.Description
|
||||
})
|
||||
};
|
||||
await context.Response.WriteAsJsonAsync(result);
|
||||
}
|
||||
});
|
||||
|
||||
// Map VexLens API endpoints
|
||||
app.MapVexLensEndpoints();
|
||||
|
||||
// Log startup
|
||||
Log.Information("VexLens WebService starting on {Urls}", string.Join(", ", app.Urls));
|
||||
|
||||
try
|
||||
{
|
||||
app.Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, "VexLens WebService terminated unexpectedly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Null implementation for development without VexHub integration.
|
||||
/// </summary>
|
||||
internal sealed class NullVexStatementProvider : IVexStatementProvider
|
||||
{
|
||||
public Task<IReadOnlyList<VexStatementWithContext>> GetStatementsAsync(
|
||||
string vulnerabilityId,
|
||||
string productKey,
|
||||
string? tenantId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult<IReadOnlyList<VexStatementWithContext>>([]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user