Complete Entrypoint Detection Re-Engineering Program (Sprints 0410-0415) and Sprint 3500.0002.0003 (Proof Replay + API)

Entrypoint Detection Program (100% complete):
- Sprint 0411: Semantic Entrypoint Engine - all 25 tasks DONE
- Sprint 0412: Temporal & Mesh Entrypoint - all 19 tasks DONE
- Sprint 0413: Speculative Execution Engine - all 19 tasks DONE
- Sprint 0414: Binary Intelligence - all 19 tasks DONE
- Sprint 0415: Predictive Risk Scoring - all tasks DONE

Key deliverables:
- SemanticEntrypoint schema with ApplicationIntent/CapabilityClass
- TemporalEntrypointGraph and MeshEntrypointGraph
- ShellSymbolicExecutor with PathEnumerator and PathConfidenceScorer
- CodeFingerprint index with symbol recovery
- RiskScore with multi-dimensional risk assessment

Sprint 3500.0002.0003 (Proof Replay + API):
- ManifestEndpoints with DSSE content negotiation
- Proof bundle endpoints by root hash
- IdempotencyMiddleware with RFC 9530 Content-Digest
- Rate limiting (100 req/hr per tenant)
- OpenAPI documentation updates

Tests: 357 EntryTrace tests pass, WebService tests blocked by pre-existing infrastructure issue
This commit is contained in:
StellaOps Bot
2025-12-20 17:46:27 +02:00
parent ce8cdcd23d
commit 3698ebf4a8
46 changed files with 4156 additions and 46 deletions

View File

@@ -0,0 +1,274 @@
using FluentAssertions;
using Microsoft.Extensions.Logging;
using StellaOps.Signals.Models;
using StellaOps.Signals.Services;
using Xunit;
namespace StellaOps.Signals.Tests;
public class SchedulerRescanOrchestratorTests
{
private readonly MockSchedulerJobClient _mockClient = new();
private readonly FakeTimeProvider _timeProvider = new();
private readonly ILogger<SchedulerRescanOrchestrator> _logger;
private readonly SchedulerRescanOrchestrator _sut;
public SchedulerRescanOrchestratorTests()
{
_logger = LoggerFactory.Create(b => b.AddDebug()).CreateLogger<SchedulerRescanOrchestrator>();
_sut = new SchedulerRescanOrchestrator(_mockClient, _timeProvider, _logger);
}
[Fact]
public async Task TriggerRescanAsync_CreatesJobWithCorrectPriority_Immediate()
{
// Arrange
var unknown = CreateUnknown("pkg:npm/lodash@4.17.21", UnknownsBand.Hot);
// Act
var result = await _sut.TriggerRescanAsync(unknown, RescanPriority.Immediate);
// Assert
result.Success.Should().BeTrue();
_mockClient.LastRequest.Should().NotBeNull();
_mockClient.LastRequest!.Priority.Should().Be(RescanJobPriority.High);
_mockClient.LastRequest.PackageUrl.Should().Be("pkg:npm/lodash@4.17.21");
}
[Fact]
public async Task TriggerRescanAsync_CreatesJobWithCorrectPriority_Scheduled()
{
// Arrange
var unknown = CreateUnknown("pkg:maven/com.example/lib@1.0.0", UnknownsBand.Warm);
// Act
var result = await _sut.TriggerRescanAsync(unknown, RescanPriority.Scheduled);
// Assert
result.Success.Should().BeTrue();
_mockClient.LastRequest!.Priority.Should().Be(RescanJobPriority.Normal);
}
[Fact]
public async Task TriggerRescanAsync_CreatesJobWithCorrectPriority_Batch()
{
// Arrange
var unknown = CreateUnknown("pkg:nuget/newtonsoft.json@13.0.1", UnknownsBand.Cold);
// Act
var result = await _sut.TriggerRescanAsync(unknown, RescanPriority.Batch);
// Assert
result.Success.Should().BeTrue();
_mockClient.LastRequest!.Priority.Should().Be(RescanJobPriority.Low);
}
[Fact]
public async Task TriggerRescanAsync_PropagatesCorrelationId()
{
// Arrange
var unknown = CreateUnknown("pkg:pypi/requests@2.28.0", UnknownsBand.Hot);
unknown.CallgraphId = "tenant123:graph456";
// Act
await _sut.TriggerRescanAsync(unknown, RescanPriority.Immediate);
// Assert
_mockClient.LastRequest!.CorrelationId.Should().Be("tenant123:graph456");
_mockClient.LastRequest.TenantId.Should().Be("tenant123");
}
[Fact]
public async Task TriggerRescanAsync_ReturnsNextScheduledRescan_ForImmediate()
{
// Arrange
var now = new DateTimeOffset(2025, 1, 20, 10, 0, 0, TimeSpan.Zero);
_timeProvider.SetUtcNow(now);
var unknown = CreateUnknown("pkg:npm/axios@1.0.0", UnknownsBand.Hot);
// Act
var result = await _sut.TriggerRescanAsync(unknown, RescanPriority.Immediate);
// Assert
result.NextScheduledRescan.Should().Be(now.AddMinutes(15));
}
[Fact]
public async Task TriggerRescanAsync_ReturnsNextScheduledRescan_ForScheduled()
{
// Arrange
var now = new DateTimeOffset(2025, 1, 20, 10, 0, 0, TimeSpan.Zero);
_timeProvider.SetUtcNow(now);
var unknown = CreateUnknown("pkg:npm/express@4.18.0", UnknownsBand.Warm);
// Act
var result = await _sut.TriggerRescanAsync(unknown, RescanPriority.Scheduled);
// Assert
result.NextScheduledRescan.Should().Be(now.AddHours(24));
}
[Fact]
public async Task TriggerRescanAsync_ReturnsNextScheduledRescan_ForBatch()
{
// Arrange
var now = new DateTimeOffset(2025, 1, 20, 10, 0, 0, TimeSpan.Zero);
_timeProvider.SetUtcNow(now);
var unknown = CreateUnknown("pkg:npm/mocha@10.0.0", UnknownsBand.Cold);
// Act
var result = await _sut.TriggerRescanAsync(unknown, RescanPriority.Batch);
// Assert
result.NextScheduledRescan.Should().Be(now.AddDays(7));
}
[Fact]
public async Task TriggerRescanAsync_ReturnsFailure_WhenClientFails()
{
// Arrange
_mockClient.ShouldFail = true;
_mockClient.FailureMessage = "Queue unavailable";
var unknown = CreateUnknown("pkg:npm/fail@1.0.0", UnknownsBand.Hot);
// Act
var result = await _sut.TriggerRescanAsync(unknown, RescanPriority.Immediate);
// Assert
result.Success.Should().BeFalse();
result.ErrorMessage.Should().Be("Queue unavailable");
}
[Fact]
public async Task TriggerBatchRescanAsync_ProcessesAllItems()
{
// Arrange
var unknowns = new[]
{
CreateUnknown("pkg:npm/a@1.0.0", UnknownsBand.Hot),
CreateUnknown("pkg:npm/b@1.0.0", UnknownsBand.Hot),
CreateUnknown("pkg:npm/c@1.0.0", UnknownsBand.Hot)
};
// Act
var result = await _sut.TriggerBatchRescanAsync(unknowns, RescanPriority.Immediate);
// Assert
result.TotalRequested.Should().Be(3);
result.SuccessCount.Should().Be(3);
result.FailureCount.Should().Be(0);
result.Results.Should().HaveCount(3);
}
[Fact]
public async Task TriggerBatchRescanAsync_EmptyList_ReturnsEmpty()
{
// Arrange
var unknowns = Array.Empty<UnknownSymbolDocument>();
// Act
var result = await _sut.TriggerBatchRescanAsync(unknowns, RescanPriority.Immediate);
// Assert
result.TotalRequested.Should().Be(0);
result.SuccessCount.Should().Be(0);
result.FailureCount.Should().Be(0);
}
[Fact]
public async Task TriggerRescanAsync_ExtractsTenantFromCallgraphId()
{
// Arrange
var unknown = CreateUnknown("pkg:npm/test@1.0.0", UnknownsBand.Hot);
unknown.CallgraphId = "acme-corp:cg-12345";
// Act
await _sut.TriggerRescanAsync(unknown, RescanPriority.Immediate);
// Assert
_mockClient.LastRequest!.TenantId.Should().Be("acme-corp");
}
[Fact]
public async Task TriggerRescanAsync_UsesDefaultTenant_WhenNoCallgraphId()
{
// Arrange
var unknown = CreateUnknown("pkg:npm/orphan@1.0.0", UnknownsBand.Hot);
unknown.CallgraphId = null;
// Act
await _sut.TriggerRescanAsync(unknown, RescanPriority.Immediate);
// Assert
_mockClient.LastRequest!.TenantId.Should().Be("default");
}
private static UnknownSymbolDocument CreateUnknown(string purl, UnknownsBand band)
{
return new UnknownSymbolDocument
{
Id = Guid.NewGuid().ToString("N"),
SubjectKey = purl,
Purl = purl,
Band = band,
Score = band switch
{
UnknownsBand.Hot => 0.85,
UnknownsBand.Warm => 0.55,
UnknownsBand.Cold => 0.35,
_ => 0.15
}
};
}
private sealed class MockSchedulerJobClient : ISchedulerJobClient
{
public RescanJobRequest? LastRequest { get; private set; }
public bool ShouldFail { get; set; }
public string FailureMessage { get; set; } = "Mock failure";
public Task<SchedulerJobResult> CreateRescanJobAsync(
RescanJobRequest request,
CancellationToken cancellationToken = default)
{
LastRequest = request;
if (ShouldFail)
{
return Task.FromResult(SchedulerJobResult.Failed(FailureMessage));
}
var jobId = $"mock-job-{Guid.NewGuid():N}";
var runId = $"mock-run-{DateTime.UtcNow:yyyyMMddHHmmss}";
return Task.FromResult(SchedulerJobResult.Succeeded(jobId, runId));
}
public async Task<BatchSchedulerJobResult> CreateRescanJobsAsync(
IReadOnlyList<RescanJobRequest> requests,
CancellationToken cancellationToken = default)
{
var results = new List<SchedulerJobResult>();
foreach (var request in requests)
{
var result = await CreateRescanJobAsync(request, cancellationToken);
results.Add(result);
}
return new BatchSchedulerJobResult(
requests.Count,
results.Count(r => r.Success),
results.Count(r => !r.Success),
results);
}
}
private sealed class FakeTimeProvider : TimeProvider
{
private DateTimeOffset _utcNow = DateTimeOffset.UtcNow;
public void SetUtcNow(DateTimeOffset value) => _utcNow = value;
public override DateTimeOffset GetUtcNow() => _utcNow;
}
}