From 73506b79f664a2174b184ea22168a770ccf307fc Mon Sep 17 00:00:00 2001 From: Mario Tarosso Date: Thu, 20 Aug 2026 08:22:38 +0100 Subject: [PATCH] [ENG-3568] Document `login` for the agents that will run it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The command was one line inside a paragraph about credentials, which is not enough for an assistant to use it correctly. Adds a section to AGENT-INSTALL.md covering when it applies, what the agent must do, and what it cannot do alone. The failure this heads off: an agent seeing a missing or rejected credential reaches for deleting .patchstackrc.json and re-scanning, which silently provisions a second site and orphans the original — widget tag already live on the deployed page, history attached to a record nothing points at any more. Says so in the place that instinct occurs. States the parts an agent must relay rather than discover: it needs the human, because approval requires their signed-in account; it should not kill and retry, because each run invalidates the code already on screen; and approving rotates, so CI, deploys and other checkouts need the new value. Adds a table of the cases where it will not work at all. The CLI now says the rotation consequence before approval as well as after, so whoever is deciding sees it in time to matter. Co-Authored-By: Claude --- AGENT-INSTALL.md | 40 ++++++++++++++++++++++++++++++++++++++++ src/cli.ts | 24 +++++++++++++++++------- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/AGENT-INSTALL.md b/AGENT-INSTALL.md index 107c971..2743b9e 100644 --- a/AGENT-INSTALL.md +++ b/AGENT-INSTALL.md @@ -119,6 +119,46 @@ These are **two independent states** — never conflate them: Local files alone cannot tell you whether the site was removed from Patchstack. Run `npx @patchstack/connect status` and read the `Site status` line, then answer with both states. For example, when the site was removed but the local files remain, say: *"The site itself was removed from Patchstack — reporting has stopped and the widget no longer renders. The local integration code (widget tag, `.patchstackrc.json`, the dependency) is still in the project; want me to remove it?"* — not "Patchstack is still installed." +## Recovering a lost credential — `login` + +Use this when the project **already has a site** but its credential is gone or rejected: `.patchstackrc.json` was deleted or never committed, the repo was cloned without it, a container was recycled, or ingest started failing with 401. + +> **Do not "fix" a missing credential by deleting `.patchstackrc.json` and running `scan` again.** That provisions a **second site**, and the original — with all its history and its widget tag already live on the deployed page — is orphaned. `login` recovers the existing one. + +### What it does + +``` +npx @patchstack/connect login + + Your code: WDJB-MJHT + Approve at: https://api.patchstack.com/monitor/pulse/device?code=WDJB-MJHT + + Waiting for approval… ✓ Credential restored +``` + +The command asks Patchstack for a short code, prints a link, and polls until the site's **owner approves it in the dashboard**. On approval it writes the new credential into `.patchstackrc.json` and exits. The link opens the approval page with the code already filled in, so the person only has to confirm. + +### What you must do, as the agent + +1. **Run the command and surface the link and code to the user verbatim.** They must open it themselves — approval requires their signed-in Patchstack account, which you do not have and must not ask for. +2. **Leave the command running.** It polls until approved or the code expires (10 minutes). Do not kill it and retry; each run issues a different code and invalidates the one already on screen. +3. **Report the outcome.** On success, tell them the credential was restored *and* that the previous one no longer works — see the warning below. + +You cannot complete this alone. It is deliberately a human-in-the-loop step: starting the flow proves nothing about who is running it, so the only authorisation is an owner approving in the browser. + +### Consequences to tell the user about + +**Approving rotates the credential — the old one stops working immediately.** Anywhere it was configured needs the new value: CI secrets, hosting-platform env vars, preview environments, other developers' checkouts. Say this before they approve, not after. + +### When it will not work + +| Situation | What happens | What to do | +|---|---|---| +| Site was never claimed | `409` — no owner exists to approve | Ask the user to claim the site in the dashboard first, or, if the site is disposable, delete `.patchstackrc.json` and `scan` to provision a fresh one | +| Running in CI | Refuses to start | CI takes its credential from `PATCHSTACK_PULSE_AUTH`; `login` is for a developer machine | +| No `siteUuid` configured | Refuses to start | There is no site to recover — run `scan` | +| Code expired | Poll ends after 10 minutes | Run the command again for a new code | + ## Uninstalling Remove only the pieces that are actually present — check for each first. If none are present, Patchstack isn't installed; report that and stop. If the user asked to remove only one piece (e.g. "just the widget"), remove only that piece. diff --git a/src/cli.ts b/src/cli.ts index 8e4e84c..7de8af5 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -103,11 +103,14 @@ Usage: what's missing, with tailored commands), then print the full setup guide. --full prints the guide even when setup is complete - patchstack-connect login [options] Recover this site's Patchstack credential when - .patchstackrc.json has been lost. Prints a short - code to approve in the dashboard; approving - rotates the credential, so the old one stops - working + patchstack-connect login [options] Recover this site's credential when + .patchstackrc.json has been lost. Prints a link + for the site's OWNER to approve in the dashboard, + then waits (10 min). Use this instead of deleting + .patchstackrc.json and re-scanning, which would + provision a second site. Approving ROTATES the + credential: CI, deploys and other machines using + the old one must be updated. Not usable in CI patchstack-connect help Print this message Options (for scan, setup, status, and uninstall): @@ -229,12 +232,19 @@ async function runLogin(args: ParsedArgs): Promise { const result = await login(config, (userCode, verificationUri) => { console.log(`\n Your code: ${userCode}`); console.log(` Approve at: ${verificationUri}\n`); - console.log(' Waiting for approval…'); + // Said before approval, not after: the person deciding needs to know it is + // a rotation, and an assistant relaying this has to pass the warning on. + console.log(" Open that link and approve it as the site's owner. Approving issues a new"); + console.log(' credential and stops the current one working — CI, deploys and any other'); + console.log(' machine using it will need the new value.\n'); + console.log(' Waiting for approval (the code expires in 10 minutes)…'); }); if (result.status === 'approved') { // The value itself is never printed — only that it landed. - console.log('\n ✓ Credential restored and saved to .patchstackrc.json.\n'); + console.log('\n ✓ Credential restored and saved to .patchstackrc.json.'); + console.log(' The previous credential no longer works. Update it anywhere else it was set:'); + console.log(' CI secrets, hosting env vars, preview environments, other checkouts.\n'); return 0; }