fix(central-ui): Flow Debugger Replay opens to OperationalAudit roles; Live run and Retry/Discard stay Deployer-only (arch-review F3)
Design D6 / §9 says a Live run is a Deployer act while Replay needs only
OperationalAudit, but the page and all three FlowDebug* commands were gated on
Deployer. The Audit Log and Execution Chain pages -- themselves OperationalAudit
-- show an "Open in Flow Debugger" drill-in that an auditor could not follow.
Implements the split:
- New `RequireFlowDebugger` policy over `FlowDebuggerAccessRoles`
{Deployer, Administrator, Viewer}; the page now carries it instead of
`RequireDeployment`.
- `FlowDebugReplayCommand` takes the same role set in the ManagementActor
matrix; `FlowDebugRunMethodCommand` / `FlowDebugRunValueChangeCommand` stay
DeployerOnly.
- The page resolves `_canLive` (Deployer) in OnInitializedAsync and, without it,
pins the mode to Replay, hides the entry-point and mode toggles, the Run
button and the Live pickers, honours only the `?executionId=` drill-in, and
leaves the parked-node Retry/Discard callbacks unset so those buttons never
render. `CanRun`, `SetMode(Live)` and `ActOnStepAsync` repeat the check so the
split does not rest on markup alone.
The NavMenu entry stays inside the Deployer-gated Deployment section -- auditors
arrive through the audit drill-ins, which is the point of the finding.
Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29
This commit is contained in:
@@ -23,6 +23,12 @@ public class RequiredRoleMatrixTests
|
||||
private static readonly string[] AreaManagers = [Roles.Designer, Roles.Deployer];
|
||||
private static readonly string[] SecuredWriteReaders = [Roles.Operator, Roles.Verifier, Roles.Administrator];
|
||||
|
||||
// arch-review F3: Flow Debugger Replay is an audit read, so it is open to the
|
||||
// OperationalAudit roles {Administrator, Viewer} in addition to Deployer. Written out
|
||||
// by hand (not read from AuthorizationPolicies.FlowDebuggerAccessRoles) to keep the
|
||||
// freeze meaningful — a change to the policy's role set must fail this table first.
|
||||
private static readonly string[] FlowDebuggerReplayers = [Roles.Deployer, Roles.Administrator, Roles.Viewer];
|
||||
|
||||
private static readonly Dictionary<string, string[]?> Expected = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
// ---- Administrator-only -----------------------------------------------------
|
||||
@@ -138,10 +144,14 @@ public class RequiredRoleMatrixTests
|
||||
["RetryParkedMessage"] = [Roles.Deployer],
|
||||
["DiscardParkedMessage"] = [Roles.Deployer],
|
||||
["DebugSnapshot"] = [Roles.Deployer],
|
||||
// Flow Debugger (design 2026-09-05 §9): Live runs + Replay are Deployer, like Debug View.
|
||||
// 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.
|
||||
// Replay only reads the audit chain, so it carries the OperationalAudit roles as
|
||||
// well — the Audit Log / Execution Chain drill-ins are the feature's main entry
|
||||
// for a past incident and an auditor must be able to follow them.
|
||||
["FlowDebugRunMethod"] = [Roles.Deployer],
|
||||
["FlowDebugRunValueChange"] = [Roles.Deployer],
|
||||
["FlowDebugReplay"] = [Roles.Deployer],
|
||||
["FlowDebugReplay"] = FlowDebuggerReplayers,
|
||||
|
||||
// ---- Two-person secured write ----------------------------------------------
|
||||
["SubmitSecuredWrite"] = [Roles.Operator],
|
||||
|
||||
Reference in New Issue
Block a user