save development progress

This commit is contained in:
StellaOps Bot
2025-12-25 23:09:58 +02:00
parent d71853ad7e
commit aa70af062e
351 changed files with 37683 additions and 150156 deletions

View File

@@ -97,6 +97,26 @@ public sealed class AlertService : IAlertService
return MapToAlert(finding);
}
/// <summary>
/// Gets a specific alert by ID (tenant extracted from alert ID).
/// </summary>
public Task<Alert?> GetAlertAsync(
string alertId,
CancellationToken cancellationToken = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(alertId);
// Extract tenant from alert ID format: tenant|artifact|vuln
var tenantId = GetTenantIdFromAlert(alertId);
return GetAsync(tenantId, alertId, cancellationToken);
}
private static string GetTenantIdFromAlert(string alertId)
{
var parts = alertId.Split('|');
return parts.Length > 0 ? parts[0] : "default";
}
private static Alert MapToAlert(ScoredFinding finding)
{
// Compute band based on risk score

View File

@@ -0,0 +1,70 @@
using Microsoft.Extensions.Logging;
using StellaOps.Findings.Ledger.Domain;
namespace StellaOps.Findings.Ledger.Services;
/// <summary>
/// Service for evidence bundle operations.
/// </summary>
public sealed class EvidenceBundleService : IEvidenceBundleService
{
private readonly ILogger<EvidenceBundleService> _logger;
public EvidenceBundleService(ILogger<EvidenceBundleService> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
/// <inheritdoc />
public Task<EvidenceBundle?> GetBundleAsync(
string tenantId,
string alertId,
CancellationToken cancellationToken = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(tenantId);
ArgumentException.ThrowIfNullOrWhiteSpace(alertId);
_logger.LogDebug("Getting evidence bundle for alert {AlertId} in tenant {TenantId}", alertId, tenantId);
// Placeholder implementation - returns null indicating bundle not found
return Task.FromResult<EvidenceBundle?>(null);
}
/// <inheritdoc />
public Task<EvidenceBundleContent?> CreateBundleAsync(
string alertId,
CancellationToken cancellationToken = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(alertId);
_logger.LogDebug("Creating evidence bundle for alert {AlertId}", alertId);
// Placeholder implementation - returns null indicating bundle cannot be created
// Full implementation would gather evidence artifacts and create a tar.gz archive
return Task.FromResult<EvidenceBundleContent?>(null);
}
/// <inheritdoc />
public Task<EvidenceBundleVerificationResult> VerifyBundleAsync(
string alertId,
string bundleHash,
string? signature,
CancellationToken cancellationToken = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(alertId);
ArgumentException.ThrowIfNullOrWhiteSpace(bundleHash);
_logger.LogDebug("Verifying evidence bundle for alert {AlertId} with hash {Hash}", alertId, bundleHash);
// Placeholder implementation - returns valid result
// Full implementation would verify hash integrity and signature
return Task.FromResult(new EvidenceBundleVerificationResult
{
IsValid = true,
HashValid = true,
SignatureValid = signature is not null,
ChainValid = true,
Errors = null
});
}
}

View File

@@ -22,6 +22,13 @@ public interface IAlertService
string tenantId,
string alertId,
CancellationToken cancellationToken = default);
/// <summary>
/// Gets a specific alert by ID (tenant from context).
/// </summary>
Task<Alert?> GetAlertAsync(
string alertId,
CancellationToken cancellationToken = default);
}
/// <summary>

View File

@@ -14,4 +14,72 @@ public interface IEvidenceBundleService
string tenantId,
string alertId,
CancellationToken cancellationToken = default);
/// <summary>
/// Creates an evidence bundle for download.
/// </summary>
Task<EvidenceBundleContent?> CreateBundleAsync(
string alertId,
CancellationToken cancellationToken = default);
/// <summary>
/// Verifies an evidence bundle.
/// </summary>
Task<EvidenceBundleVerificationResult> VerifyBundleAsync(
string alertId,
string bundleHash,
string? signature,
CancellationToken cancellationToken = default);
}
/// <summary>
/// Content for an evidence bundle download.
/// </summary>
public sealed class EvidenceBundleContent
{
/// <summary>
/// Bundle content stream.
/// </summary>
public required Stream Content { get; init; }
/// <summary>
/// Content type.
/// </summary>
public string ContentType { get; init; } = "application/gzip";
/// <summary>
/// File name for download.
/// </summary>
public string? FileName { get; init; }
}
/// <summary>
/// Result of bundle verification.
/// </summary>
public sealed class EvidenceBundleVerificationResult
{
/// <summary>
/// Overall validity.
/// </summary>
public required bool IsValid { get; init; }
/// <summary>
/// Whether the signature is valid.
/// </summary>
public bool SignatureValid { get; init; }
/// <summary>
/// Whether the hash is valid.
/// </summary>
public bool HashValid { get; init; }
/// <summary>
/// Whether the chain is valid.
/// </summary>
public bool ChainValid { get; init; }
/// <summary>
/// List of errors, if any.
/// </summary>
public IReadOnlyList<string>? Errors { get; init; }
}