Skip to content

Authentication

hypar uses better-auth with a Prisma adapter. Embryo and LLM API routes require a signed-in session via requireSessionUserId.

Sign-in / sign-up

RoutePagePurpose
/auth/signinpages/auth/signin.vueEmail + password sign-in. Social buttons appear when the corresponding env vars are set.
/auth/signuppages/auth/signup.vueEmail + password account creation. New users are created with role = 'user'.

The minimum password length is 8 characters (server/lib/auth.ts).

There is no /setup wizard and no Setting / app.configured flag. First signup is a normal user.

Providers

  • Email + password — always on.
  • Google OAuth — enabled when both GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are set.
  • GitHub OAuth — enabled when both GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET are set.

See Environment variables for the full list.

Sessions

Cookies issued by better-auth.

SettingValue
expiresIn7 days
updateAgerefreshed on activity older than 1 day
SecretBETTER_AUTH_SECRET (or AUTH_SECRET) — required, generate with openssl rand -hex 32

server/middleware/auth-session.ts attaches the session to every H3 request as event.context.auth. Server handlers should read the user id via requireSessionUserId(event) from server/utils/session.ts.

In Vue components and pages use the useAuth() composable:

ts
const { user, userId, isAdmin, isAuthenticated, isPending } = useAuth()

The browser client lives in utils/auth-client.ts and exposes signIn, signUp, signOut, useSession.

Route protection

A global client route middleware redirects unauthenticated visitors to /auth/signin for every page except PUBLIC_ROUTES (/auth/signin, /auth/signup). See middleware/auth.global.ts.

API routes that return user-scoped data call requireSessionUserId(event) and filter Prisma by that userId, so user A cannot read user B's embryos.

GET /api/health is unauthenticated (Compose healthcheck). POST /api/vitals and POST /api/client-errors are also unauthenticated telemetry sinks.

Admin

User.role is 'user' or 'admin'. Signup always creates 'user'. There is no first-user-becomes-admin hook.

/admin and /admin/users are stubs (“coming soon”). There is no /api/admin/* and no ADMIN_API_KEY. Promote someone with Prisma Studio or SQL:

sql
UPDATE "User" SET role = 'admin' WHERE email = 'you@example.com';

The header hides the admin link for non-admins. Admin pages use middleware: 'admin' and redirect everyone else home.

Next steps

MIT License