Command Models This document defines Command Models as a first-class concept in the frontend architecture. Command Models are UX-only write models used to collect, validate, and prepare user input before it is sent to the backend as a Command DTO. Command Models are not View Models and not Domain Models. ⸻ Purpose A Form Model answers the question: “What does the UI need in order to safely submit user input?” Command Models exist to: • centralize form state • reduce logic inside components • provide consistent client-side validation • build Command DTOs explicitly ⸻ Core Rules Command Models: • exist only in the frontend • are write-only (never reused for reads) • are created per form • are discarded after submission Command Models MUST NOT: • contain business logic • enforce domain rules • reference View Models • reference Domain Entities or Value Objects • be sent to the API directly ⸻ Relationship to Other Models API DTO (read) → ViewModel → UI UI Input → FormModel → Command DTO → API • View Models are read-only • Command Models are write-only • No model is reused across read/write boundaries ⸻ Typical Responsibilities A Form Model MAY: • store field values • track dirty / touched state • perform basic UX validation • expose isValid, canSubmit • build a Command DTO A Form Model MUST NOT: • decide if an action is allowed • perform authorization checks • validate cross-aggregate rules ⸻ Validation Guidelines Client-side validation is UX validation, not business validation. Allowed validation examples: • required fields • min / max length • email format • numeric ranges Forbidden validation examples: • “user is not allowed” • “league already exists” • “quota exceeded” Server validation is the source of truth. ⸻ Example: Simple Form Model (with class-validator) import { IsEmail, IsNotEmpty, MinLength } from 'class-validator'; export class SignupFormModel { @IsEmail() email = ''; @IsNotEmpty() @MinLength(8) password = ''; isSubmitting = false; reset(): void { this.email = ''; this.password = ''; } toCommand(): SignupCommandDto { return { email: this.email, password: this.password, }; } } ⸻ Usage in UI Component const form = useFormModel(SignupFormModel); async function onSubmit() { if (!form.isValid()) return; form.isSubmitting = true; await authService.signup(form.toCommand()); } The component: • binds inputs to the Form Model • reacts to validation state • never builds DTOs manually ⸻ Testing Command Models SHOULD be tested when they contain: • validation rules • non-trivial state transitions • command construction logic Command Models do NOT need tests if they only hold fields without logic. ⸻ Summary • Command Models are UX helpers for writes • They protect components from complexity • They never replace backend validation • They never leak into read flows Command Models help users. Use Cases protect the system.