Переносит архив `audits/2026-10-11/` (19 файлов) из codex/audit-remediation-2026-10-11 в develop и добавляет точечный allowlist в .gitignore.
83 KiB
Аудит 04 — Dead Code & Legacy
1. Audit metadata
- Audit ID / name: 04 / Dead Code & Legacy.
- Дата: 2026-10-11.
- Исполнитель: один независимый исполнитель направления 04; другие субагенты не запускались.
- Результат: исследование reachability и безопасных границ удаления. Изменён только этот отчёт вне application checkout.
- Workspace:
/Users/ksv741/Project/vibe/WealthLedger.
| Checkout | Абсолютный путь | HEAD, проверенный самостоятельно | Начальный status |
|---|---|---|---|
| root | /Users/ksv741/Project/vibe/WealthLedger |
dc030f84c979cedb2628ef4bd97c62d6c63a9256 |
чистый |
| frontend | /Users/ksv741/Project/vibe/WealthLedger/frontend |
c8821200ce699dab1ce65360d1968d5877a2e78b |
чистый |
| backend | /Users/ksv741/Project/vibe/WealthLedger/backend |
0ad84ff4f0b4712abc7e69dc299856f14af6eadd |
чистый |
| specs | /Users/ksv741/Project/vibe/WealthLedger/specs |
fcdc805f6c1b3be6a20a7e858e3e80cbd83a9121 |
чистый |
| docs | /Users/ksv741/Project/vibe/WealthLedger/docs |
e6fd4f64b81dd73b33959b845a1babcfac1891c8 |
чистый |
Метод фиксации: в каждом checkout выполнены
git rev-parse HEAD && git status --porcelain=v1; пустой porcelain означает
отсутствие staged, unstaged и видимых Git untracked changes, а не отсутствие
ignored файлов. Root allowlist исключает audit-results/
(.gitignore:1–7), поэтому отчёт не должен появляться в обычном root status.
Инструкции: прочитаны AGENTS каждого checkout. Для backend и frontend
прочитаны их собственные architecture, engineering и активированные
conventions: HTTP/data/testing/integrations/security для backend;
TypeScript/React/data/UI/testing/Storybook для frontend. Root conventions
использованы только для root-границы отчёта. Specs выбраны через AI_INDEX.md
и точные тематические targets; три актуальных требования нового потока,
которых нет в индексе, прочитаны по известным абсолютным путям. Вложенных
AGENTS в source-областях frontend/backend поиск не обнаружил.
Skills: установленный ponytail-audit загружен первым через Skill tool.
Применены его delete: / shrink: теги, ранжирование по сокращению ненужной
maintenance surface и запрет исправлений. Схема отчёта расширена обязательным
протоколом 04. Числовой net не выдуман: deletion diff не создавался.
Также загружены graphify и verification-before-completion.
Graphify: существующего graphify-out/graph.json не обнаружено в root
и четырёх checkout: проверены списки корневых директорий, дополнительно Glob
в frontend/backend. Graph query не выполнялся; graph generation, cache,
manifest и другие artifacts не создавались. Отсутствие существующего graph
— ограничение; выводы получены статической трассировкой актуальных source.
Что выполнялось: Read/Glob/Grep из соответствующих repo directories,
read-only rg -n -c для явно указанных символов и git inspection.
technical-audit-2026-10-11.md прочитан только как список гипотез;
его выводы и оценка ~550 lines не использованы как доказательство.
Другие новые отчёты аудиторов не читались и не изменялись.
Что не выполнялось: Node-команды, install, build, codegen, migrations,
full-suite, targeted tests, запуск приложения, запросы к реальным API,
изменение config/source/lockfiles, commits, PR и генерация исследовательских
инструментов. Это статический аудит, не runtime-воспроизведение.
npm run knip, deps, frontend test scripts предварительно вызывают
build:packages (frontend/package.json:14–26); их запуск нарушил бы
заданную read-only границу. Их результаты из прежнего отчёта не наследуются.
2. Executive verdict
- Факт: command-часть
TbankSyncService.request → dispatchне имеет production entrypoint. Nest создаёт service дляstatus, но controller предоставляет только GET. Удаление command-closure обосновано — DEAD-001. - Факт: вслед за ней обнаружен менее очевидный dead producer:
CatalogDiscoveryService.request/refresh/drain. Реальные HTTP search, detail и ticker читают онлайн либо вызывают persisted reader только сobserve=true; старый request-driven импорт каталога запускают прямые тесты и недоступная manual orchestration — DEAD-002. - Факт: frontend
observe()используется только двумя прямыми тестовыми вызовами; все восемь production consumersuseScreenSyncигнорируют его return value, а_scopeвообще не читается. Можно удалить эти API-хвосты, сохранив действующий timer — DEAD-004/005. - Факт и граница: статусный GET и backend
sync=observeдействительно публично достижимы. Отсутствие их использования в текущей SPA не доказывает отсутствия внешних consumers или старых DB rows. Их удаление сейчас не подтверждено — DEAD-006/007,INVESTIGATE. - Риск ошибочной зачистки: planner операций, hourly lifecycle, candle
loader, shared source repository и connection/attempt fences остаются
живыми. Массовое удаление по словам
screen,catalogилиsyncможет остановить данные либо каскадно удалить свечи — DEAD-008–011,KEEP. - Итог: 5 actionable findings: P0 = 0, P1 = 0, P2 = 2, P3 = 3.
Отдельно KEEP = 4, INVESTIGATE = 2. Для непроверенной внешней
совместимости указан
UNVERIFIED; экономия времени/строк не измерена.
3. Inventory & coverage
3.1. Фактическая карта entrypoints
| Вход / поток | Проверенная цепочка и owner | Следствие для reachability |
|---|---|---|
| SPA bootstrap | frontend/src/main.tsx:1–23 → src/app/ui/App.tsx:23–43 → src/app/routes/AppRoutes/AppRoutes.tsx:9–103,105–257 |
Lazy imports являются настоящими consumers page exports. CSS, i18n и dayjs locale — side effects, не orphan imports. |
| SPA routes | AppRoutes.tsx:105–257: login/register; cards/card; stocks/stock; bonds/bond; accounts/account/events/income/operations; settings; wildcard |
Страницы доступны через router, включая динамические chunks; отсутствие статического прямого import не делает их мёртвыми. |
| Backend HTTP | backend/src/main.ts:44–60 → src/app.module.ts:18–36 → controllers |
Prefix, validation, cookies, error boundary и shutdown hooks задаются src/main.ts:19–42; controller decorators являются registration. |
| Controller families | backend/src/modules/auth/presentation/auth.controller.ts:51; backend/src/modules/banking/bank-cards/presentation/bank-cards.controller.ts:79; backend/src/modules/investments/brokerage-accounts/brokerage-accounts.controller.ts:15; backend/src/modules/investments/portfolio/presentation/portfolio.controller.ts:15; backend/src/modules/investments/operations/presentation/brokerage-operations.controller.ts:18; backend/src/modules/investments/income/income-analytics.controller.ts:20; backend/src/modules/investments/upcoming-events/upcoming-events.controller.ts:18; backend/src/modules/investments/instruments/stocks/presentation/stock.controller.ts:48; backend/src/modules/investments/instruments/bonds/presentation/bond.controller.ts:37; backend/src/modules/investments/tbank-connection/tbank-connection.controller.ts:33; backend/src/modules/investments/tbank-sync/tbank-sync.controller.ts:31 |
Проверены registrations всех этих семейств поиском @Controller, root module и нужными application chains; это не полный семантический аудит CRUD/auth. |
| Hourly job | backend/src/modules/investments/tbank-sync/tbank-sync.module.ts:24–25 → scheduler onModuleInit:48–50 → tick:56–71 → reserveHourly / walk |
Один native timer, durable work и source owners; запуск не зависит от frontend. |
| Source queues | Portfolio queueSnapshot, operations sync, metadata, enrichment, candles используют setImmediate; declarations найдены в source, живые примеры traced ниже |
Удаление manual dispatcher не даёт права удалять все очереди с похожими именами. |
| Production CLI | backend/package.json:15–18; compose.yaml:24–38 |
Backend запускает dist/src/main.js; отдельная migration service — Prisma CLI. В manifest не найден CLI, вызывающий manual sync или persisted catalog producer. |
| Test dynamic entrypoint | backend/test/fixtures/tbank-sync-crash.cjs:1–17 |
Динамические require ведут в operations sync/repository, не в TbankSyncService или CatalogDiscoveryService. Fixture не запускался. |
| OpenAPI tooling | backend/scripts/generate-openapi.cjs:19–31 → AppModule preview → src/openapi.ts:6–10 |
Generator читает зарегистрированный controller contract; не вызывает service methods по именам. Наличие DTO decorator само по себе не публикует DTO. |
| Storybook / packages | frontend/.storybook/main.ts:3–7; packages/ui/package.json:9–22; src/app/ui/App.tsx:3–8 |
Stories — дополнительные entrypoints; UI CSS явно side-effectful. Feature/query candidates не экспортируются public UI package. |
| Env / imports | backend/src/config/env.validation.ts:9–33,102–113, .env.example:1–10, src/app.module.ts:18–36; frontend/vite.config.ts:54–61, tsconfig.app.json:8–20 |
Env задаёт транспорт/config, но не включает manual sync module/method или старую catalog producer ветку. Alias @/ ведёт в source. |
3.2. Метод отбора и счёта
Исследованы 12 кандидатов C01–C12, отобранных по стоимости сопровождения и риску ошибочного удаления: старая orchestration, связанные producer paths, orphan DTO, frontend API-хвосты, публичная compatibility и защищённые live owners. Число 12 — число строк Reachability Ledger, не результат analyzer. Findings — 11: C01/C02 образуют одну deletion closure DEAD-001.
Порядок: declaration → exports/DI/registration → все найденные callers → реальный runtime entrypoint → external/public accessibility → контрпример. Поиск применялся к source, затем отдельно tests/scripts/artifacts, чтобы не принять direct test invocation за пользовательский путь.
Воспроизводимые search counts: это количество matching lines, а не число AST references; вывод вручную разделён по declarations/imports/calls. Поиск не считается самостоятельным доказательством отсутствия callers.
| Поиск и границы | Результат и независимая проверка |
|---|---|
| Q01, backend source/tests/scripts, команда ниже | TbankSyncService найден только в своём service, controller и module; sync.request( — 0 строк. Controller calls только status. Для normalizeScreen(: 1 declaration, 1 вызов в dead request, 9 строк вызовов в tbank-screen.spec.ts. DTO Accepted — 1 declaration, 0 consumers. |
Backend: owner-aware поиск this.discovery.* в instruments и чтение обоих catalog services |
6 live delegation call sites: search/detail/byTicker у stocks и bonds. Ни один не вызывает read/request/refresh напрямую. discovery.refresh найден в manual dispatcher. В discovery owner три вызова this.read находятся после online-return ветки и получают observe=true; this.request — в read(!observe) и refresh. |
| Q02, frontend source/packages/Storybook/scripts, команда ниже | observe() — 2 строки, обе в resource-query.test.tsx:63,167; production вызовов 0. useScreenSync( — 8 production call lines, 2 test call lines, 1 declaration. Все 8 VM прочитаны целиком: return hook не захватывается. |
| Q03, frontend source/packages/Storybook, команда ниже | tbank-sync — 2 строки JSON snapshot и 1 generated route declaration; runtime call site 0. Литерал sync: "observe" — 1 строка в observationKey. Accepted DTO — 0. |
| Q04, backend OpenAPI artifact, команда ниже | 2 matching lines: GET path и operationId; Accepted DTO отсутствует. Artifact не регенерировался, поэтому свежесть runtime parity — UNVERIFIED; controller/source metadata дополнительно проверены. |
Команды выполнены с workdir соответствующего checkout, без cd и записи
output-файлов. Exact regex приведены вне таблицы, чтобы Markdown не подменял
alternation и не создавал лишние колонки.
# Q01 — backend
rg -n -c 'TbankSyncService|sync\.request\(|normalizeScreen\(|TbankSyncAcceptedDto|discovery\.(read|request|refresh)\(' src test scripts --glob '*.{ts,cjs,mjs}'
# Q02 — frontend
rg -n -c '\.observe\(|\["observe"\]|\[.observe.\]|\buseScreenSync\(' src packages .storybook scripts --glob '*.{ts,tsx,cjs,mjs}' --glob '!**/generated/**' --glob '!**/dist/**'
# Q03 — frontend
rg -n -c 'tbank-sync|TbankSyncAcceptedDto|sync: "observe"' src packages .storybook --glob '!**/dist/**'
# Q04 — backend
rg -n -c 'TbankSyncAcceptedDto|TbankSyncController_status|/api/v1/tbank-sync' openapi.json
Dynamic checks: source search по ModuleRef, reflection/getMetadata,
computed request/observe, import()/require, factory/alias DI и cron/timers
не выявил alternate entrypoint кандидатов на DELETE. Проверены явные
@Injectable, @Module, @Controller, @Get, ApiExtraModels, useExisting
и module exports. В backend useFactory используется для logging/auth,
TBANK_ACCESS alias — для instruments (instruments.module.ts:24);
кандидатов он не dispatch-ит. В frontend dynamic imports представлены явными
router chunks; Storybook собирает stories по glob. No-match ограничен
этими checkout: неизвестный deployed consumer не исключён.
3.3. Coverage и ограничения выборки
- Сфокусированы investments synchronization/catalog и frontend consumers, где после перехода архитектуры есть сильные гипотезы с большими closures.
- Банковские/auth routes проверены на существование root registration; correctness их бизнес-логики здесь не исследовалась.
- Tests прочитаны как callers и deletion dependencies. Тестовое покрытие проекта, mutation score и качество всех assertions не оценивались.
- Specs/docs рассматриваются как intended behavior и compatibility context, а не доказательство текущего исполнения. Архивы не являются candidates.
- Generated/dist, coverage, реальные
.env, DB, deployment logs и секреты не служили source call graph; lockfiles/dependency removal вне scope 04. - Runtime trace, bundle size, CI minutes, tokens и размер потенциального diff не измерены. Статическая карта не доказывает отсутствие внешних клиентов.
4. Findings
Severity actionable findings отражает текущую engineering cost, а не обещанную экономию. В KEEP/INVESTIGATE Severity обозначает риск ошибочного удаления; эти строки не являются подтверждёнными дефектами и не включены в actionable severity totals. Ни один finding не предлагает исправление в этом аудите.
DEAD-001 — Удалить недоступную manual screen orchestration вместе с closure
- Decision: DELETE.
- Severity: P2.
- Confidence: High.
- Evidence:
backend/src/modules/investments/tbank-sync/tbank-sync.service.ts:41–51,54–311;tbank-sync.controller.ts:31–41;tbank-sync.module.ts:23–25;tbank-sync.repository.ts:62–109,135–169;tbank-screen.ts:8–122;tbank-screen.spec.ts:1–75. Последние пять путей относительны той жеbackend/src/modules/investments/tbank-sync/. - Claim: у
request → normalizeScreen → reserve → setImmediate(dispatch)нет production entrypoint; соответственно manual child planner и writer progress поддерживаются без пользовательского сценария. - Current mechanism / runtime consumer: service зарегистрирован Nest,
но его единственный production consumer — constructor controller,
вызывающий
status.requestне имеет route/scheduler decorator, service не экспортирован TbankSyncModule, reflection dispatcher не найден.normalizeScreenфактически вызывают direct unit tests и недоступный request. - Impact / actual cost: лишняя orchestration source owners, ручные reservations, field normalization и отдельный тестовый сценарий; Impact unmeasured. Runtime RPC savings не заявляются: путь уже недоступен.
- Why now: текущие source entrypoints и
specs/openspec/specs/tbank-data-sync/spec.md:9–25передали обновление hourly owner и запрещают manual commands. Это не предположение только по ADR. - Minimum change: удалить request/dispatch,
reservations, exclusive DI/imports/constants, repositoryreserve/progress, normalization и её tests. Сохранить весь status reader и его compatibility types, пока DEAD-006 не решён; сохранить shared source owners и operations planner. - Guarantees at risk: access/revision checks внутри живого status, source CAS, hourly lifecycle, shared metadata/portfolio/candle owners. Не удалять эти owners вместе с исключёнными constructor injections.
- Counterarguments / trade-offs: создание service Nest не равно вызову всех его методов. Возвращение manual sync было бы новым продуктовым решением; restore из Git возможно. Старые screen work могут ещё читаться status: поэтому reader не входит в DELETE.
- Verification or rollback: после отдельного cleanup — type/DI proof, отсутствие POST command в configured OpenAPI, HTTP status compatibility, существующие local-read/hourly scenarios. Rollback — вернуть code-only closure одним revert; DB/schema не менять.
- Effort: M.
- Related finding IDs: DEAD-002, DEAD-006, DEAD-008, DEAD-009, DEAD-011.
DEAD-002 — Удалить недоступный persisted catalog discovery producer
- Decision: DELETE.
- Severity: P2.
- Confidence: High.
- Evidence:
backend/src/modules/investments/instruments/application/catalog-discovery.service.ts:39–64,66–86,143–149,220–227,340–496;instruments/stocks/application/stock-catalog.service.ts:21–31,59–83;instruments/bonds/application/bond-catalog.service.ts:24–34,58–82;instruments/infrastructure/catalog-discovery.repository.ts:341–464;backend/test/tbank-catalog-discovery.e2e-spec.ts:85–118,179–196,231–244,270–299. Три укороченныхinstruments/пути относительныbackend/src/modules/investments/. - Claim: producer
request/refresh/drainproduction-недостижим в текущем graph. После DEAD-001 исчезает даже его единственный caller из недоступной ветки. HTTPsync=observeсохраняет reader, но не включает этот writer. - Current mechanism / runtime consumer: ordinary search вызывает
onlineSearch; ordinary detail/byTicker выходят через online ветки. Только observe-ветки доходят доread, всегда сtrue, и потому пропускаютif (!observe) request. Единственный callerrefreshв production source — недоступный manual dispatcher. Прямые тестыservice.read(..., false/default)иservice.request(...)реально запускают queue, но не являются HTTP consumers. - Impact / actual cost: producer map/queue, forced joins, completions, logger dependency и отдельная persisted discovery publication поддерживают прежнее поколение поведения. Impact unmeasured; это сокращение maintenance, не устранение измеренного fan-out живого online search.
- Why now: онлайн-входы уже существуют; persisted discovery writer не
обслуживает ни их, ни hourly events. Online-only requirement независимо
прочитан:
specs/openspec/specs/online-instrument-information/spec.md:8–17. - Minimum change: после DEAD-001 удалить Producer/state/request/refresh/drain,
dead
read(!observe)branch и только exclusive repositorypublish. Сохранить readerread/work,enrichment, normalization/selection и online error projection. Не удалять repositoryreserve,finish,readSources,publishSource: их использует live CatalogEnrichmentService. - Guarantees at risk: shared source writes, CAS/invalid-token isolation, legacy observe read, UID/FIGI identity и candle FK. Schema и данные не входят в эту code-only deletion.
- Counterarguments / trade-offs: public
instruments.api.ts:2экспортирует provider внутри приложения, а не published npm method contract;backend/package.json:6,11–38— private application без CLI producer. HTTP compatibility может оправдать persisted reader (DEAD-007), но не writer, которого эти routes не вызывают. Прямые tests доказывают механизм, не пользовательскую reachability. - Verification or rollback: переназначить/удалить direct producer-only
cases в
test/tbank-catalog-discovery.e2e-spec.ts; сохранить проверку живого online selection/whitelist и legacy reader через существующие HTTP suites. Проверить unchangedpublishSource/candles на isolated SQLite в cleanup PR. Rollback — code-only revert без DB migration. - Effort: M.
- Related finding IDs: DEAD-001, DEAD-007, DEAD-010, DEAD-011.
DEAD-003 — Удалить orphan TbankSyncAcceptedDto
- Decision: DELETE.
- Severity: P3.
- Confidence: High.
- Evidence:
backend/src/modules/investments/tbank-sync/tbank-sync.dto.ts:212–218;tbank-sync.controller.ts:13–27,34–40;backend/test/openapi-contract.e2e-spec.ts:27–55;frontend/src/shared/api/spec/openapi.json:5102–5123. Controller путь относителен той же backend sync directory. - Claim: DTO command acceptance объявлен, но не используется controller, service, ApiExtraModels, scripts или публикуемым snapshot.
- Current mechanism / runtime consumer: module DTO загружается живым GET,
и decorators этой orphan class регистрируют её собственные metadata.
Но нет consumer, который включал бы её в response schema или исполнял её
validation. Status class — отдельный live consumer
investmentScreenSchema. - Impact / actual cost: небольшой устаревший export рядом с действующими response DTO; Impact unmeasured. Его наличие может создавать ложное впечатление сохранённой POST capability.
- Why now: POST отсутствует в actual controller и snapshot; existing
contract test явно ожидает отсутствие
/api/v1/tbank-synccommand route. - Minimum change: удалить только class
TbankSyncAcceptedDto.InvestmentScreenDto, screen schema, derived DTO иTbankSyncStatusDtoостаются нужны public status response. - Guarantees at risk: accidental изменение GET schema при избыточном удалении shared schema; сама Accepted class не является опубликованным DTO.
- Counterarguments / trade-offs:
export classи decorators не равны published contract; generator следует зарегистрированным routes. Artifact parity со свежей сборкой здесь не запускалась —UNVERIFIED. - Verification or rollback: targeted OpenAPI schema comparison при cleanup; Accepted absent, Status и его discriminator unchanged. Rollback — вернуть class.
- Effort: S.
- Related finding IDs: DEAD-001, DEAD-006.
DEAD-004 — Удалить only-test frontend observe API
- Decision: DELETE.
- Severity: P3.
- Confidence: High.
- Evidence:
frontend/src/shared/api/resource-query.ts:69–82,104–127,144;src/shared/api/resource-query.test.tsx:40–71,139–173;src/shared/api/index.ts:12–15;frontend/package.json:2–5;src/features/tbank-connection/model/screen-sync.ts:28–50. Укороченныеsrc/пути относительны frontend. - Claim:
observationKeyи возвращаемыйobserveне используются production callers; они поддерживают отдельный transport режим только для direct tests. Удаление frontend callback не означает удаления backend query. - Current mechanism / runtime consumer: live
useResourceQueryвызывается entity hooks, ноobserve()— только tests:63,167. Callback вручную переписывает queryKey для transport, cancel/query/select policy; production screen timer вызывает обычныйrefetch. - Impact / actual cost: дополнительный путь cancel/cache replacement и его own tests без UI consumer; Impact unmeasured. Bundle/runtime эффект не измерен, tree-shaking не проверялся.
- Why now: текущий runtime использует resource GET и
refetch; источник attempt state — metadata, а не orchestration notification. - Minimum change: убрать
observationKey,observe, его return member и exclusive imports (QueryFunctionContext, локальный import session snapshot). Удалить первый observe-only test; race-сценарий:139–173перенести на живой cancellation/refetch boundary, если он нужен для общей гарантии. - Guarantees at risk: не менять
useAuthenticatedQuery,invalidateResourceAccess, projected data/meta, canonical query identity, session switching и обычныйrefetchenvelope. - Counterarguments / trade-offs:
.ai/conventions/data.md:61–63всё ещё описывает наблюдение, но правило не создаёт отсутствующий production caller. SPA private, feature не public package; dynamic/router/story consumers проверены. Backendsync=observeостаётся доступен внешнему HTTP клиенту; наличие реального такого клиента здесь не подтверждено. - Verification or rollback: существующие resource tests
:72–138,174–210и auth/connection boundary tests при cleanup; synthetic MSW, без реальной сети. Rollback — вернуть callback/tests, никакой data migration. - Effort: S.
- Related finding IDs: DEAD-005, DEAD-007, DEAD-011.
DEAD-005 — Сократить unused facade useScreenSync, сохранив live timer
- Decision: SIMPLIFY.
- Severity: P3.
- Confidence: High.
- Evidence:
frontend/src/features/tbank-connection/model/screen-sync.ts:1–18,22–61;screen-sync.test.tsx:21–80в той же directory;src/pages/accounts/ui/AccountsPage/AccountsPage.vm.ts:21–24;src/pages/account/ui/AccountPage/AccountPage.vm.ts:78–84;src/pages/account-operations/ui/AccountOperationsPage/AccountOperationsPage.vm.ts:96–99;src/pages/account-events/ui/AccountEventsPage/AccountEventsPage.vm.ts:67–75;src/pages/account-income/ui/AccountIncomePage/AccountIncomePage.vm.ts:66–69;src/pages/bonds/ui/BondsPage/BondsPage.vm.ts:12–13; stock/bond VM:45–55. Всеsrc/пути относительны frontend; полные stock/bond пути перечислены в Ledger C06. - Claim:
_scope, returned manual refresh/retry/status facade и требуемые только этой facade resource fields не имеют production consumers. Timer:28–35имеет восемь route-reachable callers и не является dead code. - Current mechanism / runtime consumer: все 8 VM вызывают hook как отдельное
expression statement. Возвращённые
refresh/refreshing/retry/sourceError/ transportErrorне попадают в VM/view. Scope не читается даже самим hook. Единственные вызовы returned commands — прямые tests:50,78. - Impact / actual cost: caller собирает screen descriptor, hook создаёт
неиспользуемые commands/status, тип навязывает
queryKey/meta/isError/isFetching. Impact unmeasured; allocations/время render не измерены. - Why now: hook уже стал периодическим GET reader, но сохранил facade прежней screen orchestration.
- Minimum change: убрать scope аргумент и все восемь descriptor objects;
убрать only-test returned commands/status и exclusive fields/imports.
Оставить
resourcesRef, актуализацию resources, native interval и cleanup. Перепривязку timer к Query options этот finding не требует. - Guarantees at risk: нельзя удалить сам hook вызов: он обеспечивает reread открытого экрана. Нельзя убрать cleanup или обновление resourcesRef: смена route/filter должна читать актуальные queries.
- Counterarguments / trade-offs: тесты refresh/retry действительно исполняют callbacks, но не делают их доступными пользователю. UX потребность в retry может потребовать нового подключения к view; сейчас такого consumer нет. Таймерная политика живого пути — отдельный audit 02/07 вопрос.
- Verification or rollback: удалить direct facade-only cases, проверить существующий hook с fake time: reread актуального resource и прекращение после unmount. Page behavior и GET-only boundary сохранить. Rollback — вернуть facade/caller descriptors без изменений данных.
- Effort: S.
- Related finding IDs: DEAD-004, DEAD-009.
DEAD-006 — Статусный GET и старые screen: rows требуют compatibility proof
- Decision: INVESTIGATE.
- Severity: P2.
- Confidence: High.
- Evidence:
backend/src/modules/investments/tbank-sync/tbank-sync.controller.ts:21–41;tbank-sync.service.ts:313–391;tbank-sync.repository.ts:111–133;frontend/src/shared/api/spec/openapi.json:5102–5185;backend/test/openapi-contract.e2e-spec.ts:30–55;docs/architecture/http-api.md:46–52. Укороченные sync пути относительны backend sync directory. - Claim: GET
/api/v1/tbank-sync/{id}локально не вызывается SPA, но зарегистрирован, авторизован и опубликован. Нельзя назвать его confirmed dead или удалить screen reader вместе с недоступным writer. Наличие реальных внешних consumers — UNVERIFIED; High относится к reachability. - Current mechanism / runtime consumer: любой авторизованный HTTP consumer
может вызвать controller →
status. Reader обслуживаетscreen:intent и source works; access/revision проверяется до и после observation. Старые screen work могли сохраниться от предыдущей версии приложения. - Impact / actual cost: retained compatibility несёт reader/types/schema complexity; Impact unmeasured. Ошибочное удаление — breaking response/route.
- Why now: writer можно удалить отдельно, оставив минимальную проверенную границу совместимости. Deadline поддержки в прочитанных источниках не найден.
- Minimum change: сейчас не удалять endpoint/reader/derived DTO. Получить список поддерживаемых consumers и решить срок поддержки; затем отдельно согласовать withdrawal route либо поддержку только source status.
- Guarantees at risk: user/connection ownership, old work observation, stable scope/date discriminator и публичная wire compatibility.
- Counterarguments / trade-offs: docs говорит, что command/status не текущая AS-IS модель; это подтверждает legacy intent, но не отсутствие live HTTP route и external clients. Отсутствие frontend calls — слабое отрицательное evidence.
- Verification or rollback: самый дешёвый proof — ответ owner API о
consumers плюс существующая обезличенная access-log выборка и aggregate count
screen:work из disposable DB copy. Ничего из этого здесь не получено. Rollback будущего изменения — возврат endpoint/schema до destructive migration. - Effort: M.
- Related finding IDs: DEAD-001, DEAD-003, DEAD-007.
DEAD-007 — Backend observe/persisted reference compatibility внешне достижима
- Decision: INVESTIGATE.
- Severity: P2.
- Confidence: High.
- Evidence:
backend/src/modules/investments/instruments/stocks/presentation/stock.controller.ts:58–82,112–144;instruments/bonds/presentation/bond.controller.ts:55–89,102–114;instruments/application/catalog-discovery.service.ts:84–141,168–217,251–293;backend/src/modules/investments/investment-resource.dto.ts:15–24;docs/architecture/http-api.md:50–52;docs/adr/019-hourly-reads-and-online-instrument-reference.md:22–26. Укороченные instruments пути относительныbackend/src/modules/investments/. - Claim: persisted catalog/detail/ticker read branches являются legacy public contract, а не confirmed dead. Из DELETE old producer не следует DELETE observe readers или shared instrument storage. Нужность долгой поддержки — UNVERIFIED; High относится к подтверждённому механизму.
- Current mechanism / runtime consumer: query DTO допускает
sync=observe; controllers переводят его в boolean, передают catalog services, которые достигают reader branches. Это реальный внешний вход даже без SPA callback. - Impact / actual cost: две модели справочного чтения рядом — online и persisted compatibility; Impact unmeasured. API withdrawal требует consumer transition, а blanket data purge рискует candle coverage.
- Why now: online-only intended behavior уже принят, но compatibility сохранена source/HTTP metadata. Нужно ограничить именно поддержку старого reader, а не удалять shared business/persistence primitives по названию.
- Minimum change: сохранить текущий wire parameter/reader; отдельно решить
endpoint-specific retirement. При подтверждённой ненужности можно перестать
направлять reference reads в old branches, затем удалить их closure.
Не удалять общую
InvestmentReadQueryDtoдля всех ресурсов автоматически. - Guarantees at risk: passive observation, distinction unknown/empty/ ambiguous lookup, account access, precision, persisted calendars и candles.
- Counterarguments / trade-offs: requirement запрещает долговременную
самостоятельную reference copy, но не доказывает безопасность удаления
TbankInstrumentidentity: у неё cascade FK на candles/source rows (backend/prisma/schema.prisma:148–229). Внешние consumers не проверены. - Verification or rollback: consumer list + metadata/access logs без реальных API calls; agreed contract transition и isolated DB/FK proof перед любым data removal. Rollback code routing возможен, восстановление данных потребует backup; поэтому data purge сейчас не предложен.
- Effort: M.
- Related finding IDs: DEAD-002, DEAD-004, DEAD-006, DEAD-010, DEAD-011.
DEAD-008 — Planner и interval helpers живы через Account Ledger
- Decision: KEEP.
- Severity: P2.
- Confidence: High.
- Evidence:
backend/src/modules/investments/investment-sync-plan.ts:67–140,271–328;operations/application/brokerage-operations.service.ts:16–19,69–85,120–150,203–209;operations/application/brokerage-operations-sync.service.ts:9,106–112;investment-sync-plan.spec.ts:100–134. Укороченные пути относительныbackend/src/modules/investments/. - Claim: нельзя удалить
planInvestmentScreen,accountHistory,ledgerRangeили их файл вслед за manual sync: они обслуживают живой Ledger. - Current mechanism / runtime consumer: operations controller → read →
planner для
screen='operations', membership gating и selected interval →sync.readPlan. History/read metadata также вызывает accountHistory; interval helpers используются независимо от dead request. - Impact / actual cost: broad screen vocabulary содержит прежние ветки, но ядро живо; Impact unmeasured. Whole-file deletion ломает получение первого отсутствующего интервала, границы времени и history state.
- Why now: это конкретный counterexample прежней гипотезе «screen planner принадлежит только manual orchestration».
- Minimum change: сохранить live planner/helpers. После DEAD-001 допустим отдельный узкий reachability pass по вариантам screen, если это стоит усилий; автоматическое удаление всех planner tests недопустимо.
- Guarantees at risk: account scope, membershipKnown gating, inclusive/ exclusive end, historical boundaries, нерасширение произвольного интервала.
- Counterarguments / trade-offs: немало branches после removal manual writer станет only-test reachable. Это повод сузить конкретные варианты с equivalence proof, а не удалить финансовые interval rules. В 04 это не generic refactor.
- Verification or rollback: current ledger HTTP/local-read/interval tests при любом будущем narrowing; сравнить selected intervals, unknown membership, all/account и date-only/instant boundaries. Сейчас deletion отсутствует.
- Effort: S. Здесь и в других KEEP effort относится к сохранению deletion boundary; narrowing/migration оцениваются отдельно.
- Related finding IDs: DEAD-001, DEAD-009.
DEAD-009 — Hourly scheduler является runtime owner, а не legacy provider
- Decision: KEEP.
- Severity: P2.
- Confidence: High.
- Evidence:
backend/src/app.module.ts:14,35;src/modules/investments/tbank-sync/tbank-sync.module.ts:24–25;tbank-hourly.scheduler.ts:28–87,119–175;tbank-sync.repository.ts:174–243,245–286;compose.yaml:32–35;specs/openspec/specs/hourly-investment-sync/spec.md:8–40. Укороченные sync пути относительны backend sync directory. - Claim: отсутствие HTTP callers
tickили прямых тестов не делает scheduler dead; Nest lifecycle запускает его native timer. - Current mechanism / runtime consumer:
onModuleInit → setInterval(tick)читает connections, резервирует work и через setImmediate запускает owners membership/portfolio/operations/events;onModuleDestroyочищает timer. Метаданные ресурсов читают repository hourly result. - Impact / actual cost: runtime coordination необходима для обновления данных при закрытой SPA; Impact unmeasured. Удаление отключило бы normal personal refresh. Корректность lifecycle отдельно не сертифицируется.
- Why now: whole-folder cleanup
tbank-sync/выглядел бы коротким, но смешивает dead manual writer с current root entrypoint. - Minimum change: сохранить scheduler, registration, repository hourly методы и DTO; убирать только manual command closure DEAD-001.
- Guarantees at risk: запуск без экрана, single-attempt fence, generation, остановка timer, section result visibility и отсутствие catch-up очереди.
- Counterarguments / trade-offs: наличие lifecycle hook не доказывает правильность всех failure branches. Подозрения на их correctness направлены владельцу audit 13/08, а не использованы для рекомендации DELETE.
- Verification or rollback: перед cleanup DI/module proof и существующий source-owner behavior; scheduler error/time scenarios — отдельные проверки при изменении его поведения. Сейчас механизм сохраняется.
- Effort: S.
- Related finding IDs: DEAD-001, DEAD-005, DEAD-008, DEAD-011.
DEAD-010 — Candle loader и staging не удаляются вместе с manual force caller
- Decision: KEEP.
- Severity: P2.
- Confidence: High.
- Evidence:
backend/src/modules/investments/instruments/application/candle.service.ts:101–124,206–261,264–326;instruments/stocks/application/stock-market.service.ts:54–64;instruments/bonds/application/bond-market.service.ts:58–68;instruments/infrastructure/candle.repository.ts:137–228,257–284;backend/test/tbank-candles-persistence.e2e-spec.ts:117–200,486–501;specs/openspec/specs/tbank-data-sync/spec.md:16–22. Укороченные instruments пути относительныbackend/src/modules/investments/. - Claim:
CandleService.request, queue/stage/publication и coverage runtime-required: read запускает первое получение отсутствующего диапазона. - Current mechanism / runtime consumer: GET stock/bond candles → market
service →
history.read→ при отсутствии coveragerequest → drain/load. Отдельно enrichment.ensureDetail использует shared sources. Manual force — не единственный caller source owner. - Impact / actual cost: механизм обеспечивает запрошенный диапазон, точные decimal strings, empty coverage и transactional publication; Impact unmeasured. Удаление owner сделает cold candles недоступными.
- Why now: соседство с manual request повышает риск удалить весь loader, его source repository или associated tests без проверки hidden read caller.
- Minimum change: сохранять ordinary request/staging/coverage. Нужность отдельно forced/priority вариантов после DEAD-001 UNVERIFIED: нужен variant-level pass, в этом отчёте whole-loader deletion отвергнута.
- Guarantees at risk: точность, rollback неполного reconciliation, absence ≠ empty, unchanged coverage вне окна и connection fencing.
- Counterarguments / trade-offs: часть direct force tests относится к old
command variants; это не делает всю suite или transactional primitive legacy.
Default method caller в
read:121–123— положительное доказательство жизни. - Verification or rollback: при любой variant deletion оставить ordinary period, reopen, exact decimals, closed empty и failed publication cases; isolated SQLite proof, не mock транзакции. Сейчас deletion не требуется.
- Effort: S.
- Related finding IDs: DEAD-001, DEAD-002, DEAD-007, DEAD-011.
DEAD-011 — Shared source CAS, identity и FK защищают живые use cases
- Decision: KEEP.
- Severity: P1.
- Confidence: High.
- Evidence:
backend/src/modules/investments/instruments/application/catalog-enrichment.service.ts:64–87,164–225,545–579;instruments/infrastructure/catalog-discovery.repository.ts:154–179,184–249,280–339,466–487;backend/src/modules/investments/upcoming-events/upcoming-events.service.ts:182–239;backend/src/modules/investments/portfolio/application/portfolio.service.ts:264–283;backend/prisma/schema.prisma:148–229,232–262. Укороченные instruments пути относительныbackend/src/modules/investments/. - Claim: общая
CatalogDiscoveryRepositoryне является legacy repository целиком.reserve/finish/publishSource, attempt/initiator fences и instrument identities остаются runtime-required после removal discovery producer. - Current mechanism / runtime consumer: hourly
events.refresh → readSourcesзапускает enrichment source work; candles.ensureDetail делает то же для dependency. Enrichment.reserve/drain обращается в shared repository, где transaction проверяет origin и observer attempt до публикации public payload. Live portfolio owner также вызывает metadata.request для своих positions. - Impact / actual cost: защита от late/superseded/invalid-token publication и сохранение data relationships; Impact unmeasured. Удаление ради меньшего числа проверок может изменить чужую source revision/timestamp; удаление instrument identity каскадирует source/candle/coverage rows.
- Why now: это важная граница closure DEAD-002: method
publishexclusive старому discovery producer, methodpublishSource— живому enrichment. - Minimum change: сохранять shared owner, registration, transaction/CAS,
identity и schema. Code-only deletion может затронуть только exclusive
discovery writer
publish, а не весь repository или таблицы. - Guarantees at risk: connection isolation, conditional publication, invalid-token boundary, identity reuse, candle data и PII-safe projection.
- Counterarguments / trade-offs: online-only reference requirement не делает DB identity disposable. Название repository и один прежний caller не определяют его реальную область ответственности. Data migration, если потребуется, должна быть совместимой и отдельно доказанной.
- Verification or rollback: targeted source/candle persistence и late connection-switch proof при cleanup; перед destructive migration — disposable backup/restore и FK проверка. В этом аудите DB не открывалась.
- Effort: S.
- Related finding IDs: DEAD-001, DEAD-002, DEAD-004, DEAD-007, DEAD-009, DEAD-010.
5. DELETE / SIMPLIFY / KEEP / INVESTIGATE
| Decision | IDs | Подтверждённая граница |
|---|---|---|
| DELETE | DEAD-001 | Только manual writer/reservation/progress/normalization closure; status и live owners сохраняются. |
| DELETE | DEAD-002 | Только persisted discovery producer и exclusive repository publish; shared source repository и observe reader сохраняются. |
| DELETE | DEAD-003 | Только Accepted DTO; status screen schema сохраняется. |
| DELETE | DEAD-004 | Только frontend observe callback/transport key rewrite; auth/access/refetch и backend API сохраняются. |
| SIMPLIFY | DEAD-005 | Scope/returned command facade убрать; timer/current resources/cleanup сохранить. |
| KEEP | DEAD-008 | Live Ledger planner, history и interval boundaries. |
| KEEP | DEAD-009 | Registered hourly scheduler, durable work и lifecycle. |
| KEEP | DEAD-010 | Candle first-range load, staging, rollback и coverage. |
| KEEP | DEAD-011 | Shared enrichment repository, CAS, identity/FK и metadata source owner. |
| INVESTIGATE | DEAD-006 | Public status GET/old screen rows: consumers/retirement неизвестны. |
| INVESTIGATE | DEAD-007 | Public backend observe/persisted reference readers: transition и безопасная data граница неизвестны. |
FIX не назначен: correctness живых путей не превращалась в параллельный аудит.
5.1. Special result — Reachability Ledger
confirmed dead означает отсутствие функционального production consumer в
проверенном source graph; import metadata registration при этом может исполняться.
only-test reachable означает реальный тестовый вызов при отсутствии production
entrypoint. External-use неизвестность всегда указана отдельно.
| Candidate | Reachability evidence: declaration → exports/registration → callers → runtime entrypoints → external accessibility | Dynamic/external risks | Affected tests/docs/config | Minimum safe deletion | Rollback | Confidence |
|---|---|---|---|---|---|---|
C01 — TbankSyncService.request/dispatch; confirmed dead; DEAD-001 |
Declaration backend/src/modules/investments/tbank-sync/tbank-sync.service.ts:54–78; DI tbank-sync.module.ts:24, только class construction → controller calls status:40, command callers 0 → no method decorator/timer → no command route, только GET. Все короткие пути в backend sync directory. |
DI не auto-dispatch-ит methods; module exports только scheduler. Alternate computed/reflection/script invocation не найден. | Normalize tests C02; controller/status DTO остаются; intended boundary specs/openspec/specs/tbank-data-sync/spec.md:9–25. |
Writer closure, не service целиком. | Code-only revert. | High |
C02 — normalizeScreen, repo screen writers; only-test reachable; DEAD-001 |
backend/src/modules/investments/tbank-sync/tbank-screen.ts:9–11 export → import в dead service :28,55 → 9 test call lines → no runtime entrypoint → не public HTTP validator текущего GET. Repo reserve:62–109/progress:135–169 callers только request/dispatch. |
InvestmentScreenDto жив через Swagger/status; нельзя удалить его по association. Helpers не имеют top-level work/timer. |
tbank-screen.spec.ts:1–75 только manual descriptor behavior; status schema tests сохранить. |
Helper/test file и exclusive repo methods удалить после C01. | Вернуть closure. | High |
C03 — CatalogDiscoveryService.request/refresh/drain; only-test reachable + dead-parent reachable; DEAD-002 |
backend/src/modules/investments/instruments/application/catalog-discovery.service.ts:340–496 → provider/API registration instrument-sources.module.ts:18–21, instruments.api.ts:2 → public methods search/detail/byTicker, но online return или observe=true reader → HTTP не попадает в producer; dead manual refresh tbank-sync.service.ts:197. |
Живые exported provider/HTTP reader не равны live producer. No lifecycle writer hook; setImmediate только внутри недоступного request. | Direct service cases backend/test/tbank-catalog-discovery.e2e-spec.ts:85–322; update factory/selection checks, reader compatibility. |
Producer state/methods + exclusive repo publish, оставить shared reserve/finish/publishSource. |
Code-only revert, rows/schema untouched. | High |
C04 — TbankSyncAcceptedDto; confirmed dead export; DEAD-003 |
backend/src/modules/investments/tbank-sync/tbank-sync.dto.ts:212–218 → export with decorators → 0 consumers/ApiExtraModels → no POST response metadata → отсутствует в обоих известных OpenAPI artifacts. |
Class decorators исполняются на import, но не создают route. Shared investmentScreenSchema используется Status. Fresh parity не запускалась. |
backend/test/openapi-contract.e2e-spec.ts:30–55; no Accepted-only test/config consumer. |
Только orphan class. | Вернуть class. | High |
C05 — frontend observe/observationKey; only-test reachable; DEAD-004 |
frontend/src/shared/api/resource-query.ts:71,104,144 → hook public index src/shared/api/index.ts:12–15 → tests resource-query.test.tsx:63,167 → production pages используют refetch → private SPA, не public package export. |
Dynamic router imports и stories не используют callback; backend wire mode остаётся reachable C09. | Два observe scenarios; сохранить successful-null/refetch/access tests. Convention data :61–63 — intended old flow, не runtime. |
Callback/helper/exclusive imports; safe race proof перевести на живой caller при необходимости. | Вернуть code/tests. | High |
C06 — _scope и returned screen facade; live timer / only-test commands; DEAD-005 |
frontend/src/features/tbank-connection/model/screen-sync.ts:15–22,37–61 → feature index.ts:1 → 8 VM call sites → все calls expression statements в lazy routed pages → callback exposure вне SPA не найден. |
Удаление всего hook опасно: :28–35 timer жив. Typed resource fields не означают usage после facade removal. |
screen-sync.test.tsx:22–80 direct commands; all page callers. |
Только scope/unused commands/status/fields; live effect сохранить. | Вернуть facade/call signatures. | High |
C07 — planInvestmentScreen/accountHistory/ledgerRange; runtime required; DEAD-008 |
backend/src/modules/investments/investment-sync-plan.ts:67,287,301 exports → operations source imports → brokerage-operations.service.ts:80,120,203, sync service :106 → Account Ledger HTTP → real public read capability. |
Частично legacy vocabulary не делает файл orphan. No DI требуется чистым exported functions. | investment-sync-plan.spec.ts:100–134, interval/ledger cases; historical screen cases отдельно проверить после C01. |
Whole-file deletion запрещён; variant narrowing требует proof. | Not applicable: KEEP. | High |
| C08 — status GET и screen reader; externally reachable/unknown + legacy documented contract; DEAD-006 | backend/src/modules/investments/tbank-sync/tbank-sync.service.ts:313–391 → @Get(':id') → controller :40 → guarded HTTP + snapshot frontend/src/shared/api/spec/openapi.json:5102–5185 → любой authorized consumer с work ID. |
Local SPA calls 0; external consumers/old rows UNVERIFIED. Reflection не нужна: route явный. | Status DTO, screen discriminator, repository read/progress types, contract tests, old DB work. | Пока deletion запрещён; отдельное compatibility решение. | Вернуть route/schema; data не удалять. | High reachability |
C09 — catalog observe reader branches; externally reachable + legacy documented contract; DEAD-007 |
backend/src/modules/investments/instruments/application/catalog-discovery.service.ts:84–141,168–217,251–293 → stock/bond catalog services → controller query.sync → runtime HTTP ?sync=observe → snapshot query enum и docs compatibility. |
External use/retirement UNVERIFIED. Pub DTO decorators и router сохраняют вход без frontend observe. | Legacy reference schemas/read tests, shared DTO, persisted data; online requirement online-instrument-information/spec.md:8–17. |
Сначала consumer transition; не удалить общую storage identity/все query modes. | Code routing revert; data restore потребует backup. | High reachability |
| C10 — hourly scheduler; runtime required; DEAD-009 | backend/src/modules/investments/tbank-sync/tbank-hourly.scheduler.ts:33–56 → providers/root import → Nest onModuleInit → interval.tick + setImmediate.walk → personal source owners, а не внешняя command API. |
Lifecycle/reflection registration — positive entrypoint. Env feature switch не найден; single-process deployment compose.yaml:34. |
Hourly resource DTO/repo + mapper/source tests, hourly spec; scheduler stubs не доказательство смерти. | KEEP provider/root import/durable hourly rows. | Not applicable: KEEP. | High |
| C11 — candle request/staging; runtime required; DEAD-010 | backend/src/modules/investments/instruments/application/candle.service.ts:101–123,206–261 → source module exports → stock/bond market.history.read → controller candle GET → first missing range source work. |
Dead manual force caller не отменяет ordinary read caller. Variant-level force нужность UNVERIFIED. | backend/test/tbank-candles-persistence.e2e-spec.ts:117–200,486–501; candle coverage/decimal tests; shared source/FK. |
KEEP loader/repository; force variants не удалять без отдельного trace. | Not applicable: KEEP. | High |
| C12 — shared source repository/CAS/identity; runtime required; DEAD-011 | backend/src/modules/investments/instruments/infrastructure/catalog-discovery.repository.ts:154–179,280–339,466–487 → DI instrument-sources.module.ts:19 → enrichment request/publishSource/finish → hourly events and candle ensureDetail → resource HTTP consumes snapshots. |
Имя CatalogDiscovery вводит в заблуждение; FK Cascade на instrument → candles/coverage backend/prisma/schema.prisma:199,213,227. Source origin/observer fence — live invariant. |
Source/candle persistence, calendar consumers, Prisma schema; data purge не выполнялся. | KEEP shared repo/CAS/identity; exclusive discovery publish отделим C03. | Code rollback; destructive data rollback только backup. | High |
Полные production call sites C06:
| Page | Exact path:line-range |
|---|---|
| Accounts | frontend/src/pages/accounts/ui/AccountsPage/AccountsPage.vm.ts:21–24 |
| Account | frontend/src/pages/account/ui/AccountPage/AccountPage.vm.ts:78–84 |
| Operations | frontend/src/pages/account-operations/ui/AccountOperationsPage/AccountOperationsPage.vm.ts:96–99 |
| Events | frontend/src/pages/account-events/ui/AccountEventsPage/AccountEventsPage.vm.ts:67–75 |
| Income | frontend/src/pages/account-income/ui/AccountIncomePage/AccountIncomePage.vm.ts:66–69 |
| Bonds | frontend/src/pages/bonds/ui/BondsPage/BondsPage.vm.ts:12–13 |
| Stock | frontend/src/pages/stock/ui/StockPage/StockPage.vm.ts:45–55 |
| Bond | frontend/src/pages/bond/ui/BondPage/BondPage.vm.ts:45–55 |
5.2. Special result — Deletion Closure Plan
План предназначен для последующей отдельной реализации. В рамках аудита ни один пункт не применён. Это method-level closure, а не whole-folder purge.
| Candidate | Reachability evidence | Dynamic/external risks | Affected tests/docs/config | Minimum safe deletion | Rollback | Confidence |
|---|---|---|---|---|---|---|
| C01/C02 / DEAD-001 | No request root; normalize/repo writers only under dead writer, Ledger planner live | Status route и old screen rows отдельно C08; service/controller DI сохраняются | tbank-screen.ts, tbank-screen.spec.ts; service imports/injections/fields; repo reserve/progress; tbank-sync.module.ts reviewed, сохраняет hourly. Existing docs hourly model уже не требует command; archived ADR/spec не менять. |
Удалить request/dispatch и reservation field; helper/test files; repo screen reserve/progress; exclusive instrument/candle/metadata/portfolio/membership DI service dependencies. Оставить repository/access/operations, runId/startedAt/status и screen intent/progress types reader. | Revert только code/test deletion. | High |
| C03 / DEAD-002 | HTTP ordinary online; observe reader read(true); refresh only dead C01 | Source repository жив и backend observe externally reachable | Service imports randomUUID, logger, attempt type, missing-revision constant/state; constructor factory backend/test/tbank-catalog-discovery.e2e-spec.ts:28–35; producer-only cases; source module remains. Online selection/whitelist cases сохранить/перепривязать. Docs online intended model не требует producer; archives retain. |
Удалить Producer/state/request/refresh/drain и request branch read; удалить только repository publish:341–464. Убрать exclusive logger constructor/import. Не удалять CatalogDiscoveryService provider целиком, shared repository registration, reserve/finish/publishSource/readSources/workMany, catalog selection, online client или schema. |
Code/test revert; сохранённые reference rows остаются readable. | High |
| C04 / DEAD-003 | Declaration only, not in response/ApiExtraModels/artifacts | Status shared screen schema остаётся published | DTO class only; contract test existing. No script/config exclusive to Accepted найден. | Удалить TbankSyncAcceptedDto:212–218; сохранить соседние live classes/imports, которыми они пользуются. |
Вернуть class. | High |
| C05 / DEAD-004 | 2 direct tests, no production observe symbol consumer | Auth/access effects и server query mode сохраняются | Helper/callback/imports/return member; tests :40–71,139–173; frontend data convention old observe paragraph requires owner follow-up, not archive deletion. Feature index useResourceQuery остаётся. |
Удалить only-test observe path; не удалять resource hook или session snapshot implementation, используемую authenticated-query. Guard/cancellation race проверять через оставшийся live boundary. | Вернуть path/tests. | High |
| C06 / DEAD-005 | 8 callers ignore return, scope unused | Live timer — dangerous to remove automatically | 8 VM descriptor arguments; screen hook resource type; direct refresh/retry tests; mocked facade frontend/src/pages/account-events/ui/AccountEventsPage/AccountEventsPage.test.tsx:15 пересмотреть по новым exports. Feature barrel остаётся. |
Убрать scope/facade, narrowing inputs до использованных timer полей; оставить useEffect/ref/interval cleanup. Rename/move/new helper не требуются. | Вернуть signature/facade/caller descriptors. | High |
| C08/C09 / DEAD-006/007 | Explicit HTTP GET/query registration | ОПАСНА автоматическая зачистка: external compatibility и existing rows UNVERIFIED | Contract/source DTO/read tests и published frontend artifact; old rows и FK; potential API retirement notice | Не удалять до согласованного support/consumer решения. Получить evidence, затем отдельная route/reader closure. Destructive schema/data removal — отдельный совместимый шаг. | Restore routing/schema, не полагаться на revert для удалённых данных. | High reachability; deletion unverified |
| C07/C10/C11/C12 / DEAD-008–011 | Positive Ledger/lifecycle/candle/enrichment call traces | ОПАСНА автоматическая зачистка: live behavior, generation/CAS, rollback и cascade data loss | Planner/interval, hourly, source/candle/metadata tests; schema; module registration | KEEP; никакой whole-file/whole-folder/schema deletion по совпадению legacy vocabulary. | Не требуется без изменения; data migration отдельно. | High |
Важная closure-граница: убрать injection из TbankSyncService не означает убрать соответствующий provider из TbankModule/PortfolioModule/InstrumentSourcesModule. Наличие status branch и shared repository читается независимо от отсутствия writer. Документальные references закрываются корректировкой текущего описания только при реальном изменении поведения; история ADR/OpenSpec не стирается.
6. Cost & benefit
| IDs | Ожидаемый класс экономии | Фактическое измерение | Обязательные регрессии / безопасная граница |
|---|---|---|---|
| DEAD-001/002 | Maintenance, cognitive load, navigation/agent context; меньше old producer tests | not measured; нет готового diff, baseline CI timings или token профиля | Не менять public status/observe, source owners, CAS, hourly/candle/ledger; DI compilation + applicable isolated tests при cleanup. Runtime запросы уже недоступных paths не объявлены экономией. |
| DEAD-003 | Малое сокращение obsolete API surface | not measured | Status OpenAPI schema unchanged; no whole DTO/schema purge. |
| DEAD-004/005 | Maintenance, test surface, caller descriptors и unused facade | not measured | Session/access invalidation/refetch/cached envelope; periodic current-resource read и cleanup. Bundle/render выгода не заявлена. |
| DEAD-006/007 | Возможная будущая экономия compatibility maintenance | UNVERIFIED / not measured | Нужны consumer/retirement proof; shared identity/FK сохраняются. |
| DEAD-008–011 | Предотвращение ошибочного cleanup и регрессий | not measured | Сохранить финансовые interval/decimal/transaction/generation/lifecycle invariants. |
Ponytail-audit shortlist, от крупной closure к малой:
delete:manual screen writer/reservation/normalization. Замена: ничего; hourly source owners уже обслуживают текущий сценарий. [backend/src/modules/investments/tbank-sync/tbank-sync.service.ts:54–311]delete:persisted discovery producer и exclusive publish. Замена: существующие online paths; compatibility reader сохранить. [backend/src/modules/investments/instruments/application/catalog-discovery.service.ts:340–496]delete:frontend only-test observe callback/key rewrite. Замена: существующий ordinary refetch. [frontend/src/shared/api/resource-query.ts:69–127]shrink:screen scope/returned facade. Замена: оставить только используемый periodic GET effect. [frontend/src/features/tbank-connection/model/screen-sync.ts:15–61]delete:orphan Accepted DTO. Замена: ничего. [backend/src/modules/investments/tbank-sync/tbank-sync.dto.ts:212–218]
net: сокращение строк not measured, dependencies not assessed
(направление 12). Оценка прежнего аудита ~550 не повторяется; ни процент,
ни скорость, ни CI minutes из inspection не выводятся.
7. Top actions
Максимум подтверждённых code cleanup actions — пять, а не искусственно десять. Последовательность учитывает dependency closures и цену ошибки.
Quick wins
- DEAD-003: удалить одну orphan class; проверить Status schema.
- DEAD-004: убрать only-test frontend observe path с сохранением живых resource/auth guarantees и meaningful race boundary.
- DEAD-005: удалить unused scope и facade, не удаляя periodic effect; обновить 8 callers и проверить timer current-resource/unmount.
Более крупные closures с тестовым подтверждением
- DEAD-001: удалить manual writer плюс normalization/repo writer closure; оставить status compatibility и live DI/source owners.
- DEAD-002: после DEAD-001 удалить discovery producer и только exclusive repository publish; перепривязать нужные online/shared-source assertions.
Решения, требующие compatibility/ADR или test proof: DEAD-006/007 не являются подтверждёнными шагами DELETE. API owner должен решить external support до withdrawal route/query semantics. Отдельное ADR оправдано, только если меняется сохранённый public contract/support policy; внутренние dead methods нового ADR сами по себе не требуют. Любая data migration отдельно доказывает FK/restore.
8. Cross-audit signals
| Тема | Evidence | Рекомендуемый audit ID |
|---|---|---|
| Timer/refetch policy и disabled queries — живой путь, не DELETE | frontend/src/features/tbank-connection/model/screen-sync.ts:28–31; src/pages/bonds/ui/BondsPage/BondsPage.vm.ts:10–13 |
02 / 07 |
| Old observe convention при новых consumers и documented legacy support | frontend/.ai/conventions/data.md:61–63; docs/architecture/http-api.md:50–52 |
15 |
| Income read сохранил request-driven membership branch; это достижимое поведение | backend/src/modules/investments/operations/application/brokerage-operations.service.ts:408–435 |
07 / 13 |
| Проверка scheduler failure/time lifecycle нужна независимо от cleanup | backend/src/modules/investments/tbank-sync/tbank-hourly.scheduler.ts:93–110,178–218 |
08 / 13 |
| Producer-only tests должны быть пересмотрены по текущему entrypoint | backend/test/tbank-catalog-discovery.e2e-spec.ts:85–118,179–196; frontend/src/shared/api/resource-query.test.tsx:139–173 |
08 |
Это сигналы владельцам, не отдельные findings этих направлений. Дублирование живых mappers, dependencies, generic VM complexity и архивные docs не аудировались.
9. Open questions / verification plan
| Вопрос, меняющий решение | Текущее состояние | Самый дешёвый proof |
|---|---|---|
Есть ли поддерживаемый consumer GET /tbank-sync/{id}? |
Local SPA consumers 0; actual external use UNVERIFIED. | Owner API/deployment отвечает о clients; существующая обезличенная access-log выборка по route, без запросов к real API. |
Нужны ли старые screen: work после перехода? |
Writer недостижим, reader публичен; сохранённые DB rows не проверялись. | Aggregate count/age/scope на disposable копии SQLite + agreed support horizon. Не печатать intent/token/account payloads. |
Кто пользуется sync=observe именно у справочных routes? |
Source/DTO публикуют режим; потребитель может быть вне SPA. | Endpoint-specific consumer list/log sample и контрактное решение; не выводить removal всех modes из удаления frontend callback. |
| Можно ли удалить persisted reference storage целиком? | Нет: есть positive live source/metadata reads и cascade candle FK. | Отдельная source/FK карта нужных identities и backup/restore proof; сначала code-only producer cleanup. |
| Какие variants planner/candle force останутся после manual deletion? | Owners живы; unused variant removal отдельно UNVERIFIED. | После узкого diff пересчитать callers конкретных variants; current Ledger/candle behavior comparison, не whole-file purge. |
| Пройдут ли cleanup DI/schema/regressions? | Изменений приложения нет, tests/build не запускались. | В отдельной implementation task сначала targeted owner/HTTP/isolated persistence checks, затем локальные обязательные gates по affected repos. |
9.1. Проверка полноты и сохранности результата
- Проверены 9 общих разделов, полная finding schema для всех 11 IDs, 12 candidate chains, explicit DI/dynamic/public/external checks, Reachability Ledger и Deletion Closure Plan.
- Финальная consolidation table содержит по одной строке на finding; C01/C02 не удваивают actionable count. KEEP/INVESTIGATE не смешаны с DELETE.
- Source pointers просмотрены по локальным файлам и строкам; отрицательный поиск дополнен положительными traces/counterexamples, ограничения сохранены.
- После записи отчёта повторно проверены SHA/status всех пяти checkout и
git diff --check; source/config четырёх репозиториев и root tracking чисты. Отчёт проверен отдельно, потому что root.gitignoreего игнорирует. - Semantic/Boy Scout review ограничен самим report: не добавлены новые helpers, scripts, обязательные workflows или неподтверждённые измерения; source edits отсутствуют. Existing dated audits, archives и references не менялись.
Final machine-readable consolidation table
| ID | Decision | Severity | Confidence | Repo | Files | One-line impact | Effort | Related IDs |
|---|---|---|---|---|---|---|---|---|
| DEAD-001 | DELETE | P2 | High | backend | src/modules/investments/tbank-sync/tbank-sync.service.ts; src/modules/investments/tbank-sync/tbank-screen.ts; src/modules/investments/tbank-sync/tbank-screen.spec.ts; src/modules/investments/tbank-sync/tbank-sync.repository.ts | Недоступная manual orchestration и exclusive writer/test closure | M | DEAD-002,DEAD-006,DEAD-008,DEAD-009,DEAD-011 |
| DEAD-002 | DELETE | P2 | High | backend | src/modules/investments/instruments/application/catalog-discovery.service.ts; src/modules/investments/instruments/infrastructure/catalog-discovery.repository.ts; test/tbank-catalog-discovery.e2e-spec.ts | Producer старого persisted discovery недоступен production; shared readers/writers живы | M | DEAD-001,DEAD-007,DEAD-010,DEAD-011 |
| DEAD-003 | DELETE | P3 | High | backend | src/modules/investments/tbank-sync/tbank-sync.dto.ts | Orphan Accepted DTO без wire consumer | S | DEAD-001,DEAD-006 |
| DEAD-004 | DELETE | P3 | High | frontend | src/shared/api/resource-query.ts; src/shared/api/resource-query.test.tsx | Observe callback и key rewrite используются только direct tests | S | DEAD-005,DEAD-007,DEAD-011 |
| DEAD-005 | SIMPLIFY | P3 | High | frontend | src/features/tbank-connection/model/screen-sync.ts; src/features/tbank-connection/model/screen-sync.test.tsx; src/pages/accounts/ui/AccountsPage/AccountsPage.vm.ts; src/pages/account/ui/AccountPage/AccountPage.vm.ts; src/pages/account-operations/ui/AccountOperationsPage/AccountOperationsPage.vm.ts; src/pages/account-events/ui/AccountEventsPage/AccountEventsPage.vm.ts; src/pages/account-income/ui/AccountIncomePage/AccountIncomePage.vm.ts; src/pages/bonds/ui/BondsPage/BondsPage.vm.ts; src/pages/stock/ui/StockPage/StockPage.vm.ts; src/pages/bond/ui/BondPage/BondPage.vm.ts | Scope/returned facade unused; live periodic GET effect сохранить | S | DEAD-004,DEAD-009 |
| DEAD-006 | INVESTIGATE | P2 | High | backend | src/modules/investments/tbank-sync/tbank-sync.controller.ts; src/modules/investments/tbank-sync/tbank-sync.service.ts; src/modules/investments/tbank-sync/tbank-sync.dto.ts | Public status GET и old screen rows требуют external compatibility proof | M | DEAD-001,DEAD-003,DEAD-007 |
| DEAD-007 | INVESTIGATE | P2 | High | backend | src/modules/investments/instruments/application/catalog-discovery.service.ts; src/modules/investments/investment-resource.dto.ts; src/modules/investments/instruments/stocks/presentation/stock.controller.ts; src/modules/investments/instruments/bonds/presentation/bond.controller.ts | Backend observe readers externally reachable; retirement UNVERIFIED | M | DEAD-002,DEAD-004,DEAD-006,DEAD-010,DEAD-011 |
| DEAD-008 | KEEP | P2 | High | backend | src/modules/investments/investment-sync-plan.ts; src/modules/investments/operations/application/brokerage-operations.service.ts; src/modules/investments/operations/application/brokerage-operations-sync.service.ts | Ledger использует planner/history/interval helpers | S | DEAD-001,DEAD-009 |
| DEAD-009 | KEEP | P2 | High | backend | src/modules/investments/tbank-sync/tbank-hourly.scheduler.ts; src/modules/investments/tbank-sync/tbank-sync.module.ts; src/modules/investments/tbank-sync/tbank-sync.repository.ts | Nest lifecycle запускает живой hourly owner без frontend | S | DEAD-001,DEAD-005,DEAD-008,DEAD-011 |
| DEAD-010 | KEEP | P2 | High | backend | src/modules/investments/instruments/application/candle.service.ts; src/modules/investments/instruments/infrastructure/candle.repository.ts | Ordinary candle read требует first-range loader/staging/coverage | S | DEAD-001,DEAD-002,DEAD-007,DEAD-011 |
| DEAD-011 | KEEP | P1 | High | backend | src/modules/investments/instruments/infrastructure/catalog-discovery.repository.ts; src/modules/investments/instruments/application/catalog-enrichment.service.ts; prisma/schema.prisma | Shared source CAS/identity live; blanket deletion рискует isolation и candle data | S | DEAD-001,DEAD-002,DEAD-004,DEAD-007,DEAD-009,DEAD-010 |