diff --git a/CLAUDE.md b/CLAUDE.md index 4b6c49d..b2e4e4f 100755 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -33,7 +33,7 @@ MicCheck: open source. asp.net, c#, typescript, VueJS. Manage feature flags, pro ## Testing - Min 70% code coverage, target 90%. Unit tests focus end-user scenarios first. - Don't write tests just for coverage. Call out missing coverage rather than cover stuff not valuable to end user. -- Code not cleanly unit-testable → mark `[ExcludeFromCodeCoverage]` or exclude namespace from coverage. +- Code not cleanly unit-testable → mark `[ExcludeFromCodeCoverage]` or exclude namespace from coverage in .runsettings file - BDD-style unit tests, end-to-end as possible, no external resources (DB, filesystem). e.g. `WhenAUserDoesSomething_ThenAThingAppears` - Mock external deps w/ Moq - Mock EntityFramework DBContexts via extracted interface + Moq. Don't rely on InMemory provider. @@ -50,4 +50,4 @@ MicCheck: open source. asp.net, c#, typescript, VueJS. Manage feature flags, pro - Plan implemented from `docs/plans/.md` → save summary as `docs/plans/_output.md` ## Stack -`.gitignore` set for .NET/Visual Studio (C#, NuGet, MSBuild). Update if stack change. \ No newline at end of file +`.gitignore` set for .NET/Visual Studio (C#, NuGet, MSBuild). Update if stack change. diff --git a/src/api/MicCheck.Api/Audit/AuditLogsController.cs b/src/api/MicCheck.Api/Audit/AuditLogsController.cs index cc5311e..b815d7c 100755 --- a/src/api/MicCheck.Api/Audit/AuditLogsController.cs +++ b/src/api/MicCheck.Api/Audit/AuditLogsController.cs @@ -12,17 +12,15 @@ namespace MicCheck.Api.Audit; [ApiController] [Authorize(Policy = AuthorizationPolicies.AdminApiAccess)] [EnableRateLimiting("AdminApi")] +[Route("api/v1")] public class AuditLogsController( AuditLogQueryService auditLogQueryService, OrganizationService organizationService, ProjectService projectService, EnvironmentService environmentService) : ControllerBase { - [HttpGet("api/v1/organisation/{id}/audit-logs")] - public async Task>> ListByOrganization( - int id, - [FromQuery] AuditLogFilter filter, - CancellationToken ct) + [HttpGet("organisation/{id}/audit-logs")] + public async Task>> ListByOrganization(int id, [FromQuery] AuditLogFilter filter, CancellationToken ct) { var org = await organizationService.FindByIdAsync(id, ct); if (org is null) return NotFound(); @@ -31,11 +29,8 @@ public class AuditLogsController( return Ok(new PaginatedResponse(result.Total, null, null, result.Items.ToList())); } - [HttpGet("api/v1/project/{projectId}/audit-logs")] - public async Task>> ListByProject( - int projectId, - [FromQuery] AuditLogFilter filter, - CancellationToken ct) + [HttpGet("project/{projectId}/audit-logs")] + public async Task>> ListByProject(int projectId, [FromQuery] AuditLogFilter filter, CancellationToken ct) { var project = await projectService.FindByIdAsync(projectId, ct); if (project is null) return NotFound(); @@ -44,11 +39,8 @@ public class AuditLogsController( return Ok(new PaginatedResponse(result.Total, null, null, result.Items.ToList())); } - [HttpGet("api/v1/environment/{apiKey}/audit-logs")] - public async Task>> ListByEnvironment( - string apiKey, - [FromQuery] AuditLogFilter filter, - CancellationToken ct) + [HttpGet("environment/{apiKey}/audit-logs")] + public async Task>> ListByEnvironment(string apiKey, [FromQuery] AuditLogFilter filter, CancellationToken ct) { var environment = await environmentService.FindByApiKeyAsync(apiKey, ct); if (environment is null) return NotFound(); diff --git a/src/api/MicCheck.Api/Common/Security/ApiKeys/ApiKeyResponse.cs b/src/api/MicCheck.Api/Common/Security/ApiKeys/ApiKeyResponse.cs index 3ffa955..a2289d0 100755 --- a/src/api/MicCheck.Api/Common/Security/ApiKeys/ApiKeyResponse.cs +++ b/src/api/MicCheck.Api/Common/Security/ApiKeys/ApiKeyResponse.cs @@ -1,9 +1,3 @@ namespace MicCheck.Api.Common.Security.ApiKeys; -public record ApiKeyResponse( - int Id, - string Name, - string Prefix, - bool IsActive, - DateTimeOffset? ExpiresAt, - DateTimeOffset CreatedAt); +public record ApiKeyResponse(int Id, string Name, string Prefix, bool IsActive, DateTimeOffset? ExpiresAt, DateTimeOffset CreatedAt); diff --git a/src/api/MicCheck.Api/Features/FeatureUsageController.cs b/src/api/MicCheck.Api/Features/FeatureUsageController.cs index 82c9f37..09bbc95 100644 --- a/src/api/MicCheck.Api/Features/FeatureUsageController.cs +++ b/src/api/MicCheck.Api/Features/FeatureUsageController.cs @@ -13,10 +13,7 @@ namespace MicCheck.Api.Features; public class FeatureUsageController(FeatureUsageQueryService queryService, IMemoryCache cache) : ControllerBase { [HttpGet] - public async Task> GetDashboardUsage( - int environmentId, - [FromQuery] int days = 14, - CancellationToken ct = default) + public async Task> GetDashboardUsage(int environmentId, [FromQuery] int days = 14, CancellationToken ct = default) { days = Math.Clamp(days, 1, 90); var cacheKey = $"usage-dashboard:{environmentId}:{days}";