docs(specs): plan frontend query remediation
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
schema: spec-driven
|
||||||
|
created: 2026-08-23
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
## 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.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
## Why
|
||||||
|
|
||||||
|
Frontend declares custom React Query keys before generated API options, so the generated key silently wins. Mutations and consumers then update a different cache entry, while the documented strict TypeScript invariant is not enforced by the project configuration.
|
||||||
|
|
||||||
|
## What Changes
|
||||||
|
|
||||||
|
- Establish one exported, generated cache identity for each frontend query whose cache is consumed or invalidated outside its hook.
|
||||||
|
- Make successful T-Bank connection replacement and deletion update the same status cache and invalidate the same brokerage-account cache that the UI reads.
|
||||||
|
- Remove duplicate query-key declarations from the remaining generated query hooks while preserving their request parameters and caching policies.
|
||||||
|
- Enable TypeScript strict mode for application and Vite tooling compilation, resolve the current strict diagnostics with explicit state narrowing, and keep the existing typecheck command as the executable gate.
|
||||||
|
- Add regression tests for the T-Bank connection cache lifecycle and the affected query behavior.
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
### New Capabilities
|
||||||
|
- `frontend-query-coherence`: Ensures frontend query consumers and mutations use the generated cache identity of the data they read.
|
||||||
|
|
||||||
|
### Modified Capabilities
|
||||||
|
- `project-foundation`: Makes strict TypeScript compilation a required local frontend quality invariant.
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
|
||||||
|
Affected frontend modules are the generated-query hooks for brokerage accounts, operations, events, portfolio and T-Bank connection; the T-Bank connection mutation UI; the account view model; account/events/operations page type narrowing; colocated frontend tests; and frontend TypeScript configuration. `docs/development/audit-remediation.md` tracks the change as active and will receive completion evidence. The backend API, persisted data, OpenAPI schema and dependency set do not change.
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
## Purpose
|
||||||
|
|
||||||
|
Гарантирует, что frontend читает, обновляет и инвалидирует один и тот же кэш API-данных после связанных пользовательских действий.
|
||||||
|
|
||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: Frontend сохраняет когерентность кэша T-Bank connection
|
||||||
|
Frontend MUST использовать идентичность кэша, с которой загружается статус T-Bank connection, когда успешная замена или удаление connection обновляет этот статус. После каждого успешного создания, замены или удаления connection frontend MUST инвалидировать идентичность кэша списка Brokerage Accounts, с которой этот список загружается.
|
||||||
|
|
||||||
|
#### Scenario: Успешная замена подключения обновляет status и accounts
|
||||||
|
- **WHEN** User успешно заменяет T-Bank connection в настройках
|
||||||
|
- **THEN** frontend показывает статус из успешного ответа и следующий потребитель списка Brokerage Accounts не использует данные, загруженные до замены connection
|
||||||
|
|
||||||
|
#### Scenario: Успешное удаление подключения обновляет status и accounts
|
||||||
|
- **WHEN** User подтверждает успешное удаление T-Bank connection
|
||||||
|
- **THEN** frontend показывает состояние без подключения и следующий потребитель списка Brokerage Accounts не использует данные, загруженные до удаления connection
|
||||||
|
|
||||||
|
### Requirement: Generated API queries сохраняют транспортную и cache identity
|
||||||
|
Frontend MUST сохранять сгенерированную API-клиентом идентичность для запросов Brokerage Accounts, операций Brokerage Account, событий Brokerage Account, Portfolio и T-Bank connection. Потребитель, которому требуется прочитать или инвалидировать один из этих кэшей вне hook, MUST получать его идентичность из владельца соответствующего query, а не формировать отдельный ключ.
|
||||||
|
|
||||||
|
#### Scenario: Потребитель читает кэш списка счетов
|
||||||
|
- **WHEN** frontend определяет Brokerage Account для уже открытого account route
|
||||||
|
- **THEN** он читает тот же кэш списка Brokerage Accounts, который использует его query hook
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: Frontend typecheck строго проверяет application и tooling code
|
||||||
|
Frontend MUST включать TypeScript strict mode для application source и Vite tooling source. Команда локального frontend typecheck MUST завершаться с ошибкой при любом нарушении strict TypeScript и завершаться успешно для committed frontend code.
|
||||||
|
|
||||||
|
#### Scenario: Agent проверяет frontend перед завершением задачи
|
||||||
|
- **WHEN** агент запускает documented frontend verification или его typecheck stage
|
||||||
|
- **THEN** проверка выполняет strict TypeScript compilation application и Vite tooling source и сообщает non-zero exit code при strict diagnostic
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
## 1. Regression coverage for cache coherence
|
||||||
|
|
||||||
|
- [ ] 1.1 Add a colocated `TbankConnectionSection` integration test with a real `QueryClient`, mocked authenticated user and MSW responses; cover successful PUT and DELETE, assert the visible connection status changes, and assert the generated Brokerage Accounts cache entry is invalidated.
|
||||||
|
- [ ] 1.2 Extend affected query-hook tests only where needed to prove operations and portfolio requests still reach their generated endpoint with the existing parameters, stale times and retry policy.
|
||||||
|
|
||||||
|
## 2. Single-owner query identity
|
||||||
|
|
||||||
|
- [ ] 2.1 Refactor `useBrokerageAccounts.ts` to derive and export the generated Brokerage Accounts query key from its owner, then update `useAccountPageViewModel.ts` and the T-Bank connection mutation UI to consume that exported identity.
|
||||||
|
- [ ] 2.2 Refactor `useTbankConnectionViewModel` so its read query and successful PUT/DELETE handlers use the same generated connection-status identity.
|
||||||
|
- [ ] 2.3 Remove conflicting local query-key overrides from the operations, events and portfolio hooks while retaining their generated request initialization, enabled predicates, stale times and retry policies.
|
||||||
|
- [ ] 2.4 Run the new T-Bank connection integration test and affected query-hook tests; confirm the pre-change cache-lifecycle regression is resolved without changing API requests.
|
||||||
|
|
||||||
|
## 3. Strict TypeScript contract
|
||||||
|
|
||||||
|
- [ ] 3.1 Enable `strict` in `tsconfig.app.json` and `tsconfig.node.json`.
|
||||||
|
- [ ] 3.2 Resolve every resulting application diagnostic in the T-Bank connection feature and account events/operations pages through explicit null/error/state narrowing; preserve current loading, error, empty and loaded UI behavior without unsafe assertions or broad casts.
|
||||||
|
- [ ] 3.3 Run `npm run typecheck` and confirm strict compilation succeeds for both application and Vite tooling source.
|
||||||
|
|
||||||
|
## 4. Completion evidence and audit tracking
|
||||||
|
|
||||||
|
- [ ] 4.1 Run `npm run verify` and `openspec validate stabilize-frontend-query-and-strict-contracts --type change --store wealth-ledger-specs`; record their exact successful results.
|
||||||
|
- [ ] 4.2 Update `docs/development/audit-remediation.md`: mark WL-P1-01 and WL-P1-02 done only after all implementation and verification tasks pass, include date, archive path, commits and exact non-mutating checks, then choose the next single recommended change.
|
||||||
Reference in New Issue
Block a user