Authentication
Authentication
Section titled “Authentication”Purpose
Section titled “Purpose”Document where Clerk authentication is enforced and where downstream services trust verified upstream identity.
Participants
Section titled “Participants”- Clerk issues sessions and JWTs.
- Brisket validates user-facing requests with @clerk/nextjs middleware and auth().
- Strip validates sessions with custom Fiber middleware and clerk-sdk-go/v2.
- Brain uses a NestJS Passport guard backed by @clerk/backend.
- Sirloin generally trusts upstream auth and uses the Clerk SDK for lookups.
- Round has no auth and is internal-only.
Sequence
Section titled “Sequence”sequenceDiagram participant User participant Clerk participant Brisket participant Strip participant Brain participant Sirloin participant Round User->>Clerk: Sign in Clerk-->>Brisket: Session/JWT Clerk-->>Strip: Session/JWT Brisket->>Sirloin: Request with verified user context Strip->>Sirloin: Request with verified user context Brain->>Brain: Guard checks Clerk unless route is public/API-key Brain->>Round: Internal gRPC call Sirloin->>Clerk: Lookup user metadata when needed
Signup destinations
Section titled “Signup destinations”Until funnels launch, the main app layout keeps its existing IntroFunnelRedirect: signed-in users without a subscription or completed welcome quiz enter one simplified /welcome quiz, followed by its skippable paywall. This includes returning sign-ins who have not finished it. skip-post-signup-quiz ON bypasses the quiz; OFF shows it for eligible users. The redirect and welcome entry wait for the existing flag grace period when the flag is unresolved; if still unavailable afterward, they keep the quiz.
Email and OAuth authentication keep their existing destinations and callbacks. The app-entry redirect passes the current path and query through a sanitized return_to; closing the quiz paywall resumes that destination. Missing, unsafe or recursive returns use Explore. A direct welcome visit also honors the skip flag. Bypassing neither marks the quiz complete nor consumes funnel inputs. See the app-entry redirect, quiz entry and continuation helpers.
Quiz completion retains the existing starter-character behavior when characters-v2 is off; it does not use the saved funnel inputs.
At funnel launch, remove IntroFunnelRedirect from the main layout and retire the temporary welcome entry, skip flag and continuation helpers. Authentication has no quiz-specific wrappers to remove. Keep the auth return validation and /hop ownership checks. Existing character welcome, payment, credit, KYC and app-tour entry points remain unchanged.
A visitor already signed in on arrival at /f goes straight to Explore (/), without loading funnel progress or recording a funnel opening. A visitor who starts anonymously keeps the funnel session when authentication completes: it saves current answers and files before email, OAuth or sign-in departure. Authentication carries the exact funnel/publication reference to protected /hop, outside the main app layout. The hop resolves first; the main-layout quiz gate runs when the user reaches the resulting app destination. Server initialization completes funnel attribution before profile queries and authenticated analytics/flags mount; timeouts and transient failures log a warning, clear the pending attribution cookie, and silently redirect to Explore. Saved browser inputs are retained; failed attribution may remain unrecorded. /hop then validates browser ownership and the current publication and chooses a fixed internal destination. An unavailable character handler falls back to Explore without consuming saved data.
See funnel storage and routing, auth return policy, and hop route.
Source Links
Section titled “Source Links”- apps/brisket/src/middleware.ts
- apps/strip/internal/app/middleware/auth.go
- apps/brain/src/modules/application/auth/guards/clerk-auth.guard.ts
- apps/sirloin/internal/pkg/clerk/
State Transitions
Section titled “State Transitions”Unauthenticated browser requests become authenticated app requests after Clerk validation at the frontend/service edge. Sirloin receives user identifiers from trusted callers rather than revalidating every JWT.
Invariants
Section titled “Invariants”- User-facing services must validate Clerk identity before calling trusted backend paths.
- Sirloin trust depends on upstream callers preserving verified user identity.
- Round must remain internal-only unless an auth boundary is added.
Error Paths
Section titled “Error Paths”Invalid or missing Clerk sessions are rejected by Brisket, Strip, or Brain before protected work starts. Strip also protects return_to redirects and token size.
Tests And Verification
Section titled “Tests And Verification”- Brisket: cd apps/brisket && pnpm test
- Strip: cd apps/strip && make run-tests
- Brain: cd apps/brain && pnpm test