# Client State (Strict) This document defines the only allowed usage of client state in `apps/website`. Authoritative contract: [`WEBSITE_CONTRACT.md`](docs/architecture/website/WEBSITE_CONTRACT.md:1). ## 1) Core rule Client state is allowed only for **UI concerns**. The API remains the single source of truth. ## 2) Allowed client state Client state MAY represent: - selection (table rows, active tab) - open/closed dialogs and drawers - input values before submission - loading flags - best-effort optimistic flags ## 3) Forbidden client state Client state MUST NOT be used as: - business truth - security truth - permission truth Examples of forbidden behavior: - client code deciding that a user is allowed based on local flags - client code persisting an authoritative list state that overrides server truth ## 4) Conflict resolution rule (hard) If client state and API truth disagree, **API truth wins**. Correct handling is: - show the API result - revalidate and reload server-rendered truth ## 5) Relationship to Blockers Blockers exist to prevent UX mistakes. - Blockers are not security. - Blockers may reduce unnecessary requests. - The API still enforces rules. See [`docs/architecture/shared/BLOCKERS_AND_GUARDS.md`](docs/architecture/shared/BLOCKERS_AND_GUARDS.md:1) and [`docs/architecture/website/BLOCKERS.md`](docs/architecture/website/BLOCKERS.md:1). ## 6) Canonical placement in this repo - `apps/website/lib/blockers/**` - `apps/website/lib/hooks/**` - `apps/website/lib/command-models/**`