feat: Implement air-gap functionality with timeline impact and evidence snapshot services
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
- Added AirgapTimelineImpact, AirgapTimelineImpactInput, and AirgapTimelineImpactResult records for managing air-gap bundle import impacts. - Introduced EvidenceSnapshotRecord, EvidenceSnapshotLinkInput, and EvidenceSnapshotLinkResult records for linking findings to evidence snapshots. - Created IEvidenceSnapshotRepository interface for managing evidence snapshot records. - Developed StalenessValidationService to validate staleness and enforce freshness thresholds. - Implemented AirgapTimelineService for emitting timeline events related to bundle imports. - Added EvidenceSnapshotService for linking findings to evidence snapshots and verifying their validity. - Introduced AirGapOptions for configuring air-gap staleness enforcement and thresholds. - Added minimal jsPDF stub for offline/testing builds in the web application. - Created TypeScript definitions for jsPDF to enhance type safety in the web application.
This commit is contained in:
@@ -59,6 +59,21 @@ internal static class LedgerMetrics
|
||||
"ledger_attachments_encryption_failures_total",
|
||||
description: "Count of attachment encryption/signing/upload failures.");
|
||||
|
||||
private static readonly Histogram<double> AirgapStalenessSeconds = Meter.CreateHistogram<double>(
|
||||
"ledger_airgap_staleness_seconds",
|
||||
unit: "s",
|
||||
description: "Current staleness of air-gap imported data by domain.");
|
||||
|
||||
private static readonly Counter<long> StalenessValidationFailures = Meter.CreateCounter<long>(
|
||||
"ledger_staleness_validation_failures_total",
|
||||
description: "Count of staleness validation failures blocking exports.");
|
||||
|
||||
private static readonly ObservableGauge<double> AirgapStalenessGauge =
|
||||
Meter.CreateObservableGauge("ledger_airgap_staleness_gauge_seconds", ObserveAirgapStaleness, unit: "s",
|
||||
description: "Current staleness of air-gap data by domain.");
|
||||
|
||||
private static readonly ConcurrentDictionary<string, double> AirgapStalenessByDomain = new(StringComparer.Ordinal);
|
||||
|
||||
private static readonly ObservableGauge<double> ProjectionLagGauge =
|
||||
Meter.CreateObservableGauge("ledger_projection_lag_seconds", ObserveProjectionLag, unit: "s",
|
||||
description: "Lag between ledger recorded_at and projection application time.");
|
||||
@@ -228,6 +243,27 @@ internal static class LedgerMetrics
|
||||
public static void RecordProjectionLag(TimeSpan lag, string? tenantId) =>
|
||||
UpdateProjectionLag(tenantId, lag.TotalSeconds);
|
||||
|
||||
public static void RecordAirgapStaleness(string? domainId, long stalenessSeconds)
|
||||
{
|
||||
var key = string.IsNullOrWhiteSpace(domainId) ? "unknown" : domainId;
|
||||
var tags = new KeyValuePair<string, object?>[]
|
||||
{
|
||||
new("domain", key)
|
||||
};
|
||||
AirgapStalenessSeconds.Record(stalenessSeconds, tags);
|
||||
AirgapStalenessByDomain[key] = stalenessSeconds;
|
||||
}
|
||||
|
||||
public static void RecordStalenessValidationFailure(string? domainId)
|
||||
{
|
||||
var key = string.IsNullOrWhiteSpace(domainId) ? "unknown" : domainId;
|
||||
var tags = new KeyValuePair<string, object?>[]
|
||||
{
|
||||
new("domain", key)
|
||||
};
|
||||
StalenessValidationFailures.Add(1, tags);
|
||||
}
|
||||
|
||||
private static IEnumerable<Measurement<double>> ObserveProjectionLag()
|
||||
{
|
||||
foreach (var kvp in ProjectionLagByTenant)
|
||||
@@ -267,6 +303,14 @@ internal static class LedgerMetrics
|
||||
new KeyValuePair<string, object?>("git_sha", GitSha));
|
||||
}
|
||||
|
||||
private static IEnumerable<Measurement<double>> ObserveAirgapStaleness()
|
||||
{
|
||||
foreach (var kvp in AirgapStalenessByDomain)
|
||||
{
|
||||
yield return new Measurement<double>(kvp.Value, new KeyValuePair<string, object?>("domain", kvp.Key));
|
||||
}
|
||||
}
|
||||
|
||||
private static string NormalizeRole(string role) => string.IsNullOrWhiteSpace(role) ? "unspecified" : role.ToLowerInvariant();
|
||||
|
||||
private static string NormalizeTenant(string? tenantId) => string.IsNullOrWhiteSpace(tenantId) ? string.Empty : tenantId;
|
||||
|
||||
Reference in New Issue
Block a user