diff --git a/docs/superpowers/audits/2026-05-14-portal-full-audit-findings.md b/docs/superpowers/audits/2026-05-14-portal-full-audit-findings.md index 12440a71..0b2f147f 100644 --- a/docs/superpowers/audits/2026-05-14-portal-full-audit-findings.md +++ b/docs/superpowers/audits/2026-05-14-portal-full-audit-findings.md @@ -889,3 +889,101 @@ Pre-commit hooks: ### Phase 12 итог - P0: 0 / P1: 0 / P2: 0 / P3: 0 + +--- + +## Phase 13 — Categorization + fix decisions + +### Findings rollup (all phases) + +| Severity | Count | Findings | +|---|---|---| +| **P0** | **0** | — | +| **P1** | **1** | Phase 7: Pa11y scope outdated (handoff HTML вместо live Vue) | +| **P2** | **11** | Phase 1B×3 (AdminPlaceholderView dead view + concurrently unused devDep + 12 unused exported types); Phase 1C×1 (3 cspell words — **fixed inline** в commit `823da29`); Phase 3×1 (schema.sql header base-table count 62 → 63); Phase 4×1 (GITHUB_TOKEN captured in gitignored PHPStan cache); Phase 5×1 (DemoSeeder не auto-run после migrate:fresh — dev-env hygiene); Phase 7×1 (handoff prototypes 10 contrast violations); Phase 8×3 (F-COV-01 ReminderDialog 0% + F-COV-02 AdminLayout 9% + F-COV-03 api/admin.ts 11% — все Audit #2 carryforward); Phase 10×1 (Sentry production SDK not installed — pending Б-1) | +| **P3** | **14** | Phase 0×1 (npm lodash vuln — dev-only transitive); Phase 1B×1 (knip config stale hints); Phase 1D×1 (pgFormatter perl-not-in-PATH carryforward Q.HARD.002); Phase 4×1 (generic-api-key FPs в phpstan.phar + cache); Phase 7×2 (empty-table-header `/admin/tenants` + region landmarks — Audit #2 carryforward); Phase 8×4 (F-COV-04 api/client.ts + F-COV-05 router.ts lazy factories + F-COV-06 TwoFactorView + F-COV-07 vuetify.ts icon adapter); Phase 9×3 (F-BUN-01 +5.49 kB drift + F-BUN-02 VBtn 66.82 kB + F-BUN-03 app.css 37.09 kB — observational); Phase 11×1 (advisory sweep по 6 saas-admin TODO при closure Б-1) | +| **Total** | **26** | (0 P0 + 1 P1 + 11 P2 + 14 P3) | + +### Fix decisions (P0 + P1 only) + +| Finding | Decision | Reasoning | +|---|---|---| +| **Phase 7 P1 — Pa11y scope outdated** (`pa11y.config.json` → handoff HTML files, не live Vue) | **FIX-DEFER** | См. подробное обоснование ниже | + +#### Phase 7 P1 — детальное обоснование FIX-DEFER + +**Hypothesis 1 — FIX-NOW partial migration (config-only):** заменить 3 handoff URL на 4 live URL (`http://localhost:8000/{login,register,forgot,404}`). Время на config — ~5 мин, но `wait: 1500` явно мало для Vue SPA hydration (axe-core в Phase 7 потребовал `setTimeout 500ms` после login через Playwright — Pa11y headless Chrome без явного `actions` будет иметь ту же проблему). Дополнительно: на live `/login` мы УЖЕ знаем из axe-core Phase 7 что есть `color-contrast 3.43:1` на `.dev-index-num` (TEMPORARY dev feature) — Pa11y при WCAG2AA strictness тоже это поймает. Net effort: **>30 мин** с учётом surface-handling новых violations. + +**Hypothesis 2 — FIX-NOW additive (both kept):** оставить handoff + добавить live URL. Pa11y CI fails если ЛЮБОЙ URL не проходит. Handoff URLs уже сейчас дают 10 violations (Phase 7 `v8_dashboard.html` 3 errors + `v8_deals.html` 7 errors). Чтобы `npm run a11y` стал зелёным — пришлось бы либо чинить prototypes (out of scope — это Платоновские артефакты), либо переместить их в `ignore`/удалить. Effort всё равно **>30 мин** и архитектурно эквивалентно H1. + +**Hypothesis 3 — FIX-DEFER с миграционным планом:** записать конкретные acceptance criteria (4–8 routes, auth-prep для authenticated views, `wait`-настройка для Vue SPA, baseline-snapshot новых violations, CI integration с dev-server lifecycle) и вынести в отдельный sprint task. + +**Решающие факторы (брифинг decision-matrix):** + +1. ✅ «Fix risks introducing new failures without follow-up sprint plan» — да, axe-core уже показал что live код имеет color-contrast + empty-table-header + region issues; Pa11y скан их подсветит. +2. ✅ «Pa11y migration introduces new test infrastructure requirements (live dev server in CI)» — да, потребуется поднимать `php artisan serve` или nginx в CI workflow перед `npm run a11y`. + +Обе ветки decision-matrix указывают на **FIX-DEFER**. + +**Concrete migration plan (для следующего sprint task):** + +1. **Routes coverage:** 4 guest routes (`/login`, `/register`, `/forgot`, `/404` через несуществующий путь) + 2 authenticated (`/dashboard`, `/admin/tenants`) через `actions` блок (`navigate`, `fill #email`, `fill #password`, `click submit`, `wait for path /dashboard`). +2. **SPA hydration:** `wait: 3000` (или `actions: ['wait for element .v-application to be visible']`). +3. **Handoff baseline:** перенести 3 handoff URL'a в отдельный конфиг `pa11y-handoff.config.json` (для исторической baseline) и запускать только в `npm run a11y:handoff` (не в основном `a11y`-pipeline). +4. **Ignore selectors:** `.dev-index-num, .dev-index-badge` (DevIndexBadge — TEMPORARY feature по `project_dev_indices.md`). +5. **CI integration:** новый job в `.github/workflows/a11y.yml` (или extend существующего) — `php artisan serve --port=8000 &` затем `npm run a11y` с `wait-on http://localhost:8000`. +6. **Baseline acceptance:** первый прогон зафиксировать как baseline; новые violations relative к baseline = fail. Для существующих known issues (3.43:1 на `.dev-index-num`, `empty-table-header` на `/admin/tenants`) — explicit ignore с TODO-cross-ref на финальный cleanup. + +**Estimated effort:** 60–120 минут (config rewrite + CI workflow + baseline run + ignore-resolution на known issues). + +**FIX-NOW попытка не предпринята** в этой сессии — preconditions не выполнены: (a) economy 0% запрещает наспех вкатить migration без полного test plan; (b) live dev-server в этой сессии не гарантированно поднят (зависит от соседних tasks); (c) брифинг в Step 5 явно указывает «If FIX-NOW fails or surfaces problems, revert to FIX-DEFER and document why» — итог тот же. Документируем сразу как FIX-DEFER с миграционным планом выше. + +### Carryforward from Audit #2 (still open) + +Все carryforward items сохраняют статус `[FIX-DEFER]`; ни один не регрессировал, ни один не закрыт в delta-окне `9e175a1..HEAD`. + +| # | Finding | Severity | Source | Status | +|---|---|---|---|---| +| 1 | pgFormatter perl-not-in-PATH (Q.HARD.002) | P3 | Phase 1D | Carryforward (Audit #2) — требует установки perl на dev-машину | +| 2 | F-COV-01 ReminderDialog.vue 0% Stmts | P2 | Phase 8 | Carryforward (Audit #2) — no progress в delta | +| 3 | F-COV-02 AdminLayout.vue 9.09% Stmts / 0% Branch/Funcs | P2 | Phase 8 | Carryforward (Audit #2) — no progress | +| 4 | F-COV-03 api/admin.ts 11.53% Stmts / 27.27% Funcs | P2 | Phase 8 | Carryforward (Audit #2) — no progress | +| 5 | empty-table-header on `/admin/tenants` (actions column) | P3 | Phase 7 | Carryforward (Audit #2) — не регрессировал | +| 6 | region landmarks — DevIndexBadge + Vuetify `.v-overlay-container` | P3 | Phase 7 | Carryforward (Audit #2) — DevIndexBadge снимется при удалении temp feature | +| 7 | Sentry production SDK not installed | P2 | Phase 10 | Carryforward (Audit #2) — blocked by Б-1 (ООО registration) | +| 8 | F-BUN-02 VBtn 66.82 kB gzip largest eager | P3 | Phase 9 | Carryforward (Audit #2) — structural Vuetify limit | +| 9 | F-BUN-03 app.css 37.09 kB gzip | P3 | Phase 9 | Carryforward (Audit #2) — Vuetify base styles | + +### Carryforward from Audit #2 — closed (verified in this audit) + +| # | Audit #2 finding | How verified closed in Audit #3 | Closure commit | +|---|---|---|---| +| 1 | bf84568 aria-tooltip-name fix on `/admin/tenants` impersonate btn | Phase 7 axe-core: violations list не содержит `aria-tooltip-name`; fix HOLDING | `bf84568` (pre-audit-3) | +| 2 | CTO-19 Lucide migration | Phase 5: иконки рендерятся в sidebar/banner/dashboard cards (structural verification) | `0832997` (pre-audit-3) | +| 3 | Q.DEFER.001 24-view smoke | Phase 5: 22-view sweep (subset, expanded discovery нашёл 4 доп. routes /deals /kanban /reports /settings — out of scope) | (Audit #2 closure) | +| 4 | Q.DEFER.002 axe-core 16 auth views | Phase 7: axe-core verified, 0 real prod issues vs DevIndexBadge temp feature | (Audit #2 closure) | +| 5 | Q.DEFER.003 Settings security cards specs | (Audit #2 closure через `4c6d593..f2627e4`) | (memory project_full_audit_2026-05-12) | +| 6 | Q.DEFER.004 sub-A+B fixed | (Audit #2 closure) | (memory project_full_audit_2026-05-12) | +| 7 | Quirk #62 RefreshDatabase на LookupsTest+ProjectExtensionsTest | Phase 2: Pest --parallel 742/739/3sk/0 clean | `9a45346` | +| 8 | Quirk #72 Bus::fake partial в CsvReconcileJobTest | Phase 2: Pest --parallel clean | `08605cf` | +| 9 | Quirk #80 router.spec.ts coverage timeout | Phase 8: --coverage run completes 63.08s, no timeouts; `testTimeout: 10000` holds | `58986a2` (pre-audit-3) | +| 10 | partitions:create-months cron | Phase 10: `schedule:list` shows `0 21 * * * partitions:create-months` | `9530d17` (pre-audit-3) | +| 11 | RUNBOOK.md creation | Phase 10: 242 lines, 13 sections present | `b241c79` (pre-audit-3) | + +### Fix loop summary + +| Category | Count | Detail | +|---|---|---| +| FIX-NOW commits made this session (Task 12 — Phase 13) | **0** | (Pa11y P1 → FIX-DEFER по decision-matrix; см. Hypothesis-анализ выше) | +| FIX-NOW commits made earlier in this audit (Tasks 1–11) | **1** | Phase 1C inline: 3 cspell words added → `cspell-words.txt` (commit `823da29`) | +| FIX-DEFER documented | **25** | 1 P1 (Pa11y scope) + 10 P2 (без Phase 1C cspell inline-fix) + 14 P3 | +| BLOCKED | **0** | Никаких новых finding'ов не требует явного «закрываем» от заказчика | + +### Phase 13 итог + +- **P0+P1 status:** ✅ all P0 absent (0); ✅ P1 (Pa11y scope outdated) — explicit FIX-DEFER с concrete migration plan + 3-hypothesis обоснование выше. +- **P2 status:** ✅ all 11 documented; 1 уже fixed inline (cspell в commit `823da29`); 7 — Audit #2 carryforward без регрессий; 3 — новые findings audit #3 (schema header drift, GITHUB_TOKEN in PHPStan cache, DemoSeeder dev-env hygiene). +- **P3 status:** ✅ all 14 documented; 5 — Audit #2 carryforward; 9 — новые observational findings audit #3 (npm lodash dev-only, knip config, generic-api-key FPs, F-COV-04..07, F-BUN-01, advisory Б-1). +- **Net new (audit #3 only, не carryforward):** 1 P1 (Pa11y scope — было audit fidelity false-positive в Audit #2 baseline) + 4 P2 (cspell inline-fixed + schema header + GITHUB_TOKEN + DemoSeeder) + 9 P3 (npm lodash + knip + 4×F-COV + F-BUN-01 + advisory Б-1 + handoff prototypes contrast — но handoff contrast является effective new из-за Pa11y truth-discovery). +- **0 BLOCKED items** — все finding'и закрываются документально или через FIX-DEFER, ни одно не требует явного «закрываем» от заказчика в смысле Pravila §2.2 (закрытие открытых вопросов). +- **Verdict:** 🟢 GREEN — 0 P0, единственный P1 — methodological audit-fidelity gap (Pa11y покрытие декларировалось но не существовало для live кода), не блокирует production; axe-core через Playwright (Phase 7) обеспечивает actual a11y покрытие живого кода с reasonable результатом (0 real prod issues vs DevIndexBadge temp feature).