4.7 KiB
4.7 KiB
Step 7 Output: Audit Logging & Webhooks
Summary
Implemented the full audit logging and webhook system for MicCheck.
What Was Built
Audit Logging
AuditService—RecordAsynccaptures before/after state as{"before":{...},"after":{...}}JSON inAuditLog.Changes. Serializes withSystem.Text.Json(camelCase). EnqueuesAUDIT_LOG_CREATEDwebhook event after persisting. Methods arevirtualfor Moq compatibility.AuditLogQueryService— Separate query service withListByOrganizationAsync,ListByProjectAsync, andListByEnvironmentAsync. All return(int Total, IReadOnlyList<AuditLog> Items)tuples. Filtering viaAuditLogFilterrecord (date range, resource type, action, project/environment/actor).AuditLogFilter— Record with optional filter fields and pagination (Page,PageSize).AuditLogsController— Updated to accept[FromQuery] AuditLogFilterand returnPaginatedResponse<AuditLogResponse>.EnvironmentsController— AddedGET /{apiKey}/audit-logsendpoint.
Webhooks
WebhookEvent/WebhookEventTypes— Event model withEventType,EnvironmentId,OrganizationId,Data. Three event types:FLAG_UPDATED,FLAG_DELETED,AUDIT_LOG_CREATED.WebhookPayload— Snake_case serialized payload withdataandevent_typefields. Nested records:FlagUpdatedData,FlagDeletedData,FlagStateSnapshot,FeatureSummary,EnvironmentSummary.WebhookQueue— SingletonSystem.Threading.Channels-backed queue.EnqueueAsyncis non-blocking;ReadAllAsyncconsumed by background service.WebhookDispatcher— Scoped service. Finds active webhooks by environment + org scope, serializes payload, signs with HMAC-SHA256 (X-Flagsmith-Signature: sha256=<hex>), POSTs with 10s timeout viaIHttpClientFactory, logsWebhookDeliveryLogwithAttemptNumber.WebhookBackgroundService—BackgroundServicereading from queue, dispatching via scopedWebhookDispatcher.WebhookRetryBackgroundService— Polls every 60s. Retries failed deliveries: attempt 1→2 after 5 min, 2→3 after 30 min, max 3 total.WebhookDeliveryLog— AddedAttemptNumberproperty.WebhookService— AddedListByOrganizationAsync,CreateForOrganizationAsync,ListDeliveriesAsync.WebhookDeliveryLogResponse— New response DTO.
Admin Endpoints Added
GET /api/v1/environments/{apiKey}/webhooks/{id}/deliveries
GET /api/v1/organisations/{id}/webhooks
POST /api/v1/organisations/{id}/webhooks
PUT /api/v1/organisations/{id}/webhooks/{id}
DELETE /api/v1/organisations/{id}/webhooks/{id}
Service Updates
FeatureService— Constructor now takesWebhookQueue.DeleteAsyncfiresFLAG_DELETEDevents per environment.RecordAsyncused with before/after.FeatureStateService— Constructor now takesWebhookQueueandAuditService.UpdateAsyncandPatchAsynccapture before state and dispatchFLAG_UPDATED+ audit record.
Program.cs
Added registrations:
WebhookDispatcher(scoped)WebhookQueue(singleton)WebhookBackgroundService(hosted)WebhookRetryBackgroundService(hosted)AddHttpClient("Webhooks")withUser-AgentheaderJsonStringEnumConverterfor string enum deserializationApiBehaviorOptionsfor 422 validation error format
Migration
Added AddWebhookDeliveryAttemptNumber migration for the new AttemptNumber column on WebhookDeliveryLog.
Tests Added
| File | Tests |
|---|---|
Audit/AuditServiceTests.cs |
5 — null changes, after-only diff, before+after diff, metadata persistence, webhook event enqueued |
Webhooks/WebhookDispatcherTests.cs |
6 — signature computation, delivery without webhooks, delivery logging |
Webhooks/WebhookRetryTests.cs |
4 — retry delay values, max attempts, eligibility |
Total: 166 tests passing.
Acceptance Criteria Status
- Every create/update/delete in the Admin API produces an
AuditLogrecord - Audit logs correctly capture before/after state for updates
GET /api/v1/organisations/{id}/audit-logs/returns paginated, filtered results- Audit controllers map
AuditLogdomain objects toAuditLogResponseDTOs - Webhooks fire within 1 second of a flag state change (async via Channel)
- HMAC-SHA256 signature is correct and verifiable by receivers
- Failed webhook deliveries are logged with status code and response body
- Retry logic attempts delivery 3 times with backoff (5 min, 30 min)
- Webhook delivery does not block the API response (fire-and-forget via
WebhookQueue) - Unit tests cover: signature computation, payload serialization, retry scheduling
- Unit tests cover: audit diff generation for create/update/delete scenarios