# login ## Purpose Defines Zod schemas for the login request and response shapes used by Suaveplan's authentication endpoints. These schemas serve as the single source of truth consumed by the server route handler for `POST /auth/login`, the React login mutation hook, and the OpenAPI document generator — ensuring every layer shares the same field names, validation rules, and TypeScript types without duplication. ## Features - `LoginInput` schema — validates `{email, password}` credentials with RFC 5322 email validation - `LoginUser` embedded object schema — user identifier, email, display name, and roles array returned inside the login response - `LoginOutput` schema — wraps a short-lived access `token`, a long-lived `refreshToken`, and a `LoginUser` object - All fields non-empty with appropriate Zod refinements - Full TypeScript inference via `z.infer<>` — no manual interface duplication - Zod v4 compatible ## Usage: Basic Example ```ts import { LoginInput, LoginOutput } from "@suaveplan/api-schemas/auth"; // Validate the parsed request body const input = LoginInput.parse(req.body); // → { email: "user@example.com", password: "secret" } // Validate the response before serialising to JSON const output = LoginOutput.parse({ token: "eyJhbGciOiJFZERTQSJ9...", refreshToken: "rt_abc123", user: { id: "user_01", email: "user@example.com", name: "Alice", roles: ["member"] }, }); ``` ## Usage: Advanced Example ```ts import { LoginInput, LoginOutput } from "@suaveplan/api-schemas/auth"; async function handleLogin(rawBody: unknown): Promise { const { email, password } = LoginInput.parse(rawBody); const user = await authService.verifyPassword(email, password); const token = await tokenService.issueAccessToken(user.id); const refreshToken = await tokenService.issueRefreshToken(user.id); return LoginOutput.parse({ token, refreshToken, user }); } ``` ## API Reference ### `LoginInput` Zod object schema — login request body. | Field | Type | Description | |------------|---------------------|---------------------------------| | `email` | `string` (email) | RFC 5322 valid email address | | `password` | `string` (min 1) | Plaintext password (TLS-only) | **Type export:** `type LoginInput = z.infer` ### `LoginUser` Zod object schema — user payload embedded in the login response. | Field | Type | Description | |---------|--------------------|------------------------------------------| | `id` | `string` (min 1) | Unique user identifier | | `email` | `string` (email) | User email address | | `name` | `string` (min 1) | Display name | | `roles` | `string[]` | Array of role identifiers for this user | **Type export:** `type LoginUser = z.infer` ### `LoginOutput` Zod object schema — login success response. | Field | Type | Description | |----------------|-----------------|-------------------------------------------| | `token` | `string` (min 1)| Short-lived access token | | `refreshToken` | `string` (min 1)| Long-lived refresh token | | `user` | `LoginUser` | Authenticated user details | **Type export:** `type LoginOutput = z.infer` ## Implementation Notes The `password` field uses `z.string().min(1)` rather than a minimum-length policy constraint because the schema layer validates wire format, not security policy. Minimum password length requirements belong in the registration flow and are enforced by the auth service. The access token format (JWT, opaque, etc.) is also not validated here — `z.string().min(1)` accepts any non-empty token string, keeping the schema decoupled from the token implementation.