up
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Replay.Core;
|
||||
using StellaOps.Scanner.WebService.Domain;
|
||||
using StellaOps.Scanner.WebService.Services;
|
||||
|
||||
namespace StellaOps.Scanner.WebService.Replay;
|
||||
|
||||
internal interface IRecordModeService
|
||||
{
|
||||
Task<(ReplayRunRecord Run, IReadOnlyList<ReplayBundleRecord> Bundles)> BuildAsync(
|
||||
string scanId,
|
||||
ReplayManifest manifest,
|
||||
ReplayBundleWriteResult inputBundle,
|
||||
ReplayBundleWriteResult outputBundle,
|
||||
string sbomDigest,
|
||||
string findingsDigest,
|
||||
string? vexDigest = null,
|
||||
string? logDigest = null,
|
||||
IEnumerable<(ReplayBundleWriteResult Result, string Type)>? additionalBundles = null);
|
||||
|
||||
Task<ReplayArtifacts?> AttachAsync(
|
||||
ScanId scanId,
|
||||
ReplayManifest manifest,
|
||||
ReplayBundleWriteResult inputBundle,
|
||||
ReplayBundleWriteResult outputBundle,
|
||||
string sbomDigest,
|
||||
string findingsDigest,
|
||||
IScanCoordinator coordinator,
|
||||
string? vexDigest = null,
|
||||
string? logDigest = null,
|
||||
IEnumerable<(ReplayBundleWriteResult Result, string Type)>? additionalBundles = null,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Replay.Core;
|
||||
using StellaOps.Scanner.Core.Replay;
|
||||
using StellaOps.Scanner.WebService.Domain;
|
||||
using StellaOps.Scanner.WebService.Services;
|
||||
|
||||
namespace StellaOps.Scanner.WebService.Replay;
|
||||
|
||||
/// <summary>
|
||||
/// Prepares replay run metadata from WebService scan results. This is a thin façade that will be invoked
|
||||
/// once record-mode wiring lands in the scan pipeline.
|
||||
/// </summary>
|
||||
internal sealed class RecordModeService : IRecordModeService
|
||||
{
|
||||
private readonly RecordModeAssembler _assembler;
|
||||
|
||||
public RecordModeService(TimeProvider? timeProvider = null)
|
||||
{
|
||||
_assembler = new RecordModeAssembler(timeProvider);
|
||||
}
|
||||
|
||||
public Task<(ReplayRunRecord Run, IReadOnlyList<ReplayBundleRecord> Bundles)> BuildAsync(
|
||||
string scanId,
|
||||
ReplayManifest manifest,
|
||||
ReplayBundleWriteResult inputBundle,
|
||||
ReplayBundleWriteResult outputBundle,
|
||||
string sbomDigest,
|
||||
string findingsDigest,
|
||||
string? vexDigest = null,
|
||||
string? logDigest = null,
|
||||
IEnumerable<(ReplayBundleWriteResult Result, string Type)>? additionalBundles = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(manifest);
|
||||
|
||||
var run = _assembler.BuildRun(scanId, manifest, sbomDigest, findingsDigest, vexDigest, logDigest);
|
||||
var bundles = _assembler.BuildBundles(inputBundle, outputBundle, additionalBundles);
|
||||
|
||||
return Task.FromResult((run, bundles));
|
||||
}
|
||||
|
||||
public async Task<ReplayArtifacts?> AttachAsync(
|
||||
ScanId scanId,
|
||||
ReplayManifest manifest,
|
||||
ReplayBundleWriteResult inputBundle,
|
||||
ReplayBundleWriteResult outputBundle,
|
||||
string sbomDigest,
|
||||
string findingsDigest,
|
||||
IScanCoordinator coordinator,
|
||||
string? vexDigest = null,
|
||||
string? logDigest = null,
|
||||
IEnumerable<(ReplayBundleWriteResult Result, string Type)>? additionalBundles = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(coordinator);
|
||||
|
||||
var (run, bundles) = await BuildAsync(
|
||||
scanId.Value,
|
||||
manifest,
|
||||
inputBundle,
|
||||
outputBundle,
|
||||
sbomDigest,
|
||||
findingsDigest,
|
||||
vexDigest,
|
||||
logDigest,
|
||||
additionalBundles).ConfigureAwait(false);
|
||||
|
||||
var replay = BuildArtifacts(run.ManifestHash, bundles);
|
||||
var attached = await coordinator.AttachReplayAsync(scanId, replay, cancellationToken).ConfigureAwait(false);
|
||||
return attached ? replay : null;
|
||||
}
|
||||
|
||||
private static ReplayArtifacts BuildArtifacts(string manifestHash, IReadOnlyList<ReplayBundleRecord> bundles)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(manifestHash);
|
||||
ArgumentNullException.ThrowIfNull(bundles);
|
||||
|
||||
var summaries = bundles
|
||||
.Select(bundle => new ReplayBundleSummary(
|
||||
bundle.Type,
|
||||
NormalizeDigest(bundle.Id),
|
||||
bundle.Location,
|
||||
bundle.Size))
|
||||
.ToList();
|
||||
|
||||
return new ReplayArtifacts(manifestHash, summaries);
|
||||
}
|
||||
|
||||
private static string NormalizeDigest(string digest)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(digest))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var trimmed = digest.Trim().ToLowerInvariant();
|
||||
return trimmed.StartsWith("sha256:", StringComparison.Ordinal)
|
||||
? trimmed
|
||||
: $"sha256:{trimmed}";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user