Dinoer

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.

Session recipes → · Limits →