up
Some checks failed
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-12-12 09:35:37 +02:00
parent ce5ec9c158
commit efaf3cb789
238 changed files with 146274 additions and 5767 deletions

View File

@@ -4,7 +4,6 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using NetEscapades.Configuration.Yaml;
using StellaOps.Auth.Abstractions;
using StellaOps.Auth.ServerIntegration;
@@ -82,49 +81,7 @@ builder.Services.AddProblemDetails();
builder.Services.AddHealthChecks();
builder.Services.AddRouting(options => options.LowercaseUrls = true);
builder.Services.AddSingleton<IMongoClient>(sp =>
{
var opts = sp.GetRequiredService<IOptions<SignalsOptions>>().Value;
return new MongoClient(opts.Mongo.ConnectionString);
});
builder.Services.AddSingleton<IMongoDatabase>(sp =>
{
var opts = sp.GetRequiredService<IOptions<SignalsOptions>>().Value;
var mongoClient = sp.GetRequiredService<IMongoClient>();
var mongoUrl = MongoUrl.Create(opts.Mongo.ConnectionString);
var databaseName = string.IsNullOrWhiteSpace(mongoUrl.DatabaseName) ? opts.Mongo.Database : mongoUrl.DatabaseName;
return mongoClient.GetDatabase(databaseName);
});
builder.Services.AddSingleton<IMongoCollection<CallgraphDocument>>(sp =>
{
var opts = sp.GetRequiredService<IOptions<SignalsOptions>>().Value;
var database = sp.GetRequiredService<IMongoDatabase>();
var collection = database.GetCollection<CallgraphDocument>(opts.Mongo.CallgraphsCollection);
EnsureCallgraphIndexes(collection);
return collection;
});
builder.Services.AddSingleton<IMongoCollection<ReachabilityFactDocument>>(sp =>
{
var opts = sp.GetRequiredService<IOptions<SignalsOptions>>().Value;
var database = sp.GetRequiredService<IMongoDatabase>();
var collection = database.GetCollection<ReachabilityFactDocument>(opts.Mongo.ReachabilityFactsCollection);
EnsureReachabilityFactIndexes(collection);
return collection;
});
builder.Services.AddSingleton<IMongoCollection<UnknownSymbolDocument>>(sp =>
{
var opts = sp.GetRequiredService<IOptions<SignalsOptions>>().Value;
var database = sp.GetRequiredService<IMongoDatabase>();
var collection = database.GetCollection<UnknownSymbolDocument>(opts.Mongo.UnknownsCollection);
EnsureUnknownsIndexes(collection);
return collection;
});
builder.Services.AddSingleton<ICallgraphRepository, MongoCallgraphRepository>();
builder.Services.AddSingleton<ICallgraphRepository, InMemoryCallgraphRepository>();
builder.Services.AddSingleton<ICallgraphNormalizationService, CallgraphNormalizationService>();
// Configure callgraph artifact storage based on driver
@@ -160,7 +117,6 @@ builder.Services.AddSingleton<ICallgraphParser>(new SimpleJsonCallgraphParser("p
builder.Services.AddSingleton<ICallgraphParser>(new SimpleJsonCallgraphParser("go"));
builder.Services.AddSingleton<ICallgraphParserResolver, CallgraphParserResolver>();
builder.Services.AddSingleton<ICallgraphIngestionService, CallgraphIngestionService>();
builder.Services.AddSingleton<MongoReachabilityFactRepository>();
builder.Services.AddSingleton<IReachabilityCache>(sp =>
{
var options = sp.GetRequiredService<IOptions<SignalsOptions>>().Value;
@@ -168,6 +124,14 @@ builder.Services.AddSingleton<IReachabilityCache>(sp =>
});
builder.Services.AddSingleton<IRedisConnectionFactory, RedisConnectionFactory>();
builder.Services.AddSingleton<ReachabilityFactEventBuilder>();
builder.Services.AddSingleton<InMemoryReachabilityFactRepository>();
builder.Services.AddSingleton<IReachabilityFactRepository>(sp =>
{
var inner = sp.GetRequiredService<InMemoryReachabilityFactRepository>();
var cache = sp.GetRequiredService<IReachabilityCache>();
return new ReachabilityFactCacheDecorator(inner, cache);
});
builder.Services.AddSingleton<IUnknownsRepository, InMemoryUnknownsRepository>();
builder.Services.AddHttpClient<RouterEventsPublisher>((sp, client) =>
{
var opts = sp.GetRequiredService<SignalsOptions>().Events.Router;
@@ -221,18 +185,12 @@ builder.Services.AddSingleton<IEventsPublisher>(sp =>
sp.GetRequiredService<ILogger<InMemoryEventsPublisher>>(),
eventBuilder);
});
builder.Services.AddSingleton<IReachabilityFactRepository>(sp =>
{
var inner = sp.GetRequiredService<MongoReachabilityFactRepository>();
var cache = sp.GetRequiredService<IReachabilityCache>();
return new ReachabilityFactCacheDecorator(inner, cache);
});
builder.Services.AddSingleton<IReachabilityScoringService, ReachabilityScoringService>();
builder.Services.AddSingleton<IRuntimeFactsProvenanceNormalizer, RuntimeFactsProvenanceNormalizer>();
builder.Services.AddSingleton<IRuntimeFactsIngestionService, RuntimeFactsIngestionService>();
builder.Services.AddSingleton<IReachabilityUnionIngestionService, ReachabilityUnionIngestionService>();
builder.Services.AddSingleton<IUnknownsRepository, MongoUnknownsRepository>();
builder.Services.AddSingleton<IUnknownsIngestionService, UnknownsIngestionService>();
builder.Services.AddSingleton<SyntheticRuntimeProbeBuilder>();
if (bootstrap.Authority.Enabled)
{
@@ -488,6 +446,56 @@ signalsGroup.MapPost("/runtime-facts", async Task<IResult> (
}
}).WithName("SignalsRuntimeIngest");
signalsGroup.MapPost("/runtime-facts/synthetic", async Task<IResult> (
HttpContext context,
SignalsOptions options,
SyntheticRuntimeProbeRequest request,
ICallgraphRepository callgraphRepository,
IRuntimeFactsIngestionService ingestionService,
SyntheticRuntimeProbeBuilder probeBuilder,
SignalsSealedModeMonitor sealedModeMonitor,
CancellationToken cancellationToken) =>
{
if (!Program.TryAuthorize(context, SignalsPolicies.Write, options.Authority.AllowAnonymousFallback, out var authFailure))
{
return authFailure ?? Results.Unauthorized();
}
if (!Program.TryEnsureSealedMode(sealedModeMonitor, out var sealedFailure))
{
return sealedFailure ?? Results.StatusCode(StatusCodes.Status503ServiceUnavailable);
}
if (string.IsNullOrWhiteSpace(request.CallgraphId))
{
return Results.BadRequest(new { error = "callgraphId is required." });
}
var callgraph = await callgraphRepository.GetByIdAsync(request.CallgraphId.Trim(), cancellationToken).ConfigureAwait(false);
if (callgraph is null)
{
return Results.NotFound(new { error = "callgraph not found." });
}
var subject = request.Subject ?? new ReachabilitySubject { ScanId = $"synthetic-{callgraph.Id}" };
var events = probeBuilder.BuildEvents(callgraph, request.EventCount);
var metadata = request.Metadata is null
? new Dictionary<string, string?>(StringComparer.Ordinal)
: new Dictionary<string, string?>(request.Metadata, StringComparer.Ordinal);
metadata.TryAdd("source", "synthetic-probe");
var ingestRequest = new RuntimeFactsIngestRequest
{
CallgraphId = callgraph.Id,
Subject = subject,
Events = events,
Metadata = metadata
};
var response = await ingestionService.IngestAsync(ingestRequest, cancellationToken).ConfigureAwait(false);
return Results.Accepted($"/signals/runtime-facts/{response.SubjectKey}", response);
}).WithName("SignalsRuntimeIngestSynthetic");
signalsGroup.MapPost("/reachability/union", async Task<IResult> (
HttpContext context,
SignalsOptions options,
@@ -808,55 +816,6 @@ public partial class Program
return false;
}
internal static void EnsureCallgraphIndexes(IMongoCollection<CallgraphDocument> collection)
{
ArgumentNullException.ThrowIfNull(collection);
try
{
var indexKeys = Builders<CallgraphDocument>.IndexKeys
.Ascending(document => document.Component)
.Ascending(document => document.Version)
.Ascending(document => document.Language);
var model = new CreateIndexModel<CallgraphDocument>(indexKeys, new CreateIndexOptions
{
Name = "callgraphs_component_version_language_unique",
Unique = true
});
collection.Indexes.CreateOne(model);
}
catch (MongoCommandException ex) when (string.Equals(ex.CodeName, "IndexOptionsConflict", StringComparison.Ordinal))
{
// Index already exists with different options ignore to keep startup idempotent.
}
}
internal static void EnsureReachabilityFactIndexes(IMongoCollection<ReachabilityFactDocument> collection)
{
ArgumentNullException.ThrowIfNull(collection);
try
{
var subjectIndex = new CreateIndexModel<ReachabilityFactDocument>(
Builders<ReachabilityFactDocument>.IndexKeys.Ascending(doc => doc.SubjectKey),
new CreateIndexOptions { Name = "reachability_subject_key_unique", Unique = true });
collection.Indexes.CreateOne(subjectIndex);
var callgraphIndex = new CreateIndexModel<ReachabilityFactDocument>(
Builders<ReachabilityFactDocument>.IndexKeys.Ascending(doc => doc.CallgraphId),
new CreateIndexOptions { Name = "reachability_callgraph_lookup" });
collection.Indexes.CreateOne(callgraphIndex);
}
catch (MongoCommandException ex) when (string.Equals(ex.CodeName, "IndexOptionsConflict", StringComparison.Ordinal))
{
// Ignore when indexes already exist with different options to keep startup idempotent.
}
}
internal static bool TryEnsureSealedMode(SignalsSealedModeMonitor monitor, out IResult? failure)
{
if (!monitor.EnforcementEnabled)
@@ -876,31 +835,4 @@ public partial class Program
statusCode: StatusCodes.Status503ServiceUnavailable);
return false;
}
internal static void EnsureUnknownsIndexes(IMongoCollection<UnknownSymbolDocument> collection)
{
ArgumentNullException.ThrowIfNull(collection);
try
{
var subjectIndex = new CreateIndexModel<UnknownSymbolDocument>(
Builders<UnknownSymbolDocument>.IndexKeys.Ascending(doc => doc.SubjectKey),
new CreateIndexOptions { Name = "unknowns_subject_lookup" });
var dedupeIndex = new CreateIndexModel<UnknownSymbolDocument>(
Builders<UnknownSymbolDocument>.IndexKeys
.Ascending(doc => doc.SubjectKey)
.Ascending(doc => doc.SymbolId)
.Ascending(doc => doc.Purl)
.Ascending(doc => doc.EdgeFrom)
.Ascending(doc => doc.EdgeTo),
new CreateIndexOptions { Name = "unknowns_subject_symbol_edge_unique", Unique = true });
collection.Indexes.CreateMany(new[] { subjectIndex, dedupeIndex });
}
catch (MongoCommandException ex) when (string.Equals(ex.CodeName, "IndexOptionsConflict", StringComparison.Ordinal))
{
// Ignore to keep startup idempotent when index options differ.
}
}
}