sprints work

This commit is contained in:
master
2026-01-10 20:32:13 +02:00
parent 0d5eda86fc
commit 17d0631b8e
189 changed files with 40667 additions and 497 deletions

View File

@@ -0,0 +1,150 @@
// <copyright file="InMemoryEvidencePackStore.cs" company="StellaOps">
// Copyright (c) StellaOps. Licensed under the AGPL-3.0-or-later.
// </copyright>
using System.Collections.Concurrent;
using StellaOps.Evidence.Pack.Models;
namespace StellaOps.Evidence.Pack.Storage;
/// <summary>
/// In-memory implementation of <see cref="IEvidencePackStore"/> for testing.
/// Sprint: SPRINT_20260109_011_005 Task: EVPK-005
/// </summary>
public sealed class InMemoryEvidencePackStore : IEvidencePackStore
{
private readonly ConcurrentDictionary<string, EvidencePack> _packs = new();
private readonly ConcurrentDictionary<string, SignedEvidencePack> _signedPacks = new();
private readonly ConcurrentDictionary<string, List<string>> _runLinks = new();
/// <inheritdoc/>
public Task SaveAsync(EvidencePack pack, CancellationToken cancellationToken)
{
_packs[pack.PackId] = pack;
return Task.CompletedTask;
}
/// <inheritdoc/>
public Task SaveSignedAsync(SignedEvidencePack signedPack, CancellationToken cancellationToken)
{
_signedPacks[signedPack.Pack.PackId] = signedPack;
return Task.CompletedTask;
}
/// <inheritdoc/>
public Task<EvidencePack?> GetByIdAsync(string tenantId, string packId, CancellationToken cancellationToken)
{
// Wildcard tenant search
if (tenantId == "*")
{
return Task.FromResult(_packs.TryGetValue(packId, out var pack) ? pack : null);
}
if (_packs.TryGetValue(packId, out var p) && p.TenantId == tenantId)
{
return Task.FromResult<EvidencePack?>(p);
}
return Task.FromResult<EvidencePack?>(null);
}
/// <inheritdoc/>
public Task<SignedEvidencePack?> GetSignedByIdAsync(string tenantId, string packId, CancellationToken cancellationToken)
{
// Wildcard tenant search
if (tenantId == "*")
{
return Task.FromResult(_signedPacks.TryGetValue(packId, out var pack) ? pack : null);
}
if (_signedPacks.TryGetValue(packId, out var sp) && sp.Pack.TenantId == tenantId)
{
return Task.FromResult<SignedEvidencePack?>(sp);
}
return Task.FromResult<SignedEvidencePack?>(null);
}
/// <inheritdoc/>
public Task<IReadOnlyList<EvidencePack>> ListAsync(
string tenantId,
EvidencePackQuery? query,
CancellationToken cancellationToken)
{
var results = _packs.Values
.Where(p => p.TenantId == tenantId);
if (query is not null)
{
if (!string.IsNullOrEmpty(query.CveId))
{
results = results.Where(p => p.Subject.CveId == query.CveId);
}
if (!string.IsNullOrEmpty(query.Component))
{
results = results.Where(p => p.Subject.Component == query.Component);
}
if (!string.IsNullOrEmpty(query.RunId))
{
var packIds = _runLinks.TryGetValue(query.RunId, out var ids)
? ids.ToHashSet()
: new HashSet<string>();
results = results.Where(p => packIds.Contains(p.PackId));
}
if (query.Since.HasValue)
{
results = results.Where(p => p.CreatedAt >= query.Since.Value);
}
results = results.Take(query.Limit);
}
return Task.FromResult<IReadOnlyList<EvidencePack>>(
results.OrderByDescending(p => p.CreatedAt).ToList());
}
/// <inheritdoc/>
public Task LinkToRunAsync(string packId, string runId, CancellationToken cancellationToken)
{
var links = _runLinks.GetOrAdd(runId, _ => new List<string>());
lock (links)
{
if (!links.Contains(packId))
{
links.Add(packId);
}
}
return Task.CompletedTask;
}
/// <inheritdoc/>
public Task<IReadOnlyList<EvidencePack>> GetByRunIdAsync(string runId, CancellationToken cancellationToken)
{
if (!_runLinks.TryGetValue(runId, out var packIds))
{
return Task.FromResult<IReadOnlyList<EvidencePack>>(Array.Empty<EvidencePack>());
}
var packs = packIds
.Select(id => _packs.TryGetValue(id, out var pack) ? pack : null)
.Where(p => p is not null)
.Cast<EvidencePack>()
.OrderByDescending(p => p.CreatedAt)
.ToList();
return Task.FromResult<IReadOnlyList<EvidencePack>>(packs);
}
/// <summary>
/// Clears all stored data (for testing).
/// </summary>
public void Clear()
{
_packs.Clear();
_signedPacks.Clear();
_runLinks.Clear();
}
}