Skip to content

fix(auth): make email-verification signup completable - #3017

Open
jakevis wants to merge 3 commits into
emdash-cms:mainfrom
jakevis:fix/signup-verification-link
Open

fix(auth): make email-verification signup completable#3017
jakevis wants to merge 3 commits into
emdash-cms:mainfrom
jakevis:fix/signup-verification-link

Conversation

@jakevis

@jakevis jakevis commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Email-verification signup dead-ended three ways, described in #3007:

  1. The verification email linked to /_emdash/api/auth/signup/verify — the JSON endpoint the admin SPA calls — so a person clicking it saw a raw success payload. It now links to /_emdash/admin/signup?token=…, built the same way the invite email builds its link; SignupPage already reads ?token= from the URL and verifies it.
  2. /_emdash/admin/signup wasn't on the middleware's list of admin pages an anonymous visitor may open, so the page redirected to login. It now joins login and invite/accept.
  3. The login redirect carried only url.pathname, dropping ?token=. It now keeps the query string — worth having for any future token-bearing admin URL, not just this one.

Tests: signup email link assertion updated; new middleware test covers the three public admin pages and asserts the redirect preserves the full URL. Changeset included for @emdash-cms/auth and emdash.

Closes #3007

Type of change

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings in the admin UI are wrapped for translation (if applicable)
  • I have added and reviewed the user-facing changeset (if this PR changes a published package)
  • New features link to an approved Discussion
  • I have included screenshots below if this PR changes the UI

AI-generated code disclosure

  • This PR includes AI-generated code — model/tool: Claude Fable 5.1 (Claude Code)

Screenshots / test output

tests/unit/auth/signup.test.ts, tests/unit/middleware/admin-public-routes.test.ts, tests/unit/middleware/oauth-csrf.test.ts  42 passed

The verification email linked to /_emdash/api/auth/signup/verify — the JSON
endpoint the admin SPA calls — so a person clicking it saw a raw success
payload and no account. The invite flow, in the same package, already links
to its admin page; signup now does the same, and the SignupPage already
reads ?token= from the URL and verifies it.

That alone would have redirected them to login, because
/_emdash/admin/signup was not on the middleware's short list of pages an
anonymous visitor may open. And the redirect to login carried only the
pathname, so the token would have been lost on the way back. Both fixed:
signup joins login and invite/accept as public admin pages, and the login
redirect keeps the query string — that last one for any future token-bearing
admin URL, not just this one.

Fixes emdash-cms#3007
@changeset-bot

changeset-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bb35869

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 17 packages
Name Type
@emdash-cms/auth Patch
emdash Patch
@emdash-cms/auth-atproto Patch
@emdash-cms/release-service Patch
@emdash-cms/cloudflare Patch
@emdash-cms/sandbox-workerd Patch
@emdash-cms/fixture-perf-site Patch
@emdash-cms/perf-demo-site Patch
@emdash-cms/cache-demo-site Patch
@emdash-cms/do-demo-site Patch
@emdash-cms/do-solo-demo-site Patch
@emdash-cms/admin Patch
@emdash-cms/blocks Patch
create-emdash Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Sep 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@3017

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@3017

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@3017

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@3017

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@3017

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@3017

emdash

npm i https://pkg.pr.new/emdash@3017

create-emdash

npm i https://pkg.pr.new/create-emdash@3017

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@3017

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@3017

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@3017

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@3017

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@3017

@emdash-cms/registry-moderation

npm i https://pkg.pr.new/@emdash-cms/registry-moderation@3017

@emdash-cms/registry-verification

npm i https://pkg.pr.new/@emdash-cms/registry-verification@3017

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@3017

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@3017

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@3017

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@3017

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@3017

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@3017

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@3017

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@3017

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@3017

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@3017

commit: bb35869

@github-actions github-actions Bot added the review/needs-review No maintainer or bot review yet label Sep 10, 2026
@ascorbic ascorbic added the bot:review Trigger an emdashbot code review on this PR label Sep 11, 2026

@emdashbot emdashbot 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.

The approach is sound. The PR fixes the three real dead‑ends for email‑verification signup: the email link now points to the existing admin signup page, that page is reachable without a session, and the login redirect keeps the token query string. These changes are additive and consistent with how the invite flow already works.

I checked the diff, the full changed files, the route injection (/_emdash/admin/[...path]), getSiteBaseUrl semantics (siteOrigin/_emdash), the admin router redirect handling, and the updated tests. One issue stands out: the unit test updated its email‑link assertion but dropped the /_emdash mount segment, so it no longer verifies the link users actually receive in production. Other than that test fixture/expectation mismatch the code changes look correct.

(The reported pnpm test output could not be verified here because this is a static review.)

expect(sentEmails[0]!.text).toContain(
"https://example.com/_emdash/api/auth/signup/verify?token=",
);
expect(sentEmails[0]!.text).toContain("https://example.com/admin/signup?token=");

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.

[needs fixing] The updated assertion no longer verifies the real email link.

The production caller (packages/core/src/astro/routes/api/auth/signup/request.ts) passes baseUrl from getSiteBaseUrl, which returns the public origin suffixed with /_emdash (e.g. https://example.com/_emdash). The new code in packages/auth/src/signup.ts uses new URL(\${config.baseUrl}/admin/signup`), so the emitted link is https://example.com/_emdash/admin/signup?token=…`, matching the PR description and the middleware public route /_emdash/admin/signup.

However, the test still passes baseUrl: "https://example.com" (line 103) and asserts "https://example.com/admin/signup?token=". The test will pass, but it validates a URL shape that is never sent to users and could miss regressions in the mount path.

Update the fixture to pass baseUrl: "https://example.com/_emdash" and assert the production URL:

Suggested change
expect(sentEmails[0]!.text).toContain("https://example.com/admin/signup?token=");
expect(sentEmails[0]!.text).toContain(
"https://example.com/_emdash/admin/signup?token=",
);

@emdashbot emdashbot Bot removed the bot:review Trigger an emdashbot code review on this PR label Sep 11, 2026
@github-actions github-actions Bot added review/awaiting-author Reviewed; waiting on the author to respond and removed review/needs-review No maintainer or bot review yet labels Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth area/core review/awaiting-author Reviewed; waiting on the author to respond size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Email-verification signup cannot complete: the email links to the API route, and /_emdash/admin/signup is not public

2 participants