# consolidate-tbank-connection-resolution — Tasks ## 1. Backend: основа shared access module - [x] 1.1 Создать `backend/src/tbank/tbank-token.service.ts` и зарегистрировать его в `TbankConnectionModule`. Service должен владеть `TbankCrypto.fromBase64(config.getOrThrow('TOKEN_ENCRYPTION_KEY'))`, предоставлять `encrypt(value: string): string`, `decrypt(payload: string): string` и один helper, который переводит `Error('INVALID_TBANK_TOKEN')` в `BadRequestException({ code: 'INVALID_TBANK_TOKEN' })`, а остальные ошибки пробрасывает без изменений. Verification: `npm test -- tbank/tbank-token.service.spec.ts --runInBand` в `backend`. - [x] 1.2 Добавить focused tests в `backend/src/tbank/tbank-token.service.spec.ts`: encrypt/decrypt roundtrip через service, перевод invalid-token в `BadRequestException`, неизменённое propagation для `ServiceUnavailableException({ code: 'TBANK_UNAVAILABLE' })`. Verification: `npm test -- tbank/tbank-token.service.spec.ts --runInBand` в `backend`. - [x] 1.3 Создать `backend/src/tbank/tbank-account-policy.ts` с единой supported upstream account policy, которая сейчас дублируется между services. Policy должна маппить supported upstream types в normalized `type` и fallback display `name`, предоставлять supported-account filtering для list flows и account-access matching для account-scoped flows. Verification: `npm test -- tbank/tbank-account-policy.spec.ts --runInBand` в `backend`. - [x] 1.4 Добавить focused tests в `backend/src/tbank/tbank-account-policy.spec.ts`: supported brokerage/IIS/invest-box/money-market accounts маппятся в текущие normalized values и fallback names; unsupported upstream accounts исключаются; account-scoped matching отклоняет unsupported account даже при совпавшем account id. Verification: `npm test -- tbank/tbank-account-policy.spec.ts --runInBand` в `backend`. ## 2. Backend: T-Bank access service - [x] 2.1 Создать `backend/src/tbank/tbank-access.service.ts` и зарегистрировать его в `TbankConnectionModule`. Service должен использовать `PrismaService`, `TbankTokenService`, `TbankClient` и `tbank-account-policy`, предоставляя list-oriented use case для supported accounts и account-scoped wrapper use case. Verification: `npm test -- tbank/tbank-access.service.spec.ts --runInBand` в `backend`. - [x] 2.2 Добавить access-service tests для list behavior: missing connection возвращает `ConflictException({ code: 'TBANK_NOT_CONNECTED' })`; saved token расшифровывается до `getOpenAccounts`; unsupported accounts фильтруются через shared policy; invalid token из `getOpenAccounts` становится `BadRequestException`; `ServiceUnavailableException` пробрасывается без изменений. Verification: `npm test -- tbank/tbank-access.service.spec.ts --runInBand` в `backend`. - [x] 2.3 Добавить access-service tests для account-scoped behavior: inaccessible account возвращает `NotFoundException`; accessible supported account передаёт resolved `{ token, account }` в feature handler; `INVALID_TBANK_TOKEN`, выброшенный handler, становится `BadRequestException`; unrelated handler errors пробрасываются без изменений. Verification: `npm test -- tbank/tbank-access.service.spec.ts --runInBand` в `backend`. ## 3. Backend: refactor feature services - [x] 3.1 Refactor Portfolio flow на использование `TbankAccessService` для account-scoped access; удалить direct connection lookup, direct token decrypt, local `supportedAccounts` и local invalid-token string catch из `backend/src/tbank/portfolio.service.ts`. Fresh snapshot short-circuit и stale snapshot fallback semantics должны сохраниться без изменений. Verification: `npm test -- tbank/portfolio.service.spec.ts --runInBand` в `backend`. - [x] 3.2 Обновить `backend/src/tbank/portfolio.service.spec.ts`, чтобы повторяющиеся access branches мокали `TbankAccessService`, а не Prisma/config/open-account setup. Сохранить service-specific coverage для normalization, metadata fallback, fresh snapshot reuse, fallback only on temporary upstream errors и invalid token not masked by stale snapshot. Verification: `npm test -- tbank/portfolio.service.spec.ts --runInBand` в `backend`. - [x] 3.3 Refactor Account Ledger flow на использование `TbankAccessService` для account-scoped access; удалить direct connection lookup, direct token decrypt, local `supportedAccounts` и local invalid-token string catch из `backend/src/tbank/brokerage-operations.service.ts`. Порядок должен сохраниться: access wrapper выполняется до page cache lookup, затем page cache lookup, затем `getOperationsByCursor` при cache miss. Verification: `npm test -- tbank/brokerage-operations.service.spec.ts --runInBand` в `backend`. - [x] 3.4 Обновить `backend/src/tbank/brokerage-operations.service.spec.ts`, сохранив focused service-specific tests для date boundaries, category filtering, empty future ranges, pagination/cache keys, LRU eviction и regression, что cached pages не bypass current account access checks. Verification: `npm test -- tbank/brokerage-operations.service.spec.ts --runInBand` в `backend`. - [x] 3.5 Refactor Future Cash Events flow на использование `TbankAccessService` для account-scoped access; удалить direct connection lookup, direct token decrypt, local `supportedAccounts` и local invalid-token string catch из `backend/src/tbank/upcoming-events.service.ts`. Event projection, batching, source failure behavior и existing caches должны сохраниться. Verification: `npm test -- tbank/upcoming-events.service.spec.ts --runInBand` в `backend`. - [x] 3.6 Обновить `backend/src/tbank/upcoming-events.service.spec.ts`, чтобы access resolution мокался один раз, а service-specific tests покрывали projection, inaccessible account short-circuit через access service, ticker/instrument lookup behavior, skipped cancelled dividends, cache TTL reuse и no partial result on source failure. Verification: `npm test -- tbank/upcoming-events.service.spec.ts --runInBand` в `backend`. ## 4. Backend: list и connection settings flows - [x] 4.1 Refactor Brokerage Accounts list на использование list-oriented `TbankAccessService` use case и shared account policy. Удалить local `accountTypes`, direct connection lookup, direct token decrypt и local invalid-token string catch из `backend/src/tbank/brokerage-accounts.service.ts`. Verification: `npm test -- tbank/brokerage-accounts.service.spec.ts --runInBand` в `backend`. - [x] 4.2 Обновить `backend/src/tbank/brokerage-accounts.service.spec.ts`, сохранив list-specific coverage: no T-Bank call without connection, supported account normalization, unsupported account exclusion, invalid token translated to BadRequest, empty upstream list unchanged и unavailable upstream response propagated. Verification: `npm test -- tbank/brokerage-accounts.service.spec.ts --runInBand` в `backend`. - [x] 4.3 Refactor T-Bank connection settings на использование `TbankTokenService` для encryption и invalid-token translation, сохранив candidate-token validation, upsert/delete behavior и Portfolio snapshot invalidation в `backend/src/tbank/tbank-connection.service.ts`. Verification: `npm test -- tbank/tbank-connection.service.spec.ts --runInBand` в `backend`. - [x] 4.4 Обновить `backend/src/tbank/tbank-connection.service.spec.ts`: invalid candidate tokens не persist, valid tokens encrypt через `TbankTokenService`, delete остаётся idempotent и вызывает Portfolio invalidation. Verification: `npm test -- tbank/tbank-connection.service.spec.ts --runInBand` в `backend`. ## 5. Backend: integration checks и cleanup - [x] 5.1 Удалить now-unused imports, constructor parameters, local `supportedAccounts` declarations, local `accountTypes` declarations и local `TbankCrypto.fromBase64` instantiation из affected services. Verification: `npm run lint && npm run typecheck:app && npm run typecheck:test` в `backend`. - [x] 5.2 Запустить полный backend Jest suite для cross-service regressions в T-Bank behavior. Verification: `npm test -- --runInBand` в `backend`. - [x] 5.3 Запустить backend canonical gate под Node 22. Verification: `npm ci && npm run verify` в `backend`. ## 6. Specs и workspace verification - [x] 6.1 Выполнить semantic verification против Proposal и Design: подтвердить, что HTTP routes, DTO fields, OpenAPI output, frontend behavior, supported account types, cache TTLs и token replacement semantics не изменились. Verification: записать checked areas и conclusion в implementation summary перед archive. - [x] 6.2 Проверить OpenSpec change структурно. Verification: `openspec validate consolidate-tbank-connection-resolution --type change --strict --store wealth-ledger-specs` из `specs`. - [x] 6.3 После завершения affected tasks запустить workspace change dispatcher под Node 22. Verification: `bash specs/scripts/verify-workspace-change.sh consolidate-tbank-connection-resolution` из workspace root.