Files
git.stella-ops.org/docs/aoc/guard-library.md
master a1ce3f74fa
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Implement MongoDB-based storage for Pack Run approval, artifact, log, and state management
- Added MongoPackRunApprovalStore for managing approval states with MongoDB.
- Introduced MongoPackRunArtifactUploader for uploading and storing artifacts.
- Created MongoPackRunLogStore to handle logging of pack run events.
- Developed MongoPackRunStateStore for persisting and retrieving pack run states.
- Implemented unit tests for MongoDB stores to ensure correct functionality.
- Added MongoTaskRunnerTestContext for setting up MongoDB test environment.
- Enhanced PackRunStateFactory to correctly initialize state with gate reasons.
2025-11-07 10:01:47 +02:00

131 lines
5.7 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.
- `AocError` — canonical error DTO (`code`, `message`, `violations[]`) re-used by HTTP helpers, CLI tooling, and telemetry.
- `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
```csharp
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.
- Prefer the `RequireAocGuard` extension when wiring endpoints; it wraps `AddEndpointFilter`
and handles single-payload scenarios without additional boilerplate.
- Wrap guard exceptions with `AocHttpResults.Problem` to ensure clients receive machine-readable codes (`ERR_AOC_00x`). The helper now emits the serialized `AocError` under the `error` extension for consumers that want a typed payload.
### Allowed top-level fields
`AocWriteGuard` enforces the contracts top-level allowlist: `_id`, `tenant`, `source`, `upstream`,
`content`, `identifiers`, `linkset`, `supersedes`, `createdAt`/`created_at`, `ingestedAt`/`ingested_at`, and `attributes`.
Unknown fields produce `ERR_AOC_007` violations. When staging schema changes, extend the allowlist through
`AocGuardOptions.AllowedTopLevelFields`:
```csharp
builder.Services.Configure<AocGuardOptions>(options =>
{
options.AllowedTopLevelFields =
options.AllowedTopLevelFields.Add("experimental_field");
});
```
## 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:
```csharp
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.
- Extend `AllowedTopLevelFields` for temporary schema experiments so that guard runs stay clean while the contract is updated.
- 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`.