Entscheidungen aus dem Testbetrieb umgesetzt (#572): #577 #579 #581 #589 #193 #205 #594 #595 #597 #598 #599 #588

- Engine: leere Antworten nachfassen, Aufgaben enden mit Ergebniszeile (EmptyResponse/Incomplete),
  gleiche Fehlschlaege erkennen (RepeatedFailure), Zeitzeile vor Chatnachrichten,
  Werkzeugergebnisse gerahmt, Vorpruefung vor dem Staging, Belegkosten wie RunUsage
- Staging: gescheiterte Freigaben als Failed; AgentEditor-Aenderungen freigabepflichtig,
  Selbstbearbeitung gesperrt (allowSelfEdit)
- Taskboard: Termine beim Anlegen pruefen, naechster/letzter Lauf, pausieren, Sofortlauf,
  Kostenprognose, Hinweis auf wachsenden Kontext; Jobs-Reiter und /api/jobs entfernt
- Release: Instanzmanager samt Weboberflaeche im Paket, setup.json fragt manager.json ab,
  Token nicht mehr ins systemd-Journal
Version 0.1.6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-15 11:23:10 +02:00
co-authored by Claude Opus 5
parent 8ab9d99abe
commit 0b6ea73ec1
42 changed files with 2646 additions and 512 deletions
@@ -137,6 +137,44 @@ public sealed class FileRWTool : IAgentTool, IToolStateProbe
}
}
/// <summary>
/// #579: Rechte und Pfad pruefen, bevor ein Aufruf in die Freigabeliste kommt. Dieselben
/// Pruefungen wie in <see cref="ExecuteAsync"/>, ohne etwas anzufassen.
/// </summary>
public string? Preflight(JsonElement input, AgentToolContext context)
{
if (input.ValueKind != JsonValueKind.Object
|| !input.TryGetProperty("action", out var a) || a.ValueKind != JsonValueKind.String)
return null;
var action = a.GetString() ?? "";
var workspace = (input.TryGetProperty("workspace", out var w) && w.ValueKind == JsonValueKind.String
? w.GetString() : null) ?? "personal";
if (!IsActionAllowed(action, workspace, context))
return $"Zugriff verweigert: Die Aktion '{action}' ist im Workspace '{workspace}' für diesen Agenten nicht erlaubt.";
var rootPath = workspace == "shared" ? context.SharedWorkspacePath : context.WorkspacePath;
if (action != "delete" || string.IsNullOrWhiteSpace(rootPath))
return null;
try
{
rootPath = Path.GetFullPath(rootPath);
var path = GetAndValidatePath(input, rootPath, workspace, false, context);
if (workspace == "shared" && !IsAdminLevel(context) && IsPathProtected(path, rootPath, context))
return $"🛡️ Geschützter Bereich: '{Path.GetRelativePath(rootPath, path)}' darf nicht gelöscht werden.";
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
// Dieselbe Pfadpruefung wirft bei der Ausfuehrung - dort wird daraus ein Fehler.
return $"Zugriff verweigert: {ex.Message}";
}
return null;
}
private bool IsActionAllowed(string action, string workspace, AgentToolContext context)
{
if (workspace == "personal") return true; // Alles erlaubt