Files
specs/openspec/changes/stabilize-frontend-query-and-strict-contracts/design.md
T

44 lines
3.9 KiB
Markdown

## Context
See `proposal.md` for motivation. `openapi-react-query` derives both its request function and default cache identity from the query key. The current frontend replaces that generated key in some hooks and separately guesses short keys in consumers, so a successful mutation can write or invalidate a cache entry the query hook never uses. Enabling TypeScript strict mode exposes the same duplicate-key defect and 11 additional nullable-state/error-handling diagnostics.
## Goals / Non-Goals
**Goals:**
- Give every affected generated query one transport-compatible cache identity and expose it only where another slice must consume it.
- Preserve existing API requests, stale-time, retry, user flows and user-visible loading/error states while making all current strict diagnostics explicit.
- Prove connection mutations affect the cached status and account-list lifecycle through behavior-focused regression tests.
**Non-Goals:**
- Changing backend endpoints, OpenAPI types, API-client dependencies, cache duration or refetch policy.
- Addressing the separate stale-data and cold-start resilience findings WL-P2-07 and WL-P2-08.
- Broad refactoring of unrelated frontend modules or lint-staged tooling.
## Decisions
### Preserve generated keys; do not overwrite them
Each affected hook will build its options from `apiQueryClient.queryOptions` without replacing `queryKey`. This is required because the generated `queryFn` receives that key and derives the HTTP method, path and request init from it. The Brokerage Accounts entity will export its generated query key for the account page and connection mutation; the T-Bank connection feature will keep and reuse its generated status key within the feature. Other affected hooks have no external cache consumer and only remove their conflicting local key.
The rejected alternative is placing a custom key after generated options. Although it appears to make cache invalidation match the custom key, it makes the generated query function receive an incompatible key and can break the HTTP request. The rejected alternative of duplicating generated key tuples in every consumer again leaves a second owner for cache identity.
### Make strict compilation configuration, not convention
Both `tsconfig.app.json` and `tsconfig.node.json` will enable `strict`. Existing diagnostics will be resolved by preserving the current UI state machine while explicitly narrowing absent query data, normalizing an optional mutation error code to the existing request-error state, and filtering nullable cursor values with a type predicate. No non-null assertions, `any`, or broad unsafe casts will be introduced to silence diagnostics.
### Test the cache lifecycle at the feature boundary
Colocated T-Bank connection tests will render the feature with the real QueryClient and MSW handlers. They will assert successful PUT and DELETE flows update the cache under the exported/generated status key and mark the generated Brokerage Accounts query stale. Query-hook tests will retain coverage that request parameters remain encoded through the generated client.
## Risks / Trade-offs
- [A generated key format changes in a future API-client version] → keys are derived from `queryOptions` in their owning modules and tests observe feature behavior rather than copying the tuple format.
- [Strict narrowing accidentally changes a loaded screen into a loading screen] → preserve existing loading and error branches, add an explicit absent-data branch only where type safety requires it, and run existing route tests.
- [Tests assert React Query internals instead of user behavior] → assert visible connection state first; inspect query state only to prove the cache invalidation contract that has no separate visual surface.
## Migration Plan
No data migration or deployment sequencing is required. The frontend can be rolled back as one commit because endpoint contracts and persisted state do not change.