feat(mediator): add persisted sample auditing#790
Conversation
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Removed the explicit generator TypeConverter path in b5d8e79. Native Minimal API binding rejects |
…plicit API naming
There was a problem hiding this comment.
Pull request overview
Adds persisted, queryable auditing to the MediatorFramework sample, and extends the Minimal API generator + OpenAPI conventions to support richer query/route binding (type-converter-based values, enum-as-string, and string collection query params) needed by the new audit query endpoint.
Changes:
- Persist audit records (SQL + in-memory) alongside greeting mutations and expose a paged audit query endpoint contract.
- Extend Minimal API generator + OpenAPI conventions for type-converter-wrapped parameters and string collection query binding.
- Add/adjust tests (generator snapshots + behavioral scenario) and update task tracker/docs.
Reviewed changes
Copilot reviewed 30 out of 34 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Ark.Tools.MediatorFramework.Tests/MinimalApiHostingExtensionsTests.cs | Adds runtime binding/OpenAPI tests for type-converter wrappers and enum string binding. |
| tests/Ark.Tools.MediatorFramework.Tests/GeneratorSnapshotTests.cs | Adds generator snapshots for string collection binding, type-converter wrapping, and enum handling. |
| src/mediator-framework/Ark.Tools.MediatorFramework.MinimalApi/ArkTypeConverterValue.cs | Introduces parameter wrapper using TypeConverter binding + endpoint metadata for OpenAPI. |
| src/mediator-framework/Ark.Tools.MediatorFramework.MinimalApi/ArkOpenApiEx.cs | Adds OpenAPI transformer to emit schemas for wrapped CLR types. |
| src/mediator-framework/Ark.Tools.MediatorFramework.MinimalApi.Generators/MinimalApiEndpointGenerator.cs | Updates generator binding strategy (collections, type converters, GET/DELETE bindings). |
| src/common/Ark.Tools.Nodatime/NodaTimeConverters.cs | Adds NodaTimeConverter.Register() facade for NodaTime TypeConverter registration. |
| src/common/Ark.Tools.Nodatime.Protobuf/Ark.Tools.Nodatime.Protobuf.csproj | Normalizes proto import path separators. |
| samples/Ark.MediatorFramework.Sample/test/Ark.MediatorFramework.Sample.Tests/Steps/GreetingSteps.cs | Adds step verifying audit records via HTTP query (including timestamp filter). |
| samples/Ark.MediatorFramework.Sample/test/Ark.MediatorFramework.Sample.Tests/Features/Greetings.feature | Adds scenario asserting persisted audit visibility after greeting creation. |
| samples/Ark.MediatorFramework.Sample/test/Ark.MediatorFramework.Sample.Tests/Ark.MediatorFramework.Sample.Tests.csproj | Fixes database project reference path. |
| samples/Ark.MediatorFramework.Sample/test/Ark.MediatorFramework.Sample.GrpcClient/Ark.MediatorFramework.Sample.GrpcClient.csproj | Normalizes proto import paths for cross-platform builds. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.WebInterface/SampleStartup.cs | Registers NodaTime type converters and wires new OpenAPI transformer. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.WebInterface/SampleJsonSerializerContext.cs | Adds JSON source-gen metadata for audit query/records and paged result. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Database/Security/Schemas.sql | Adds ops schema for test reset procedure. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Database/Script.PostDeployment.sql | Adds post-deploy guard for DB existence. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Database/packages.lock.json | Adds lockfile for DB project (restore locked mode compatibility). |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Database/ops/ResetFull_OnlyForTesting.sql | Extends reset procedure to clear new Audit table. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Database/dbo/Tables/Outbox.sql | Adds Outbox table definition to DB project. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Database/dbo/Tables/Greeting.sql | Adds AuditId column to greeting storage. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Database/dbo/Tables/Audit.sql | Adds Audit table definition. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Database/Ark.MediatorFramework.Sample.Database.sqlproj | Adds ProjectGuid to DB project (but currently all-zero). |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Application/SampleDataContext.cs | Writes/reads audits transactionally; adds audit paging/query logic; persists AuditId with greetings. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Application/GreetingStore.cs | Extends store interface for audit persistence/query; adds in-memory audit queue. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Application/GreetingHandlers.cs | Writes audit entries on greeting mutations and adds GetAuditsHandler. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Application/GreetingContracts.cs | Adds AuditId to GreetingResponse contract. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Application/AuditValidators.cs | Adds paging validation for audit query (needs Sort validation too). |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Application/AuditContracts.cs | Adds audit entry/record contracts and GetAuditsQuery endpoint contract. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Application/ApplicationComposition.cs | Registers clock and audit query handler. |
| samples/Ark.MediatorFramework.Sample/README.md | Updates database project path reference. |
| docs/mediator-framework/tasks/sample-parity/SMP-03-persisted-auditing.md | Marks SMP-03 acceptance items as completed. |
| docs/mediator-framework/tasks/README.md | Marks SMP-03 complete and adds GEN-07/GEN-08 to task list. |
| docs/mediator-framework/tasks/generator-dx/GEN-08-from-assembly-api-names.md | Adds new release-blocker task doc. |
| docs/mediator-framework/tasks/generator-dx/GEN-07-automatic-proto-export.md | Adds new release-blocker task doc. |
| .vscode/launch.json | Adds a launch profile for the sample web interface. |
Comments suppressed due to low confidence (1)
samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Database/Ark.MediatorFramework.Sample.Database.sqlproj:15
- ProjectGuid is set to all zeros, which is not a stable unique project identifier and can confuse tooling/MSBuild (compare Ark.Reference.Core.Database.sqlproj which uses a real GUID). Either remove this element or replace it with a real, unique GUID.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Andrea Cuneo <kaildio@gmail.com>
| <CompatibilityMode>160</CompatibilityMode> | ||
| <EnableDefaultSqlItems>false</EnableDefaultSqlItems> | ||
| <IsPackable>false</IsPackable> | ||
| <ProjectGuid>{00000000-0000-0000-0000-000000000000}</ProjectGuid> |
There was a problem hiding this comment.
Replaced the all-zeros placeholder with a valid random GUID (A3F7C251-8E14-4B9D-BE62-5D1F2C830947) in the latest commit.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 30 out of 34 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Application/GreetingStore.cs:153
- InMemoryGreetingStore assigns a new Guid to AuditRecord.Id instead of using the provided AuditEntry.Id. This breaks correlation with GreetingResponse.AuditId and diverges from the SQL store behavior (which persists audit.Id).
_audits.Enqueue(new AuditRecord
{
Id = Guid.NewGuid(),
UserId = audit.UserId,
EntityType = audit.EntityType,
Identifier = audit.Identifier,
Operation = audit.Operation,
Timestamp = audit.Timestamp,
});
samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Database/Ark.MediatorFramework.Sample.Database.sqlproj:14
- ProjectGuid is set to the all-zero GUID, which is not a valid unique project identifier and can cause tooling/solution conflicts. Use a real, stable GUID (see Ark.Reference.Core.Database.sqlproj for precedent).
…Api generator MinimalApi natively handles TypeConverter-backed types when they are string-convertible, so the generator wrapper (ArkTypeConverterValue<T>) is not needed. The ArkTypeConverterValue class is retained for manual use. - Remove RequiresTypeConverterBinding method and PropertyModel field - Simplify BindingType/BindingValue to drop TypeConverter paths - Rename/update snapshot test to verify direct binding for unknown types - Fix sqlproj ProjectGuid placeholder with valid random GUID Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Removed |
…for route and query parameters
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 30 out of 34 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.Application/GreetingStore.cs:148
- In-memory audit records should preserve the provided AuditEntry.Id so callers can correlate GreetingResponse.AuditId / audit entry IDs with queried AuditRecord.Id. Generating a new Guid here breaks that correlation and diverges from the SQL store behavior.
_audits.Enqueue(new AuditRecord
{
Id = Guid.NewGuid(),
UserId = audit.UserId,
The mediator sample only tracked audits with an in-memory counter. Implement persisted, transactional auditing with a queryable HTTP endpoint, matching the SMP-03 task requirements.
Audit persistence
Audittable and test reset support.Audit query
GET /api/v{version}/audits.SkipandLimit.Coverage