feat(tasks): add Task CRUD API with 5-state workflow

- TaskService with CRUD operations + state machine enforcement
- 5 DTOs: TaskListDto, TaskDetailDto, CreateTaskRequest, UpdateTaskRequest
- Minimal API endpoints: GET /api/tasks, GET /api/tasks/{id}, POST, PATCH, DELETE
- State machine: Open→Assigned→InProgress→Review→Done (invalid transitions → 422)
- Concurrency: DbUpdateConcurrencyException → 409 Conflict
- Authorization: POST (Manager+), DELETE (Admin), GET/PATCH (Member+)
- RLS: Automatic tenant filtering via TenantDbConnectionInterceptor
- 10 TDD integration tests: CRUD, state transitions, concurrency, role enforcement
- Build: 0 errors (6 BouncyCastle warnings expected)

Task 14 complete. Wave 3: 2/5 tasks done.
This commit is contained in:
WorkClub Automation
2026-03-03 19:19:21 +01:00
parent cff101168c
commit 8550dd213a
9 changed files with 1035 additions and 0 deletions

View File

@@ -3,7 +3,9 @@ using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using WorkClub.Api.Auth;
using WorkClub.Api.Endpoints.Tasks;
using WorkClub.Api.Middleware;
using WorkClub.Api.Services;
using WorkClub.Application.Interfaces;
using WorkClub.Infrastructure.Data;
using WorkClub.Infrastructure.Data.Interceptors;
@@ -25,6 +27,7 @@ builder.Services.AddMultiTenant<TenantInfo>()
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<ITenantProvider, TenantProvider>();
builder.Services.AddScoped<SeedDataService>();
builder.Services.AddScoped<TaskService>();
builder.Services.AddSingleton<TenantDbConnectionInterceptor>();
builder.Services.AddSingleton<SaveChangesTenantInterceptor>();
@@ -117,6 +120,8 @@ app.MapGet("/weatherforecast", () =>
app.MapGet("/api/test", () => Results.Ok(new { message = "Test endpoint" }))
.RequireAuthorization();
app.MapTaskEndpoints();
app.Run();
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)