using System.Text.Json; using ZB.MOM.WW.ScadaBridge.Commons.Messages.Management; using ZB.MOM.WW.ScadaBridge.Commons.Types.Debugging; using ZB.MOM.WW.ScadaBridge.Commons.Types.Scripts; using ZB.MOM.WW.ScadaBridge.ScriptAnalysis; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Services; /// /// Outcome of a Flow Debugger run or replay as the page consumes it: the built /// (null on failure), the raw server result (null when the command /// itself was refused), and a classified error. /// /// The flow graph built from the returned audit events; null when the command failed outright. /// The server's ; null when no result came back. /// Human-readable failure, null on success. /// Machine-readable failure code (STANDBY_NODE, NO_TRIGGER_WITHIN_WINDOW, UNAUTHORIZED, SERVICE_UNAVAILABLE, …), null on success. /// /// Step logs (design 2026-09-09 D7): true when the inline trace collector dropped low-priority /// ScriptLog rows to protect room for the step rows — the run's lines are incomplete inline, /// while Replay (which reads the never-truncated audit store) is complete. Mirrors /// so the page can note it without unwrapping the raw result. /// public sealed record FlowDebugOutcome( FlowGraph? Graph, FlowDebugRunResult? Raw, string? Error, string? ErrorCode, bool LogsTruncated = false) { /// True when a graph was built (the run may still have finished incomplete — see ). public bool Success => Graph != null && Error == null; /// Creates a failed outcome. public static FlowDebugOutcome Fail(string error, string errorCode) => new(null, null, error, errorCode); } /// /// Outcome of a Retry / Discard relayed from a Flow Debugger node (follow-ups plan 2026-09-06 D4). /// is operator-facing and uses the same wording as the Site Calls / /// Notification report pages, whether the relay was refused before it left the page or the /// owning site / outbox answered. /// /// True when the relay was applied (site Applied, or outbox success). /// What happened, in the report pages' words. public sealed record FlowOutboundActionResult(bool Success, string Message); /// /// One script of an instance as the Flow Debugger's script picker shows it (design 2026-09-08 §5): /// canonical name, trigger kind, the trigger's attribute for write kinds, the effective parameter /// definitions for call kinds, and the script's own execution timeout (client Ask sizing). /// /// Path-qualified script name from the flattened configuration (Module.Script for a composed member). /// The effective trigger type, or null when the script has none. /// The monitored attribute of a write-kind trigger; null for every other kind. /// JSON parameter definitions the Inputs card renders for a call kind; null = none. /// The script's own execution timeout, or null to use the site default. public sealed record FlowScriptOption( string CanonicalName, string? TriggerType, string? TriggerAttribute, string? ParameterDefinitions, int? ExecutionTimeoutSeconds) { /// True when the debugger fires this script by writing . public bool IsWriteKind => ScriptTriggerAttribute.IsWriteKind(TriggerType); /// Picker label suffix: ValueChange: Level, Call, no trigger… public string TriggerLabel => string.IsNullOrWhiteSpace(TriggerType) ? "no trigger" : TriggerAttribute is { } a ? $"{TriggerType}: {a}" : TriggerType!; } /// /// CentralUI facade over the Flow Debugger (design 2026-09-05 §5.5/§7.1, script entry /// 2026-09-08 §5): the instance's script list read from its flattened configuration, static /// shape prediction from script syntax, and the four management commands (Live run of a /// method, of a script, of a value change; Replay) dispatched to the per-node ManagementActor /// through the in-process ManagementActorHolder — the SAME Ask path the HTTP /// /management endpoint uses, so the server stays the single enforcer of the Deployer /// gate and the active-node refusal (STANDBY_NODE). /// public interface IFlowDebugService { /// Predicts the flow shape of an inbound API method from its script and the site scripts its constant routes resolve to. /// The method id. /// Cancellation token. /// The predicted flow; when the method does not exist. Task PredictMethodAsync(int apiMethodId, CancellationToken cancellationToken = default); /// The instance's scripts from its flattened configuration, ordered by canonical name; empty when the instance does not exist. /// The instance id. /// Cancellation token. Task> GetInstanceScriptsAsync(int instanceId, CancellationToken cancellationToken = default); /// Predicts the flow of running : the write + spawned script for a write kind, a RouteCall root + the script for a call kind. /// The instance id. /// Canonical script name (case-insensitive). /// Cancellation token. Task PredictScriptAsync(int instanceId, string scriptName, CancellationToken cancellationToken = default); /// Runs an inbound API method with tracing on the active central node and returns the flow. /// The method id. /// Flat JSON object of parameters, or null. /// Cancellation token. Task RunMethodAsync(int apiMethodId, JsonElement? parameters, CancellationToken cancellationToken = default); /// Runs a script by name (write kinds take , call kinds ) and returns the flow. /// The instance id. /// Canonical script name (case-insensitive). /// Call kinds: flat JSON object of parameters, or null. /// Write kinds: the new value for the trigger's attribute, in canonical string form. /// Cancellation token. Task RunScriptAsync(int instanceId, string scriptName, JsonElement? parameters, string? value, CancellationToken cancellationToken = default); /// Rebuilds a past flow from the central audit store. /// Any execution id in the chain. /// Cancellation token. Task ReplayAsync(Guid executionId, CancellationToken cancellationToken = default); /// /// Relays a Retry of a parked outbound node to its owner — the Site Call Audit relay for an /// / (keyed by the step's /// = TrackedOperationId and ), /// the Notification Outbox for a (CorrelationId = /// NotificationId). A step that is not outbound, not , /// has no correlation id, or (site kinds) no site id is refused with a message and never relayed. /// /// The outbound step to retry. /// Cancellation token. Task RetryOutboundAsync(FlowStep step, CancellationToken cancellationToken = default); /// /// Relays a Discard of a parked outbound node to its owner. Same routing and refusals as /// . /// /// The outbound step to discard. /// Cancellation token. Task DiscardOutboundAsync(FlowStep step, CancellationToken cancellationToken = default); }