feat(mcp): resolve per-run tokens in MCP auth + register TaskRunMcpService

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-06-04 15:57:12 +02:00
parent 9d133e227b
commit f3052dc5fc
3 changed files with 64 additions and 7 deletions

View File

@@ -0,0 +1,44 @@
using ClaudeDo.Data.Repositories;
using ClaudeDo.Worker.Planning;
using ClaudeDo.Worker.Runner;
using ClaudeDo.Worker.Tests.Infrastructure;
using Microsoft.AspNetCore.Http;
using Xunit;
namespace ClaudeDo.Worker.Tests.Hub;
public sealed class TaskRunTokenAuthTests : IDisposable
{
private readonly DbFixture _db = new();
public void Dispose() => _db.Dispose();
[Fact]
public async Task Valid_taskRun_token_populates_TaskRunContext_and_calls_next()
{
var reg = new TaskRunTokenRegistry();
reg.Register("run-token", "task-1");
bool nextCalled = false;
var mw = new PlanningTokenAuthMiddleware(_ => { nextCalled = true; return Task.CompletedTask; });
var ctx = new DefaultHttpContext();
ctx.Request.Path = "/mcp";
ctx.Request.Headers["Authorization"] = "Bearer run-token";
using var db = _db.CreateContext();
await mw.InvokeAsync(ctx, new TaskRepository(db), reg);
Assert.True(nextCalled);
var resolved = ctx.Items["TaskRunContext"] as TaskRunMcpContext;
Assert.NotNull(resolved);
Assert.Equal("task-1", resolved!.CallerTaskId);
}
[Fact]
public async Task Unknown_token_returns_401()
{
var mw = new PlanningTokenAuthMiddleware(_ => Task.CompletedTask);
var ctx = new DefaultHttpContext();
ctx.Request.Path = "/mcp";
ctx.Request.Headers["Authorization"] = "Bearer nope";
using var db = _db.CreateContext();
await mw.InvokeAsync(ctx, new TaskRepository(db), new TaskRunTokenRegistry());
Assert.Equal(401, ctx.Response.StatusCode);
}
}