- Added detailed task completion records for KMS interface implementation and CLI support for file-based keys. - Documented security enhancements including Argon2id password hashing, audit event contracts, and rate limiting configurations. - Included scoped service support and integration updates for the Plugin platform, ensuring proper DI handling and testing coverage.
		
			
				
	
	
	
		
			4.6 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	Aggregation-Only Guard Library Reference
Packages:
StellaOps.Aoc,StellaOps.Aoc.AspNetCore
Related tasks:WEB-AOC-19-001,WEB-AOC-19-003,DEVOPS-AOC-19-001
Audience: Concelier/Excititor service owners, Platform guild, QA
The Aggregation-Only Contract (AOC) guard library enforces the canonical ingestion
rules described in docs/ingestion/aggregation-only-contract.md. Service owners
should use the guard whenever raw advisory or VEX payloads are accepted so that
forbidden fields are rejected long before they reach MongoDB.
Packages
StellaOps.Aoc
IAocGuard/AocWriteGuard— validate JSON payloads and emitAocGuardResult.AocGuardOptions— toggles for signature enforcement, tenant requirements, and required top-level fields.AocViolation/AocViolationCode— structured violations surfaced to callers.ServiceCollectionExtensions.AddAocGuard()— DI helper that registers the singleton guard.AocGuardExtensions.ValidateOrThrow()— throwsAocGuardExceptionwhen validation fails.
StellaOps.Aoc.AspNetCore
AocGuardEndpointFilter<TRequest>— Minimal API endpoint filter that evaluates request payloads through the guard before invoking handlers.AocHttpResults.Problem()— Produces a RFC 7807 payload that includes violation codes, suitable for API responses.
Minimal API integration
using StellaOps.Aoc;
using StellaOps.Aoc.AspNetCore.Routing;
using StellaOps.Aoc.AspNetCore.Results;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAocGuard();
builder.Services.Configure<AocGuardOptions>(options =>
{
    options.RequireSignatureMetadata = true;
    options.RequireTenant = true;
});
var app = builder.Build();
app.MapPost("/ingest", async (IngestionRequest request, IAocGuard guard, ILogger<Program> logger) =>
    {
        // additional application logic
        return Results.Accepted();
    })
    .AddEndpointFilter(new AocGuardEndpointFilter<IngestionRequest>(
        request => new object?[] { request.Payload },
        serializerOptions: null,
        guardOptions: null))
    .ProducesProblem(StatusCodes.Status400BadRequest)
    .WithTags("AOC");
app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        var exceptionHandler = context.Features.Get<IExceptionHandlerFeature>();
        if (exceptionHandler?.Error is AocGuardException guardException)
        {
            var result = AocHttpResults.Problem(context, guardException);
            await result.ExecuteAsync(context);
            return;
        }
        context.Response.StatusCode = StatusCodes.Status500InternalServerError;
    });
});
Key points:
- Register the guard singleton before wiring repositories or worker services.
 - Use 
AocGuardEndpointFilter<TRequest>to protect Minimal API endpoints. ThepayloadSelectorcan yield multiple payloads (e.g. batch ingestion) and the filter will validate each one. - Wrap guard exceptions with 
AocHttpResults.Problemto ensure clients receive machine-readables codes (ERR_AOC_00x). 
Worker / repository usage
Inject IAocGuard (or a module-specific wrapper such as IVexRawWriteGuard) anywhere documents
are persisted. Call ValidateOrThrow before writes to guarantee fail-fast behaviour, for example:
public sealed class AdvisoryRawRepository
{
    private readonly IAocGuard _guard;
    public AdvisoryRawRepository(IAocGuard guard) => _guard = guard;
    public Task WriteAsync(JsonDocument document, CancellationToken cancellationToken)
    {
        _guard.ValidateOrThrow(document.RootElement);
        // proceed with storage logic
    }
}
Configuration tips
- Adjust 
AocGuardOptions.RequiredTopLevelFieldswhen staging new schema changes. All configured names are case-insensitive. - Set 
RequireSignatureMetadata = falsefor legacy feeds that do not provide signature envelopes yet; track the waiver in the module backlog. - Use module-specific wrappers (
AddConcelierAocGuards,AddExcititorAocGuards) to combine guard registration with domain exceptions and metrics. 
Testing guidance
- Unit-test guard behaviour with fixture payloads (see 
src/Aoc/__Tests). - Service-level tests should assert that ingestion endpoints return 
ERR_AOC_*codes viaAocHttpResults. - CI must run 
stella aoc verifyonce CLI support lands (DEVOPS-AOC-19-002). - Roslyn analyzer enforcement (
WEB-AOC-19-003) will ensure the guard is registered; keep services wired through the shared extensions to prepare for that gate. 
For questions or updates, coordinate with the BE‑Base Platform guild and reference WEB-AOC-19-001.