Skip to content

feat: relay the caller's own keyless signup link from the API - #467

Merged
rakshith48 merged 6 commits into
mainfrom
rak/keyless-short-links
Sep 30, 2026
Merged

rakshith48 merged 6 commits into
mainfrom
rak/keyless-short-links

Conversation

@rakshith48

@rakshith48 rakshith48 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Keyless recovery messages now relay the caller's own https://firecrawl.dev/k/<token> signup link from the API, in place of the fixed utm_medium=mcp link. The token is a 12-character encrypted value (keyless IPv4, surface, prompt reason) that the site decrypts to keyless attribution; the API stores nothing per identity.

  • A keyless 429 uses its signup_url. An eligibility refusal uses signupUrl.
  • When a hosted keyless session calls an account-only tool, the server asks /v2/keyless/eligibility?signup_link=1 for the caller's link. The API tags that token with the account_only_tool reason, and issuing it is free (no rows), so this call stays.
  • Relays only the API's own links: firecrawl.dev/k/<12-char token>, or the regular keyless signin link the API sends when it has no token (signin?utm_source=keyless&utm_medium=<surface>), on www. or the bare host. Anything else (another host, the old 8-character ids, or no link) falls back to the regular MCP signin link (signin?utm_source=keyless&utm_medium=mcp&redirect=%2Fapp%2Fapi-keys), so MCP attribution is kept.
  • Recovery payloads carry the link as signup_url.
  • Tests cover the 429, eligibility and account-only paths, including an account-only case that relays the regular link and drops an untrusted or legacy one.

Safe to deploy before the API change, since it falls back to the regular MCP signin link.


Summary by cubic

Keyless recovery messages now relay the caller's own https://firecrawl.dev/k/<token> signup link from the API instead of the fixed utm_medium=mcp link, keeping attribution on the identity that was rate-limited.

  • The API issues stateless 12-character encrypted tokens; legacy 8-character ids and non-firecrawl.dev links are rejected.
  • A keyless 429 uses its signup_url; an eligibility refusal uses signupUrl; an account-only tool on a hosted keyless session asks /v2/keyless/eligibility?signup_link=1 for the caller's link.
  • Links are checked field by field: https on firecrawl.dev/www.firecrawl.dev, either /k/<12-char token> with no query, or /signin with utm_source=keyless, utm_medium=api|mcp|cli, and an optional redirect=/app/api-keys. Anything else falls back to the regular MCP signup link and unrecognized Firecrawl-hosted links are logged once for drift visibility.
  • Recovery payloads carry the link as signup_url, and the server ships as 3.27.0.

Safe to deploy before the API change, since it falls back to the regular MCP signup link.

Migration
Ship in order: web /k route and signup decrypt, API issuing links, MCP relay, then CLI. Set KEYLESS_SIGNUP_LINK_KEYS in the web env before the API ships.

Written for commit 583a554. Summary will update on new commits.

Review in cubic

Rollout order (ship in this order)

  1. firecrawl/firecrawl-db#310: migrations
  2. firecrawl/firecrawl-web#3849: /k/<token> route and signup decrypt (must be live before the API ships, or new links 404)
  3. feat(api): link keyless prompts to opaque per-identity /k links聽firecrawl#4856: API issues the links
  4. feat: relay the caller's own keyless signup link from the API聽#467: MCP relays them
  5. feat: print the API's keyless signup link as-is and send X-Origin: cli聽cli#291: CLI release

Web and API must share KEYLESS_SIGNUP_LINK_KEYS before the API ships. Set the same value in the web env first, then in the API env. If the API encrypts with a key the web doesn't have, signups keep the raw token in keyless_ref but get no decoded columns.

馃 Generated with Claude Code

Keyless recovery messages linked to a fixed
/signin?utm_source=keyless&utm_medium=mcp URL. The API now issues each keyless
identity an opaque https://firecrawl.dev/k/<id> link per surface, which the
site resolves to MCP keyless attribution and which lets a signup be joined to
the keyless identity. The server relays that link instead of the constant:

- a keyless 429 from the API: its signup_url
- an eligibility refusal: signupUrl from /v2/keyless/eligibility
- an account-only tool on a hosted keyless session: the server asks
  /v2/keyless/eligibility?signup_link=1 for the caller's link

Only firecrawl.dev/k links are relayed; anything else, or no link, falls back
to https://firecrawl.dev/k, which the site still tags as keyless. Recovery
payloads carry the link as signup_url.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread tests/mcp-smoke.test.mjs Outdated
The invalid-link test only exercised the core 429 path. Loop it over the
eligibility path too, so a regression in reading or validating signupUrl
falls back to the bare /k link instead of relaying an untrusted URL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Sep 30, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Auto-approved: Per-caller keyless signup links are now relayed from the API into recovery messages, with strict URL validation and a fallback to the bare /k link; the change is bounded to message/payload formatting and covered by new tests.

Re-trigger cubic

The API now sends the regular keyless signup link
(signin?utm_source=keyless&utm_medium=<surface>) when it can't give a /k
link. Accept and relay it, and use the regular MCP signup link instead of
the bare /k when there is no API link at all, so the MCP surface is still
attributed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 4 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread tests/mcp-smoke.test.mjs
Comment thread src/index.ts
Comment thread src/index.ts Outdated
@cubic-dev-ai
cubic-dev-ai Bot dismissed their stale review September 30, 2026 07:45

Dismissed because Cubic found issues in a newer review.

The API now issues stateless 12-character tokens (firecrawl.dev/k/<token>)
instead of 8-character database ids, so the trusted-link pattern accepts
/k/<12 chars> on either host and no longer accepts the old ids. The regular
keyless signin link is still relayed, now on the bare host too, and the
regular MCP signin link stays the fallback.

Adds coverage for the account-only tool path: a regular link from the
signup_link=1 check is relayed, and an untrusted or legacy one falls back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread src/index.ts Outdated
Replace the literal regex with a parsed check: https on firecrawl.dev or
www.firecrawl.dev, either /k/<12-char token> with no query, or /signin with
exactly utm_source=keyless, utm_medium=api|mcp|cli and an optional
redirect=/app/api-keys, in any order and percent-encoding case. Firecrawl-hosted
links that fail are logged once each, so an API format change is visible
instead of silently falling back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 4 files (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Auto-approved: Per-caller keyless signup links from the API are relayed in recovery messages only after strict URL validation, with fallback to the standard MCP signin link; the change is confined to recovery formatting and covered by tests.

Re-trigger cubic

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 2 files (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Auto-approved: Keyless recovery messages now relay a caller-specific, API-issued signup link only after strict field-by-field URL validation, falling back to the standard MCP signin link otherwise; the behavior is confined to recovery messaging and covered by focused tests.

Re-trigger cubic

@rakshith48
rakshith48 merged commit f256646 into main Sep 30, 2026
2 checks passed
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