Skip to content

[NO-TICKET] Add a doctor command that checks everything and says how to fix it - #453

Merged
mariojgt merged 2 commits into
mainfrom
mariot/doctor-command
Oct 26, 2026
Merged

mariojgt merged 2 commits into
mainfrom
mariot/doctor-command

Conversation

@mariojgt

@mariojgt mariojgt commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

What changed

A new command, npx @patchstack/connect doctor [--url <live app>], runs every check Patchstack depends on and prints each problem with its fix. It is meant for the assistant installing Patchstack as much as for a person.

What it checks

  • Patchstack is installed, as a regular dependency.
  • The project is on Patchstack (has a site).
  • The site is connected to an account. If not, it is flagged as report-only, with the link.
  • The guard is wired (protect --check) and carries the site.
  • Setup can find exactly one guard rules file.
  • That file has the read-only rules credential, and Patchstack still accepts it (one token request; the token is not kept).
  • The app's map is linked to the guard (the build ID).
  • Installs and builds run the Patchstack check, and the production marker and widget are in place.
  • With --url: the live app carries the widget, and its guard blocks a test attack (?file=../../../../etc/passwd). If the page itself does not load, no test attack is sent.
  • Whether the published app fetches its rules. It reads Patchstack's record from the new monitor/pulse/sync-status/<uuid> (patchstack/saas PR below), with the token from the credential it already checks: the site key if this machine holds one, otherwise the read-only credential.
    • It says when the published app last fetched its rules, and how many.
    • It never fetches rules itself, because that fetch would be recorded and fake the signal.
    • An app with no visitors does not fetch, so an old or missing fetch is a ? until doctor --url has just visited the app, and a ✗ after.
    • A fetch made only with the site key is reported as such, not as the published app.
    • A server without the endpoint is reported as "does not report rules syncing yet".

What it reports

  • Problems come first, each with a Fix: line, then what could not be checked (?), then what passed.
  • Steps only the app's owner can take (connecting the account, publishing) are marked "for the app owner". The closing lines separate them, so an assistant fixes the rest and passes those on rather than waiting on them.
  • It writes nothing and exits 1 when it finds a problem.

The endpoint answers only rules-fetch times and counts. It returns nothing about attack reports (that would be a detection oracle on a credential that can be public) and nothing about visitor activity.

These checks cover the silent failures found on Lovable and Hostinger apps: no read-only credential, a refused credential, a map not linked, a guard not wired, and a live app that has not been republished.

AGENT-INSTALL.md

  • The JS/Node path gets a new step 5: run doctor after setup, fix each ✗ and run it again until none is left. Owner steps are passed on.
  • doctor gets a row in the command table, disclosing what it sends:
    • the claim-page lookup;
    • monitor/pulse/token with the read-only credential (and the site key, when present);
    • one monitor/pulse/sync-status/<uuid> read;
    • with --url, two GET requests to that address, noting that another firewall may also flag the test attack.
  • "Verifying the install" mentions it. README.md lists the command.

Example (a copy of a real Lovable project)

  ✗ Patchstack refused the read-only rules credential (the site key was replaced, or the site was removed)
      Fix: Run: npx @patchstack/connect setup (it writes a current one)
           Then publish the app again.
  ✗ The app's map is not linked to the guard, so rules written for this app's own inputs can only report, not block
      Fix: Run: npx @patchstack/connect setup --verbose and fix the reason on its "could not bind this map" line
           Then run setup again.
  ✗ The live app does not carry the Patchstack widget for this site yet (for the app owner)
      Fix: Publish the app again: the live app still runs a build from before setup.
  ✓ Connected to a Patchstack account
  ✓ Protection is wired into your server (TanStack Start)
  ✓ The live app's guard blocked a test attack
  …
2 problems to fix in the project. Fix each ✗ above as its Fix line says, then run npx @patchstack/connect doctor again until none is left.
1 step for the app owner (marked "for the app owner"): connecting their Patchstack account or publishing the app. Pass it on; nothing in the project fixes it.

How it was verified

  • tests/doctor.test.ts (16 tests):
    • a project set up as setup leaves it has no problems;
    • not on Patchstack;
    • an unclaimed site is flagged once, with its link;
    • a missing credential, a refused one, and an offline check (?, not a problem);
    • an unlinked map;
    • an unwired guard;
    • --url cases: blocked, let through, and a page that does not load (no test attack is sent);
    • the closing lines, including owner steps;
    • rules syncing: a recent fetch passes, using the token and never requesting the rules endpoint; an old fetch is ? without a visit and ✗ after one; never fetched after a visit; a key-only fetch; a server without the endpoint.
  • Real runs on a copy of a Lovable project against live Lovable apps: a blocked test attack, a site whose page answers 404, and a widget for another site.
  • Gates: npm run typecheck, npm run build, full npm test (4638 passed; 3 timing tests timed out under full-suite load and pass alone) and capabilities:check are green. No new endpoints: it reuses the claim-page lookup and the token endpoint, and starts no process.

Rollout

  • Pairs with the SaaS endpoint PR (linked in a comment). Until it is deployed, the sync check reports "does not report rules syncing yet" and everything else works.

New command and AGENT-INSTALL.md changes, so the hostile field test is owed after the release that carries this, plus standard/lovable for doc accuracy.

🤖 Generated with Claude Code

`npx @patchstack/connect doctor` runs every check Patchstack depends on
in one go and prints each problem with its fix: the install, the site,
the account, the guard's wiring, its rules file, the read-only rules
credential (and whether Patchstack still accepts it), the map link and
the build steps. With --url it also checks the live app: that it
carries the widget, and that its guard blocks a test attack.

Problems only the app's owner can fix (connecting the account,
publishing) are marked as theirs, so an assistant fixes the rest and
passes those on instead of waiting on them. It writes nothing and exits
1 when it finds a problem.

AGENT-INSTALL.md tells the agent to run it after setup and fix each
problem until none is left, and discloses what it sends.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mariojgt

Copy link
Copy Markdown
Contributor Author

/review

@coderbuds

coderbuds Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

🎯 Elite quality (94%) — Adds a well-structured doctor command with injectable fetch and thorough tests for each finding path.

📦 Large, and not size-checked — 473 lines changed, over your team's 400-line limit. Coding agents can call the assess-change-fit tool before opening, while a change this size is still cheap to split.

🤖 Written by Claude Code — going by its own attribution. Unknown whether a person read it; agents can report that with the report-ai-usage tool.

See how your team is trending →

doctor now reads Patchstack's record of the app's rules fetches from
monitor/pulse/sync-status/<uuid>, with the token from the credential it
already checks (the site key when this machine holds one, otherwise the
read-only credential). It says when the published app last fetched its
rules and how many, and never fetches rules itself, which would be
recorded as a fetch and fake the signal.

An app with no visitors does not fetch, so an old or missing fetch is a
question until doctor --url has just visited the app, and a problem
after. A fetch only on the site key is reported as such, not as the
published app. A server without the endpoint is reported as not
reporting syncing yet.

AGENT-INSTALL.md discloses the extra token request and the read.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mariojgt

Copy link
Copy Markdown
Contributor Author

Pairs with patchstack/saas#2318 (the monitor/pulse/sync-status/{uuid} endpoint doctor reads). Until that is deployed, doctor reports "does not report rules syncing yet" for that one check.

@mariojgt
mariojgt merged commit c4ec8b3 into main Oct 26, 2026
23 checks passed
@mariojgt
mariojgt deleted the mariot/doctor-command branch October 26, 2026 12:05
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