feat: Implement Runtime Facts ingestion service and NDJSON reader
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Added RuntimeFactsNdjsonReader for reading NDJSON formatted runtime facts.
- Introduced IRuntimeFactsIngestionService interface and its implementation.
- Enhanced Program.cs to register new services and endpoints for runtime facts.
- Updated CallgraphIngestionService to include CAS URI in stored artifacts.
- Created RuntimeFactsValidationException for validation errors during ingestion.
- Added tests for RuntimeFactsIngestionService and RuntimeFactsNdjsonReader.
- Implemented SignalsSealedModeMonitor for compliance checks in sealed mode.
- Updated project dependencies for testing utilities.
This commit is contained in:
master
2025-11-10 07:56:15 +02:00
parent 9df52d84aa
commit 69c59defdc
132 changed files with 19718 additions and 9334 deletions

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
@@ -155,6 +156,48 @@ public sealed class SurfaceManifestStageExecutorTests
context.Analysis.Set(ScanAnalysisKeys.LayerComponentFragments, ImmutableArray.Create(fragment));
}
[Fact]
public async Task ExecuteAsync_IncludesDenoObservationPayloadWhenPresent()
{
var metrics = new ScannerWorkerMetrics();
var publisher = new TestSurfaceManifestPublisher("tenant-a");
var cache = new RecordingSurfaceCache();
var environment = new TestSurfaceEnvironment("tenant-a");
var hash = new DefaultCryptoHash();
var executor = new SurfaceManifestStageExecutor(
publisher,
cache,
environment,
metrics,
NullLogger<SurfaceManifestStageExecutor>.Instance,
hash);
var context = CreateContext();
var observationBytes = Encoding.UTF8.GetBytes("{\"entrypoints\":[\"mod.ts\"]}");
var metadata = new Dictionary<string, string?>
{
["deno.observation.hash"] = "sha256:abc",
["deno.observation.entrypoints"] = "1"
};
var observation = new AnalyzerObservationPayload(
analyzerId: "deno",
kind: "deno.observation",
mediaType: "application/json",
content: observationBytes,
metadata: metadata,
view: "observations");
context.Analysis.Set(ScanAnalysisKeys.DenoObservationPayload, observation);
await executor.ExecuteAsync(context, CancellationToken.None);
Assert.Equal(1, publisher.PublishCalls);
var request = Assert.NotNull(publisher.LastRequest);
Assert.Contains(request.Payloads, payload => payload.Kind == "deno.observation");
Assert.Contains(cache.Entries.Keys, key => key.Namespace == "surface.artifacts.deno.observation");
}
private sealed class RecordingSurfaceCache : ISurfaceCache
{
private readonly Dictionary<SurfaceCacheKey, byte[]> _entries = new();