Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

08 — Form Specifications (Auth Module)

Every form field-by-field for the Auth module. Validation mirror class-validator decorators exactly from src/modules/auth/dto/*.ts; messages follow the VALIDATION_ERROR (400) envelope with per-field details. Passwords havehed server side (Argon2id). Client validates inline then submits; server 400 shadows client.


1. Login Form — POST /auth/login (login.dto.ts)

#FieldLabelHint / PlaceholderKeyboardAutofillValidation (server)Client UX
1emailEmailjohn.doe@springfield.eduemailAddressusername@IsEmail() requiredtrim+lower; error: "Enter a valid email"; TextInputAction.next
2passwordPasswordtype your passwordtext(default)current-password@IsString() + @MinLength(6) requiredobscure+reveal; error: Password must be at least 6 characters; onSubmitted submits

Cta: primary full 48 h, loading replaces label. Server 401 → field-level inline "Invalid email or password." (both fields). Double-submit blocked (00-shared/08 §6).

2. Register Form — POST /auth/register (register.dto.ts)

Form metadata: firstName(req), lastName(req), email(req), password(req, min8), tenantId(req), phone(opt).

#FieldTypeAutofillDecoratorsNotes/UX
3firstNametextgiven-name@IsString() reqfirst on form
4lastNametextfamily-name@IsString() req
5emailemailusername@IsEmail() reqnormalized lowercase by server (user.schema.ts:28)
6phonetel (optional)tel@IsOptional() @IsString()country-code prefix; no server format check
7passwordpasswordnew-password@IsString() @MinLength(8)min 8; show strength meter (client-only, not server policy)
8passwordConfirmpassword (client-only)must equal password; no server field — local only
9tenantIdtext@IsString() reqschool slug/tenant id; placeholder "e.g. springfield-school"

Submit → loading → server:

  • 201/409: 409 DUPLICATE_RESOURCE → banner "An account with this email already exists."
  • success: navigate /home + "verify your email" banner (server mints tokens in register(); navigating to /home uses them).

Password minimums: register 8, login 6 (MinLength mismatch between register.dto.ts:19 and login.dto.ts:12 — flag: login accepting 6-char passwords implies legacy/other-created accounts; display rule is min 8 for new).

3. Forgot Password — POST /auth/forgot-password (forgot-password.dto.ts)

#FieldTypeKeyboardAutofillValidation
10emailemailusername@IsEmail() required

Behavior: submit disabled until valid email; on success a neutral confirmation screen (identical copy whether the account exists — server returns same message for both, auth.service.ts:256-283). Rate auth 3/min (auth.controller.ts:92-95). On 429 → disable resubmit + countdown.

4. Reset Password — POST /auth/reset-password (reset-password.dto.ts)

#FieldTypeAutofillValidation
11tokenhidden (from deep-link ?token=)@IsString() required
12passwordpasswordnew-password@IsString() @MinLength(8)
13passwordConfirmpasswordnew-password= password (client)

Errors: token invalid → banner 400 "Invalid or expired reset token.", button "Request a new link" (→ forgot). Token expired → banner "Reset token has expired" (server: auth.service.ts:293-296). Success → "Password reset successfully." (clears sessions) → re-login.

5. 2FA (enable/verify/disable) — totp-setup.dto.ts

One field token (TOTP code): 6 digits (default TOTP_DIGITS=6; env.ts:78), numeric, 8 digits max (min/max from env.ts:78), keyboard number, Regex validation client ^\d{6,8}$, exactly 6 unless org config differs.

6. API Key Create — POST /auth/api-keys (create-api-key.dto.ts)

FieldTypeRequiredValidationUX
nametext@IsString()max length 48 (client), autofocus
scopeschipsno@IsArray() @IsString({each:true})free-text input chips; hinted "e.g. report.generate"; no enum validation server-side — free string list

Submit → returns {id, prefix, key} → swaps form for AppSecretReveal. Done → list refresh. If 429 → disable button, countdown.

7. Verify Email — verify-email.dto.ts

token @IsString() — presented via deep link or manual paste box "Enter your code".


Form-level rules (all)

  • Double-submit: disabled while pending; stop-media-first.
  • Optimistic: no optimistic writes for any auth mutation (tokens/credentials are never guessed) — always server-confirm.
  • Undo: none applicable to credential/secret actions; revoke has a confirm (14).
  • Abandonment: pre-auth config is single-state; clearing email preserves injected token.
  • Keyboard: .next sequence, last .done; Enter submits.
  • Password managers: autofillHints set on every auth field (09 §10).
  • Error copy: from message of envelope only for business 4xx; codes for the rest.

Client-side error priority

  1. 400 VALIDATION → field.
  2. 401 UNAUTHENTICATED → form message.
  3. 409 DUPLICATE_RESOURCE → inline.
  4. 422 BUSINESS_RULE_VIOLATION → banner.
  5. 429 RATE_LIMITED → countdown.
  6. 5xx → AppErrorState.