mirror of
https://github.com/euzu/tuliprox.git
synced 2026-09-24 10:02:29 +02:00
The transition graph landed as the single source of truth for state
changes, but the frontend never saw it. `action_availability` restated
the rules in TypeScript-shaped Rust: its own pausable set, its own
cancellable set, its own resumable-kind check. Two copies of a state
machine, and the module docstring already recorded that they had drifted
once before -- the queue would pause a task in any state while the
frontend offered pause for three.
`RecordingAllowedActions` moves to `shared` and rides on
`RecordingTaskDto`, computed by `allowed_actions` from the same
predicates the commands themselves use. The frontend now narrows that
set by permission and renders it:
pause: can_manage && allowed.pause
State rules appear once, on the server.
The frontend tests that asserted "Live cannot be paused" and "VOD can be
retried" are gone rather than ported. They were restating the backend's
table through a second implementation, and the backend already proves it
exhaustively over kind x state x command. What is left tests what the
frontend actually decides now: that a command the server would refuse is
never offered, and that manage and delete gate separately.
`the_dto_offers_exactly_what_the_transition_graph_permits` walks all
three kinds across all nine states and compares the DTO against the
graph, so the projection cannot quietly stop matching.
The field is `#[serde(default)]`: a client that has not been rebuilt
sees an empty set and offers no controls, which fails closed.