feat: Bao/Iris-Statusrechte + Bao→Iris-Notifications + Agent-Workflow-Übersicht
- Bao darf jetzt Status ändern (neben Iris), Sub-Agents weiterhin nicht - CanEditContent für Inhaltsbearbeitung durch alle bekannten Caller - Bao-Content-Änderungen triggern task_content_changed-Notification an Iris - Bao-Status-Änderungen triggern task_status_changed-Notification an Iris - Iris-Status-Änderungen triggern task_status_changed-Notification an Bao - Neue WorkTask-Felder: IsAgentTask (bool), ExpectedFrom (string) - Agent-Workflow-API: CreateAgentTask, WaitingTasks, AgentOverview - Frontend: Agent-Task-Badge, Iris-Overview-Panel, isBao-Getter - Login-Rate-Limiter mit strukturiertem JSON-Fehlermeldungs-Body - Volume-Name: nexus-postgres → postgres-data (Standardisierung)
This commit is contained in:
@@ -6,6 +6,7 @@ using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Nexus.Api.Data;
|
||||
using Nexus.Api.Integrations;
|
||||
using Nexus.Api.RateLimiting;
|
||||
using Nexus.Api.Repositories;
|
||||
using Nexus.Api.Routing;
|
||||
using Nexus.Api.Services;
|
||||
@@ -71,6 +72,37 @@ public static class ServiceCollectionExtensions
|
||||
services.AddRateLimiter(options =>
|
||||
{
|
||||
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
||||
|
||||
options.OnRejected = async (context, ct) =>
|
||||
{
|
||||
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
|
||||
context.HttpContext.Response.Headers.ContentType = "application/json";
|
||||
|
||||
var retryAfterSeconds = 60;
|
||||
|
||||
// Try to read retry-after info from the metadata
|
||||
if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
|
||||
{
|
||||
retryAfterSeconds = (int)retryAfter.TotalSeconds;
|
||||
}
|
||||
|
||||
// Set standard headers
|
||||
context.HttpContext.Response.Headers.RetryAfter = retryAfterSeconds.ToString();
|
||||
context.HttpContext.Response.Headers["X-RateLimit-Remaining"] = "0";
|
||||
context.HttpContext.Response.Headers["X-RateLimit-Reset"] =
|
||||
DateTimeOffset.UtcNow.AddSeconds(retryAfterSeconds).ToUnixTimeSeconds().ToString();
|
||||
|
||||
var body = new
|
||||
{
|
||||
error = "rate_limit_exceeded",
|
||||
message = $"Too many attempts. Try again in {retryAfterSeconds} second(s).",
|
||||
remaining = 0,
|
||||
retryAfterSeconds
|
||||
};
|
||||
|
||||
await context.HttpContext.Response.WriteAsJsonAsync(body, ct);
|
||||
};
|
||||
|
||||
options.AddPolicy("auth", context => RateLimitPartition.GetFixedWindowLimiter(
|
||||
context.Connection.RemoteIpAddress?.ToString() ?? "unknown",
|
||||
_ => new FixedWindowRateLimiterOptions
|
||||
@@ -171,6 +203,7 @@ public static class ServiceCollectionExtensions
|
||||
public static IServiceCollection AddNexusApplicationServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddHttpContextAccessor();
|
||||
services.AddSingleton<LoginAttemptTracker>();
|
||||
services.AddTransient<ModelRoutingService>();
|
||||
services.AddScoped<IAuthService, AuthService>();
|
||||
services.AddScoped<IAgentService, AgentService>();
|
||||
|
||||
Reference in New Issue
Block a user