Trigger: Felder mit festem Typ, streng als Standard, nachsichtig abschaltbar (#725)
Das Token sagt, wer schickt - nicht, wer den Inhalt geschrieben hat. Felder
mit festem Typ (Kennung, Zahl, Ganzzahl, Datum, Datum+Uhrzeit, ja/nein,
Auswahl, Mailadresse) koennen keine Anweisung tragen und gehen als geprueft
an den Agenten, auch als {feld} im Auftrag. Freitext bleibt Fremdinhalt.
Streng (Standard): unpassende Lieferung -> 400 mit Grund, im Audit.
Nachsichtig (fuer Absender, die sich nicht an die Felder halten): nichts
wird abgewiesen, Passendes gilt als geprueft, der Rest bleibt Fremdinhalt;
der Trigger ist dann 'unsicher' und wird so angezeigt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
38bd304ca6
commit
ace215eaa2
@@ -3,10 +3,13 @@ namespace ClawdDotNet.Web.Contracts;
|
||||
/// <summary>#725: An inbound trigger — never with its token.</summary>
|
||||
public sealed record TriggerDto(
|
||||
string Id, string Label, string AgentId, int PerHour, DateTime CreatedAt, DateTime? RevokedAt,
|
||||
DateTime? LastUsedAt, int Received, bool Active, string Slug, string Instruction, int Priority);
|
||||
DateTime? LastUsedAt, int Received, bool Active, string Slug, string Instruction, int Priority,
|
||||
IReadOnlyList<Core.Triggers.TriggerField> Fields, bool Strict);
|
||||
|
||||
/// <summary>What a human sets on a trigger; <c>Slug</c> empty means "from the label" (new) or "unchanged" (edit).</summary>
|
||||
public sealed record TriggerInputDto(string AgentId, string? Label, int? PerHour, string? Instruction = null, int? Priority = null, string? Slug = null);
|
||||
public sealed record TriggerInputDto(
|
||||
string AgentId, string? Label, int? PerHour, string? Instruction = null, int? Priority = null, string? Slug = null,
|
||||
IReadOnlyList<Core.Triggers.TriggerField>? Fields = null, bool? Strict = null);
|
||||
|
||||
/// <summary>The token, once — the instance keeps only its hash.</summary>
|
||||
public sealed record TriggerIssuedDto(TriggerDto Info, string Token);
|
||||
|
||||
@@ -269,16 +269,18 @@ internal static class McpEndpoints
|
||||
Core.Triggers.TriggerOutcome.Unauthorized => Results.Json(new { ok = false, error = result.Message }, statusCode: StatusCodes.Status401Unauthorized),
|
||||
Core.Triggers.TriggerOutcome.Limited => Results.Json(new { ok = false, error = result.Message }, statusCode: StatusCodes.Status429TooManyRequests),
|
||||
Core.Triggers.TriggerOutcome.TooLarge => Results.StatusCode(StatusCodes.Status413PayloadTooLarge),
|
||||
Core.Triggers.TriggerOutcome.Invalid => Results.Json(new { ok = false, error = result.Message }, statusCode: StatusCodes.Status400BadRequest),
|
||||
_ => Results.Json(new { ok = false, error = result.Message }, statusCode: StatusCodes.Status503ServiceUnavailable)
|
||||
};
|
||||
}
|
||||
|
||||
private static TriggerDto TriggerDtoOf(Core.Triggers.InboundTrigger t)
|
||||
=> new(t.Id, t.Label, t.AgentId, t.PerHour, t.CreatedAtUtc, t.RevokedAtUtc, t.LastUsedAtUtc, t.Received, t.Active,
|
||||
t.AddressName, t.Instruction, t.Priority);
|
||||
t.AddressName, t.Instruction, t.Priority, t.FieldList, t.Strict);
|
||||
|
||||
private static Core.Triggers.TriggerSpec SpecOf(TriggerInputDto input)
|
||||
=> new(input.Label ?? "", input.AgentId, input.PerHour ?? 30, input.Instruction, input.Priority ?? 3, input.Slug);
|
||||
=> new(input.Label ?? "", input.AgentId, input.PerHour ?? 30, input.Instruction, input.Priority ?? 3, input.Slug,
|
||||
input.Fields ?? [], input.Strict ?? true);
|
||||
|
||||
private static string? TriggerProblem(AppHost host, TriggerInputDto input)
|
||||
{
|
||||
@@ -288,7 +290,7 @@ internal static class McpEndpoints
|
||||
return $"The instruction is longer than {Core.Triggers.InboundTriggers.MaxInstructionChars} characters.";
|
||||
if (!string.IsNullOrWhiteSpace(input.Slug) && Core.Triggers.InboundTriggers.Slugify(input.Slug).Length == 0)
|
||||
return "An address name needs letters or digits.";
|
||||
return null;
|
||||
return Core.Triggers.TriggerFields.Problem(input.Fields);
|
||||
}
|
||||
|
||||
/// <summary>Only the header — never the query string: an address ends up in logs.</summary>
|
||||
|
||||
Reference in New Issue
Block a user