diff --git a/JobTrackerApi/Controllers/ProfileCvController.cs b/JobTrackerApi/Controllers/ProfileCvController.cs
index 65d50ba..a599d69 100644
--- a/JobTrackerApi/Controllers/ProfileCvController.cs
+++ b/JobTrackerApi/Controllers/ProfileCvController.cs
@@ -883,6 +883,10 @@ public sealed class ProfileCvController : ControllerBase
return run;
}
+ // Invoked by CvProcessingHostedService (this controller is also registered as a
+ // transient service). NonAction keeps it off the HTTP surface: without it the
+ // controller-level [Route] exposes it as an any-verb endpoint.
+ [NonAction]
public async Task ProcessQueuedRunAsync(int runId, CancellationToken cancellationToken)
{
var run = await _db.CvExtractionRuns.FirstOrDefaultAsync(x => x.Id == runId, cancellationToken);
diff --git a/JobTrackerApi/JobTrackerApi.csproj b/JobTrackerApi/JobTrackerApi.csproj
index 5cd7b4c..feaf612 100644
--- a/JobTrackerApi/JobTrackerApi.csproj
+++ b/JobTrackerApi/JobTrackerApi.csproj
@@ -11,6 +11,7 @@
+
diff --git a/JobTrackerApi/Program.cs b/JobTrackerApi/Program.cs
index 6a36ce0..13400eb 100644
--- a/JobTrackerApi/Program.cs
+++ b/JobTrackerApi/Program.cs
@@ -112,6 +112,7 @@ builder.Services.AddCors(options =>
// Add controllers
builder.Services.AddControllers();
+builder.Services.AddOpenApi();
var dataRoot = (builder.Configuration["Data:Root"] ?? "").Trim();
if (string.IsNullOrWhiteSpace(dataRoot))
{
@@ -441,4 +442,10 @@ app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
+// API schema for tooling/docs. Dev-only: not exposed in production deployments.
+if (app.Environment.IsDevelopment())
+{
+ app.MapOpenApi().AllowAnonymous();
+}
+
app.Run();