feat: Add documentation and task tracking for Sprints 508 to 514 in Ops & Offline

- Created detailed markdown files for Sprints 508 (Ops Offline Kit), 509 (Samples), 510 (AirGap), 511 (Api), 512 (Bench), 513 (Provenance), and 514 (Sovereign Crypto Enablement) outlining tasks, dependencies, and owners.
- Introduced a comprehensive Reachability Evidence Delivery Guide to streamline the reachability signal process.
- Implemented unit tests for Advisory AI to block known injection patterns and redact secrets.
- Added AuthoritySenderConstraintHelper to manage sender constraints in OpenIddict transactions.
This commit is contained in:
master
2025-11-08 23:18:28 +02:00
parent 536f6249a6
commit ae69b1a8a1
187 changed files with 4326 additions and 3196 deletions

View File

@@ -6,7 +6,6 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -19,6 +18,7 @@ using StellaOps.Concelier.RawModels;
using StellaOps.Concelier.Storage.Mongo;
using StellaOps.Concelier.Storage.Mongo.Documents;
using System.Text.Json;
using StellaOps.Cryptography;
namespace StellaOps.Concelier.Connector.Common.Fetch;
@@ -40,15 +40,17 @@ public sealed class SourceFetchService
private readonly IAdvisoryRawWriteGuard _guard;
private readonly IAdvisoryLinksetMapper _linksetMapper;
private readonly string _connectorVersion;
public SourceFetchService(
IHttpClientFactory httpClientFactory,
RawDocumentStorage rawDocumentStorage,
IDocumentStore documentStore,
ILogger<SourceFetchService> logger,
private readonly ICryptoHash _hash;
public SourceFetchService(
IHttpClientFactory httpClientFactory,
RawDocumentStorage rawDocumentStorage,
IDocumentStore documentStore,
ILogger<SourceFetchService> logger,
IJitterSource jitterSource,
IAdvisoryRawWriteGuard guard,
IAdvisoryLinksetMapper linksetMapper,
ICryptoHash hash,
TimeProvider? timeProvider = null,
IOptionsMonitor<SourceHttpClientOptions>? httpClientOptions = null,
IOptions<MongoStorageOptions>? storageOptions = null)
@@ -60,6 +62,7 @@ public sealed class SourceFetchService
_jitterSource = jitterSource ?? throw new ArgumentNullException(nameof(jitterSource));
_guard = guard ?? throw new ArgumentNullException(nameof(guard));
_linksetMapper = linksetMapper ?? throw new ArgumentNullException(nameof(linksetMapper));
_hash = hash ?? throw new ArgumentNullException(nameof(hash));
_timeProvider = timeProvider ?? TimeProvider.System;
_httpClientOptions = httpClientOptions ?? throw new ArgumentNullException(nameof(httpClientOptions));
_storageOptions = storageOptions ?? throw new ArgumentNullException(nameof(storageOptions));
@@ -103,7 +106,7 @@ public sealed class SourceFetchService
}
var contentBytes = await response.Content.ReadAsByteArrayAsync(cancellationToken).ConfigureAwait(false);
var contentHash = Convert.ToHexString(SHA256.HashData(contentBytes)).ToLowerInvariant();
var contentHash = _hash.ComputeHashHex(contentBytes, HashAlgorithms.Sha256);
var fetchedAt = _timeProvider.GetUtcNow();
var contentType = response.Content.Headers.ContentType?.ToString();

View File

@@ -1,10 +1,10 @@
using System.Security.Cryptography;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using MongoDB.Bson;
using StellaOps.Concelier.Connector.Common.Fetch;
using StellaOps.Concelier.Storage.Mongo;
using StellaOps.Concelier.Storage.Mongo.Documents;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using MongoDB.Bson;
using StellaOps.Concelier.Connector.Common.Fetch;
using StellaOps.Concelier.Storage.Mongo;
using StellaOps.Concelier.Storage.Mongo.Documents;
using StellaOps.Cryptography;
namespace StellaOps.Concelier.Connector.Common.State;
@@ -15,23 +15,26 @@ public sealed class SourceStateSeedProcessor
{
private readonly IDocumentStore _documentStore;
private readonly RawDocumentStorage _rawDocumentStorage;
private readonly ISourceStateRepository _stateRepository;
private readonly TimeProvider _timeProvider;
private readonly ILogger<SourceStateSeedProcessor> _logger;
public SourceStateSeedProcessor(
IDocumentStore documentStore,
RawDocumentStorage rawDocumentStorage,
ISourceStateRepository stateRepository,
TimeProvider? timeProvider = null,
ILogger<SourceStateSeedProcessor>? logger = null)
{
_documentStore = documentStore ?? throw new ArgumentNullException(nameof(documentStore));
_rawDocumentStorage = rawDocumentStorage ?? throw new ArgumentNullException(nameof(rawDocumentStorage));
_stateRepository = stateRepository ?? throw new ArgumentNullException(nameof(stateRepository));
_timeProvider = timeProvider ?? TimeProvider.System;
_logger = logger ?? NullLogger<SourceStateSeedProcessor>.Instance;
}
private readonly ISourceStateRepository _stateRepository;
private readonly TimeProvider _timeProvider;
private readonly ILogger<SourceStateSeedProcessor> _logger;
private readonly ICryptoHash _hash;
public SourceStateSeedProcessor(
IDocumentStore documentStore,
RawDocumentStorage rawDocumentStorage,
ISourceStateRepository stateRepository,
ICryptoHash hash,
TimeProvider? timeProvider = null,
ILogger<SourceStateSeedProcessor>? logger = null)
{
_documentStore = documentStore ?? throw new ArgumentNullException(nameof(documentStore));
_rawDocumentStorage = rawDocumentStorage ?? throw new ArgumentNullException(nameof(rawDocumentStorage));
_stateRepository = stateRepository ?? throw new ArgumentNullException(nameof(stateRepository));
_hash = hash ?? throw new ArgumentNullException(nameof(hash));
_timeProvider = timeProvider ?? TimeProvider.System;
_logger = logger ?? NullLogger<SourceStateSeedProcessor>.Instance;
}
public async Task<SourceStateSeedResult> ProcessAsync(SourceStateSeedSpecification specification, CancellationToken cancellationToken)
{
@@ -138,7 +141,7 @@ public sealed class SourceStateSeedProcessor
_logger.LogWarning("Seed document URI '{Uri}' does not appear to be absolute.", document.Uri);
}
var sha256 = Convert.ToHexString(SHA256.HashData(payload)).ToLowerInvariant();
var contentHash = _hash.ComputeHashHex(payload, HashAlgorithms.Sha256);
var existing = await _documentStore.FindBySourceAndUriAsync(source, document.Uri, cancellationToken).ConfigureAwait(false);
@@ -168,12 +171,12 @@ public sealed class SourceStateSeedProcessor
var metadata = CloneDictionary(document.Metadata);
var record = new DocumentRecord(
document.DocumentId ?? existing?.Id ?? Guid.NewGuid(),
source,
document.Uri,
document.FetchedAt ?? completedAt,
sha256,
var record = new DocumentRecord(
document.DocumentId ?? existing?.Id ?? Guid.NewGuid(),
source,
document.Uri,
document.FetchedAt ?? completedAt,
contentHash,
string.IsNullOrWhiteSpace(document.Status) ? DocumentStatuses.PendingParse : document.Status,
document.ContentType,
headers,
@@ -181,9 +184,9 @@ public sealed class SourceStateSeedProcessor
document.Etag,
document.LastModified,
gridId,
document.ExpiresAt);
var upserted = await _documentStore.UpsertAsync(record, cancellationToken).ConfigureAwait(false);
document.ExpiresAt);
var upserted = await _documentStore.UpsertAsync(record, cancellationToken).ConfigureAwait(false);
documentIds.Add(upserted.Id);

View File

@@ -17,6 +17,7 @@
<ProjectReference Include="..\StellaOps.Concelier.Storage.Mongo\StellaOps.Concelier.Storage.Mongo.csproj" />
<ProjectReference Include="..\StellaOps.Concelier.Normalization\StellaOps.Concelier.Normalization.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.Plugin/StellaOps.Plugin.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.Cryptography/StellaOps.Cryptography.csproj" />
<ProjectReference Include="..\StellaOps.Concelier.Core\StellaOps.Concelier.Core.csproj" />
</ItemGroup>
</Project>
</Project>