Status: done
As a a system, I want all security-relevant and operational events captured by a shared logging service, so that audit history is uniformly available across all application features from day one without per-feature implementation.
Campaign_Tracker.Server/campaign-tracker-client/_bmad-output/implementation-artifacts/_bmad-output/planning-artifacts/epics.md (Epic 1 / Story 1.5)_bmad-output/planning-artifacts/architecture.md_bmad-output/planning-artifacts/ux-design-specification.mdclaude-sonnet-4-6
IAuditService + AuditEvent general-purpose contract. AuditEventType constants centralise event names (SESSION_LOGIN, SESSION_LOGOUT, etc.). Interface is intentionally append-only: only Record() and GetRecent() — no delete or update methods (AC #4).AppendOnlyFileAuditService: writes JSON Lines to daily-rotating .jsonl files in a configurable directory. Files are never deleted by the service (AC #2). Record() wraps IO failures in AuditServiceUnavailableException and propagates, blocking the caller (AC #5).InMemoryAuthenticationAuditStore to accept IAuditService via constructor injection. Each Record*() method enqueues to the in-memory queue (for fast test assertions) AND calls IAuditService.Record() for durable persistence. Exceptions from IAuditService.Record() propagate to the caller per AC #5.IAuditService → AppendOnlyFileAuditService in Program.cs. Log directory is configurable via Audit:LogDirectory configuration key (defaults to <ContentRoot>/audit-logs).InMemoryAuthenticationAuditStore now uses constructor DI for IAuditService — satisfies AC #3 (calling features use shared contract, not own persistence).AuthEndpointTests to use AuthIntegrationTestFactory (custom WebApplicationFactory subclass) that injects an in-memory IAuditService passthrough. This keeps integration tests file-system-independent while the real file service is validated by AuditServiceTests. AC #5 integration test confirms that a failing IAuditService blocks the authenticated session endpoint.GetRecent has bounded argument handling, token exchange/refresh paths write shared audit events, and authorization allowed/challenged/denied outcomes are centrally audited.dotnet test .\Campaign_Tracker.Server.Tests\Campaign_Tracker.Server.Tests.csproj /p:UseAppHost=false passed (86 tests).dotnet build .\campaign-tracker.sln /p:UseAppHost=false passed with 0 warnings and 0 errors.Campaign_Tracker.Server/Audit/IAuditService.csCampaign_Tracker.Server/Audit/AppendOnlyFileAuditService.csCampaign_Tracker.Server/Controllers/AuthTokenController.csCampaign_Tracker.Server/Authorization/AuthorizationAuditResultHandler.csCampaign_Tracker.Server/Authentication/InMemoryAuthenticationAuditStore.csCampaign_Tracker.Server/Program.csCampaign_Tracker.Server.Tests/AuditServiceTests.csCampaign_Tracker.Server.Tests/AuthEndpointTests.cs_bmad-output/implementation-artifacts/1-5-shared-audit-logging-infrastructure.md_bmad-output/implementation-artifacts/sprint-status.yaml| Date | Version | Description | Author |
|---|---|---|---|
| 2026-05-05 | 1.0 | Implemented shared audit logging infrastructure: IAuditService, AppendOnlyFileAuditService, InMemoryAuthenticationAuditStore refactor, Program.cs registration, AuditServiceTests, AuthEndpointTests refactor. 23/23 tests passing. | Amelia (Dev) |
| 2026-05-06 | 1.1 | Applied code-review fixes for UTC normalization, required-field validation, token/authorization audit coverage, and bounded recent-event retrieval. 86/86 backend tests passing. | GPT-5 Codex |
Powered by TurnKey Linux.