Skip to main content

Module interactive

Module interactive 

Source
Expand description

Run a journey in the logged-on user’s interactive session from a session-0 (SSH) process. Run a journey in the logged-on user’s interactive desktop session from a session-0 process (an SSH logon or a service on Windows), through a ONE-SHOT Task Scheduler task.

Why: a hidden WebView2 app never gets a ready window from session 0, so a native journey driven over SSH fails with “app window never became ready … session 0”. The whole journey command (the harness AND the app) must run in the interactive session; this module relaunches it there.

Design (see the README, Windows section):

  • Opt-in only: opted_in (--interactive or RIGHTKIT_QA_INTERACTIVE=1). Without it a session-0 process keeps failing with the existing clear error (Decision::NotOptedIn).
  • decide is pure: it maps SessionFacts to a Decision. The task is only created when the current account is the console (logged-on interactive) account.
  • The task runs THIS executable in __child <spec.json> mode (child_main), never cmd.exe or a shell: the journey program and its arguments travel as JSON data and are spawned as argv, so no journey argument is ever parsed by a shell. Only one generated path appears on the task command line, quoted with the CommandLineToArgvW rules (quote_windows_arg) and XML-escaped (task_xml).
  • The child redirects stdout and stderr to files in a private temp dir and writes the exit code file last, by rename (atomic). The parent polls, streams new output, and propagates the code.
  • run_interactive owns a cleanup guard: the task is ended and deleted and the temp dir removed on success, error, timeout and unwinding.

Account and token: LogonType = InteractiveToken, UserId = the current account, RunLevel = LeastPrivilege. No password is stored, requested or accepted. Task Scheduler runs an InteractiveToken task only for a user who is logged on, in that user’s session.

Structs§

Account
A Windows account, domain\user (domain may be empty).
ChildSpec
Everything the child wrapper needs; written as JSON into the job directory.
Request
One interactive run.
Schtasks
schtasks.exe from %SystemRoot%\System32, invoked with argv (no shell).
SessionFacts
What the process can tell about where it runs. Pure data so decide is testable.
TaskSpec
What the generated task runs.

Enums§

ConsoleUser
Who is logged on at the physical console.
Decision
Stream

Constants§

CHILD_MARKER_ENV
Set by the child wrapper in the journey’s environment so a journey never relaunches itself.
ERR_FILE
EXIT_FILE
OPT_IN_ENV
Opt-in environment variable (1 or true).
OUT_FILE
PID_FILE
SPEC_FILE
Files inside the job directory.
TASK_FOLDER
Task Scheduler folder every one-shot task lives in; the task name is <folder><uuid>.
TASK_XML_FILE
WRAPPER_FAILED
Exit code the wrapper reports when it could not start the journey at all.

Traits§

Scheduler
Task Scheduler operations, a trait so the orchestration is tested without a real scheduler.

Functions§

child_main
The child wrapper, run inside the interactive session as <exe> __child <spec.json>. Reads and deletes the spec, starts the journey with the files as stdout and stderr, records its pid, waits, then writes the exit code file by rename. Returns the journey’s exit code.
decide
non_interactive_reason
Some(reason) when the process is outside the interactive desktop; None when interactive or undeterminable (the same rule the launch hint uses).
opted_in
True when the flag is given or the environment value is 1 / true.
parse_exit_code
Parse the exit code file: one decimal integer. Windows codes above i32::MAX (for example 0xC0000005) are accepted as unsigned and returned with the same bit pattern as i32.
quote_windows_arg
Quote one argument for a Windows command line (CommandLineToArgvW rules).
run_interactive
Run the request through sched and return the journey’s exit code. Output is handed to sink as it is written. Errors: task creation or start failure, the task never starting, the timeout (the journey tree is killed), an unreadable exit file.
same_account
Same account: user names equal ignoring case, and domains equal ignoring case unless either side has none.
select_env
Environment forwarded to the journey. Scheduled tasks do not inherit the SSH environment, so it is explicit: every RIGHTKIT_* variable (except the opt-in and child markers), the variables named in pass (case-insensitive), then explicit pairs, which win.
session_facts
Facts about this process. Not Windows: nothing known, so decide returns Direct.
task_xml
The one-shot task definition: no triggers (started only by /run), InteractiveToken for the given user, least privilege, no password anywhere, a hard execution time limit.
utf16le_with_bom
UTF-16 little endian with a byte order mark: the encoding schtasks /xml always accepts.