Skip to content

Let a host app sign the panel in and open a run - #72

Closed
DavertMik wants to merge 3 commits into
mainfrom
feat/host-handoff
Closed

Let a host app sign the panel in and open a run#72
DavertMik wants to merge 3 commits into
mainfrom
feat/host-handoff

Conversation

@DavertMik

Copy link
Copy Markdown

A desktop app that launches Chrome with this extension loaded can hand the panel a ready session, so the tester never pastes a token to run the test the app just sent them to. Built for Testeiya, but nothing here knows about Testeiya beyond the name it puts in the file.

The contract

The host drops handoff.json beside the manifest and opens the panel:

{
  "app": "Testeiya",
  "baseUrl": "https://app.testomat.io",
  "projectId": "my-project",
  "jwt": "eyJ…",
  "projectToken": "tstmt_…",
  "runUrl": "https://app.testomat.io/projects/my-project/runs/abcd1234",
  "at": 1756160000000
}

Two credentials because the panel talks to two APIs: projectToken is what /api/v2 takes, jwt is a web session for the routes v2 lacks. runUrl is optional. at is milliseconds and has to grow on every push.

A file rather than a command line: --load-extension argv is readable by every process on the machine, and these are credentials. A panel already open takes a new push through window.TestomatHandoff.apply(), which answers {ok, projectId, run} so the host can report the result; a build without that global predates this contract.

Beside a token the tester pasted

An offer overlays the ordinary sign-in, it never replaces it. Their General token and their preferences are kept, and each request uses whichever credential fits — the project token on the project it was issued for, their own token anywhere else, the handed session for the web API. So the project switcher stays open for a tester who has their own token and is pinned for one who does not, and when the host closes its browser the panel keeps working on their token instead of falling back to nothing.

jwt is never stored. It lives in memory exactly like the one POST /api/login returns, and is re-read from the file on every panel load — which is why the file stays until the host that wrote it deletes it. Disconnect can't delete a file it doesn't own, so it marks that at answered and a newer push wins.

Also here

openRunFromUrl now reports whether it actually landed the panel on a view. A run that 404s used to leave the panel showing nothing at all — reachable today through "Run in Extension", and reachable more often once a host is pushing runs.

Checked

Driven against a real project on a real instance: cold boot, a live poke switching runs in place, both API surfaces answering, decline-then-newer-push, a handoff landing on top of an existing token and the fallback after the file goes. With no host involved the panel logs one ERR_FILE_NOT_FOUND for handoff.json at boot — that is the check for the file, not a fault.

🤖 Generated with Claude Code

A desktop app that launches Chrome with this extension loaded drops
handoff.json beside the manifest: a project token for v2, a web session
for the JSON:API, and optionally the run to open. The tester pastes
nothing.

A file, not argv — --load-extension command lines are readable by every
process on the machine. Only the project token is stored; the session
token stays in memory and is re-read, like the one /api/login returns.
The project is pinned, since one project's token was handed over.
Disconnect cannot delete a file it does not own, so it marks that push
answered and a newer one wins.

Also: opening a run from a URL now reports whether it landed anywhere.
A run that 404s used to leave the panel showing nothing at all.
A panel the host has just opened consumes the offer during its own boot,
so the poke that follows found the run already opened and reported none.
The host asked whether its run is up, so answer that.
Adopting a handoff used to delete the General token saved for that host,
so closing the host's browser left the panel with nothing and the tester
re-pasting a token they had already given us.

Both credentials are kept side by side instead. The project token is
tagged with the project it was issued for and used only there, so a
switch elsewhere falls back to the account token — which also means the
switcher only has to be pinned for a tester who has no token of their
own. The host's name is stored with the connection, because the card has
to name whose session ended after the file it came from is gone.
@DavertMik

Copy link
Copy Markdown
Author

Superseded by #73, which carries these commits plus the auth change that grew out of them: authorizing at /app-auth hands back a session that can read each project's own v2 key, so the panel needs one credential and projectToken in the handoff drops to an optional shortcut. The contract described here changed with it, so closing this in favour of the one PR.

@DavertMik DavertMik closed this Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants