Earlier quoted context omitted.
Thanks for this thoughtful and insightful comment. Many problems can be workflow problems, sometimes even pulling in a rule engine, or require a job queue to do things that can fail. Then you have software such as https://temporal.io/ which is really powerful for resilient workflows. Imagine coordinating the user with a workflow with asynchronous data collection steps. Imagine programming "reaction to user behaviour…
This workflow engine of yours seems to expect a very predictable and linear sequence of actions. What happens if the user clicks "log out" after user.tutorial(); It's basically making an already easy case easier.
Or if you want to be more literal, declare a specific type:
type Authenticated(User) = No | Yes(User)
And each stage of your workflow matches on Authenticated.Yes, and so only executes if the user is authenticated. That's basically what any system does internally, this just makes that implicit behaviour explicit.