# 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/**`
