# Pathrule Pattern: Client State Management (1.0.0)
# ::pathrule:package:client-state-management

### [RULE] Store each fact once and derive the rest  (path: /src/state)
<!-- scope: folder | priority: high | strict -->

Every state value has one authoritative owner, update path, reset event, and persistence policy. Duplicated and contradictory fields create impossible states such as selected objects no longer present in the latest list or loading flags that outlive the request. Enforce this boundary in /src/state so invalid work stops before it reaches another subsystem or creates an externally visible side effect.

- Classify state before choosing a store: server resource, URL navigation, form draft, local interaction, cross-screen client state, or derived view.
- Keep server resources in the server-state layer and store stable identifiers in client state instead of copying full records.
- Derive filtered lists, totals, validation, selection objects, and status flags from authoritative inputs unless measured performance requires memoization.
- Define reset behavior for logout, tenant switch, route exit, successful submit, cancel, and schema version change.

Verification: Exercise each ownership transition and intentionally update one source while another is stale; confirm the model cannot represent contradictory or cross-identity state.

---

### [MEMORY] The URL owns shareable navigation state  (path: /src/routes)

Filters, search, sorting, pagination, tabs, and selected resources that define the visible page should survive refresh and support links, history, and browser navigation. Parse URL input through a typed boundary, normalize defaults, and write changes using push or replace according to the user's navigation expectation.

Keep transient hover, open popover, unsaved text, and secret values out of the URL. Use stable identifiers rather than display labels and make invalid combinations resolve predictably. Let loaders and cache keys consume the normalized URL state so rendered data and address cannot drift. Keep the decision explicit at /src/routes; moving it into an incidental caller makes behavior depend on which route happened to execute first.

See /src/components for local interactions and /src/state for cross-screen ownership. That related boundary consumes this decision and carries the evidence that proves it still holds.

---

### [MEMORY] Persistence is a migration commitment  (path: /src/state)

Putting state in local storage, IndexedDB, or a native store means old schemas and prior identities can reappear after new code ships. Persist only values whose user benefit survives reload, and include schema version, owning identity, tenant, created time, and expiry where relevant.

Migrate or discard incompatible versions explicitly instead of catching parse errors and keeping partial state. Clear identity-scoped data before another user or tenant can render. Never persist credentials or sensitive server records merely to avoid a refetch. Keep the decision explicit at /src/state; moving it into an incidental caller makes behavior depend on which route happened to execute first.

See /src/routes for shareable state and the authentication pattern for identity transitions. That related boundary consumes this decision and carries the evidence that proves it still holds.
