Skip to content

feat(authenticate): separate login from signup with an explicit intent - #1912

Draft
rohanchkrabrty wants to merge 1 commit into
feature/featconsent-add-the-user_consents-table-with-immutabilityfrom
feature/featauthenticate-separate-login-from-signup-with-an-explicit
Draft

feat(authenticate): separate login from signup with an explicit intent#1912
rohanchkrabrty wants to merge 1 commit into
feature/featconsent-add-the-user_consents-table-with-immutabilityfrom
feature/featauthenticate-separate-login-from-signup-with-an-explicit

Conversation

@rohanchkrabrty

@rohanchkrabrty rohanchkrabrty commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a flow intent so frontier can tell a signup from a login, per RFC 0002, Enforcement → Login and signup. Ships value on its own with no consent involved: a login never creates an account, and a signup never logs an existing user in.
  • Two gates, because OIDC has no email until the provider returns. StartFlow is the fast path for the strategies that know the address up front, so a rejection lands before anything is mailed; getOrCreateUser is the gate that matters, since every strategy ends there. It now takes the flow, and ErrLoginUserNotFound / ErrSignupUserExists join the existing error block.
  • The intent replaces the guess. StartFlow used to look the user up to decide between the passkey register and login ceremonies, which meant a passkey login could create an account; the intent now picks the ceremony, and an unspecified intent keeps the old guess.
  • The intent and the accepted document ids ride on flow.Metadata (existing JSONB, no migration), read back through two nil-receiver-safe accessors that parse rather than assert — JSONB returns []any and an RFC 3339 string, not what it was given.
  • Unspecified stays permissive, so existing clients are unaffected and this lands without a client release. Beyond the RFC: the flow-start gate also covers mail link, which knows the address exactly as early as mail OTP and shares applyMailOTP at the other end.

@rohanchkrabrty rohanchkrabrty self-assigned this Aug 31, 2026
@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
frontier Ready Ready Preview Aug 31, 2026 7:11pm

@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coveralls

coveralls commented Aug 31, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 33429107510

Coverage increased (+0.4%) to 49.524%

Details

  • Coverage increased (+0.4%) from the base build.
  • Patch coverage: 4 uncovered changes across 2 files (115 of 119 lines covered, 96.64%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
core/authenticate/service.go 67 64 95.52%
core/authenticate/authenticators.go 1 0 0.0%
Total (3 files) 119 115 96.64%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 40611
Covered Lines: 20112
Line Coverage: 49.52%
Coverage Strength: 15.83 hits per line

💛 - Coveralls

Frontier cannot tell a signup from a login: every strategy ends at
getOrCreateUser, which returns the existing user or creates one, so a
login with an unknown address silently creates the account.

Adds a FlowIntent carried on flow metadata and both gates from the RFC's
intent by strategy table. StartFlow is the fast path, rejecting a login
with no account or a signup with one before an OTP is sent, for the
strategies that know the email that early. User creation is the gate that
matters, since every strategy reaches it and OIDC has no email until the
callback.

The intent also replaces the passkey guess: signup picks the register
ceremony, login picks the login ceremony. An unspecified intent keeps
today's create-or-get and today's guess, so existing clients and
deployments are unaffected.

Flow.Metadata is existing JSONB, so no migration. The accessors parse
rather than assert, since JSONB does not return the types it was given,
and are nil-receiver-safe so the caller without a flow needs no branch.

Error mapping at the handlers and all consent work follow separately.

Refs docs/rfcs/0002-explicit-consent-at-signup.md

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VW3nysiE4H83VQk6BroMYc
@rohanchkrabrty
rohanchkrabrty force-pushed the feature/featauthenticate-separate-login-from-signup-with-an-explicit branch from 1cb69f7 to fac50ad Compare August 31, 2026 19:10
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