Skip to content

Keep login renderable when the optional signup route is absent #296

Description

@alexeygrigorev

Status

P0 deterministic regression; engineer-ready and independent of #186. This issue repairs login-route composability only. It does not decide or alter whether account creation is enabled.

Scheduled full regression 33315212334 at exact origin/main SHA face8e4808d65afbf0374d1ced7a88079950d663 proves /accounts/login/ returns 500 when the active URLConf intentionally exposes accounts.urls without allauth's optional account_signup name. The traceback is exact:

  • accounts/views/login.py:118 eagerly evaluates reverse("account_signup");
  • Django raises NoReverseMatch because core.tests.seo_fixture_urls deliberately includes accounts.urls, Studio, and the management API, but not allauth.urls;
  • preview and Studio redirects therefore reach a broken login page instead of the required safe sign-in surface.

Commit a792553 introduced the hard dependency while making the existing login-page account links use a resolved destination. Full website.urls does include allauth after accounts.urls, so the ordinary site has the route; the reduced security/preview surface intentionally does not.

Normative authority

  • _docs/specs/01-platform-architecture.md § “Member signup, profile, Slack, and course registration”: signup is conditional, and return intent is server-side/path-only.
  • _docs/specs/07-security-privacy-operations.md §§ “Web and application security” and “Identity and authorization”: safe errors must not expose sensitive state; login/signup controls remain bounded and fail closed.
  • _docs/PROCESS.md: a regression receives its own groomed lifecycle and exact-candidate engineer, tester, PM, merge, and on-call evidence.
  • Enforce non-indexable development and preview behavior #36 owns the non-indexable development/preview surface whose reduced URLConf exposed this failure.
  • /accounts/signup/ is open despite ACCOUNT_ALLOW_REGISTRATION = False #186 exclusively owns the unresolved account-creation posture.

Product contract

The login view is usable under every supported URLConf that exposes it. The account-creation destination is an optional navigation capability, not a prerequisite for rendering or authenticating.

  • When account_signup resolves in the active URLConf, preserve the current exact signup destination and safe next behavior.
  • When it does not resolve, render the normal login page successfully and omit every account-creation entrance that would otherwise point to it.
  • Do not invent or hard-code /accounts/signup/, add allauth to a reduced URLConf, redirect to an unrelated destination, or expose a broken/empty anchor.
  • Absence of the optional route creates no account, EmailAddress, session, durable job, audit success event, or network/provider side effect.

This is policy-neutral fail-closed behavior. It neither approves open signup nor implements #186 Option A, B, or C.

Scope

  • Make social_login_view represent optional signup-route availability without raising NoReverseMatch during view execution or template rendering.
  • Make both responsive account-creation placements in accounts/templates/accounts/login.html conditional on a real resolved destination.
  • Add focused tests for the full URLConf and a deliberately reduced URLConf with login present and account_signup absent.
  • Preserve safe internal next on the real signup link and existing login/provider/local-owner behavior.
  • Complete graph-selected verification and independent responsive screenshot review on the exact frozen candidate.

Explicit non-goals

  • No change to ACCOUNT_ALLOW_REGISTRATION, ACCOUNT_EMAIL_VERIFICATION, ACCOUNT_ADAPTER, allauth signup behavior, social consolidation, identity inventory, account models, or migrations.
  • No choice or partial implementation of /accounts/signup/ is open despite ACCOUNT_ALLOW_REGISTRATION = False #186's signup, verification, collision, enumeration, abuse, or public-entrance posture.
  • No redesign or copy change to the login or signup pages.
  • No addition of allauth/signup routes to core.tests.seo_fixture_urls or another intentionally reduced URLConf.
  • No weakening/removal of the preview, Studio, safe-redirect, noindex, cache, console, or external-request assertions that exposed the defect.
  • No hard-coded fallback URL and no broad redesign/Audit and refine sitewide design consistency #237 replay.

Dependencies and lifecycle boundary

No product decision is required, and #186 is not a dependency: the full URLConf's currently available signup link remains unchanged whichever posture the owner later selects. #186 remains open with decision; this issue must not remove that label or infer approval.

Use a fresh clean worktree from current origin/main. A local redesign-lineage commit named d331827 is not issue-owned evidence and must not be replayed wholesale. Its reverse_lazy("account_signup") approach merely defers lookup until template coercion; because the template renders the value, laziness alone does not establish the absent-route contract. Implement and prove the explicit optional capability instead.

Acceptance criteria

  • With full website.urls, signed-out GET /accounts/login/ returns 200, renders the existing Create an account entrances with exact destination /accounts/signup/, and preserves an allowed internal next value exactly through the signup destination.
  • With a supported reduced URLConf that includes accounts.urls but has no account_signup name, signed-out GET /accounts/login/ returns 200 with the normal Sign In page and no NoReverseMatch or server error.
  • In that absent-route state, no Create an account link, empty/broken account-creation anchor, hard-coded signup URL, or alternate signup promise is rendered in either responsive placement.
  • The absent-route state does not add a signup route: direct resolution/request remains the reduced URLConf's safe missing-route result and creates no user, EmailAddress, authenticated session, durable job, audit success event, or provider/network call.
  • Existing provider choices, development-owner form availability, generic safe error copy, rate-limit behavior, and safe path-only login next behavior remain unchanged in both URLConf states.
  • External, scheme-relative, credential-bearing, malformed, and auth-loop next values remain rejected and are not reflected into either login or signup destinations.
  • Focused Django tests exercise both route-present and route-absent states and prove template rendering, not merely context construction or lazy-object creation.
  • The fresh change-selective plan is generated from the exact candidate; all selected checks complete with no undocumented skips, and the regression cases from run 33315212334 reach their intended assertions rather than failing on login rendering.
  • An independent tester inspects desktop and mobile screenshots of the reduced preview/Studio login state and the full-URLConf login state, confirming the correct page, conditional entrance, focus/readability, no error page, and no layout regression.
  • A separate PM accepts the exact tester-passed fingerprint before an engineer creates a focused Closes #296 commit; orchestrator then performs the no-ff merge/push and on-call alone observes exact-SHA CI.

Browser scenarios

  1. At desktop and mobile widths, a signed-out visitor follows the protected preview redirect under core.tests.seo_fixture_urls; login returns 200, shows Sign In, preserves the safe preview intent, omits account-creation links, and has no console/server error.
  2. At desktop and mobile widths, a signed-out visitor follows the Studio redirect under the same reduced URLConf and receives the same safe login contract without gaining a signup route.
  3. Under full website.urls, the existing account-creation links remain visible and target /accounts/signup/ with a valid internal next; unsafe intent is discarded.
  4. Keyboard traversal in both states reaches only real visible controls with the existing focus treatment; no empty or broken account-creation control remains.

Engineering handoff

Start from exact current origin/main, not the dirty root or local redesign branch. Keep the candidate uncommitted and frozen after posting the Software Engineer report. This issue changes a rendered conditional, so full graph-selected Playwright and tester-owned screenshots are required; a backend-only smoke run is not sufficient.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Must-have or release-blockingauthArea: authbugSomething isn't workingsecurityArea: securitytestingArea: testing

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions