Переносит архив `audits/2026-10-11/` (19 файлов) из codex/audit-remediation-2026-10-11 в develop и добавляет точечный allowlist в .gitignore.
491 lines
68 KiB
Markdown
491 lines
68 KiB
Markdown
# Аудит 11 — Validation & CI/CD Efficiency
|
||
|
||
## 1. Audit metadata
|
||
|
||
- **Audit ID/name:** 11 / Validation & CI/CD Efficiency.
|
||
- **Дата:** 2026-10-11.
|
||
- **Режим:** read-only для application/specs/docs repos; единственная запись — этот отчёт в родительском workspace.
|
||
- **Область:** execution DAG проверок, triggers, независимые CI guarantees, повторная подготовка, staged hooks, генерация контрактов и граница image publication. Алгоритмы самописных инструментов, assertions тестов, dependency security и поведение агента не аудировались.
|
||
- **Skill:** установленный `ponytail-audit` прочитан через Skill tool и применён к complexity-pass. Его ограничения сохранены: correctness findings ниже — результат протокола аудита 11, а не вывод skill. Дополнительно прочитан `verification-before-completion` для контроля итогового артефакта.
|
||
- **Предыдущий аудит:** `audit-results/technical-audit-2026-10-11.md` прочитан как реестр гипотез. Его измерения dependency graph, совпадения OpenAPI и выводы о тестах не использованы как актуальное доказательство.
|
||
|
||
Workspace: `/Users/ksv741/Project/vibe/WealthLedger`. Это родительская папка самостоятельных Git-репозиториев:
|
||
|
||
| Repo | Найденный путь относительно workspace | HEAD SHA | Ветка | Начальный `git status --short` |
|
||
| --- | --- | --- | --- | --- |
|
||
| frontend | `frontend/` | `c8821200ce699dab1ce65360d1968d5877a2e78b` | `codex/fix-stock-screener-race` | clean |
|
||
| backend | `backend/` | `0ad84ff4f0b4712abc7e69dc299856f14af6eadd` | `codex/add-stock-screener` | clean |
|
||
| specs | `specs/` | `fcdc805f6c1b3be6a20a7e858e3e80cbd83a9121` | `codex/add-stock-screener` | clean |
|
||
| docs | `docs/` | `e6fd4f64b81dd73b33959b845a1babcfac1891c8` | `codex/add-stock-screener` | clean |
|
||
| workspace root, вспомогательная область | `./` | `dc030f84c979cedb2628ef4bd97c62d6c63a9256` | `release/0.2.1` | clean |
|
||
|
||
Также обнаружен отдельный `deploy/.git`; его исходники и pipeline не исследовались. Downstream deployment описан только по доступным root Compose и `docs/architecture/deployment.md`. Наличие локального checkout не доказывает production state.
|
||
|
||
### Что выполнялось
|
||
|
||
1. Статическое чтение repo instructions, manifests, workflows, hooks, compiler/test/build configs и вызываемых entry points; файловый inventory через Read/Glob/Grep.
|
||
2. В каждом из четырёх repos и root: `git status --short --branch`, `git rev-parse HEAD`.
|
||
3. В четырёх repos: read-only `git config --get core.hooksPath`. Frontend: `.husky/_`; specs: `.githooks`; backend/docs: значение отсутствует, команда вернула 1 без вывода. Это отсутствие настройки, а не ошибка проверки приложения.
|
||
4. В specs: `git diff --check && git diff --stat && git diff --cached --stat` — exit 0, вывода нет; проверены пустые локальные diffs, не PR content.
|
||
5. Через Context7 прочитана актуальная документация Gitea о PR activity types и head ref: [Actions FAQ](https://docs.gitea.com/usage/actions/faq), [webhook payload](https://docs.gitea.com/usage/repository/webhooks). Внешний источник подтверждает поддержку `edited`; версия и настройки реального Gitea не запрашивались.
|
||
6. После записи отчёта: повторный read-only контроль Git status/HEAD всех пяти областей — SHA не изменились, working trees clean. `git diff --check` root — без diagnostics. No-index whitespace-check отчёта относительно `/dev/null` — без diagnostics; exit 1 обозначает наличие нового содержимого относительно пустого файла. Root `git status --short --ignored -- <report>` показывает игнорируемый `audit-results/`, согласно allowlist; отчёт не добавлялся в tracking.
|
||
|
||
**Не выполнялось:** npm/Node/OpenSpec команды, install, lifecycle hooks, tests, lint, build, full verify, Prisma/OpenAPI codegen, Docker, migrations, обращения к брокерским/банковским API, npm audit, чтение secrets, commit/PR, изменение source/config/lockfiles/generated artifacts. CI runs/logs и branch protection settings не запрашивались. Тайминги отсутствуют; все оценки экономии — **not measured**.
|
||
|
||
## 2. Executive verdict
|
||
|
||
1. **Факт / FIX:** `specs verify` в CI проверяет разницу working tree с index, а не проверяемые commits. В чистом checkout это пустая проверка, хотя её статус является задуманным required check. Самый дешёвый полезный gate — whitespace-check явного диапазона commits без Node installation в этом job. `VERIFY-001`.
|
||
2. **Факт / риск:** четыре repos исключают PR `edited` из triggers commitlint. Заголовок можно изменить после зелёного статуса без нового запуска; frontend/backend README обещают обратное. `VERIFY-002`.
|
||
3. **Факт / SIMPLIFY:** backend non-scheduled verify job содержит **3 явных Prisma generation и 2 Nest build**. При этом standalone `verify` генерирует client слишком поздно для чистого checkout. Нужен один owner подготовки до потребителей типов и reuse той же сборки в e2e, а не механическое удаление первого generate. `VERIFY-003`.
|
||
4. **Факт / SIMPLIFY:** frontend pre-commit после staged lint каждый раз собирает два private packages и сканирует весь dependency graph, даже для Markdown-only commit. Полный граф проверяется также в final verify и CI. Обязательные security/staged lint можно сохранить, а full graph оставить composed gates. `VERIFY-004`.
|
||
5. **KEEP:** CI уже избегает дублирующего feature-branch push-run, имеет fail-fast цепочку `commits → security → verify`, отмену устаревших ревизий и вынесенный тяжёлый performance benchmark. Unit/SQLite, JSDOM/Chromium и два dependency graphs имеют разные гарантии; объединять их по похожим именам нельзя.
|
||
6. **UNVERIFIED:** фактические CI minutes, npm/browser/build cache hits, версия Gitea, действующие required checks и защита устаревшего PR head от нового base не проверены. Это вопросы для короткого просмотра существующего run и настроек, а не основание отключать gates.
|
||
|
||
**Итог:** четыре подтверждённых P2 findings, без подтверждённых P0/P1. Основная экономия достигается сокращением повторной подготовки и правильным input scope дешёвых gates; расширение количества валидаторов не требуется.
|
||
|
||
## 3. Inventory & coverage
|
||
|
||
### 3.1 Изученные объекты и метод подсчёта
|
||
|
||
| Объект | Охват и метод | Результат |
|
||
| --- | --- | --- |
|
||
| CI definitions | Полное чтение всех файлов в `.gitea/workflows/` четырёх repos и root | 11 workflow files, 15 job definitions; сумма: frontend 2/4, backend 2/4, specs 3/3, docs 3/3, root 1/1 |
|
||
| CI platforms | Все перечисленные job definitions и `.nvmrc` | Один label `ubuntu-latest`, нет OS/Node matrix; все `.nvmrc` — `24.21.0` |
|
||
| Local commands | Пять root manifests, три frontend workspace manifests | Раскрыты `verify`, standalone checks, build, generation, release entry points и root lifecycle |
|
||
| Git hooks | Tracked hook files, actual hooksPath, backend/docs `.git/hooks`, Husky launcher | Frontend: pre-commit + commit-msg; specs: commit-msg; backend/docs: только `.sample`; активных pre-push checks не найдено |
|
||
| Backend e2e selection | Glob `backend/test/*.e2e-spec.ts` + `test/sqlite.cjs:7–17` | 20 suite files; `--all` выбирает 19 functional suites, исключая один performance suite; это число файлов, не assertions |
|
||
| Browser selection | Glob `*.browser.test.tsx` в frontend `src`/`packages` + `vitest.config.ts:36–64` | 2 файла, каждый включён для narrow/wide Chromium instances: 4 configured file-instance combinations без фактического запуска |
|
||
| Contracts | Backend generator + runtime integration suite; frontend check/generate | Прослежены источник, временный output, byte comparison, freshness и consumers |
|
||
| Downstream artifacts | Dockerfiles, image workflows, coverage/Sonar configs, docs deployment | Build provenance boundary и consumers покрыты статически; registry/deploy execution не проверены |
|
||
|
||
Counts относятся только к найденным локальным checkout, не к server-wide jobs/runners. Явные повторы команд считались разворачиванием manifest chains и workflow steps на успешном пути; lifecycle сторонних packages и cache-hit effects не выдаются за измеренную длительность.
|
||
|
||
Из installed manifests отдельно проверены `backend/node_modules/@prisma/client/package.json:264–275` и `backend/node_modules/prisma/package.json:194–205`: у этой версии client нет postinstall generation, Prisma имеет preinstall. Это поддерживает гипотезу cold-checkout failure standalone verify; установленное дерево не заменяет воспроизведение fresh install.
|
||
|
||
### 3.2 Исследовательский порядок и исключённые гипотезы
|
||
|
||
1. Inventory entry points → выбор рисков stale/no-op proof и повторной подготовки.
|
||
2. Tracing workflow → package script → runner/generator/build outputs → consumer.
|
||
3. Проверка альтернатив: отдельный front generate нужен до типов; standalone wrappers обеспечивают свежесть packages; graph modes отличаются; OpenAPI delivery явно ручная; image publication не равна server rollout.
|
||
4. Сформированы четыре findings; без искусственного расширения до всех возможных оптимизаций.
|
||
|
||
Не аудировались assertions и качество coverage, алгоритмы custom scripts, advisories/overrides, OpenSpec schema/lifecycle design, глобальные editor/agent hooks и отдельный deploy repo. Исторические archives не использованы как proof текущих triggers.
|
||
|
||
## 4. Check Execution DAG
|
||
|
||
Ниже **фактическая конфигурация**. Обязательное локальное действие из conventions отмечено отдельно от автоматического trigger.
|
||
|
||
### 4.1 Edit/save и ручная проверка
|
||
|
||
```text
|
||
developer / agent edits
|
||
├─ frontend npm run dev [только если процесс запущен]
|
||
│ └─ build:packages → Vite/HMR на изменениях
|
||
├─ frontend npm run dev:catalog [только если процесс запущен]
|
||
│ └─ build:packages → Storybook dev :6006
|
||
├─ frontend npm test [только если вручную выбран watch]
|
||
│ └─ build:packages → Vitest watch
|
||
├─ backend start:dev/debug [только если запущен]
|
||
│ └─ Nest watch → dist-dev; это не full test gate
|
||
└─ manual checks [решение автора]
|
||
├─ frontend targeted test / typecheck / lint / deps
|
||
│ └─ каждый standalone wrapper сначала build:packages
|
||
├─ backend targeted Jest / typecheck / isolated SQLite
|
||
└─ feature complete [локальное требование engineering:60–62]
|
||
├─ npm ci → root/dependency lifecycle
|
||
├─ frontend verify
|
||
└─ backend verify + risk-specific e2e/contract/durability
|
||
```
|
||
|
||
Автоматического full verify на каждый save в просмотренных application configs нет. Vite transform/HMR не доказывает typecheck, test coverage или production bundling. Backend dev compilation не заменяет configured HTTP/DB suites. Все global editor integrations остаются вне этого inventory.
|
||
|
||
### 4.2 Раскрытые gates
|
||
|
||
```text
|
||
frontend verify [всё через &&, stop на первой ошибке]
|
||
build:packages
|
||
├─ icons: vite build → tsc declarations
|
||
└─ ui: vite build → tsc declarations
|
||
tokens: JSON export, build script отсутствует
|
||
→ openapi:check [temp generation + byte compare types]
|
||
→ tsc -b --noEmit
|
||
→ eslint . --max-warnings=0
|
||
→ test:lint [node:test]
|
||
→ vitest run --coverage [JSDOM + Chromium narrow/wide]
|
||
→ knip
|
||
→ depcruise base
|
||
→ depcruise Storybook, reachability/runtime graph
|
||
→ tsc -b
|
||
→ vite build [app/PWA dist]
|
||
→ storybook build [storybook-static]
|
||
|
||
backend verify [всё через &&]
|
||
lint → test:lint → typecheck:app → typecheck:test
|
||
→ test:cov --runInBand [Jest в src]
|
||
→ build [prisma generate → nest build]
|
||
|
||
backend test:e2e
|
||
build [prisma generate → nest build]
|
||
→ sqlite.cjs --all
|
||
для каждой functional suite последовательно:
|
||
temp DB → штатные migrate deploy → Jest --runInBand → cleanup
|
||
|
||
backend test:openapi-contract
|
||
build → sqlite.cjs openapi-contract.e2e-spec.ts
|
||
configured app schema ↔ generator from dist in temporary cwd
|
||
|
||
docs verify
|
||
Markdown lint + relative links/anchors
|
||
→ отдельный CHANGELOG lint profile → git diff --check
|
||
|
||
specs verify
|
||
git diff --check [working tree ↔ index, не PR range]
|
||
```
|
||
|
||
Sources: `frontend/package.json:9–38`, workspace manifests, `backend/package.json:11–38,123–138`, `backend/test/sqlite.cjs:7–17,57–95`, `docs/package.json:8–13`, `specs/package.json:8–14`.
|
||
|
||
### 4.3 Commit/push/PR
|
||
|
||
```text
|
||
git commit frontend [actual hooksPath .husky/_]
|
||
Husky sh -e
|
||
→ staged Gitleaks, fail closed + redaction
|
||
→ lint-staged → ESLint --fix [selected staged JS/TS]
|
||
→ npm run deps → build:packages → full working-tree graph
|
||
→ commit-msg → commitlint
|
||
|
||
git commit specs
|
||
commit-msg → commitlint --strict
|
||
|
||
git commit backend/docs
|
||
application hooks отсутствуют в просмотренном checkout
|
||
|
||
git push feature branch
|
||
pre-push application checks отсутствуют
|
||
├─ без открытого PR: verify workflow не запускается
|
||
└─ с открытым PR: synchronize → PR workflow
|
||
|
||
PR opened / synchronize / reopened
|
||
frontend/backend:
|
||
commits [checkout head, npm ci --ignore-scripts, title + commit range]
|
||
→ security [full-history Gitleaks + npm audit]
|
||
→ verify [fresh npm ci; подготовка; full gates]
|
||
→ Sonar только для develop push, не PR
|
||
docs/specs:
|
||
commits ∥ security ∥ verify [независимые workflows]
|
||
root:
|
||
commits, включая edited [только root PR]
|
||
|
||
PR edited
|
||
root commits запускается
|
||
четыре repo commitlint workflows не подписаны
|
||
|
||
push develop/main
|
||
frontend/backend: commits skipped → security → verify
|
||
docs/specs: security ∥ verify; commits отсутствует
|
||
|
||
daily schedule
|
||
frontend/backend/specs/docs: security only
|
||
```
|
||
|
||
Frontend/backend PR branch не имеет отдельного push-run: это уже полезная защита от двойного CI для одного feature push. Push после merge проверяет новое состояние интеграционной ветки, а не автоматически бесполезно повторяет PR trust boundary.
|
||
|
||
В Gitea PR ref указывает на **head**, не на synthetic merge commit — это подтверждено Actions FAQ. Отсутствие merge preview нельзя компенсировать предположением, что зелёный PR автоматически проверен с новым base. Actual stale-branch protection — `UNVERIFIED`.
|
||
|
||
### 4.4 Build/publication/deploy
|
||
|
||
```text
|
||
release:prepare [manual, release/*]
|
||
release-it guards + check-release
|
||
→ version/lock/changelog commit; tag/push disabled
|
||
manual release PR + protected merge + tag vX.Y.Z
|
||
→ component image.yml
|
||
version + HEAD/revision validation
|
||
→ npm ci → canonical verify [backend также e2e]
|
||
→ registry login → immutable tag absence check
|
||
→ Docker production build/push
|
||
→ pull exact digest → labels + container smoke
|
||
→ cleanup registry session [always]
|
||
→ explicit operator selection of component tags / deploy bundle
|
||
→ rollout [отдельный repo, здесь не проверялся]
|
||
```
|
||
|
||
Docker заново выполняет installation/build внутри packaging environment. Это другая гарантия: чистый Linux image с нужными native modules/assets, а не повтор host typecheck ради того же proof. Backend дополнительно имеет повтор генерации *внутри* Docker stages — `VERIFY-003`.
|
||
|
||
Container smoke сейчас идёт **после push**, поэтому его failure не отменяет publication. Это не automatic deploy: `docs/architecture/deployment.md:76–85,132–135` явно требует отдельно проверить artifact и выбрать bundle, запрещает удалять tag ради retry. Backend workflow отказывается повторно публиковать существующий tag; frontend умеет проверить существующий digest. Без доказательства опасного rollout это не отдельный дефект аудита; immutable guards и operator smoke — **KEEP**.
|
||
|
||
## 5. Guarantee-to-Check Matrix
|
||
|
||
Для всех rows **expected runtime = not measured**. Timeout job — верхняя граница ожидания, а не measured runtime. `R` = read-only для versioned inputs; `W` = writes outputs/index/config. Даже R-check может иметь временные cache files.
|
||
|
||
| Check | Guarantee | Trigger / input scope | Read/write behavior | Downstream consumer |
|
||
| --- | --- | --- | --- | --- |
|
||
| `npm ci` | Manifest/lock reproducible installation, не semantic proof | Conventions completion; CI install; все lockfile dependencies | W: node_modules; lifecycle, frontend Husky/specs hooks config | Все Node checks; Docker dependencies |
|
||
| Frontend `build:packages` | JS/CSS/declarations для package exports актуальны | Standalone wrappers, verify, dev/catalog/build; icons/ui целиком | W: package dist | TS, ESLint resolver, Vitest, app/Storybook |
|
||
| Frontend `openapi:check` | Committed `schema.d.ts` байтово соответствует генерации из принятого snapshot | Full verify; snapshot + generator version + generated file | R tracked; W private temp + cleanup | Frontend typed API client |
|
||
| Backend `openapi:generate` | Artifact построен из текущего compiled backend | Manual delivery; current DTO/Swagger + dist | W: root ignored openapi.json; сначала build | Явно передаваемый consumer artifact |
|
||
| Backend OpenAPI integration | Generator output from current build равен schema configured current app; generator не открывает сеть | Contract change; CI e2e --all | W private DB/temp JSON; не versioned snapshot | Публичный generator и HTTP contract |
|
||
| Frontend `tsc -b`, с/без CLI `--noEmit` | Repo-wide strict TS configs и test/story/package compilation | typecheck, verify, app build; referenced projects | W buildinfo; app/node configs имеют noEmit | Локальный proof типов, bundle gates |
|
||
| Backend typecheck app/test | Production roots и test compilation | verify / manual; app subset и весь src+test | R, incremental:false/noEmit:true | Unit/e2e compilation confidence |
|
||
| Full ESLint + config tests | Configured rules, zero-warning policy, validation profile | verify/standalone; repo JS/TS | R для check; lint:fix отдельно W | Code review и next gates |
|
||
| lint-staged | Lint selected staged JS/TS + fixes | Frontend commit | W: selected content/index, возможный stash | Commit contents; не full-repo proof |
|
||
| Frontend Vitest coverage | Unit/transport/UI + actual layout checks; configured coverage floors | verify/coverage; full configured projects | W: coverage HTML/lcov и test artifacts | Merge gate, Sonar lcov |
|
||
| Backend Jest coverage | Colocated src unit suite проходит | verify/test:cov; src specs | W: coverage; общего threshold нет | Merge gate, Sonar lcov |
|
||
| SQLite functional runner | Configured HTTP/DB suites на isolated fresh migrations | test:e2e, CI; 19 выбранных suite files | W: temp DB only, cleanup | Authorization, transaction/CAS/replay/contract proof |
|
||
| `test:sqlite` | Auth/cards subset, не все HTTP suites | Manual risk-based iteration; default 2 suite files | W isolated DB; требует заранее generated client | Быстрая DB regression feedback |
|
||
| Base dependency-cruiser | Cycles, resolution, public API и layer boundaries | deps/verify/hook; весь src+packages, TS deps | R graph; wrapper W package build | Architecture gate |
|
||
| Storybook dependency-cruiser | Runtime reachability stories/preview не доходит до data/auth/routes | deps:storybook/verify; graph + preview, tsPreCompilationDeps:false | R graph; wrapper W package build | Независимость UI catalog |
|
||
| Knip | Unused exports/dependencies с repo entry point policy | verify/standalone; all workspaces | R analysis, wrapper W package build | Maintenance feedback |
|
||
| Vite/Storybook builds | App/PWA и catalog действительно bundle | verify/build; разные roots/plugins | W dist/storybook-static | Docker app output / UI catalog |
|
||
| Commitlint title + range | Заголовок и выбранные commits Conventional Commits | PR events; title + BASE/HEAD | R; job installation W | Required commits status; release history |
|
||
| Gitleaks | Staged/history secret scan + redaction/fail closed | Frontend commit index; CI full available history, daily | R inputs; CI downloads scanner; temp hook test | Commit/merge security boundary |
|
||
| npm audit | Registry advisory policy проходит для выбранных trees/levels | PR/push/daily security | Network read + возможные local logs; lock unchanged | Required security status |
|
||
| Docs Markdown | Syntax + local Markdown links/anchors, включая новые файлы | verify/CI; all Markdown + отдельный CHANGELOG | R | Docs consistency; не Mermaid/semantic proof |
|
||
| Specs/docs `git diff --check` | Whitespace errors в незакоммиченном working-tree diff | local verify, также current CI commands | R; untracked/index-only/committed changes не охвачены | Локальная проверка; в clean CI inputs пусты |
|
||
| Docker production build + smoke | Packaging, native runtime/assets/migrations и startup проходят | Release tag; image environment и pulled digest | W image/registry/disposable volumes | Explicit deployment selection |
|
||
| Sonar Quality Gate | Remote analyzer принял source и existing unit lcov | Только develop push после gates | W remote analysis | Develop push status, не PR proof |
|
||
| Durability / performance / runner regression | Migration/restart/backup proof либо load/runner behavior | Manual risk checks; не ordinary verify | W disposable outputs/DB; regression многократно запускает e2e | Schema-change proof / dedicated investigation |
|
||
|
||
### OpenAPI: четыре разных утверждения
|
||
|
||
1. **Backend file equals frontend snapshot:** сравнение двух сохранённых JSON доказало бы лишь их текущее совпадение. В этом аудите оно не выполнялось.
|
||
2. **Backend generator freshness:** `test/openapi-contract.e2e-spec.ts:108–158` вызывает generator from fresh dist в temporary cwd и сравнивает его JSON с `createOpenApiDocument(app)` current source/configured app. Это реально покрывается CI e2e.
|
||
3. **Frontend type freshness:** `scripts/check-openapi.mjs:10–38` генерирует из frontend-local accepted snapshot и сравнивает bytes `schema.d.ts`; backend freshness из этого не следует.
|
||
4. **Release compatibility / latest delivery:** предыдущий release и предоставленный frontend artifact — другие inputs. Backend не имеет versioned JSON baseline (`backend/.gitignore:69–70`), delivery описана явно (`backend/README.md:218–228`, `frontend/README.md:201–204`). Эти guarantees не были заявлены existing check и здесь остаются unverified.
|
||
|
||
**KEEP:** independent producer/consumer checks и offline generator guard. Не добавлять обязательный sibling checkout или второй editable contract source.
|
||
|
||
## 6. Duplicate Execution Matrix
|
||
|
||
### 6.1 Check × triggering context
|
||
|
||
Это configured occurrences на успешном пути, **не частота реальных действий**. `F` = один frontend full verify; `B` = один backend full verify. Host и Docker считаются раздельно.
|
||
|
||
| Check | Frontend targeted wrapper | F | Frontend pre-commit | Frontend CI verify job | Backend targeted contract | B | Backend CI verify job: pre-step + B + e2e | Release image job |
|
||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||
| Frontend package build | 1 для test/type/lint/deps/knip | 1 | 1 всегда после lint-staged | 1 | — | — | — | 1 host F + 1 Docker app build при cold build |
|
||
| Frontend repo tsc build mode | 0 или 1, по wrapper | 2 invocations | 0 | 2 | — | — | — | F + Docker type/build path |
|
||
| Frontend base depcruise | 0 или 1 | 1 | 1 | 1 | — | — | — | 1 host F |
|
||
| Storybook graph | 0 или 1 | 1 | 0 | 1 | — | — | — | 1 host F |
|
||
| Vitest target / full coverage | Targeted subset | 1 full | 0 | 1 full | — | — | — | 1 host full |
|
||
| Prisma generation, explicit | — | — | — | — | 1 | 1, поздно | 3 | 3 host + 2 Docker stage path при cold backend image build |
|
||
| Nest build | — | — | — | — | 1 | 1 | 2 | 2 host + 1 Docker |
|
||
| Backend unit coverage | — | — | — | — | 0 | 1 | 1 | 1 host |
|
||
| OpenAPI integration | — | — | — | — | 1 suite | 0 | 1 suite внутри --all | 1 suite внутри --all |
|
||
| Backend functional SQLite suites | — | — | — | — | 1 suite | 0 | 19 suite files | 19 host suite files |
|
||
|
||
Frontend два tsc invocations **не равны двум полным recompilations**: referenced configs уже `noEmit`, используются buildinfo. Ускорение от удаления второго не измерено. Backend app/test typecheck имеют перекрытие src, но разные program roots; удаление app-only proof без проверки ambient test effects не рекомендовано.
|
||
|
||
### 6.2 Матрица трёх событий
|
||
|
||
| Событие | Возможный локальный путь | Commit | Push / PR | Где повтор действительно лишний / где оправдан |
|
||
| --- | --- | --- | --- | --- |
|
||
| (a) Одна UI правка в frontend | HMR, optional `test:run -- <path>` → по completion policy npm ci + F | Staged Gitleaks + ESLint fixes + full deps с package build | Feature push: только PR synchronize, если PR открыт; CI fresh install + F | Targeted test и F дают разные scope/coverage; CI — independent boundary. Hook повторяет package build/base graph после F; для Markdown этот же hook не имеет relevant graph input |
|
||
| (b) Backend contract change | Targeted HTTP/contract; `test:openapi-contract` уже build+suite → B + relevant e2e; generator delivery отдельно | Backend application hook нет | PR: commits → security → pre-generate + B + build/e2e | Отдельный contract command и --all могут повторить ту же suite; в одной неизменённой local revision повторный targeted run не нужен. В CI 3 generate/2 builds обслуживают одну revision и environment |
|
||
| (c) git push / PR | Push сам не вызывает local verify | pre-push checks нет | Feature без PR: pipeline нет. PR open/update: full gates. Merge push develop/main: integration gates. Release tag: image pipeline | PR/branch/tag stages имеют отдельные inputs и trust boundaries. Не удалять tag verification без same-SHA/lock/environment gated proof. Изменение только PR title сейчас не вызывает новый commits check |
|
||
|
||
UI изменение не запускает backend/specs/docs checks автоматически: это независимые repositories. Backend artifact change требует проверки frontend только при явном изменении принятого frontend input, а не обязательного просмотра соседнего repo для любой backend правки.
|
||
|
||
## 7. Findings
|
||
|
||
### VERIFY-001 — Specs CI verify не проверяет проверяемый commit range
|
||
|
||
- **Decision = FIX; Severity = P2; Confidence = High; Effort = S.**
|
||
- **Evidence:** `specs/package.json:8–14`; `specs/.gitea/workflows/verify.yml:13–22`; `specs/README.md:33–35,52–55,68–70`. Для сравнения настоящее content-check в docs: `docs/package.json:8–10`, `docs/.gitea/workflows/verify.yml:23–25`.
|
||
- **Claim:** required-by-intent specs `verify` в clean CI checkout не проверяет whitespace committed PR/push content. Node setup/install обслуживает фактически пустой worktree diff.
|
||
- **Current mechanism:** workflow checkout → setup-node → npm ci → `git diff --check`; перед этой командой нет изменения tracked content и не передаются BASE/HEAD. `prepare` меняет hooksPath, не рабочие Markdown inputs.
|
||
- **Consumer:** PR required `verify` из README; локальный автор использует тот же script. Локально команда полезна для unstaged tracked diff, но не охватывает уже staged changes и новые untracked files.
|
||
- **Impact / actual cost:** ошибки whitespace в committed change проходят этот job; ложная уверенность в проверке diff. Отдельные setup/install steps не дают content guarantee. **Impact unmeasured**: реальный пропущенный PR и CI minutes не наблюдались.
|
||
- **Why now:** это можно исправить существующим Git check, не вводя новую validation framework и не изменяя ответственность specs.
|
||
- **Minimum change:** оставить локальный script локальной проверкой либо явно охватить staged diff; в CI выбрать содержательный commit range и вызвать Git напрямую. Для PR обеспечить наличие base/head commits, проверить merge-base → head; для push — before → after, с явно определённым fallback для creation/zero SHA. Только после этого убрать setup-node/npm ci из *verify job*; commits/security остаются прежними.
|
||
- **Guarantees at risk:** корректность range и presence of history. Shallow checkout без нужного base даёт неполную проверку; просто удалить job при unchanged required-check settings нельзя.
|
||
- **Counterarguments / trade-offs:** specs README обещает лишь diff, не native OpenSpec validation. Finding не требует запускать schema/semantic validation на каждый push. Docs verify не является no-op: его Markdown lint действительно читает содержимое, хотя последующий worktree diff там также пустой.
|
||
- **Verification or rollback:** в будущем PR с trailing whitespace в committed Markdown должен fail, исправленный — pass; проверить staged/local и first-push fallback отдельно. Достаточен disposable test branch/repo, application suite не нужна. До proof оставить существующий required check и затем сохранить его имя. Rollback — вернуть workflow, не менять Git history.
|
||
- **Related finding IDs:** VERIFY-002; cross-audit 15 только по самостоятельной native OpenSpec policy.
|
||
|
||
### VERIFY-002 — Commitlint не перезапускается при изменении заголовка PR
|
||
|
||
- **Decision = FIX; Severity = P2; Confidence = High; Effort = S.**
|
||
- **Evidence:** `frontend/.gitea/workflows/verify.yml:3–7,17–37`; `backend/.gitea/workflows/verify.yml:3–7,17–37`; `docs/.gitea/workflows/commits.yml:3–5,23–30`; `specs/.gitea/workflows/commits.yml:3–5,23–30`; обещание — `frontend/README.md:116–120`, `backend/README.md:80–85`; работающий root precedent — `.gitea/workflows/commits.yml:3–5,19–26`.
|
||
- **Claim:** все четыре repo workflows фильтруют `opened/synchronize/reopened` и не обрабатывают `edited`; title input может измениться без rerun validation, при том же HEAD.
|
||
- **Current mechanism:** job читает event PR_TITLE и проверяет его вместе с commit range только на перечисленных events. Local commit-msg проверяет commit, а не будущий PR title, и не компенсирует отсутствие trigger.
|
||
- **Consumer:** required `commits` status, Conventional Commit policy для PR/release history. Gitea FAQ подтверждает `edited` activity; отсутствие этого type — конфигурационное, а не отсутствие platform capability.
|
||
- **Impact / actual cost:** green status относится к прежнему title; после invalid rename policy proof становится stale. Фактический merge с таким title не наблюдался; **Impact unmeasured**.
|
||
- **Why now:** несоответствие дешёвого check собственному input trigger устраняется малой правкой; не нужны новые rules.
|
||
- **Minimum change:** обеспечить commits/title check на `edited`; docs/specs могут добавить type в отдельный commits workflow. Для frontend/backend сохранить selective dispatch: metadata-only event должен обновить commits proof без нового Chromium/Jest/build run. Не добавлять `edited` в full workflow без условия, если это просто умножит дорогие gates.
|
||
- **Guarantees at risk:** текущие names required checks и отношение skipped jobs к имеющимся success statuses. При разделении workflow нельзя случайно сделать старый обязательный context недостижимым или заменить failed verification на skipped success.
|
||
- **Counterarguments / trade-offs:** title lint — выбранное самим проектом правило, не runtime-security boundary. Его можно отдельно пересмотреть как policy, но workflow сейчас обещает его enforce. Содержание PR body тоже может давать `edited`; желательно проверять title-change payload, если платформа предоставляет нужные fields, без сложного custom classifier.
|
||
- **Verification or rollback:** на existing successful PR изменить только title на invalid, убедиться в новом failed commits check; вернуть valid title и получить success без нового verify run. Проверить branch protection contexts и поведение skipped statuses на фактической Gitea. Rollback — trigger/job changes, contexts восстанавливаются согласованно.
|
||
- **Related finding IDs:** VERIFY-001; остальные guarantees independent.
|
||
|
||
### VERIFY-003 — Backend preparation повторяется и не принадлежит standalone verify целиком
|
||
|
||
- **Decision = SIMPLIFY; Severity = P2; Confidence = High; Effort = S.**
|
||
- **Evidence:** `backend/.gitea/workflows/verify.yml:83–89`; `backend/.gitea/workflows/image.yml:30–33`; `backend/package.json:12–13,22–34`; `backend/.gitignore:7–8`; `backend/prisma/schema.prisma:1–5`; `backend/src/prisma/prisma.service.ts:1–5`; `backend/Dockerfile:8–10,12–22`; `backend/test/openapi-contract.e2e-spec.ts:139–156`.
|
||
- **Claim:** в одном обычном verify job explicit generation вызывается 3 раза, Nest build 2 раза. Одна revision проверяется без changes между этими шагами. Local standalone `verify` при отсутствующем ignored client доходит до typechecks до собственной generation.
|
||
- **Current mechanism:** (1) CI explicit prisma generate; (2) verify заканчивается build = generate + nest build; (3) test:e2e начинает тот же build. Root `verify` не имеет preparation перед typed lint/typecheck. Installed client manifest этой версии не имеет postinstall generation. Docker production path также наследует direct generate из dependencies stage, затем генерирует в package build ещё раз.
|
||
- **Consumer:** typed source import generated Prisma, app/test typechecks и unit tests; runtime OpenAPI generator импортирует `dist/src/app.module.js`. Последний требует свежую сборку, а не просто возможность Jest transpile source.
|
||
- **Impact / actual cost:** подтверждён лишний запуск двух host generations и одного host Nest build; cold Docker path ещё одного generate. Потенциальный cold-local failure выводится из import/order, но fresh checkout runtime-воспроизведение не выполнялось. **Impact unmeasured** для latency/CPU; число explicit configured calls измерено статически.
|
||
- **Why now:** same job, same SHA и одно environment дают возможность reuse без ослабления независимой CI boundary.
|
||
- **Minimum change:** сделать standalone verify владельцем generation **до typed consumers**, оставить один Nest build; после successful verify вызвать существующий `node test/sqlite.cjs --all` без второй сборки. Удалить workflow pre-generate только после переноса подготовки в verify. Сохранить standalone `build` и `test:e2e` self-contained. В Docker перенести direct generation в development target, если production build уже гарантирует её: development должен сохранить generated client.
|
||
- **Guarantees at risk:** свежесть generated client для schema change; наличие current dist для OpenAPI; copied proto assets и native Linux modules; standalone command UX. Кеширование host-generated dist между разными environments не предложено.
|
||
- **Counterarguments / trade-offs:** первый CI generate необходим сейчас — его удаление само по себе ломает clean typechecks. Второй build необходим standalone `test:e2e`, но избыточен в composed CI после verify. Build в Docker не удаляется: он доказывает packaging environment. Generation/internal build cache могут уменьшать стоимость повтора, но не устраняют лишний invocation.
|
||
- **Verification or rollback:** один clean disposable checkout с approved install: standalone verify → existing SQLite --all; лог должен показать 1 explicit host generate и 1 Nest build при тех же 19 suites и runtime schema comparison. Schema change должен влиять на типы и generator. Development и production Docker targets проверить отдельно. Rollback — scripts/workflow/stage ordering; source/data migrations не нужны.
|
||
- **Related finding IDs:** VERIFY-004, только общая тема подготовки; не объединять repos общим tooling.
|
||
|
||
### VERIFY-004 — Frontend pre-commit всегда делает package build и whole-repo graph
|
||
|
||
- **Decision = SIMPLIFY; Severity = P2; Confidence = High; Effort = S.**
|
||
- **Evidence:** `frontend/.husky/pre-commit:1–3`; installed launcher `frontend/.husky/_/h:6,14–22`; `frontend/package.json:25–26,33,36–38`; `frontend/packages/icons/package.json:9–20`; `frontend/packages/ui/package.json:9–24`; `frontend/dependency-cruiser.cjs:24–29,78–86`.
|
||
- **Claim:** каждый successful frontend commit, включая Markdown-only, после staged lint запускает два package builds и full base graph. Команда не зависит от staged input relevance и не повторяет именно staged proof.
|
||
- **Current mechanism:** actual hooksPath → Husky `sh -e` → Gitleaks index → lint-staged → `npm run deps` → build workspaces → depcruise src/packages working tree. Final verify/CI уже включают тот же base graph и отдельный Storybook graph.
|
||
- **Consumer:** local commit readiness. Граф working tree может блокировать commit из-за незакоммиченного unrelated code; это отличается от selected staged ESLint input.
|
||
- **Impact / actual cost:** 2 workspace library builds + whole-repo dependency analysis на каждый такой commit, даже при отсутствии changed code/config inputs; после final verify — повтор в той же local revision, если код не менялся. **Impact unmeasured**: hook duration, частота commits и `--no-verify` не измерены и не утверждаются.
|
||
- **Why now:** перенести existing whole-repo proof в existing final/CI boundary проще, чем писать новый staged graph builder.
|
||
- **Minimum change:** убрать `npm run deps` из mandatory pre-commit; сохранить full graph в final verify/CI. Сохранить fail-closed staged Gitleaks и staged lint. Если early graph feedback обязательно по принятому workflow, минимально ограничить existing command relevant source/package/TS/resolver/dependency config changes, не считать content-only import diff полноценным incremental graph proof.
|
||
- **Guarantees at risk:** более поздняя обратная связь о cycles/import boundaries. CI guarantee не теряется при сохранении full graph и required verify; staged lint обязан получать актуальные package declarations при relevant package changes.
|
||
- **Counterarguments / trade-offs:** standalone deps prep нужна для fresh package exports, поэтому её нельзя убрать глобально из command. Local graph catches errors до отправки и полезен, если runtime мал. Без measured duration рекомендована минимальная смена layer, не сложная cache/fingerprint orchestration.
|
||
- **Verification or rollback:** будущий Markdown-only commit должен выполнять staged secret scan и commitlint, без package build/graph. Secret fixture должен по-прежнему fail до downstream commands; existing `scripts/test-pre-commit.mjs` использовать при изменении hook. Import cycle должен fail в full verify/CI. Проверить relevant staged TS lint на clean/fresh declarations. Rollback — вернуть одну hook command.
|
||
- **Related finding IDs:** VERIFY-003; cross-audit 10 — implementation quality custom hook test, здесь не исследовалась.
|
||
|
||
## 8. DELETE / SIMPLIFY / KEEP / INVESTIGATE
|
||
|
||
| Decision | Механизм | Основание и сохраняемая гарантия |
|
||
| --- | --- | --- |
|
||
| DELETE, условно после FIX | Node setup/npm ci в specs verify job | После перехода на meaningful Git range Node не consumer; commits/security dependency checks остаются. VERIFY-001 |
|
||
| SIMPLIFY | Backend host generation/build DAG и Docker duplicate generate | Один свежий artifact в каждом environment; не удалять pre-type preparation. VERIFY-003 |
|
||
| SIMPLIFY | Mandatory full deps в frontend pre-commit | Whole-repo graph оставить final + required CI; staged Gitleaks/lint сохранить. VERIFY-004 |
|
||
| FIX | Specs CI input range; title edited triggers | Proof должен зависеть от actual checked input. VERIFY-001/002 |
|
||
| KEEP | Независимый CI после local checks | Local success не trusted proof для merge; install/checks повторяются на новой boundary обоснованно |
|
||
| KEEP | SQLite functional suites и temp DB guard | Unit mocks не заменяют authorization/CAS/transaction/replay proof; e2e-env отклоняет неisolated DB |
|
||
| KEEP | Current-build OpenAPI/runtime comparison и frontend byte check | Разные producer/consumer inputs; standalone offline generator guard сохраняется |
|
||
| KEEP | Base и Storybook dependency graphs | TS graph и runtime reachable graph имеют разные policy/inputs |
|
||
| KEEP | JSDOM и narrow/wide Chromium | DOM logic не доказывает реальную геометрию; viewports не OS matrix |
|
||
| KEEP | Full coverage в final/CI и Sonar lcov | Targeted tests без coverage — iteration feedback; не заменяют global coverage floor или report consumer |
|
||
| KEEP | Security before expensive verify; fail-closed exits | Cheap failures останавливают дорогую работу в пределах DAG; не превращать advisory/secret fail в green |
|
||
| KEEP | Feature PR-only verification, event-scoped cancellation, immutable image labels/tags | Уже уменьшает redundant runs и защищает artifact identity; фактическая server configuration остаётся unverified |
|
||
| KEEP | Performance/durability отдельными commands | Wall-clock shared-runner budget отдельно; schema-risk proof не отменять из-за того, что он вне ordinary verify |
|
||
| INVESTIGATE | npm/browser cache | В workflows не задан cache input/action; persistent runner cache может уже работать. До timing/hit proof не вводить новый cache layer |
|
||
| INVESTIGATE | Full app gate для Markdown-only application PR | Trigger сейчас whole-repo. Сначала определить affected paths и required-check semantics; не вводить path filters, оставляющие required status pending/skipped |
|
||
| INVESTIGATE | Второй frontend tsc, перекрытие backend app/test typecheck | Invocation overlap есть; cache и program-root differences не позволяют доказать ценность удаления без diagnostics comparison |
|
||
| INVESTIGATE | PR head freshness against updated base | Gitea не строит merge preview; actual branch protection не доступна в static checkout |
|
||
|
||
### Complexity-pass по фактическому `ponytail-audit`
|
||
|
||
- `shrink:` сократить повтор host generation/build в backend composed CI до одной подготовки; reuse existing SQLite runner. [`backend/package.json:12,28,34`; `.gitea/workflows/verify.yml:83–89`]
|
||
- `delete:` убрать mandatory whole-repo deps/build из frontend pre-commit; replacement — existing final/CI graph gate. [`frontend/.husky/pre-commit:3`]
|
||
- `native:` заменить пустой CI worktree diff + Node installation в specs на Git commit-range check. [`specs/.gitea/workflows/verify.yml:18–22`]
|
||
|
||
**net:** lines/dependencies reduction **not measured**, подтверждённых кандидатов на удаление dependency нет. Skill заканчивается оценкой net; числовой `-N lines` здесь не выдумывается, поскольку patch не готовился. Это не proposal удалить checks как таковые.
|
||
|
||
## 9. Cost & benefit
|
||
|
||
| Изменение | Ожидаемый класс benefit | Фактическое основание | Обязательный regression proof |
|
||
| --- | --- | --- | --- |
|
||
| Meaningful Git range без Node в specs job | CI minutes, maintenance, trust in gate | Один setup-node и один npm ci станут unnecessary для Git-only consumer; время **not measured** | Committed whitespace fail, safe range/fetch/fallback, preserved required context |
|
||
| Metadata-only title check | Reliability; avoidance of expensive metadata rerun | Сейчас `edited` не обрабатывается; новых минут/сокращения **not measured** | Invalid title fail + valid pass без app rerun; no skipped-status bypass |
|
||
| Backend preparation once | CI CPU/minutes и local reproducibility | 3 explicit host generate → intended 1; 2 host build → intended 1 на composed path; время **not measured** | Cold checkout/types/schema/dist, same e2e selection, runtime OpenAPI equality |
|
||
| Lean frontend pre-commit | Developer waiting, cognitive load | Один unconditional package-build/full-graph chain можно снять с hook; время/частота **not measured** | Secrets remain fail closed, staged lint meaningful, cycle caught at required CI |
|
||
| Iteration without full coverage/build | Local runtime и feedback latency | Existing targeted commands уже есть; usage frequency/agent tokens **not measured** | Whole-repo final/CI и relevant risk tests остаются |
|
||
| Optional download caching | Potential network/CI minutes | Workflow cache config отсутствует; actual hit/miss state **UNVERIFIED** | Same npm ci + lock integrity; Linux native rebuild; Gitea cache compatibility |
|
||
|
||
Ни runtime savings приложения, ни процентов ускорения, ни сокращения agent tokens не измерено. Уменьшение числа explicit commands не равно пропорциональному уменьшению времени.
|
||
|
||
## 10. Recommended Tiered Verification Policy
|
||
|
||
Это **рекомендация**, не изменённые инструкции. Сейчас оба engineering-файла требуют `npm ci` и full verify при code/dependency completion; audit read-only не отменяет это правило задним числом.
|
||
|
||
| Layer | Frontend | Backend | Specs/docs/root | Guarantees retained |
|
||
| --- | --- | --- | --- | --- |
|
||
| `edit` | HMR + relevant `test:run -- <path>` без coverage; targeted ESLint; package preparation при первом запуске/изменении packages | Relevant Jest pattern; configured HTTP/SQLite subset при boundary changes; current generated client до typed checks | Изменённый текст/anchors; локальный diff, staged отдельно | Быстрый observable feedback; money/auth/CAS cases по затронутому риску |
|
||
| `feature complete` | Один full verify после последнего relevant input change; targeted visual/a11y proof | Один full verify с self-contained preparation + relevant HTTP/DB suites; contract proof при wire change; durability при schema/data change | Docs full Markdown/link gate; specs meaningful diff + native validation при requirements/schema change; root config/text checks | Full types/lint/coverage/architecture/bundle и risk-specific proof |
|
||
| `pre-commit` | Fail-closed staged secrets → staged lint/fix → commit-msg; full graph оставить final/CI | Existing policy без новых integration hooks | Specs commit-msg; root/docs не добавлять full app hook | Проверяется actual commit input; fix не выдаётся за read-only proof |
|
||
| `CI` | Fresh lock installation → full verify + Chromium; full graph и coverage floors; security и commits required | Fresh generated client → full verify → existing isolated SQLite --all без повторного build; commits/security required | Git-range specs check; full docs links; title on edited; root commitlint | Independent merge proof; whole-repo cross-consumer regressions; no ignored errors |
|
||
| `scheduled` | Existing daily security; deep suite только при обоснованном риске | Existing daily security; performance на dedicated/manual environment; runner-regression не каждый PR | Existing daily security; native/store checks по owned risk, не новый обязательный blanket process | Advisory drift ловится без edit; load noise не блокирует functional gate |
|
||
|
||
Installation локально следует привязать к manifest/lock/Node/install-state change, а не каждой source правке; в CI сохранить воспроизводимую installation. Это часть общей local/agent policy — см. cross-audit 14, без повторного отдельного finding.
|
||
|
||
### Что можно проверять адресно, что нельзя считать полным proof
|
||
|
||
| Check | Safe targeted use | Что incremental selection пропускает |
|
||
| --- | --- | --- |
|
||
| ESLint | Selected files с тем же typed config и fresh declarations | Новые config/rule effects на untouched files; import/type changes у consumers |
|
||
| Jest/Vitest | Relevant suite/pattern/project без coverage during iteration | Shared helper/provider/transport регрессии в других suites, global coverage floors |
|
||
| SQLite | Existing runner с explicit affected suite | Другие access/transaction consumers, shared migration/schema regressions; schema change требует broad DB proof |
|
||
| Typecheck | Existing project boundary, не случайный список changed `.ts` | Reverse dependencies и public type consumers; production isolation при смешивании test roots |
|
||
| dependency-cruiser | Можно выбирать момент full scan по relevant input paths | Whole-graph cycles/reachability/resolver effects; `changed files only` не эквивалент full graph |
|
||
| Knip | Full at completion/CI, optional during iteration | Reverse references, config-discovered entries и dependency usage across workspaces |
|
||
| OpenAPI | Producer current-build proof; consumer provided snapshot proof | Breaking changes against old release и delivery freshness вне explicit input set |
|
||
| Markdown relative links | Changed source + incoming references при локальном переносе | Удаление target ломает unchanged incoming links; final docs full check сохраняется |
|
||
| App/Storybook/image build | Local selective build для affected artifact | Shared package/theme/plugins влияют на оба frontend consumers; image native/assets не доказаны host build |
|
||
|
||
### Fail-fast, parallelism и resources
|
||
|
||
- Frontend/backend jobs действительно выстроены по `needs`; failed commits/security не запускают expensive verify. Daily event не запускает verify. Внутри scripts `&&` останавливает downstream checks.
|
||
- Frontend pre-commit использует `sh -e`; explicit Gitleaks `|| exit $?` **передаёт failure**, а не маскирует его. Temporary OpenAPI checks и SQLite runner устанавливают ненулевой exit code при failure. `continue-on-error`/blanket `|| true` в прочитанных workflows отсутствуют.
|
||
- Docs/specs jobs независимы и могут занимать разные runners одновременно. Последовательность одного application DAG не ограничивает server-wide capacity; README указывает настройку `runner.capacity: 1` вне repo. Actual capacity — unverified.
|
||
- SQLite runner уже даёт каждой suite отдельный temp DB и запускает её `--runInBand`; suites с explicit listen используют port 0. Это уменьшает DB/port collisions, но не доказывает безопасность полной параллелизации всех suites. Общий generated client/dist и CPU/memory остаются shared resources.
|
||
- **KEEP serial default:** без timings не добавлять Jest/SQLite/Chromium параллельные jobs. Не выполнять одновременно повторные builds, которые перезаписывают одни outputs. Unit/static parallelism допустим только после single preparation и доказанного resource isolation, если measured critical path это оправдывает.
|
||
- Chromium install сейчас идёт до full verify, то есть до cheap type/lint failures. Возможен более ранний static stage, но новый составной gate/повтор package build требует cost proof; это не подтверждённый отдельный finding.
|
||
|
||
### Explicit guarantees retained
|
||
|
||
1. Денежная точность и boundary regressions остаются в existing meaningful unit/HTTP/DB checks; audit не предлагает заменить их coverage percentage.
|
||
2. Real SQLite authorization, transactions/rollback, CAS, replay/idempotency и connection-isolation proof остаются CI functional suites; DB никогда не заменяется пользовательской.
|
||
3. Generated client и current dist свежи до своих consumers; runtime contract сравнивается с current generator без внешней сети.
|
||
4. Frontend accepted snapshot/type equality, full types и reverse-consumer proof остаются локальными и independent от sibling checkout.
|
||
5. Full graph cycles/public API/reachability, Chromium layout и app/catalog packaging остаются final/CI checks.
|
||
6. Staged secrets/history security не bypass; failures не становятся green; required contexts не ослабляются через skipped jobs.
|
||
7. Release SHA/version identity, immutable tags, Linux native/assets, post-publication digest smoke и explicit rollout selection остаются.
|
||
8. Durability при data/schema change и controlled lifecycle regression tests не исключаются из risk-based verification из-за их стоимости; содержательность assertions — отдельный аудит 08.
|
||
|
||
## 11. Top actions
|
||
|
||
### Quick wins: подтверждённые механизмы, малый diff
|
||
|
||
| Rank | Действие | Value / risk / effort | Finding |
|
||
| --- | --- | --- | --- |
|
||
| 1 | Сделать specs CI whitespace-check явного commit range; затем убрать Node install из этого Git-only job | Убирает no-op proof и лишнюю installation; риск неверного range покрывается tiny fixture; S | VERIFY-001 |
|
||
| 2 | Добавить PR title edit coverage, сохранив selective metadata-only execution и проверив contexts | Исправляет stale check без full pipeline rerun; S | VERIFY-002 |
|
||
| 3 | Свести backend host preparation к одному generate/build на revision, сохранив clean standalone verify и existing e2e runner | Подтверждённый same-job повтор; cold-checkout/schema/dist proof обязателен; S | VERIFY-003 |
|
||
| 4 | Снять unconditional full graph/build с frontend pre-commit; оставить staged security/lint и required final/CI graph | Улучшает каждый commit path без нового tooling; риск только более поздней обратной связи; S | VERIFY-004 |
|
||
|
||
### Решения, требующие тестового подтверждения
|
||
|
||
| Rank | Действие | Необходимое подтверждение | Finding |
|
||
| --- | --- | --- | --- |
|
||
| 5 | Устранить второй generate в backend production Docker path, оставив его development target | Обе Docker targets сохраняют current client, native modules/assets и runtime smoke | VERIFY-003 |
|
||
|
||
Новое ADR для перестановки уже существующих checks не требуется. Новая policy удаления обязательного gate или изменения public delivery/merge trust boundary потребует отдельного согласованного решения; такой migration здесь не предлагается. Cache tuning и удаление перекрывающихся typechecks не входят в confirmed top actions.
|
||
|
||
## 12. Cross-audit signals
|
||
|
||
- **Audit 10 — custom tooling:** `frontend/scripts/check-image-publication.cjs`, `scripts/test-pre-commit.mjs`, backend runner-regression/durability entry points; отдельно проверить maintenance/consumer ownership, без ревью их алгоритмов здесь.
|
||
- **Audit 14 — agent/local workflow:** `frontend/.ai/conventions/engineering.md:60–62`, `backend/.ai/conventions/engineering.md:60–62`; mandatory npm ci + full completion gate и session повторяемость относятся к policy использования commands; реальные session counts здесь не измерены.
|
||
- **Audit 08 — test intent:** `backend/test/openapi-contract.e2e-spec.ts`, SQLite functional suites и frontend browser tests; этот аудит подтверждает selection/trigger, не достаточность assertions.
|
||
- **Audit 12 — dependency/security policy:** `backend/.gitea/workflows/verify.yml:62–65`; разные audit levels и advisory option требуют dependency-policy проверки, не переноса network audit на data edit.
|
||
- **Audit 15 — specs/docs:** `specs/README.md:18–35`, `specs/.gitea/workflows/verify.yml`; необходимость и version ownership native OpenSpec validation — отдельно от подтверждённого no-op Git range.
|
||
|
||
## 13. Open questions / verification plan
|
||
|
||
| Вопрос, меняющий решение | Статус | Самый дешёвый способ подтверждения |
|
||
| --- | --- | --- |
|
||
| Required commits/security/verify contexts действительно обязательны? Проверяется ли outdated base/head? | UNVERIFIED: локальный workflow не задаёт server protection | Read-only Settings/branch protection export и один existing PR status; не запускать full suite |
|
||
| Фактическая Gitea версия поддерживает concurrency/edited/skipped status behavior как ожидает README? | UNVERIFIED для сервера; docs подтверждают edited/head semantics | Server version + существующий cancellation log; для VERIFY-002 metadata-only rename на disposable PR |
|
||
| Насколько дорогие npm ci, package build, Chromium install, повтор Nest build? Есть ли persistent cache? | not measured | Step timestamps одного успешного PR и image run, runner cache/hit logs; после changes сравнить те же steps; не запускать full pipeline ради аудита |
|
||
| Clean standalone backend verify действительно fails до generation? | Выводится из import/order; runtime fresh-install proof не выполнялся | При реализации VERIFY-003 один disposable clean checkout с normal approved install; проверить до/после. Не использовать локальный generated directory как baseline |
|
||
| Можно ли удалить второй frontend tsc или backend app-only typecheck без потери diagnostics? | INVESTIGATE, не top action | Compare configured compiler roots/diagnostics на real type regression; удалить только после equivalence proof, не ради invocation count |
|
||
| Нужен ли mandatory local graph до каждого commit, если final/CI его сохраняют? | Trade-off VERIFY-004 | Выбрать feedback layer у владельца; измерить один existing hook timing. Не писать новый graph-diff/cache инструмент |
|
||
| Есть ли гарантированное подтверждение принятого frontend artifact перед component rollout? | UNVERIFIED для deploy repo | Read-only release/deployment record с producer SHA/consumer snapshot provenance; separate deployment owner, без обращения к банковским API |
|
||
|
||
Вопросы о benchmark SLAs, существующих business assertions и advisory correctness намеренно не разворачиваются в этом аудите. Отсутствие run/log evidence не означает отсутствие защиты.
|
||
|
||
## 14. Машинно-считываемая таблица для консолидации
|
||
|
||
| ID | Decision | Severity | Confidence | Repo | Files | One-line impact | Effort | Related IDs |
|
||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||
| VERIFY-001 | FIX | P2 | High | specs | specs/package.json; specs/.gitea/workflows/verify.yml | Clean CI checks empty worktree diff, not committed changes; Node install gives no content proof | S | VERIFY-002 |
|
||
| VERIFY-002 | FIX | P2 | High | frontend,backend,specs,docs | frontend/.gitea/workflows/verify.yml; backend/.gitea/workflows/verify.yml; specs/.gitea/workflows/commits.yml; docs/.gitea/workflows/commits.yml | PR title edits leave previous Conventional Commit status stale | S | VERIFY-001 |
|
||
| VERIFY-003 | SIMPLIFY | P2 | High | backend | backend/package.json; backend/.gitea/workflows/verify.yml; backend/.gitea/workflows/image.yml; backend/Dockerfile | Same CI revision explicitly generates client 3 times and builds twice; standalone preparation occurs late | S | VERIFY-004 |
|
||
| VERIFY-004 | SIMPLIFY | P2 | High | frontend | frontend/.husky/pre-commit; frontend/package.json | Every commit runs package builds and full graph even without relevant staged code | S | VERIFY-003 |
|