---
name: pup-vendor-login
description: "How to sign a user into a third-party vendor portal (Autodesk, Fusion, Mouser, DigiKey, and other SSO sites) inside a pup window, so the login PERSISTS and later visits are automatic. Covers the autonomous 'Continue with Google/Microsoft' path that needs no typed password (it reuses the profile's existing Google session), the OAuth-popup behaviour pup shows, driving Google's FedCM account chooser (which rejects ALL programmatic clicks — needs a real desktop_hover-then-click), which profile to use for crash-isolation, and the hard limit that some heavy account-admin SPAs (Autodesk's Kepler/React portal) JAM CDP so pup cannot drive the in-portal admin UI. Read this before opening any vendor login in pup. Trigger words: log into autodesk, autodesk sign in, sign into fusion, continue with google, vendor login, portal login, sso login in pup, log into mouser, digikey login, assign a license, autodesk account, manage.autodesk.com, store my login, oauth popup, account chooser."
---

# pup-vendor-login — signing a user into a vendor portal that persists

Goal: get the user signed into a third-party site (Autodesk, Fusion, Mouser, DigiKey, …) inside a
pup window so the session is **stored in the durable profile** and every later window is already
signed in. Autodesk is the worked example; the pattern generalises.

## The one-paragraph model

A vendor login is an OAuth/SSO flow. The **fastest autonomous path is "Continue with Google"** (or
Microsoft/Apple) because pup's durable `adom-you` profile usually already holds the user's Google
session — so no password is typed. The click sends the window (or an OAuth popup) to Google's
account chooser; you click the user's account; it redirects back signed-in; and the vendor cookie
persists on disk. Email+password works too but needs a credential you do not have — prefer SSO.

## The recipe (Autodesk, proven 2026-07-28)

1. **Open the login page in a durable profile, FRESH window, and pace slowly.**
   ```
   pup_open_window {"sessionId":"autodesk","url":"https://accounts.autodesk.com/logon"}
   ```
   Then WAIT ~10s before the first probe. Do NOT machine-gun navigate+eval+screenshot — rapid ops
   on these heavy SSO pages destabilise the CDP connection (measured: three Chrome crashes from
   churn alone). One op, settle, next op.

2. **Click the SSO button** (trusted CDP click via a text match; the button text often has hidden
   whitespace so match with a regex, not `===`):
   ```
   pup_eval {"sessionId":"autodesk","expr":"(()=>{const b=[...document.querySelectorAll('button,a,[role=button]')].find(e=>/continue with google/i.test(e.textContent||'')&&e.offsetParent!==null); b.click(); return 'clicked';})()"}
   ```
   Wait ~8s.

3. **Find where the OAuth landed — TWO shapes, handle both:**
   - The main window navigates to `accounts.google.com/.../accountchooser` (most common), OR
   - An OAuth **popup** opens. Autodesk's popup has **no opener**, so pup's popup-tracker skips it
     and the reclaim sweep adopts it as its **own session** named like `adom-you-win<rand>` at
     `signin.autodesk.com`. Run `pup_list_windows` and look for the new session; drive THAT one.

4. **Click the account — Google's "Sign in with Google" chooser (FedCM) REJECTS every in-page and
   in-app click.** Proven 2026-07-28 signing John into Autodesk: DOM `.click()`, a full synthetic
   pointer-event sequence, `page.mouse.click` (pup_click x/y), AND UIA-by-name
   (`desktop_ui_click`) ALL failed — the account lives in a cross-origin FedCM iframe hardened
   against automation. **The ONLY thing that works is a REAL OS cursor HOVER-then-CLICK** via AD's
   desktop verbs (this is the breakthrough):
   ```
   pup_raise_os_window {sessionId, foregroundReason:"<the user's words>"}   # FedCM needs the window focused
   desktop_screenshot_window {hwnd}                                             # get shotId + coordMap
   desktop_hover  {space:"image", shotId, x:<account px>, y:<account px>}        # MOVE the real cursor FIRST — this is the key
   desktop_click  {space:"image", shotId, x:<same>, y:<same>}                   # then the real SendInput click
   ```
   The HOVER before the click is what satisfies FedCM's genuine-user-activation check — a bare
   desktop_click with NO preceding hover did NOT advance; hover-then-click did. Aim by the
   SCREENSHOT pixel (the account is in an iframe, so top-frame getBoundingClientRect can't locate
   it). If even this is refused, the window is foregrounded with the account visible — ask the USER
   to tap it once.

5. **Confirm the redirect landed** by SCREENSHOT, not eval — the eval often reads one beat before the
   redirect completes and reports the stale chooser URL while the screenshot already shows the
   signed-in dashboard ("Hi, <name>"). Trust the picture.

6. **FLUSH THE COOKIE BEFORE DOING ANYTHING ELSE — persistence is NOT automatic.** Reaching the
   dashboard does NOT mean the login is saved. Chrome writes new cookies to disk lazily (on idle /
   graceful shutdown), and a fresh vendor cookie can be LOST if the Chrome crashes before it flushes.
   Measured live 2026-07-28: sign-in reached the Autodesk dashboard, the very next navigation crashed
   the Chrome, and the login was gone — a later window opened SIGNED OUT (while Gmail, whose cookie was
   flushed days earlier, survived). So after the dashboard appears:
     a. Do nothing heavy for ~10-15s (let Chrome flush), OR better, `pup_close_window` the login
        window — a graceful close flushes cookies to disk.
     b. Reopen the vendor site in the durable profile and CONFIRM it is signed in (screenshot) BEFORE
        promising the user anything. Only a verified reopen proves persistence.
   Once flushed and confirmed, the cookie survives close, Chrome kill, and bridge restart like any
   other durable-profile login. Do NOT tell the user "you're logged in and it'll stick" until the
   reopen check passes — that claim was made falsely once and the window came up logged out.

## ORG DEFAULT (v1.9.162): ONE shared profile for everything

John's standing decision: ALL pup windows use the single durable `adom-you` profile so logins
accumulate into one growing store that gets nicer to use over time. So the "dedicated per-vendor
profile" advice below is the SAFER-but-not-default option — reach for `{profile:"autodesk"}` only
when a specific portal is known to crash and the user asks for isolation. By default, sign the user
in on the shared profile (no `profile` arg). The crash tradeoff is knowingly accepted: one Chrome
process, so a portal crash takes every session down together — which is exactly why the
close+reopen+verify flush discipline in step 6 matters even more.

## Which profile — the isolation option (not the default)

- **Persistence needs a durable profile** (default `adom-you`, or a named one). Never `isolated:true`
  for a login you want to keep.
- **Crash isolation argues for a DEDICATED durable profile per vendor**, e.g.
  `pup_open_window {"profile":"autodesk", ...}`. A crash/hang during a vendor login on the SHARED
  `adom-you` profile takes down EVERY other session in that one Chrome process — measured live: the
  Autodesk flow crashed the shared Chrome and killed the user's Gmail session twice, and lost the
  in-flight Autodesk login because its cookie had not flushed before the crash. A per-vendor durable
  profile keeps the login persistent AND contains the blast radius. The one cost: SSO in a dedicated
  profile only reuses an existing Google session if that profile already has one; the very first
  Google sign-in there is a real login.

## HARD LIMIT: heavy account-admin SPAs jam CDP

`manage.autodesk.com/billing/user-management/...` (Autodesk's "Kepler"/React account portal) reliably
**jams pup's CDP pipe**: the window signature is HUNG-alive / CDP-DEAD — the process lives, the log
shows `KEPLER: Auth is not yet ready to mount providers`, and every `page.eval`/`page.screenshot`
times out (20s), then the frame detaches. pup CANNOT reliably drive the in-portal admin UI (assigning
a license seat, editing users). Do not promise to click through it. Options, in order:
1. **Hand the in-portal action to the USER** — pup got them signed in; the window is theirs to finish
   the seat assignment by hand. This is the honest, reliable answer today.
2. **Use the vendor's API** instead of the web UI where one exists (Autodesk has account-management
   APIs) — no CDP, no jam.
3. Never deep-link straight to the admin URL right after login — it JAMS and can CRASH the Chrome,
      and if the login cookie has not flushed yet (step 6) that crash DESTROYS the fresh login. Flush
      first (close+reopen+verify), THEN, in a SEPARATE dedicated-profile window, hand the admin page
      to the user — so a portal crash can never cost the sign-in again.

## The RESPECTFUL way to do the FedCM click: pup_assisted_click (v1.9.167)

Do NOT hand-roll raise + hover + click for the account chooser — use `pup_assisted_click`, which
does the whole protocol John required (never foreground-and-act while the user is not ready):
```
# first: desktop_screenshot_window {hwnd} to SEE the chooser and read the account's window-pixel x,y
pup_assisted_click {sessionId, x:<account px>, y:<account px>,
                        reason:"clicking your Google account to finish signing into Autodesk",
                        label:"your Google account (John Lauer)"}
```
It: captions the reasoning + toasts BEFORE touching the screen; foregrounds; then **waits, detecting
if you alt-tabbed away** and captioning "Adom is waiting — click back when ready" until your
foreground actually IS the window (nothing clicks until then; times out as `user_not_ready` clicking
nothing); then runs the TIGHT hover→click that FedCM accepts and captions each step. THE TIGHT
SEQUENCE MATTERS: any screenshot/eval BETWEEN the raise and the click steals focus / invalidates the
coordMap and the click silently no-ops (measured: interleaved ops failed 5x; the tight raise→capture
→hover→click worked). pup_assisted_click encapsulates that — use it, don't reinvent it.

## Pitfalls recap (each paid for on 2026-07-28)
- Rapid ops crash the Chrome → pace slowly, one op + settle.
- Shared-profile crash kills all sessions + loses un-flushed logins → dedicated durable profile.
- Google FedCM chooser rejects ALL clicks (DOM/synthetic/page.mouse/UIA) → real OS desktop_hover THEN desktop_click; the hover is mandatory.
- Button text has hidden whitespace → regex match, not `===`.
- Eval reads stale mid-redirect → confirm with a screenshot.
- The account-admin SPA jams CDP → hand off to the user or the API; do not fight it.
- A fresh login is NOT persisted until Chrome flushes it → close+reopen+verify BEFORE claiming it
  stuck; a portal crash before flush silently destroys the just-completed sign-in (happened once).

## ⛔ BEFORE any real-cursor step: WARN THE USER AND WAIT (John, 2026-07-29)

The `desktop_hover`-then-`desktop_click` recipe below is **native OS input**. It does NOT target a
window — it goes to **whatever window has OS focus at that instant**. This user runs several AI
threads and alt-tabs back to their own work almost immediately after any window is foregrounded.

An agent fired `desktop_type` here without warning; the user had already alt-tabbed away and the
text landed in THEIR document. The agent then blamed Windows for "failing to foreground the window"
instead of the obvious: the human took their focus back because nobody asked them not to.

**So for EVERY native step in this skill:**
1. `notify_user` toast + `desktop_caption` BEFORE asking for the screen.
2. Say it explicitly: **"please don't type or click until I say done."**
3. Wait until the window is genuinely the OS foreground; if they alt-tab away, HOLD, don't dispatch.
4. Re-verify foreground **immediately before each event** — focus can move between two keystrokes,
   and half a password typed into the wrong window is real harm.
5. Caption when DONE so they know they can use their keyboard again.

`pup_assisted_click` implements all five — prefer it over hand-rolling raise-then-click. And
remember the ordering rule: **CDP input (`pup_click`/`pup_type`/`pup_hover`) needs no
foreground and disturbs nobody** — native input is the LAST resort, only for what CDP genuinely
cannot drive (the FedCM chooser, native OS dialogs, sites that reject synthetic events).
