feat(m9/T28a): strict expression-trigger analysis kind (advisory default, strict escalates)
This commit is contained in:
@@ -320,12 +320,19 @@ public class ValidationService
|
||||
List<ValidationEntry> warnings)
|
||||
{
|
||||
var expression = ExtractExpressionFromTriggerConfig(triggerConfigJson);
|
||||
var strict = IsStrictAnalysis(triggerConfigJson);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(expression))
|
||||
{
|
||||
warnings.Add(ValidationEntry.Warning(category,
|
||||
$"The {entityLabel} '{entityName}' has an expression trigger with no expression; it will never fire.",
|
||||
entityName));
|
||||
// M9-T28a: the blank-expression finding is the only advisory one. Under the
|
||||
// default Advisory kind it stays a non-blocking warning (it merely never fires);
|
||||
// under Strict it is promoted to a deploy-blocking error. Pure escalation —
|
||||
// the message and category are unchanged.
|
||||
var message = $"The {entityLabel} '{entityName}' has an expression trigger with no expression; it will never fire.";
|
||||
if (strict)
|
||||
errors.Add(ValidationEntry.Error(category, message, entityName));
|
||||
else
|
||||
warnings.Add(ValidationEntry.Warning(category, message, entityName));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -374,6 +381,35 @@ public class ValidationService
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the optional <c>"analysisKind"</c> discriminator from a trigger
|
||||
/// configuration (M9-T28a). <c>true</c> only when the value is the case-insensitive
|
||||
/// literal <c>"Strict"</c>; everything else — a missing key, the literal
|
||||
/// <c>"Advisory"</c>, any other value, or malformed JSON — defaults to Advisory
|
||||
/// (<c>false</c>), preserving today's behavior exactly.
|
||||
/// </summary>
|
||||
/// <param name="triggerConfigJson">The trigger configuration JSON to parse.</param>
|
||||
/// <returns><c>true</c> when the configured analysis kind is Strict; otherwise <c>false</c> (Advisory).</returns>
|
||||
internal static bool IsStrictAnalysis(string? triggerConfigJson)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(triggerConfigJson))
|
||||
return false;
|
||||
try
|
||||
{
|
||||
using var doc = JsonDocument.Parse(triggerConfigJson);
|
||||
if (doc.RootElement.TryGetProperty("analysisKind", out var prop)
|
||||
&& prop.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
return string.Equals(prop.GetString(), "Strict", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
// Not valid JSON — Advisory (no escalation), matching the blank-expression default.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authoritative syntax/trust check for a trigger expression. Delegates to the
|
||||
/// shared <see cref="ZB.MOM.WW.ScadaBridge.ScriptAnalysis"/> analyzer (same gate
|
||||
|
||||
Reference in New Issue
Block a user