Files
git.stella-ops.org/docs/aoc/guard-library.md
master 9e5e958d42
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
feat: Document completed tasks for KMS, Cryptography, and Plugin Libraries
- 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.
2025-10-31 14:33:05 +02:00

4.6 KiB
Raw Blame History

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 emit AocGuardResult.
  • 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() — throws AocGuardException when 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 RFC7807 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. The payloadSelector can yield multiple payloads (e.g. batch ingestion) and the filter will validate each one.
  • Wrap guard exceptions with AocHttpResults.Problem to 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.RequiredTopLevelFields when staging new schema changes. All configured names are case-insensitive.
  • Set RequireSignatureMetadata = false for 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 via AocHttpResults.
  • CI must run stella aoc verify once 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 BEBase Platform guild and reference WEB-AOC-19-001.