Reference
When a run needs a person, it asks — and says whether anyone was told.
Google can require the account owner's phone approval during a sign-in or authenticator setup. The run asks only when that challenge is actually shown, reports whether the operator was notified, waits for the provider's answer and can be answered or cancelled as a run.
What a run asks for#
A run that reaches a step only a person can perform opens a request: one durable record naming the account, the instruction, the host and the Weles run that waits on it (run_ids). It belongs to that run. weles runs list shows each live run that waits for a person with WAITS FOR YOU and the instruction; weles runs show <run> prints the request in full: what it asks, since when, every page attempt, every answer and what the run noted about it. GET /runs and GET /runs/<run> carry it as the run's operator_request; null means the run waits on nobody.
No clock closes a request. The run closes it with the provider's outcome. A prompt Google lets expire beside its Resend it keeps the request open and pages the operator again. A Google page under accounts.google.com/info/ (sessionexpired among them) ends the sign-in itself: the request closes as not approved and the run ends with google_sign_in_ended_during_approval, naming that page and when the approval was asked; nothing about the account changed, and a new run of the same action starts the sign-in again. The worker reports a request as abandoned only when the run's process has exited; a missing process id or unreadable process state is unknown, not proof that the run is waiting. A second run that needs the same person for the same thing on the same account joins the open request instead of paging again, and is added to its run_ids, so either run can be answered.
Opening a request also asks the operator through Oko, where he chose to be asked: Weles runs oko asks ask --from weles --subject run-<run> and offers the answers a waiting run acts on (ready, approved, not_received) as the ask's choices, so Oko Desktop and Oko iOS show them as buttons and refuse any other answer. The run then waits on the ask with oko asks wait; the choice the operator taps is put on the request as an answer from Oko (answered in Oko on oko-desktop or oko-ios) and the run acts on it at once, exactly as on weles runs answer. A wait that fails is kept as a note on the request with Oko's words; the ask is withdrawn when the request closes. This needs an Oko release that takes --choice and wait; an older one refuses the ask, which is recorded on the request with Oko's words. On a host without oko the request is paged instead: Weles calls stado alerts send, which fans the message out to every alert channel that deployment resolves and reports per channel whether the provider took it. Each attempt is written into the record, so a request nobody could be told about never reads as delivered. The records live on the worker in ~/.weles/operator-requests, one JSON file per request, schema wisent.weles-operator-request.v1. WELES_OPERATOR_REQUEST_DIR moves the directory; WELES_OPERATOR_REQUEST_PAGING=off suppresses the page and records that suppression as the reason nobody was reached.
Commands#
| Command | What it does |
|---|---|
weles runs list [--json] | Every run the managed worker has a live child for, with how long ago it last wrote anything and, for a run that waits for a person, the instruction, whether the person was paged and whether its process still waits. |
weles runs show <run-id> [--json] | One run: its stage, last output lines and the request it waits on, with every page, answer and note; a finished run prints its record. |
weles runs answer <run-id> --ready|--approved|--not-received [--detail <text>] [--json] | Tell a run that waits for a person what the person did. --ready says the phone is in hand: only then does a Google phone approval send Google's prompt, and the run asks again to approve it with the number to match; before it no prompt is sent, so none expires unseen. --not-received makes the run press Google's Resend it (for a prompt that never arrived or expired), or end with google_prompt_not_received when Google offers none; --approved makes it read the page and record what Google still shows. A run that waits on nobody is refused with run_not_waiting and the stage it stands at; a finished run with run_not_running_here; an unknown run with run_not_found. Exactly one of the three flags is required; otherwise the command is a usage error: runs answer requires exactly one of --ready, --approved or --not-received. |
weles runs cancel <run-id> --detail <text> [--json] | End the wait by ending the run: its process group is killed and the run is recorded as cancelled with --detail. |
What the operator receives#
The page identifies the action, account, host and the Weles run that waits, and names the two commands that act on it. For a Google phone challenge, the instruction may include the number Google explicitly asks the user to match. It does not copy the page body, tokens or authenticator seed into an alert. A run no Weles worker started has no run id; the page says so, and only the provider's page can end its wait.
Weles is waiting for one action from you.
What to do: Approve the Google sign-in for <account> on your phone.
Account: <account>
Host: <worker-target>
Run: google-sign-in <account> (Weles run <run-id>)
Watch it: weles runs show <run-id>
Answer it: weles runs answer <run-id> --approved | --not-received
The run waits until you act or it is cancelled; if it ends first, this request is recorded as abandoned.Where runs ask#
Normal Codex, Claude Code and Kimi Google sign-ins use a stored authenticator when available. Without a seed, Weles can use an offered phone approval, and it sends Google's prompt only when the operator answers ready: the run opens its request saying it will send the prompt on ready, waits for that answer (weles runs answer <run> --ready, Desktop Ready, send it, or the Ready choice of its Oko ask), then chooses Google's phone method and asks him to approve it with the number to match. An answer other than ready before that is recorded and the wait goes on. If Google leaves its challenge meanwhile (accounts.google.com/info/sessionexpired), the run ends with google_sign_in_ended_during_approval saying no prompt was sent; choosing the phone method without reaching Google's device prompt ends with google_phone_prompt_not_shown and the page Google showed. When Google shows its device prompt on its own there is nothing to hold back and the run asks for approval at once. A sign-in step where nobody is asked only reads whether a phone prompt is offered and sends none. A provider refusal or browser error is not an approval. The sign-in result retains second_factor.required and the observed phone or authenticator method; absent evidence remains unknown.
Both readiness and approval release their operator-file watcher when the browser observation fails, as well as when either source answers. A closed browser preserves its actual failure and closes the request as unapproved; the abandoned watcher must not keep the trajectory process alive after that failure.
Authenticator setup and app-password actions use the caller's page-readiness observation after shared button clicks, not an additional deliberate idle pause. During authenticator enrolment, setup_code_input_not_found means neither the visible code input nor its Next action was available; setup_code_submit_not_found means the page offered no visible submit action for the entered code. Both refusals retain a redacted page preview. A failed input lookup remains a browser error instead of being treated as a missing field, and neither refusal writes the authenticator seed.
Authenticator enrolment uses the same phone approval flow. Google asks for the password again (Verify it's you) before it shows a security setting, so after each sign-in the enrolment reopens the authenticator page and signs in again wherever Google asks; it stops with google_sign_in_required only when Google asks a second time at an address it already asked at after a sign-in. It refuses an existing authenticator with authenticator_replacement_requires_consent rather than rotating it. setup_confirmation_unobserved means Google did not show completed setup; no seed is written. Concurrent requests for the same account and login join one live enrolment, while a conflicting login receives authenticator_enrolment_in_progress. A stale account revision is refused before the browser runs.
FENG SMART form filling asks with feng-portal-login when the browser is on a login route and feng-form-review after field processing. These requests identify the PARP browser session and its process, not an account identity the automation has verified. Login continuation observes the browser leaving its login route; review ends when its page closes. A browser error closes the corresponding request as unapproved, and an exited process is reported as abandoned. The former 240-read login limit and claimed one-hour review window do not apply. A closed review page does not prove that the form was saved or submitted; recorded field errors keep a non-zero exit status.
JuicySMS topup asks with juicysms-payment-verification only after observing an embedded Stripe or 3DS verification frame in its current checkout. The instruction identifies the requested USD amount and asks the account owner to complete that existing bank verification, not submit a second payment. The run refuses a live request belonging to another run and never closes that other request. Its own request closes as approved only after a matching provider receipt reports paid=true, an order identity and the requested USD amount and currency; a failed or unconfirmed outcome closes it as unapproved, not as proof that no charge occurred. The run closes its session and drains its own observations before closing the request. A confirmed provider payment is not a claim that JuicySMS has credited the balance.
In Weles Desktop#
Work → Running reads the authenticated managed worker, not a same-named directory on the laptop, with the same connection as the CLI: WELES_WORKER_API_BASE with WELES_WORKER_TOKEN, otherwise Stado resolves weles-admission for consumer operator and the bearer is the token of the item playing the worker's API role (stado credentials get --role echo-weles-api --field token); no item name is built in. Missing configuration or an unreadable worker response is shown as a failure, never an empty list.
A run that waits for a person shows waits for you and its instruction in the list. Its detail shows what it asked, paging, answers and notes, and the buttons Ready, send it, I approved it and No prompt arrived, which make the same call as weles runs answer (POST /runs/<run>/answer). Ready is the one a phone approval waits for before Google's prompt is sent. Approving on the phone needs nothing here: Weles sees Google's page move. Cancel run ends the wait by ending the run (weles runs cancel).
Authenticated worker routes#
GET /runs and GET /runs/<run> carry operator_request for a run that waits for a person, with abandoned as true, false or null. POST /runs/<run>/answer takes {answer: ready | approved | not_received, detail} and answers {ok, run_id, running}. All require the worker operator bearer; they do not accept the narrowly scoped Brama reauthentication bearer.
Missing admission is HTTP 401. Another answer is HTTP 400 invalid_answer, naming POST /runs/<run>/cancel as the way to end the wait. An unknown run is HTTP 404 run_not_found; a finished run or one no live child answers for is HTTP 409 run_not_running_here; a running run that waits on nobody is HTTP 409 run_not_waiting with the stage it stands at.
Real checks#
node tests/runs/answer.mjs --waiting-run <run-id> --finished-run <run-id> runs the built CLI against the managed worker: the removed weles operator-requests command and malformed answers exit 2, an unknown and a finished run are refused, and the waiting run's request records the --approved answer. Without a waiting run named the check is blocked, not passed. Reports stay under build/real-tests/runs.
On the Stado-selected dedicated host, node --test tests/operator/approval-cancellation.mjs reads the real request named by WELES_OPERATOR_REQUEST_ID without answering or changing it, opens an isolated managed WSession and closes its page during the approval observation. The child must propagate the browser failure, preserve the request and exit naturally after session cleanup. Its source revision, command, exit status, output and recording directory remain under build/real-tests/approval-cancellation. This cancellation check does not prove a successful Google phone approval.
For second factors, first run Brama's tests/authentication/journey.rs against an isolated real account in phone or authenticator mode. It must save a passing report that proves the sign-in and persisted credential. Then run node tests/security/second-factor.mjs --authentication-report <BRAMA_REPORT> from the matching Weles source revision, with the normal worker connection configured. It verifies real worker admission and input refusals, reads the phone request through the sign-in run's record in the API and CLI, refuses an answer to the finished run, rejects stale account revisions and, in authenticator mode, checks that concurrent enrolments join one run without replacing an existing factor. Missing access, approval or matching software is a failed or blocked run, never a pass.