Skip to content

feat(signup): agents could not get past the signup question, which only surfaced as a raw HTTP 428 body - #73

Draft
AnderRV wants to merge 3 commits into
mainfrom
feat/signup-challenge
Draft

AnderRV wants to merge 3 commits into
mainfrom
feat/signup-challenge

Conversation

@AnderRV

@AnderRV AnderRV commented Oct 22, 2026

Copy link
Copy Markdown
Member

Why

The agent signup endpoint can now ask one short question before it creates an account (HTTP 428, challenge_required). The CLI only showed that as a raw body in cause:, so an agent had no clear way to answer it, and every CLI run is a new process with no memory of the question.

What changed

  • A 428 challenge_required becomes the error SIGNUP_CHALLENGE. The message carries the question, next_action says to run zenrows signup --answer "<your answer>" and then re-run the original command, and --json adds error.challenge (id, question, expires_at).
  • The pending question is kept in .zenrows/signup-challenge.json (no secret: id, question, expiry, and the signup URL that asked it). The file is added to the workspace .gitignore list.
  • New zenrows signup --answer <text> posts {challenge_id, answer} to that URL with the usual signup headers. A right answer stores the key and account exactly like auto signup, prints the claim link and says to re-run the original command. A wrong or late answer stores and shows the new question. A 429 challenge_locked becomes SIGNUP_CHALLENGE_LOCKED with retry_after. No pending or an expired question gives SIGNUP_CHALLENGE_MISSING without a request.
  • A question or the lock stops the signup endpoint fallback loop, since both are real answers from a working endpoint. Other statuses (429 rate_limited, 503, network errors) behave as before.
  • zenrows signup without --answer is unchanged. Help text, README and the zenrows skill describe the question and how to answer it.

How tested

  • npm run typecheck passes.
  • npm test: new tests/signup-challenge.test.ts covers 428 parsing and persistence, --json shape, ensureApiKey, right / wrong / locked / none pending / expired answers, signup --answer --json, and a non-challenge 428. Existing signup tests (201, fallback, 429 rate limited) pass unchanged.
  • End to end against a local backend with the question enabled: zenrows fetch showed the question, a wrong answer showed a new one, the right answer stored the key and account, and a second --answer reported no pending question.

…ly surfaced as a raw HTTP 428 body

Signup may now ask one short question before it creates an account. The
CLI reports it as SIGNUP_CHALLENGE with the question, keeps it in
.zenrows/signup-challenge.json across runs, and adds
zenrows signup --answer to answer it. A wrong answer shows the new
question, and the per-network lock is SIGNUP_CHALLENGE_LOCKED.

This branch has not been deployed

No deployments
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.

1 participant