Files
docs/audits/2026-08-frontend-repository-audits/frontend-repository-audit.md
T

511 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Repository Audit: WealthLedger Frontend
**Дата:** 2026-08-31
**Session ID:** `01a05590-9243-7df0-9664-508acc5fc3e9`
**Invoked skills:** `repository-audit`
**Supporting skills invoked:** none
**External research performed:** no
## Scope and Confidence
**Target:** `frontend/`, Git branch `main`.
**Target commit:** `7ab043dce63a3fbacbfc9ac7d15b00dd714a541f`
(`docs: remove useless`).
**Initial target state:** `git status --porcelain=v1 --untracked-files=all` был
пуст; целевой репозиторий не содержал tracked или untracked изменений.
**Reference:** `references/frontend-ai-template/`. Директория не является
Git-репозиторием, поэтому commit identity недоступна. Идентичность
зафиксирована SHA-256 checksum аудируемого содержимого:
`7fced9c6906bdc846847eec40e05aac7c2c59f9fe593acc298eaab4bb29e2a9a`.
Checksum получен как SHA-256 отсортированного списка per-file SHA-256 и
относительных путей. Из scope исключены `node_modules` на любой глубине,
`.idea`, `.playwright-mcp`, cache-, build- и coverage-директории. Эталон
использовался только для сравнения эквивалентных обязанностей, не как authority.
Аудит standalone и read-only: OpenSpec/SDD workflow не запускался. Единственная
запись — этот отчёт вне `frontend/` и reference. В inventory вошли все 145
tracked-файлов target (117 под `src`, 22 test-файла) и 220 релевантных файлов
reference после исключения локальных зависимостей и ephemeral artifacts.
Углублённо проверены manifests/lockfile, TypeScript/Vite/Vitest/Biome/Knip/
dependency-cruiser/Husky configuration, repository instructions и frontend
docs, auth/session и API seams, routing/error boundary, representative finance
pages, entities, ViewModels, tests и эквивалентные reference responsibilities.
По всему `src` выполнены searches импортов, network calls, generated types,
tests и крупных modules; не каждый CSS-файл и не весь generated OpenAPI файл
читались построчно.
Выполненные проверки:
- `npm run deps` — exit 0; 136 modules и 484 dependency edges, нарушений нет;
- `npm run knip` — exit 0, findings отсутствуют;
- offline generation `openapi-typescript` во временный файл — текущий
`schema.d.ts` байтово совпадает со snapshot;
- controlled invalid-date probe под Node 22 —
`RangeError: Invalid time value`, подтверждающий F-03.
Полный `npm run verify`, `test:coverage`, build, Storybook и E2E не запускались:
они создают или могут изменять `coverage`, `dist`, reports и caches, что не
соответствует read-only контракту аудита. Также не выполнялись install,
dependency advisory scan, backend runtime contract test и browser-based visual/
accessibility checks. Поэтому выводы о текущем полном gate, supply-chain
уязвимостях, реальном backend и визуальном поведении не заявляются.
**Общая confidence:** high для статической архитектуры, tooling и найденных
расхождений; medium для production/release risk из-за локальной границы системы
и отсутствия runtime/browser evidence.
**Preservation check:** после всех inspection/validation commands target
остался на том же commit с пустым porcelain status; повторный reference checksum
совпал с исходным. Временный generated artifact удалён. Единственное
сохранённое изменение сессии — этот Markdown report.
## Executive Summary
Репозиторий в целом находится в хорошем состоянии: небольшой React/Vite client
имеет строгий TypeScript, один typed HTTP boundary, risk-oriented Vitest/MSW
tests, coverage floors, dead-code analysis и более сильные dependency rules,
чем reference. Критических findings нет.
Наибольшую ценность дадут F-01 и F-02: восстановить детерминированную проверку
generated OpenAPI artifact и закрыть реальный login journey существующим test
stack. F-03 — небольшой, но уже воспроизводимый trust-boundary defect в URL date
validation. F-04 уточняет существенное ограничение заявленного public-API gate:
он не видит type-only dependencies и уже пропускает семь внутренних imports.
Остальная архитектурная стоимость сосредоточена в двух ownership seams (F-05,
F-08) и в документации, которая местами описывает удалённые либо избыточно
жёсткие guardrails (F-06, F-07).
Эталон полезен как подтверждение ценности OpenAPI drift check, но его Storybook,
browser MSW, Playwright harness, локальный OpenSpec и 17 agent skills не должны
переноситься в target: текущая система локальна, а эти поверхности не решают
наблюдаемую проблему пропорционально своей стоимости.
## Priority Findings
| Severity | Finding | Category | Action | Effort |
| --- | --- | --- | --- | --- |
| high | F-01. Generated OpenAPI types не защищены от drift | Tooling / API Contract | add | small |
| high | F-02. Основной auth journey не проверяется | Testing / Security | add | small |
| medium | F-03. Некорректная календарная дата бросает исключение | Correctness / Validation | change | small |
| medium | F-04. Type-only dependencies обходят public-API guardrail | Architecture / Tooling | change | small |
| medium | F-05. Ubiquitous Money formatting принадлежит Portfolio | Architecture / Ownership | change | medium |
| medium | F-06. Entry-point docs обещают отсутствующие проверки | AI Readiness / Documentation | change | small |
| low | F-07. File-splitting rule создаёт ложный hard invariant | Complexity / AI Readiness | simplify | small |
| low | F-08. T-Bank status обходит общий authenticated-query seam | Architecture / Maintainability | change | small |
## Findings
### F-01. Generated OpenAPI types не защищены от drift
**Category:** Tooling / API Contract
**Severity:** high
**Confidence:** high
**Action:** add
**Effort:** small
**Observed:** Frontend хранит и OpenAPI snapshot, и generated
`schema.d.ts`, но canonical `verify` не проверяет, что второй детерминированно
получен из первого. Workflow полагается на ручное выполнение
`npm run openapi:generate` после копирования snapshot.
**Evidence:** `frontend/package.json:17-20` содержит `openapi:generate`, но
`verify` состоит только из typecheck, Biome, coverage, Knip,
dependency-cruiser и build. `frontend/docs/API-LAYER.md:3-5` прямо описывает
ручные два шага. Backend `test:openapi-contract` сравнивает runtime contract с
frontend snapshot, но не snapshot с `frontend/src/shared/api/generated/schema.d.ts`.
Текущий controlled check с генерацией в `/private/tmp` показал
`OPENAPI_GENERATED_MATCH yes`, то есть finding относится к отсутствующему
guardrail, а не к текущему рассинхрону. TypeScript и build являются
counter-evidence только для внутренней согласованности кода со stale generated
типами; происхождение этих типов они доказать не могут.
**Why it matters:** Изменение snapshot без генерации может одновременно пройти
frontend `verify` и backend runtime-contract check, оставив приложение
скомпилированным против старого публичного контракта. Для auth и финансовых
response shapes это даёт silent contract risk в главном typed boundary.
**Reference repository:** **adopt from reference — capability only.** Reference
имеет `scripts/check-openapi.mjs`, `openapi:check` и включает его в `verify` и
pre-commit (`reference/package.json:13-28`,
`reference/scripts/check-openapi.mjs:1-32`). Это узкий guardrail с прямой
проблемой и без новой dependency. Остальной reference toolchain для него не
нужен.
**Recommended direction:** Добавить один non-mutating offline check: с помощью
уже установленного `openapi-typescript` генерировать temp artifact, сравнивать
его с committed `schema.d.ts` и включить сравнение в canonical `verify`.
Не синхронизировать backend и не переписывать tracked files внутри gate.
### F-02. Основной auth journey не проверяется
**Category:** Testing / Security
**Severity:** high
**Confidence:** high
**Action:** add
**Effort:** small
**Observed:** Test suite хорошо покрывает восстановление session, Bearer retry,
очистку cache, anonymous redirects и одну отрицательную registration validation,
но ни один тест не выполняет успешный login/register/logout через public UI/
provider boundary. В частности, untested остаётся связка `AuthForm` →
`AuthProvider.authenticate` → auth endpoint → in-memory access token → переход
на protected route.
**Evidence:** Поиск по всем 22 test-файлам нашёл auth assertions только в
`src/shared/api/client.test.ts`, `src/shared/api/authenticated-query.test.tsx`,
`src/features/auth/model/auth.test.tsx`, `src/features/auth/ui/AuthForm.test.tsx`
и `src/app/routes/AppRoutes.test.tsx`. `auth.test.tsx:11-102` проверяет три
refresh/401 сценария; `AuthForm.test.tsx:16-41` — только несовпадающее
подтверждение пароля; route test восстанавливает session через refresh.
Tests не вызывают `login`, `register` или `logout`, не отправляют валидную
форму и не проверяют `LoginForm`/`RegisterForm` navigation. Это проверено
repository-wide search, а не выводом из отсутствия отдельного filename.
**Why it matters:** Auth — security-sensitive и critical user journey по
действующей risk-based testing policy. Независимо покрытые низкоуровневые seams
не обнаружат поломку их композиции: неверный endpoint/body, потерянное session
state update, неработающий `returnTo`, navigation до завершения auth или
неочищенный UI после logout.
**Reference repository:** **reference approach is unnecessary.** Reference
имеет Playwright и browser MSW, но его E2E покрывает Todo demo, не auth. Перенос
всего browser harness ради этого риска добавит больше lifecycle cost, чем
существующий Vitest + Testing Library + MSW boundary.
**Recommended direction:** Добавить минимальный risk-focused integration test
на существующем stack, который вводит валидные credentials, проходит реальный
`AuthProvider`/MSW login и наблюдает protected landing/session outcome. Logout
или failure следует добавлять только там, где их риск не покрыт уже имеющимися
provider/client tests; Playwright для этого finding не требуется.
### F-03. Некорректная календарная дата бросает исключение
**Category:** Correctness / Validation
**Severity:** medium
**Confidence:** high
**Action:** change
**Effort:** small
**Observed:** `isDate` сначала проверяет только форму `YYYY-MM-DD`, затем без
проверки validity вызывает `toISOString()`. Строка вроде `2026-99-99` проходит
regex и приводит к `RangeError`, а не к validation result `false`.
**Evidence:** `src/pages/account-income/ui/AccountIncomePage.vm.ts:35-46` подаёт
`isDate` в Zod refinements; `:51-71` читает даты из untrusted URL search params;
`:114-132` использует `new Date(...).toISOString()` в `isDate` и затем снова в
`validPeriod`. Controlled Node 22 probe над этой же операцией вернул
`INVALID_DATE_THROW RangeError: Invalid time value`. Existing income tests
покрывают analytics, empty bucket, chart и recoverable server error, но не
malformed URL/form dates. Общий `RouteErrorBoundary` ограничивает blast radius,
но превращает validation error в аварийный route state.
**Why it matters:** Пользователь или внешняя ссылка может сломать income route
одним syntactically-shaped query parameter. Это доступность и корректность на
trust boundary; exception bypasses предусмотренное восстановление default
period и field-level validation.
**Reference repository:** **neither reflects a directly comparable case.**
Reference валидирует numeric route params через Zod `safeParse`, но не содержит
эквивалентной календарной логики, поэтому переносить его hook не нужно.
**Recommended direction:** Сделать date predicate total: проверить parsed date
до `toISOString` либо валидировать год/месяц/день безопасным стандартным
преобразованием, затем зафиксировать malformed query/form date регрессионным
тестом. Новая date library не нужна.
### F-04. Type-only dependencies обходят public-API guardrail
**Category:** Architecture / Tooling / AI Readiness
**Severity:** medium
**Confidence:** high
**Action:** change
**Effort:** small
**Observed:** Dependency-cruiser проверяет cycles, layer direction и public
entrypoints только для dependencies, существующих после TypeScript compilation.
Type-only edges не входят в graph, хотя repository docs формулируют public-API
правило без такого исключения. В результате семь consumers импортируют
внутренний generated module `@/shared/api/generated/schema` напрямую.
**Evidence:** В `frontend/dependency-cruiser.cjs:45-48` задан `tsConfig`, но нет
`tsPreCompilationDeps`; установленный dependency-cruiser 18.2.0 устанавливает
его default в `false` (`node_modules/dependency-cruiser/src/main/options/defaults.mjs:9`).
`frontend/docs/CONVENTIONS.md:9` и `frontend/docs/STRUCTURE.md:11-13` требуют
cross-slice imports через `index.ts`, а `frontend/AGENTS.md:34` называет это
dependency-cruiser-enforced boundary. При этом прямые type-only imports
`@/shared/api/generated/schema` находятся в пяти entity API hooks,
`features/auth/model/auth.tsx` и
`features/tbank-connection/ui/TbankConnectionSection.tsx`;
`frontend/src/shared/api/index.ts` не реэкспортирует `paths`. Успешный
`npm run deps` не является counter-evidence: эти edges отсутствуют в
анализируемом graph. Counter-evidence по масштабу риска — остальные найденные
type-only imports идут через public APIs в разрешённом направлении, а текущие
семь generated imports не создают runtime coupling.
**Why it matters:** Заявленный machine-enforced invariant фактически не
распространяется на compile-time architecture. Новый type-only upward import,
type cycle или обращение к внутренностям другого slice сможет пройти canonical
gate; существующий generated seam уже демонстрирует расхождение code и policy.
Severity остаётся medium, потому что текущие edges стираются при compilation и
не создают runtime cycle или bundle dependency.
**Reference repository:** **adopt from reference — capability, not exception.**
Reference включает `tsPreCompilationDeps: true`, но исключает generated subtree
из dependency analysis. Target может сохранить более строгий и ясный public API,
не копируя это исключение.
**Recommended direction:** Реэкспортировать generated `paths` как type из
`shared/api/index.ts`, перевести семь consumers на `@/shared/api` и включить
`tsPreCompilationDeps: true` в существующем dependency-cruiser config. Если
generated path действительно должен быть публичным исключением, сначала
зафиксировать его явно и всё равно проверять остальные type-only edges. Новая
dependency или второй architecture checker не нужны.
### F-05. Ubiquitous Money formatting принадлежит Portfolio
**Category:** Architecture / Ownership
**Severity:** medium
**Confidence:** high
**Action:** change
**Effort:** medium
**Observed:** Общий display formatter `formatMoney` типизирован через
`Portfolio["totalsByCurrency"][number]` и экспортируется из Portfolio entity,
хотя используется для Brokerage Account, Ledger Entry, Income Analytics и
Future Cash Event. `formatSnapshotTime` и instrument logo helper также частично
разделяются через тот же Portfolio public API.
**Evidence:** Canonical domain glossary определяет Money как самостоятельный
ubiquitous value `{ currency, value }`, который frontend форматирует для
отображения (`docs/architecture/domain-glossary.md:20-28`). Реализация в
`src/entities/portfolio/model/display.ts:1-18` выводит Money type из Portfolio.
Repository-wide usage показывает импорт Portfolio formatter из
`src/entities/brokerage-account/ui/BrokerageAccountList.tsx`,
`src/entities/broker-operation/ui/LedgerEntryRow.tsx`, account/events/income
pages и их section views. `npm run deps` проходит, потому что текущие rules
контролируют direction/public entrypoints, но не смыслового владельца peer
entities. Counter-evidence: formatter один, протестирован и не дублируется;
проблема именно в owner/type dependency, а не в реализации форматирования.
**Why it matters:** Изменение Portfolio transport shape или реорганизация
Portfolio заставляет менять несвязанные account, ledger и income consumers.
Граница утверждает, что общий Money concern принадлежит одной product entity,
и легализует entity-to-entity coupling, которое dependency tool не различает.
**Reference repository:** **reference approach is unnecessary.** Todo-only
reference не моделирует shared Money value и не предлагает применимого owner.
**Recommended direction:** Переместить только действительно ubiquitous
display primitives (в первую очередь Money formatting и, при подтверждении
общего смысла, date formatting) в нейтральный существующий lower-level owner.
Оставить `formatShare` и portfolio error behavior в Portfolio. Не вводить Money
service, interface hierarchy или новую domain layer ради одного formatter.
### F-06. Entry-point docs обещают отсутствующие проверки
**Category:** AI Readiness / Documentation
**Severity:** medium
**Confidence:** high
**Action:** change
**Effort:** small
**Observed:** Человеческий entrypoint сообщает, что `verify` отклоняет неверный
Node runtime и проверяет repository hygiene, а conventions утверждают, что
pre-commit запускает OpenAPI check. Ни одной из этих команд в текущих scripts/
hook нет.
**Evidence:** `frontend/README.md:25-27` перечисляет runtime и hygiene;
`frontend/docs/CONVENTIONS.md:14` перечисляет pre-commit OpenAPI check.
Фактически `frontend/package.json:9-22` не содержит `runtime:check`,
`hygiene:check` или `openapi:check`, а `.husky/pre-commit` выполняет только
`npx lint-staged` и `npm run deps`. Counter-evidence: `.nvmrc`,
`engines.node = 22.x` и repository-local `AGENTS.md` корректно требуют
`nvm use --silent`; canonical config остаётся discoverable. Расхождение
ограничено двумя stale prose claims, а не всей документацией.
**Why it matters:** Новый разработчик или coding agent получает ложное
completion evidence и может считать runtime, env hygiene или generated artifact
проверенными. Особенно опасно сочетание с F-01: docs называют guardrail, которого
больше нет.
**Reference repository:** **both are acceptable only where config and prose
agree.** Reference действительно включает свой `openapi:check`, но его намного
больший documentation surface не нужен target. Target уже лучше как concise,
canonical entrypoint; ему требуется синхронизация нескольких утверждений, а не
перенос reference docs.
**Recommended direction:** Привести README и CONVENTIONS к фактическим scripts:
описать manual Node activation и реальные hook/gate stages. Если F-01 добавлен,
упомянуть только реально включённый OpenAPI check. Не возвращать отдельные
runtime/hygiene scripts без нового конкретного failure mode.
### F-07. File-splitting rule создаёт ложный hard invariant
**Category:** Complexity / AI Readiness
**Severity:** low
**Confidence:** high
**Action:** simplify
**Effort:** small
**Observed:** UI docs объявляют обязательным отдельный file для каждого
top-level state и каждого именуемого page section, но несколько текущих modules
сознательно хранят cohesive presentation рядом. Самый заметный пример —
388-line `AccountIncomePage.view.tsx` с loading/error/loaded и шестью semantic
section components.
**Evidence:** `frontend/docs/CONVENTIONS.md:12-13` и
`frontend/docs/UI-PATTERN.md:30-35` формулируют правило как Must/«нельзя».
`src/pages/account-income/ui/AccountIncomePage.view.tsx:29-380` содержит
`AccountIncomePageLoading`, `AccountIncomePageError`, loaded view, summary,
comparisons, trend, breakdown и forecast. Подобная colocated state structure
есть в `AccountsPage.view.tsx` и небольшом T-Bank view. Counter-evidence:
важная граница container → VM → props-only view в проверенных finance pages
соблюдается; большой income view читается последовательно и покрыт одним
behavior-level page test. Поэтому само количество components/files не является
failure mode.
**Why it matters:** Непроверяемое и уже нарушенное Must заставляет agents либо
игнорировать authority, либо создавать file/ barrel sprawl без улучшения
ownership. Оно также маскирует действительно важный invariant — views не должны
владеть data fetching и collection derivation.
**Reference repository:** **reference approach is unnecessary.** Reference
часто создаёт отдельную директорию и file для каждого Todo state; это полезно
для component catalog demo, но увеличивает navigation cost для текущего product
client и не должно становиться механической нормой.
**Recommended direction:** Оставить VM/view ownership rule обязательным, а
file splitting сделать locality-based guidance: выделять section, когда у неё
есть самостоятельная responsibility, reuse, test/change cadence или она мешает
пониманию owner. Не добавлять line-count checker и не требовать one-component-
per-file.
### F-08. T-Bank status обходит общий authenticated-query seam
**Category:** Architecture / Maintainability
**Severity:** low
**Confidence:** high
**Action:** change
**Effort:** small
**Observed:** Все entity queries используют shared `useAuthenticatedQuery`,
который подписывается на session snapshot. T-Bank connection status вместо
этого импортирует `useAuth` из соседней feature и вручную задаёт
`enabled: Boolean(accessToken)` обычному `useQuery`.
**Evidence:** `src/shared/api/authenticated-query.ts:13-33` владеет session
gating; его используют brokerage account, operation, event, income и portfolio
hooks. `src/features/tbank-connection/ui/TbankConnectionSection.vm.ts:1-15`
создаёт второй механизм и feature → feature dependency на `features/auth`.
`dependency-cruiser.cjs` не запрещает peer-feature dependencies, поэтому
успешный `npm run deps` не является counterexample. Counter-evidence: текущее
поведение функционально совпадает, access token обновляется через AuthProvider,
а mutations всё равно идут через общий authenticated fetch.
**Why it matters:** Изменение определения authenticated readiness,
`configureAuthClient` или session clearing может примениться ко всем entity
queries, но не к T-Bank status. Соседняя feature становится зависимой от auth
implementation detail при уже существующей lower-level seam.
**Reference repository:** **not comparable.** Reference не имеет auth/session
boundary.
**Recommended direction:** Переиспользовать existing authenticated-query seam
для status query и убрать feature-to-feature dependency. Новая abstraction или
расширение dependency rules ради единственного случая не нужны.
## Missing Practices
- F-01 — отсутствует доказательство происхождения committed generated API
types из committed snapshot.
- F-02 — отсутствует risk-focused integration proof главного auth journey.
- F-03 — trust-boundary date validation не total и не имеет malformed-input
regression coverage.
- F-04 — type-only dependencies не входят в заявленный public-API/layer gate;
уже существуют семь direct generated-internal imports.
Отсутствие CI/CD и deployment automation не считается finding: canonical
`docs/architecture/system-overview.md` явно ограничивает текущую поставку
локальной системой, а `frontend/AGENTS.md` требует отдельного approved change
для CI, Playwright или Storybook.
## Over-engineering / Simplification Opportunities
- F-07 — сузить file-splitting Must до правила ownership/locality, сохранив
важную VM/view границу.
- Не переносить из reference Storybook, browser MSW mode, Playwright harness,
локальный `openspec/` и 17 repository-provided skills: для target нет
наблюдаемой проблемы, оправдывающей этот context и maintenance surface.
- F-05 следует исправлять переносом маленьких shared primitives, не созданием
Money service/interface/factory.
- Не добавлять второй FSD framework или checker: текущий dependency-cruiser уже
проверяет cycles, public entrypoints и layer direction лучше reference.
## AI Readiness
AI readiness выше средней: `AGENTS.md` короткий, различает hard guardrails и
review guidance, направляет к специализированным docs и canonical multi-repo
authority; scripts и public APIs предсказуемы; generated seam явно помечена;
dependency-cruiser и Knip снижают необходимость загружать длинные инструкции.
Главные ухудшения — F-04 (type-only blind spot), F-06 (несовпадение prose с
executable truth) и F-07 (непроверяемый structural Must). Reference agent
surface значительно больше и для target был бы регрессом context locality.
## What Is Already Good
- Строгая и воспроизводимая основа: Node 22 contract, npm lockfile, exact direct
dependency versions, strict TypeScript и Biome.
- `npm run deps` подтверждает отсутствие cycles/layer/public-API violations в
анализируемых runtime edges; target имеет отдельные cycle/public-API rules,
которых нет в reference, но F-04 ограничивает полноту этого доказательства.
- Один HTTP owner: repository-wide search не нашёл прямой network access вне
`src/shared/api/client.ts`; transport types выводятся из OpenAPI.
- Auth design соответствует system/domain authority: access token остаётся в
memory, refresh использует cookie и single-flight behavior; Bearer exclusion,
refresh retry и cache clearing имеют focused tests.
- 22 colocated test-файла покрывают loading/error/empty/cached snapshot,
finance display, filtering/pagination, route boundary и T-Bank mutations.
- Coverage floors, Knip, dependency checks и production build собраны в одном
canonical local gate; controlled Knip/dependency runs успешны.
- UI resilience и доступные loading/error regions не только описаны, но и
представлены в code/tests; общий route error boundary ограничивает failures.
- Текущий OpenAPI snapshot и generated types фактически синхронны; F-01 —
prevention gap, не текущая поломка.
## Recommended Order
### Do now
1. F-01 — добавить non-mutating OpenAPI generated-artifact equivalence в
canonical gate.
2. F-02 — закрыть успешный auth journey существующим Vitest/MSW stack.
3. F-03 — сделать date validation total и закрепить malformed-input case.
4. F-04 — включить type-only edges и провести generated types через public API.
5. F-06 — синхронизировать README/CONVENTIONS с фактическими scripts и hooks.
### Do next
1. F-05 — вернуть ubiquitous Money display primitive нейтральному owner без
нового service layer.
### Consider later
1. F-08 — устранить единичный bypass authenticated-query seam при ближайшем
изменении T-Bank connection.
2. F-07 — упростить file-splitting guidance до решения по locality/ownership.
### Do not add
- Storybook, browser MSW mode или Playwright только потому, что они есть в
reference; F-02 дешевле и надёжнее закрывается текущим integration stack.
- Локальный OpenSpec store или копии reference agent skills: canonical SDD
authority уже находится вне target и entrypoint достаточно короткий.
- CI/CD, deployment или release platform вне отдельного approved scope:
as-built system явно локальна.
- Runtime validation каждого OpenAPI response без конкретного наблюдаемого
trust-boundary failure; это существенно расширит runtime и schema ownership.
- Новый FSD framework, line-count gate, one-component-per-file rule, Money
service/interface или dependency ради findings, которые решаются текущими
tools и небольшими ownership corrections.