Weles/Docs

Integrations

Brama asks Weles to sign an account in, buy one, or finish an authorization.

The routes Brama calls on Weles, the stream each run answers, how a run that waits for a person is paged and answered, and where its evidence stays.

Reauthentication#

Skarbiec owns subscription identities and login material; Weles has no separate account catalogue. Brama resolves an exact subscription through authenticated POST /reauth/resolve, supplying provider and subscription_id, then calls POST /reauth with the returned account_revision. Weles follows the existing Skarbiec source references, performs OAuth on its Stado-selected browser host and stores the grant on the same subscription. It never imports provider CLI sessions. Brama confirms the repair only after its own credential refresh succeeds.

An admitted POST /reauth answers application/x-ndjson, one JSON object per line while the run goes: admitted (the resolved identity, and coalesced when the request joined a run already under way), started (run id and host), one stage per step the trajectory reports, operator_request when the run waits for a person (the request's id, account and instruction, also paged and shown by weles runs list and weles runs show), and last result, the run's verdict with every stage it passed. A browser sign-in has no clock that ends it, so this is how a caller says what it is waiting for. A refusal before a run is admitted is a plain JSON answer with its HTTP status. The run's record (GET /diagnostics/<run>, run-result.json) holds the stages reached so far while it runs.

Results identify the subscription, login item, actual failed operation, HTTP status and run id. account_revision describes Skarbiec data; source_revision identifies the Weles software. Missing source references, cycles, conflicting login material and changed identity are refused before credential persistence.

Skarbiec asks for the same sign-in itself when a subscription's grant is absent or a consumer recorded the provider refusing it (skarbiec subscription run, and each skarbiec maintain pass on the vault owner). It reaches Weles only as Stado's browser-automation family: stado capabilities call browser-automation --operation subscription-sign-in runs weles accounts refresh --provider <provider> --subscription <id> --json, which takes the provider as the subscription's own brama:provider: tag names it, sends POST /reauth with the bearer of the item playing brama-weles-reauth and prints the run's result. A run whose result states its failure retryable is accounts.refresh-unavailable and exits 69; any other failure is accounts.refresh-failed and names the run for weles runs show.

Weles reads the login, its second factor and seed, and writes the new grant, as the Skarbiec consumer weles. Every request carries X-Consumer: weles and the bearer kept in the file Stado declares for Weles's grant on the skarbiec service, which stado capabilities resolve secrets --consumer weles answers under grants (declare it with stado service directory consumer add skarbiec weles --grant-consumer weles --grant <action:item#field> --token-file <absolute owner-only file>). The grant itself is issued on the vault owner with the bearer in that file (skarbiec grant issue weles --capabilities <...> --token-file <that file> --until-revoked), since Weles reads whole items, which a field grant does not hold. The bearer file is read at every request: an owner-only regular file of Weles's account, trailing line breaks off. Items are reached only through Skarbiec's consumer routes (POST /v1/items/list, /v1/items/get, /v1/items/set-json, /v1/items/retag, DELETE /v1/items), each judged by Weles's grant on the one item named, so the vault owner grants weles read, write and trash on the subscription and login items it signs in, by item or by tag; the operator routes Weles asks besides need call:skarbiec#v1/operator/policy, totp/judge and route/declare, and items/factors a read of the login. No grant declared for weles is secrets.identity-undeclared, a bearer file that is absent, a link, another account's or open to others is secrets.bearer-unsafe, one holding whitespace inside the bearer secrets.bearer-malformed, each said before anything is sent; what Skarbiec refuses is secrets.vault-refused with Skarbiec's own cause and fix (vault-grant-required names the capability to add).

Buying an account#

POST /subscriptions/acquire (provider, subscription_id carrying the correlation id Brama chose, plan_tier such as default_claude_max_20x, reason) is admitted by Brama's token and answers the same stream. It buys one account of provider by running that provider's own purchase trajectory, src/trajectories/<provider>/account/acquire.mjs: a provider with that file is bought for, and any other is refused provider_unsupported before a run starts, naming the missing file and the providers that have one. Adding a provider is adding its trajectory and its declaration in Brama's providers.json, never another branch in Weles.

The claude trajectory buys one Claude account: a fresh identity on an inbound domain Weles reads, the claude.ai sign-up with the code it mails (stages email_code_requested, email_code_waiting, email_code_entered, onboarding, account_created), the login row (weles-login-<subscription>, login_method email_code) and the subscription item (brama-sub-<subscription>, tagged brama:subscription, brama:provider:claude-code, brama:id:, brama:account:, brama:login:) written to the vault (account_banked), the Max plan with the multiplier the tier names paid with the purchase card (plan_page, card_entry, payment_submitted, payment_challenge with an operator_request of kind payment_approval when the card issuer holds the payment, plan_paid), and the account signed in for Brama in the same browser (oauth_consent, token_exchange, credential_persist).

The result names account, subscription_id (the member the run banked, <brama provider>-<account>), subscription_item, login_item and paid whenever they exist, also when a later step failed, so a paid account is never unnamed; Brama's correlation id comes back as request_id and never in place of the member. Failures are named plan_tier_unknown, purchase_card_missing, purchase_card_incomplete, phone_verification_required, onboarding_page_unrecognized, plan_choice_missing, plan_proceed_missing, card_entry_failed, payment_submit_missing, payment_declined and email_code_unreadable, each with the page and its DOM snapshot where a page was involved.

Finishing an authorization, and reading the pool#

POST /reauth/authorize (provider, subscription_id, authorize_url) completes one OAuth authorization a coding-agent harness started, as the subscription's account. Only the provider's own authorize page is driven, and only when its redirect_uri is the harness's localhost listener (authorize_url_refused otherwise). The browser catches that redirect (oauth_redirect) and result.redirect_url carries it back, so the harness (omp login anthropic, which reads the final redirect URL on stdin) mints and refreshes its own grant with the verifier only it holds. A login row may sign in with google_sso, email_password or email_code.

POST /reauth/accounts (provider) answers, without starting anything, which accounts the vault's subscriptions of that provider resolve to (accounts: subscription_id, account, login_item) and every subscription that does not resolve, with its refusal (errors). A machine that holds no vault of its own reads the pool here.

Runs that wait#

A sign-in is coalesced per account: every later sign-in of that account joins the run already under way. weles runs list (GET /runs) lists every run the worker has a live child for, with when it last wrote anything and, when it waits for a person, what it asked for and whether the person was paged. weles runs show <run> (GET /runs/:run_id) prints the last lines it wrote, every page, answer and note of the request it waits on, or its record once it finished. weles runs answer <run> with --ready, --approved or --not-received and an optional --detail (POST /runs/:run_id/answer) tells a waiting run what the person did; a run that waits on nobody is refused (409 run_not_waiting) with the stage it stands at.

weles runs cancel <run> --detail <who and why> (POST /runs/:run_id/cancel) kills the run's process group and records it as cancelled with that detail; a sign-in ends with failure run_cancelled at the stage it reached, and the next sign-in of that account starts a new run. A run that already finished is refused (409) with when; a run recorded as running that no live child answers for was left by a server that stopped. Weles Desktop Running has the same list, what a run waits for, the last output, the Ready, I approved it and No prompt arrived buttons, and Cancel.

A closing session prints [wsession] fingerprint probe: <section> before each part of its close-time fingerprint probe that waits on the browser, so a probe that never answers is named by the section it stands in. Every worker run closes its browser without that probe (WELES_FINGERPRINT=0): its verdict does not wait on a detection probe, and the probe would send the signed-in browser to a third-party TLS echo after the provider's pages.

Google approval and provider challenges#

Google sign-in selects a visible password choice before opening alternative methods. Hidden refusal templates do not count as provider refusals; a visible refusal or unavailable password challenge reports its observed page and stage, and the same run never resubmits the selected challenge. An authenticator code must leave Google's challenge before provider handoff. Without a stored seed, Weles uses an offered phone approval and sends Google's prompt only when the operator says he is ready: the run asks him first, chooses Google's phone method on weles runs answer <run> --ready (Weles Desktop, Running, Ready, send it), then asks him to approve it with the number to match. A sign-in nobody is asked about sends no prompt and stops with google_push_approval_required.

A request is paged through stado alerts send, which reaches the operator by the channels he chose for the fleet (stado alerts preferences set --channel <name>); with no choice the page is refused and the request records that nobody was told. It names the Weles runs that wait on it (run_ids; a second run that needs the same person for the same account joins the request instead of paging again), and waits until Google's page moves or the operator answers the run. A new alert shown beside Google's own Resend it is the prompt expiring: the run records the expiry with its time, pages him again with weles runs answer <run> --not-received as the way to get a new prompt, and keeps waiting. --not-received makes the run press Resend it, or end with google_prompt_not_received when Google offers none. A Google page under accounts.google.com/info/ ends the sign-in: 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.

google_2fa_material_missing remains a structured refusal when no usable authenticator material or offered phone method can answer the challenge. Enrolment refuses to replace an existing authenticator and writes a seed only after observing completed Google setup. Results preserve the observed second_factor method; a successful grant without that evidence stays unknown.

A Claude sign-in whose claude.ai page shows Continue with Google disabled reports stage gis_gate_pending and waits for the page to enable it or move on. When claude.ai puts a captcha challenge (hCaptcha, reCAPTCHA, Arkose or Turnstile) over its page after Google signed the account in, Weles answers it with its captcha solver (stage claude_captcha_answer) through the solving services whose keys Skarbiec holds, and continues. It ends the sign-in only with a refusal naming the challenge: provider_captcha_unreadable (with its DOM snapshot), provider_captcha_no_solver (Skarbiec holds no solving-service key) or provider_captcha_unsolved (the challenge kind, its site key, the services tried and the DOM snapshot).

Credentials and evidence#

Brama and Weles each acquire brama-weles-reauth/token from Skarbiec with their own workload identities, and Weles accepts that bearer only on the reauthentication routes. No shared environment file or copied token connects them. They resolve the canonical Skarbiec endpoint through Stado and use its attested active executable for local capability brokering, never an alternate vault. Brama reaches weles-admission only through the route Stado's service directory hands the consumer brama for credential-lifecycle; no environment variable names another address.

Reauthentication evidence survives releases under $HOME/.stado/var/weles/recordings; run verdicts live under $HOME/.stado/weles-detached-runs. Authenticated GET /diagnostics/<run_id> includes run-result.json for accepted runs, including pre-browser failures, and lists retained DOM, video and trajectory logs when present. A completed diagnostic journey is not proof that the website operation succeeded; read the recorded result and final state.