Innova uses Supabase Auth with asymmetric JWT tokens (ES256 or RS256) validated on every request against the Supabase JWKS endpoint. Every request to a protected endpoint must include a valid, unexpired JWT in theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/vruizz22/innova-backend-serverless/llms.txt
Use this file to discover all available pages before exploring further.
Authorization: Bearer <token> header. The only public surfaces are GET / and all /auth/* endpoints — every other route runs through SupabaseAuthGuard and, where applicable, RolesGuard.
Roles
Four roles are defined inroles.enum.ts. A user’s role is resolved from app_metadata.role (set by admin provisioning) or user_metadata.role (set by the frontend at signup), with student as the default fallback.
| Role | Value | Description |
|---|---|---|
STUDENT | "student" | Can submit attempts, view own mastery, access assigned guides and practice |
TEACHER | "teacher" | Can manage guides, view class mastery and alerts, create assignments |
PARENT | "parent" | Can view children’s mastery summaries via parent-link |
ADMIN | "admin" | Can manage the error-tag catalog and platform configuration |
Role values are lowercase strings in the JWT payload and in all API responses (e.g.
"teacher", not "TEACHER"). Use the exact lowercase values when setting role in registration or seed scripts.Register
POST /auth/register — Creates a new user and a corresponding role profile (Student, Teacher, or Parent record) in one transaction. If the email already exists the password and role are updated (upsert). Returns a full session with accessToken, refreshToken, and the user object.
Valid email address. Normalized to lowercase and trimmed on the server.
Minimum 8 characters. Stored as a salted scrypt hash — never in plaintext.
One of
"student", "teacher", "parent", "admin". Determines which role profile is auto-created.Short-lived JWT for authenticating API requests. Include as
Authorization: Bearer <accessToken>.Long-lived token used to obtain a new
accessToken without re-entering credentials.The Prisma
User.id (UUID). Use this as the subject for user-management operations.Normalized email of the registered user.
The role assigned at registration (e.g.
"teacher").The role-specific record ID (
Student.id, Teacher.id, or Parent.id). Pass this to domain endpoints such as GET /mastery/:studentId.Login
POST /auth/login — Authenticates an existing user with email and password. Returns the same session shape as /auth/register.
Registered email address.
Minimum 8 characters. Verified with timing-safe comparison against the stored scrypt hash.
Using the Token
Include theaccessToken in the Authorization header of every authenticated request:
Refresh Tokens
POST /auth/refresh — Exchanges a valid refreshToken for a new session. The refresh token is verified against the stored tokenVersion; if the user has revoked their sessions (e.g. via a password reset), old refresh tokens are rejected.
The
refreshToken value returned by /auth/register or /auth/login.Password Reset
Password reset is a two-step flow: first request a reset code, then confirm with that code and a new password.Request a reset code
POST /auth/forgot-password — Sends a password reset email via Resend. The email contains a link to your app’s /auth/reset page, with a token query parameter encoding the reset code. The code expires in 15 minutes.The registered email address of the account to reset.
Confirm the reset
POST /auth/confirm-forgot-password — Verifies the reset code and sets the new password. On success, the user’s tokenVersion is incremented, invalidating all existing refresh tokens.The same email address used in step 1.
The 6-digit reset code extracted from the email link’s
token parameter.The new password. Minimum 8 characters.
Current User
GET /auth/me — Returns the authenticated user’s profile, including their role-specific profileId. Requires a valid JWT in the Authorization header.
The Prisma
User.id (UUID). This is the identity anchor for all user-management operations.The user’s email address.
Display name from
user_metadata.full_name (or name, or display_name). Falls back to the email local-part if no name metadata is present.The user’s resolved role string.
The role-specific record ID. Use this value for domain endpoints that accept a student, teacher, or parent ID.
Logout
POST /auth/logout — Revokes the current session on the server side. Requires a valid JWT. After logout, the token remains cryptographically valid until its exp claim, so clients should also discard stored tokens immediately.
JWT Validation Details
For developers building integrations or debugging token issues:- Algorithm: Supabase signs JWTs with either ES256 (EC P-256, new projects) or RS256 (RSA, older projects). The backend accepts both via
passport-jwt+jwks-rsa, so key rotation and algorithm changes are transparent. - Audience: Tokens must have
aud: "authenticated". - Issuer: Tokens must be issued by
https://<your-project>.supabase.co/auth/v1. - JWKS endpoint: Public keys are fetched (with caching and rate limiting) from
https://<your-project>.supabase.co/auth/v1/.well-known/jwks.json. - Role claims: The
roleis read fromapp_metadata.rolefirst (admin-provisioned), then falls back touser_metadata.role(set at signup), then defaults to"student". - User linking: On each validated request,
UserLinkerService.ensureUser()creates or updates the correspondingUserrow in Postgres, keeping Supabase Auth and the application database in sync automatically.
Routes decorated with
@Public() — currently GET /, POST /auth/register, POST /auth/login, POST /auth/refresh, POST /auth/forgot-password, and POST /auth/confirm-forgot-password — skip JWT validation completely. The SupabaseAuthGuard checks for this decorator before invoking Passport, so unauthenticated clients can reach these endpoints without a token.