feat(management): dispatch FlowDebugRunScriptCommand (Deployer-only, long-running) on the ManagementActor

Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29
This commit is contained in:
Joseph Doherty
2026-09-08 01:18:52 -04:00
parent 51ce72404b
commit 3f4fde3e35
5 changed files with 23 additions and 11 deletions
@@ -197,7 +197,7 @@ public class ManagementActor : ReceiveActor
// arch-review F3: Flow Debugger Replay is an audit read, so it carries the same role
// set as the RequireFlowDebugger page policy ({Deployer, Administrator, Viewer}). The
// two Live run commands stay DeployerOnly.
// three Live run commands stay DeployerOnly.
private static readonly string[] FlowDebuggerReplayRoles = AuthorizationPolicies.FlowDebuggerAccessRoles;
// arch-review C6: area management is reconciled to any-of [Designer, Deployer].
@@ -310,12 +310,13 @@ public class ManagementActor : ReceiveActor
or RetryParkedMessageCommand or DiscardParkedMessageCommand
or DebugSnapshotCommand => DeployerOnly,
// Flow Debugger (design 2026-09-05 §9 / D6, arch-review F3). A Live run executes
// scripts and writes attributes on operator input, so it stays Deployer-only, like
// the Debug View. Replay only reads the audit chain, so it additionally accepts the
// OperationalAudit roles — the Audit Log / Execution Chain drill-ins are the
// feature's main entry for a past incident and an auditor must be able to use them.
FlowDebugRunMethodCommand or FlowDebugRunValueChangeCommand => DeployerOnly,
// Flow Debugger (design 2026-09-05 §9 / D6, arch-review F3; script entry added by
// design 2026-09-08). All three Live run commands execute scripts and write
// attributes on operator input, so they stay Deployer-only, like the Debug View.
// Replay only reads the audit chain, so it additionally accepts the OperationalAudit
// roles — the Audit Log / Execution Chain drill-ins are the feature's main entry for
// a past incident and an auditor must be able to use them.
FlowDebugRunMethodCommand or FlowDebugRunValueChangeCommand or FlowDebugRunScriptCommand => DeployerOnly,
FlowDebugReplayCommand => FlowDebuggerReplayRoles,
// Two-person secured write. Submit is an Operator action;
@@ -418,6 +419,7 @@ public class ManagementActor : ReceiveActor
// Flow Debugger (design 2026-09-05 §7.1) — one execution path for the UI and the CLI.
FlowDebugRunMethodCommand cmd => await sp.GetRequiredService<FlowDebug.FlowDebugRunner>().RunMethodAsync(sp, cmd, user, CancellationToken.None),
FlowDebugRunValueChangeCommand cmd => await sp.GetRequiredService<FlowDebug.FlowDebugRunner>().RunValueChangeAsync(sp, cmd, user, CancellationToken.None),
FlowDebugRunScriptCommand cmd => await sp.GetRequiredService<FlowDebug.FlowDebugRunner>().RunScriptAsync(sp, cmd, user, CancellationToken.None),
FlowDebugReplayCommand cmd => await sp.GetRequiredService<FlowDebug.FlowDebugRunner>().ReplayAsync(sp, cmd, CancellationToken.None),
// External Systems
@@ -58,6 +58,9 @@ public static class ManagementEndpoints
// Flow Debugger (design 2026-09-05 §7.1): a Live run lasts up to the method timeout
// (+ grace) or the value-change wait window — never the ordinary Ask timeout.
typeof(FlowDebugRunMethodCommand), typeof(FlowDebugRunValueChangeCommand),
// script entry (design 2026-09-08): a direct call lasts up to the script's timeout
// (+ grace), a write kind up to its wait window.
typeof(FlowDebugRunScriptCommand),
];
/// <summary>
@@ -160,8 +160,9 @@ public static class AuthorizationPolicies
/// This is page ACCESS only, and is deliberately NOT sufficient for a Live
/// run: the Run controls, the Live entry-point pickers and the parked-node
/// Retry/Discard actions are gated on <see cref="RequireDeployment"/> in the
/// page, and <c>FlowDebugRunMethodCommand</c> /
/// <c>FlowDebugRunValueChangeCommand</c> stay Deployer-only in the
/// page, and <c>FlowDebugRunMethodCommand</c>,
/// <c>FlowDebugRunValueChangeCommand</c> and
/// <c>FlowDebugRunScriptCommand</c> stay Deployer-only in the
/// ManagementActor role matrix. Only <c>FlowDebugReplayCommand</c> accepts
/// <see cref="FlowDebuggerAccessRoles"/>.
/// </remarks>