Skip to content

Auth frontend: login, verify, session, and logout#48

Open
RandyJDean wants to merge 1 commit into
07-09-auth_wire_spring_security_spring_session_jdbc_end_to_endfrom
07-09-auth_frontend_login_verify_session_and_logout
Open

Auth frontend: login, verify, session, and logout#48
RandyJDean wants to merge 1 commit into
07-09-auth_wire_spring_security_spring_session_jdbc_end_to_endfrom
07-09-auth_frontend_login_verify_session_and_logout

Conversation

@RandyJDean

Copy link
Copy Markdown
Contributor
  • apiFetch now unwraps the ApiResponder envelope (typed payloads,
    server-authored error messages) and states the cookie contract with
    credentials: same-origin; sample MSW mock updated to match
  • New features/auth/: Login page (email -> generic check-your-email
    panel), Verify page (POSTs the emailed token once on mount with a
    StrictMode guard; routes shell accounts to /sign-up), and hooks —
    useSession (moved from lib/api as its comment mandated; 401 resolves
    to null), useRequestLink, useVerifyMagicLink, useLogout
  • RequireAuth redirects signed-out visitors to /login and incomplete
    profiles to /sign-up; AppLayout gains a Log out button
  • Router mounts /login and /auth/verify under the public layout
  • Test infra: auth MSW handlers composed into the server, MemoryRouter
    initialEntries support; page + guard tests cover the happy paths,
    expired links, and shell redirects

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

- apiFetch now unwraps the ApiResponder envelope (typed payloads,
  server-authored error messages) and states the cookie contract with
  credentials: same-origin; sample MSW mock updated to match
- New features/auth/: Login page (email -> generic check-your-email
  panel), Verify page (POSTs the emailed token once on mount with a
  StrictMode guard; routes shell accounts to /sign-up), and hooks —
  useSession (moved from lib/api as its comment mandated; 401 resolves
  to null), useRequestLink, useVerifyMagicLink, useLogout
- RequireAuth redirects signed-out visitors to /login and incomplete
  profiles to /sign-up; AppLayout gains a Log out button
- Router mounts /login and /auth/verify under the public layout
- Test infra: auth MSW handlers composed into the server, MemoryRouter
  initialEntries support; page + guard tests cover the happy paths,
  expired links, and shell redirects

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

RandyJDean commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@sonarqubecloud

sonarqubecloud Bot commented Jul 9, 2026

Copy link
Copy Markdown

@RandyJDean RandyJDean marked this pull request as ready for review July 10, 2026 18:47
@RandyJDean RandyJDean requested a review from a team as a code owner July 10, 2026 18:47
@graphite-app graphite-app Bot requested review from Arshadul-Monir and arklian July 10, 2026 18:47
@graphite-app

graphite-app Bot commented Jul 10, 2026

Copy link
Copy Markdown

Graphite Automations

"Request reviewers once CI passes" took an action on this PR • (07/10/26)

2 reviewers were added to this PR based on Henry Chen's automation.

Comment thread js/src/lib/api/client.ts
}

return response.json() as Promise<T>;
return envelope?.payload as T;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Returns undefined when the backend sends a successful response without a payload field or with invalid JSON, but casts it as type T. If T is not nullable, downstream code will crash at runtime.

For example, if the server returns {success: true, message: "OK"} without payload, or if JSON parsing partially succeeds but produces an object without the payload key, envelope?.payload evaluates to undefined but is typed as T.

if (!envelope?.payload && response.ok) {
  throw new ApiError(
    response.status,
    "Server returned success without payload"
  );
}
return envelope.payload as T;

Alternatively, ensure the type system reflects that payload can be undefined: return envelope?.payload as T | undefined; and update call sites to handle undefined.

Suggested change
return envelope?.payload as T;
if (!envelope?.payload && response.ok) {
throw new ApiError(
response.status,
"Server returned success without payload"
);
}
return envelope!.payload as T;

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

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