Administering a web interface end to end
The retained browser core still does real, multi-step, authenticated work — the case Dinoer forked this ability from, kept deliberately rather than by accident.
Not this project’s headline case — that is a locked research corpus, not an
admin panel. But the ability did not disappear when the perception layer
did: rpa.py still drives an authenticated interface the way a person would,
over several steps, behind a login. Real when a research campaign needs to
authenticate to read a gated source; real on its own when the task genuinely
is configuration, not research.
Behind a network-level Basic challenge
A target sitting behind a reverse proxy’s own HTTP Basic layer, on top of its application login:
{"http_credentials": true, "url": "https://target.local/admin", "actions": [...]}
The scenario still names no secret — http_credentials tells Dinoer to
resolve it from the encrypted directory, scoped to that origin, the same
mechanism a form field uses.
What makes this case work
One call for anything stateful. Log in, act, confirm — in a single
invocation. Splitting it across calls loses the DOM state silently: a saved
session is cookies and localStorage only, never what was open on screen.
An assertion at the top. If the page is not the one expected, stop before typing anything anywhere:
{"type": "evaluer", "script": "document.title", "contient": "Sign in"}
The encrypted directory for every credential.
{"type": "remplir", "selecteur": "input[name=\"username\"]",
"valeur": "depuis_secrets", "secret_cle": "username"},
{"type": "remplir", "selecteur": "input[name=\"password\"]",
"valeur": "depuis_secrets", "secret_cle": "password"},
{"type": "cliquer", "selecteur": "button[type=\"submit\"]"},
{"type": "attendre_selecteur_present", "selecteur": ".user-menu"}
The scenario stays committable because it names keys, never values.
Signals read, not just the verdict. After each step: where am I really
(boussole.url_courante), what did the server say
(boussole.dernier_code_http), did the session hold (session_derive).
Where it stops
Operations lasting minutes fit badly — the retained core returns one final
answer, not a stream, and a timeout does not mean failure: the server keeps
working after the client stops waiting. Bulk mutations across many
independent targets are better handled by campagne.py, or by an API if one
exists for the target. And nothing here can be undone: it executes the list
you wrote, at machine speed.