Every screen of the Auth module, its intent, route, composition, states, permissions,
platform behavior and events. Authoritative components in 00-shared/03 ; this file
enumerates which ones each screen uses with module specifics.
States = idle / loading / success / empty / error(offline, rate, invalid) / disabled / permission.
Analytics events follow {module}.{screen}.{action} (proposed; SDK open — 00-shared/10 §8 ).
Field Detail
Purpose Authenticate with email/password → token pair
Entry cold app, any deep link, session expiry, "log out" piggyback
Exit success → /home; → /forgot-password; → /register; → /login/2fa (planned)
Inputs AppTextField email (autofill username), AppTextField password (obscure, autofill current-password)
Primary CTA Login filled button (fullWidth)
Secondary "Forgot password?" (text), "Register your school" (text)
States loading (button), error (inline field/server), rate-limited (429 countdown), offline (banner+native retry), locked (specific copy)
Analytics auth.login.submit, auth.login.success, auth.login.failure(code)
Keyboard email → .emailAddress; password → .visiblePassword-ish + onSubmit
Adaptive phone single pane; tablet/desktop centered card ≤ 480 dp with brand mark
a11y labels linked, error live-region, focus first invalid
Motion m-fast focus; error shake; success → swap to home m-base slide
Field Detail
Purpose Second factor check after password (server-dependent — blocked OQ-1)
Entry from login challenge signal
Exit success → /home; failure → same screen with inline TOTP error
Input one 6-digit TOTP field (auto-advance)
Primary CTA Verify
States loading, invalid code (401 → clear + focus), rate-limited; "remember device" toggle (client prefs only, no server flag)
a11y single semantics label "6-digit verification code"; keyboard number
Note Server returns no challenge today: feature is forward-looking ; keep route dormant
Field Detail
Purpose Create org admin + tenant in one step (server assigns org_admin)
Entry /login "register", fresh install
Exit success → token stored → /home (+ "verify your email" banner)
Inputs firstName, lastName, email, password (min8), confirm (client-only), tenantId, phone optional
Auto-fill given-name, family-name, email, new-password, tel
Primary CTA Create account
Secondary "Back to login"
States as login; plus 409 duplicate (email) inline
Deep note Registration returns tokens immediately → user is authenticated; duplicate email → ConflictException 409 (auth.service.ts:57)
Content informational "what happens next" list (verify email, 2FA prompt)
Field Detail
Purpose Consume verification token from email link/banner
Entry deep link /login/?token=; auto-fires; banner direct-entry
Exit success → /home (or /login); error → form with "resend"
Input implicit token (hidden)
Primary CTA Verify email (auto-submit on prefilled token); Resend email
States verifying (spinner), success check, error invalid/expired, resend throttled (5/120s)
Adaptive centered card; scroll when keyboard
a11y success announced via live region
Field Detail
Purpose Request one-time reset email (never reveals existence)
Input AppTextField email
Primary CTA "Send reset link"
States success screen-as-message identical for existing/missing (privacy auth.service.ts:259-282); rate (3/min)
Note design should play "email sent" neutrally
Field Detail
Purpose Set new password with 1 h token; revokes all sessions
Input password (min8), confirm
Primary CTA "Set new password"
States success → login redirect; token expired/invalid 400 (inline + "request new link")
Security note session-array cleared server-side (auth.service.ts:306); login requires manual re-setup of any clients
Table rows (AppListTile): Two-factor authentication (status switch, badge on/off),
Devices & sessions (count badge), API keys (count badge). Master-detail on tablets.
Field Detail
Purpose List current user's active sessions
Route /settings/security/devices (list) + sheet for detail
Source GET /auth/sessions → array of documents (deviceName, browser, operatingSystem, platform, ipAddress, location, expiresAt, lastActivityAt)
Widgets ListTile group (current device labeled "You"), per-item icon inherits platform
Pull-to-refresh RefreshIndicator
Empty "No other devices"
Row actions AppMenu → "Log out this device" (DELETE /auth/sessions/:id) with confirm dialog
CTA bottom button "Log out all devices" (POST /auth/logout-all)
Field Detail
Source GET /auth/api-keys
Widgets AppCard per key: prefix…, scopes chips, createdAt / lastUsedAt, menu (revoke)
FAB FAB "New key" (one per screen)
Field Detail
Purpose two-step: form → one-time secret reveal
Form name (required), scopes chips (optional, free-text input chip)
Reveal full raw key + Copy + "I've saved it" (server never re-serves)
Source POST /auth/api-keys returns {id, prefix, key} — key shown once
Confirm + DELETE /auth/api-keys/:id → snackbar; item leaves list (optimistic, rollback on fail).
Field Detail
Status tile TOTP on/off (badge)
Enable flow POST /auth/2fa/enable → QR + secret, copy; input 6-digit → POST /auth/2fa/verify → set ON (server sets enabled only after this)
Disable flow input current code → POST /auth/2fa/disable
States secret visible once?; turn-off needs typed code
App-level: biometric/Whisper unlock of locally-stored session; style consistent with
settings.read-gated surfaces; no server API.
AppTextField, AppButton, AppSnackbar, AppCard, AppListTile, AppBottomSheet,
AppDialog, AppMenu, AppSkeleton, AppEmptyState, AppOfflineBanner, AppFAB,
AppChips, AppBadge, AppAvatar. Module-specific: 2FA code field, secret reveal card, session tile — defined in 07_Component_Library.md .
auth.login.{submit,success,failure}, auth.register.{submit,success,duplicate},
auth.verify.{success,invalid}, auth.reset.{sent,completed,expired},
auth.2fa.{enabled,disabled,verify_failed}, auth.session.{list,revoke,logout_all},
auth.apikey.{create,reveal,revoke} (all proposed).
Pre-auth: portrait-first; landscape uses scroll; tablet/desktop constrain width.
Sessions/api-keys on tablet: two-column list/detail; desktop hover row highlights.
All fields keyboard-avoidance + ScrollView resizeToAvoidBottomInset.